t/op/calling_61.pir crashes because Parrot's trying to treat the number -1 as
a PMC. Why?
Parrot_convert_arg (interp=0x804f040, st=0xbf8b70c0) at src/inter_call.c:905
905 if (key->vtable->base_type != enum_class_Key)
(gdb) bt
#0 Parrot_convert_arg (interp=0x804f040, st=0xbf8b70c0)
at src/inter_call.c:905
#1 0xb7d39d51 in set_nci_P (interp=0x804f040, st=0xbf8b70c0, val=0xffffffff)
at src/nci.c:150
#2 0xb7d3ce40 in pcf_P_JPP (interp=0x804f040, self=0x80da230)
at src/nci.c:1771
#3 0xb7e3532e in Parrot_NCI_invoke (interp=0x804f040, pmc=0x80da230,
next=0x0)
at ./src/pmc/nci.pmc:309
#4 0xb7d1c534 in Parrot_pcc_invoke_sub_from_sig_object (interp=0x804f040,
sub_obj=0x80da230, sig_obj=0x80f38f8) at src/inter_call.c:2471
#5 0xb7d27b80 in Parrot_mmd_multi_dispatch_from_c_args (interp=0x804f040,
name=0xb7f2bc3e "cmp", sig=0xb7f03acf "PP->I") at src/multidispatch.c:629
#6 0xb7e00166 in Parrot_default_cmp (interp=0x804f040, pmc=0x80f3930,
value=0x80f3914) at ./src/pmc/default.pmc:2447
#7 0xb7ccacfa in Parrot_lt_p_i_ic (cur_opcode=0x8127c88, interp=0x804f040)
at src/ops/cmp.ops:315
The desired MMD sub should take two PMCs and returns an INTVAL (frame #5,
signature "PP->I"), but the invoked MMD sub takes two PMCs and returns a PMC.
The crash comes in convert_arg, where the C function has returned INTVAL -1,
but the argument passing code expects that it has returned and Integer PMC.
Because 0xffffffff isn't a valid PMC pointer, there's a crash.
If you look at src/pmc/integer.pmc, the cmp MULTIs there return INTVALs
(signature IJPP), but the MULTI registration code declares them as signature
PJPP. I modified Parrot::Pmc2c::MULTI to improve the return-value-of-cmp
regexp and the test passes.
-- c
Index: lib/Parrot/Pmc2c/MULTI.pm
===================================================================
--- lib/Parrot/Pmc2c/MULTI.pm (revision 30934)
+++ lib/Parrot/Pmc2c/MULTI.pm (working copy)
@@ -93,7 +93,7 @@
# prepend the short signature return type
if ($self->name =~ /^i_/) {
$short_sig = "v" . $short_sig;
- } elsif ($self->name =~ /^is_/ or $self->name =~ /^cmp_/) {
+ } elsif ($self->name =~ /^is_/ or $self->name =~ /\bcmp\b/) {
$short_sig = "I" . $short_sig;
} else {
$short_sig = "P" . $short_sig;