[BUG] IMCC looking in P3[0] for 1st arg

0 views
Skip to first unread message

Steve Fink

unread,
Oct 26, 2003, 1:50:45 AM10/26/03
to perl6-i...@perl.org
I am getting a seg fault when doing a very simple subroutine call with
IMCC:

.sub _main
newsub $P4, .Sub, _two_of
$P6 = new PerlHash
.pcc_begin prototyped
.arg $P6
.arg 14
.pcc_call $P4
after:
.pcc_end
end
.end

.pcc_sub _two_of non_prototyped
.param PerlHash Sunknown_named3
.param int mode
.pcc_begin_return
.pcc_end_return
.end

The problem is that IMCC is checking to see whether the 1st argument
is of the correct type (PerlHash), but it looks for the argument in
P3[0], when in fact it isn't an overflow arg and so is in P5. P3, in
fact, is null and so parrot seg faults.

Oddly, if I take away the int parameter (and corresponding argument),
it does not crash. But this also seems to remove the typecheck
entirely.

Leopold Toetsch

unread,
Oct 26, 2003, 4:19:08 AM10/26/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:
> I am getting a seg fault when doing a very simple subroutine call with
> IMCC:

> .sub _main
> newsub $P4, .Sub, _two_of
> $P6 = new PerlHash
> .pcc_begin prototyped

^^^^^^^^^^
> .pcc_sub _two_of non_prototyped
^^^^^^^^^^^^^^

You are stating explicitely conflicting call types. That can't work.
When you remove "non_prototyped" in the sub, its prepared to be called
either way and it works.

leo

Melvin Smith

unread,
Oct 26, 2003, 11:32:07 AM10/26/03
to Steve Fink, perl6-i...@perl.org
At 11:50 PM 10/25/2003 -0700, Steve Fink wrote:
> newsub $P4, .Sub, _two_of

Leo answered your question, I just wanted to point out that you can
now write the above as:

$P4 = newsub _two_of


As Leo said, the call types conflict. In this case we eventually
should be able to make IMCC warn you since the sub is declared in
the same module, but in other cases, where the called method
may not be bound until runtime, we may not know.

I think the problem is more of a high level language problem than an
IMCC problem. Eventually the HLL has to track its own symbols and
calling conventions and IMCC just has to trust what it gets. IMCC should
eventually be _able_ to do compile time loading of bytecodes and check
prototypes and declarations, but it should be controlled by the HLL, not
the default (I think).

-Melvin


Steve Fink

unread,
Oct 26, 2003, 12:28:09 PM10/26/03
to Leopold Toetsch, perl6-i...@perl.org

Doh! Thanks, I definitely should have noticed that.

Although this does bring up another issue -- should parrot really be
seg faulting when it gets a uninitialized (null) PMC? It happens to me
quite often. In a way, the current behavior is rather nice, since the
errors tend to be more obvious. Then again, that's only because all my
test programs die early enough that no incorrect but non-null values
have snuck into my registers yet. Also, I wouldn't expect a VM to fall
flat on its face from something like this.

Leopold Toetsch

unread,
Oct 26, 2003, 1:21:13 PM10/26/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:

> Although this does bring up another issue -- should parrot really be
> seg faulting when it gets a uninitialized (null) PMC?

The problem is of course that we call pmc->vtable->some_meth_od() on a
NULL PMC. We could do the checks always, slowing down each PMC
operation. But OTOH a correct HLL compiler wouldn't produce such broken
code (hopefully). So that's probably something for the bounds-checking
and safe run cores.

Further if we have some kind of hint for the assembler, what is the main
program, we could spit out an unitialized warning (the code is mostly
there) and in case of an "in PMC" parameter make a fatal error out of
it.

leo

Melvin Smith

unread,
Oct 26, 2003, 1:39:24 PM10/26/03
to l...@toetsch.at, Steve Fink, dan Sugalski, perl6-i...@perl.org
At 07:21 PM 10/26/2003 +0100, Leopold Toetsch wrote:
>Steve Fink <st...@fink.com> wrote:
>
> > Although this does bring up another issue -- should parrot really be
> > seg faulting when it gets a uninitialized (null) PMC?
>
>The problem is of course that we call pmc->vtable->some_meth_od() on a
>NULL PMC. We could do the checks always, slowing down each PMC
>operation. But OTOH a correct HLL compiler wouldn't produce such broken
>code (hopefully). So that's probably something for the bounds-checking

This is an old discussion. While I agree with Leo (and Dan) on not putting
checks everywhere, I also think segfaulting on faulty bytecode is
violating the "Virtual Machine" contract.

I also don't wan't to see the performance hit of checking PMC regs everywhere.

I think a compromise would be to do define a interpreter global PMCNull
and point (or init) all Px registers to it.

All methods in this class would be implemented to throw an exception or
dump the bytecode for debugging and we could always trap a "NULL"
register access.

This way we never have a NULL pointer access with regards to Px regs.

The downside is fast initialization of register blocks. memsetting with
NULL (0)
will not be possible, but I'd have to actually go check and see if that
is really all that common.

-Melvin


Steve Fink

unread,
Oct 26, 2003, 9:25:03 PM10/26/03
to Leopold Toetsch, perl6-i...@perl.org
On Oct-26, Leopold Toetsch wrote:

That is working for me now for the parameter passing, but not for
return values. The below code seg faults because it is attempting to
pry return values out of P3; it works if I switch the line
.pcc_begin non_prototyped
to
.pcc_begin prototyped

I'm not sure if this is implemented yet, though.

Code follows:

.sub __main
.local Sub main_sub
main_sub = newsub _main
.pcc_begin non_prototyped
.pcc_call main_sub
ret:
.result $I0
.result $I1
.pcc_end
print "Returned "
print $I0
print ","
print $I1
print "\n"
end
.end

.pcc_sub _main prototyped
.pcc_begin_return
.return 10
.return 20
.pcc_end_return
.end

Melvin Smith

unread,
Oct 26, 2003, 11:09:06 PM10/26/03
to Steve Fink, Leopold Toetsch, perl6-i...@perl.org

It is still the same issue. This code explicitly mixes 2 call conventions.
_main is declared as prototyped so it will return 1 in I0 which signals that
it is returning its values in registers in prototyped convention. Your
call explicitly calls in non_prototyped mode which does not generate any
code to check the return convention since you are saying by your code
that you _know_ what the call convention is.

However, I see your point. To be orthogonal would suggest that we
implement the same feature for .pcc_call that we do for the .pcc_sub
declaration. If you left off the calling convention to .pcc_call it would
generate code
to check for either. Although this would really bloat the code, it might
be wise to support the feature for some instances.

-Melvin


Melvin Smith

unread,
Oct 26, 2003, 11:13:04 PM10/26/03
to Steve Fink, Leopold Toetsch, perl6-i...@perl.org

>However, I see your point. To be orthogonal would suggest that we
>implement the same feature for .pcc_call that we do for the .pcc_sub

I meant .pcc_begin here since that is where the proto|non_proto goes.

-Melvin


Steve Fink

unread,
Oct 27, 2003, 1:55:52 AM10/27/03
to Melvin Smith, Leopold Toetsch, perl6-i...@perl.org
On Oct-26, Melvin Smith wrote:
> At 06:25 PM 10/26/2003 -0800, Steve Fink wrote:
> > .pcc_sub _main prototyped
> > .pcc_begin_return
> > .return 10
> > .return 20
> > .pcc_end_return
> > .end
>
> It is still the same issue. This code explicitly mixes 2 call conventions.
> _main is declared as prototyped so it will return 1 in I0 which signals that
> it is returning its values in registers in prototyped convention. Your
> call explicitly calls in non_prototyped mode which does not generate any
> code to check the return convention since you are saying by your code
> that you _know_ what the call convention is.

Oops, I meant to leave the "prototyped" off of the _main sub. This
behaves indistinguishably from declaring it prototyped; it seg faults
if called non_prototyped. I believe it's supposed to work when called
with either style.

Sorry for the bad example.

Likewise, if I declare the .pcc_sub to be non_prototyped (so that both
the call and declaration are non_prototyped), I get the same error:

.sub _main
.local Sub myfunc
myfunc = newsub _myfunc
.pcc_begin non_prototyped
.pcc_call myfunc


ret:
.result $I0
.result $I1
.pcc_end
print "Returned "
print $I0
print ","
print $I1
print "\n"
end
.end

.pcc_sub _myfunc non_prototyped


.pcc_begin_return
.return 10
.return 20
.pcc_end_return
.end

% ./perl6 -Rt mini.imc

.
.
.
PC=60; OP=38 (invoke_p); ARGS=(P1=RetContinuation=PMC(0x40c04998))
PC=21; OP=1003 (restoretop)
PC=22; OP=801 (shift_i_p); ARGS=(I17=0, P3=NULL)
Error: '/home/sfink/parrot/parrot -t -r mini.imc ' failed
died with signal 11 (SIGSEGV)

> However, I see your point. To be orthogonal would suggest that we
> implement the same feature for .pcc_call that we do for the .pcc_sub
> declaration. If you left off the calling convention to .pcc_call it
> would generate code to check for either. Although this would really
> bloat the code, it might be wise to support the feature for some
> instances.

No, sorry, my bad example obscured the issue. I was not asking for a
.pcc_begin that works in either case; I just want it to be possible to
call a subroutine without a prototype and have it successfully return
values. True, I would also like to be able to call the same subroutine
*with* a prototype in another call site, but that is already
implemented. I don't think allowing people to leave off the
{non_,}prototyped declaration from .pcc_begin provides anything but
superficial syntactic orthogonality; a call site really ought to know
whether it can see the prototype of what it's calling or not! (Well...
except I sometimes call non_prototyped even when I know the prototype,
because pdd03 calling convention prototypes don't handle everything in
a Perl6 prototype. But that's irrelevant here.)

My brain doesn't seem to be working all that well this weekend...

I'll throw in one more thing just because I know a certain Mr. P.
Cawley dearly loves people to pile unrelated things into a single
thread: could there be a way to expose which continuation to invoke
when returning from a routine? In a regex, I'd really like a rule to
be invoked with a "success" continuation and a "fail, so backtrack"
continuation. And possibly with some more extreme failure
continuations for cuts and commits and things. But right now the
return continuation in P1 is hidden inside the PCC mechanism. (I guess
I could just manually overwrite P1, but that seems like it's working
against imcc rather than with it.)

I'm faking it for now by returning a boolean status code, but that
doesn't really feel like the "right" solution.

Melvin Smith

unread,
Oct 27, 2003, 2:34:54 AM10/27/03
to Steve Fink, Leopold Toetsch, perl6-i...@perl.org

>I'll throw in one more thing just because I know a certain Mr. P.
>Cawley dearly loves people to pile unrelated things into a single
>thread: could there be a way to expose which continuation to invoke
>when returning from a routine? In a regex, I'd really like a rule to
>be invoked with a "success" continuation and a "fail, so backtrack"
>continuation. And possibly with some more extreme failure
>continuations for cuts and commits and things. But right now the
>return continuation in P1 is hidden inside the PCC mechanism. (I guess
>I could just manually overwrite P1, but that seems like it's working
>against imcc rather than with it.)

Technically its not a problem and relatively easy to implement. I
suppose it needs to be discussed as an addition to the calling
convention first, though. I'm up for it.

-Melvin


Leopold Toetsch

unread,
Oct 27, 2003, 2:31:06 AM10/27/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:

> That is working for me now for the parameter passing, but not for
> return values.

As Melvin said, you are still mixing calling conventsion. *But* return
conventions are currently only prototyped. We don't have any syntax yet
to denote the desired behavior.

I'm still waiting on design documents about unification of call and
return conventions.

IMHO the whole PCC stuff needs some tweaking. Argument passing/param
binding and return value passing/result binding seem to be almost the
same to me. Though the former has some more variants like r/o, copy, by
ref, whatever.

The whole Ix register usage for prototyped calls seems rather unneeded
to me. When both sides know, how they pass params and return values,
there is no need for additional information. Depending on the run core,
there can be significant (--profile shows one third of execution time in
the fibonacci benchmark) overhead for register setup. For JIT this boils
down to nothing though.

Then we need some means to define and lookup function signatures for
library code. When HLLs should finally be able to use any library of all
HLLs that use Parrot, these libaries have to specify their interfaces.

Prototyped and non-prototyped are two different ways to call a function
(or return some values). But these are known ways. We might have
additionally the case, that a function is called either way.

leo

Leopold Toetsch

unread,
Oct 27, 2003, 3:00:41 AM10/27/03
to Melvin Smith, perl6-i...@perl.org
Melvin Smith <mrjol...@mindspring.com> wrote:

> Technically its not a problem and relatively easy to implement.

[ Aother note ]

$ perldoc imcc/docs/calling_conventions.pod

· pcc_call
Takes either 2 arguments: the sub and the return
continuation, or the sub only. For the latter case an
invokecc gets emitted.

> -Melvin

leo

Leopold Toetsch

unread,
Oct 27, 2003, 2:55:41 AM10/27/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:

> Likewise, if I declare the .pcc_sub to be non_prototyped (so that both
> the call and declaration are non_prototyped), I get the same error:

Non-protyped returns are not implemented.

> I'll throw in one more thing just because I know a certain Mr. P.
> Cawley dearly loves people to pile unrelated things into a single
> thread: could there be a way to expose which continuation to invoke
> when returning from a routine?

.pcc_call Sub, RetCont

is implemented. S. e.g. imcc/t/syn/pcc_2.imc

leo

Dan Sugalski

unread,
Oct 27, 2003, 9:59:58 AM10/27/03
to Melvin Smith, l...@toetsch.at, Steve Fink, perl6-i...@perl.org
On Sun, 26 Oct 2003, Melvin Smith wrote:

> At 07:21 PM 10/26/2003 +0100, Leopold Toetsch wrote:
> >Steve Fink <st...@fink.com> wrote:
> >
> > > Although this does bring up another issue -- should parrot really be
> > > seg faulting when it gets a uninitialized (null) PMC?
> >
> >The problem is of course that we call pmc->vtable->some_meth_od() on a
> >NULL PMC. We could do the checks always, slowing down each PMC
> >operation. But OTOH a correct HLL compiler wouldn't produce such broken
> >code (hopefully). So that's probably something for the bounds-checking
>
> This is an old discussion. While I agree with Leo (and Dan) on not putting
> checks everywhere, I also think segfaulting on faulty bytecode is
> violating the "Virtual Machine" contract.
>
> I also don't wan't to see the performance hit of checking PMC regs everywhere.
>
> I think a compromise would be to do define a interpreter global PMCNull
> and point (or init) all Px registers to it.
>
> All methods in this class would be implemented to throw an exception or
> dump the bytecode for debugging and we could always trap a "NULL"
> register access.
>
> This way we never have a NULL pointer access with regards to Px regs.

This works. The safe code still needs to check, and null registers are
still a possibility but the null op and the register block-clearing code
can do this when they clear out register blocks. The Null PMC should pitch
a fatal exception for everything it does, so we can catch this stuff.

Probably should be a compile-time option so it can be turned on for
debugging/development runs and off for general usage.


Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Jeff Clites

unread,
Oct 27, 2003, 8:28:58 PM10/27/03
to Melvin Smith, dan Sugalski, l...@toetsch.at, Steve Fink, perl6-i...@perl.org
On Oct 26, 2003, at 10:39 AM, Melvin Smith wrote:

> I think a compromise would be to do define a interpreter global PMCNull
> and point (or init) all Px registers to it.

...


> The downside is fast initialization of register blocks. memsetting
> with NULL (0)
> will not be possible, but I'd have to actually go check and see if that
> is really all that common.

If we determine that it makes a difference, we can store away a
register block filled with our PMCNull, and memcpy (or memmove) from
that to initialize a block. Should be nearly as fast.

JEff

Melvin Smith

unread,
Oct 27, 2003, 8:48:26 PM10/27/03
to Jeff Clites, dan Sugalski, l...@toetsch.at, Steve Fink, perl6-i...@perl.org

If the obvious were a truck, I'd be dead. Thanks for pointing that out. :)

Luckily we init registers with a for loop so there won't be any change.
Either way it won't affect the opcode loop (or will barely).

-Melvin


Dan Sugalski

unread,
Oct 28, 2003, 8:58:27 AM10/28/03
to Jeff Clites, Melvin Smith, l...@toetsch.at, Steve Fink, perl6-i...@perl.org

Yup. Going all-NULL bought us a win when we were moving the registers
around on top of frames, since new frames were always NULL--joys of zeroed
allocations from the OS, about the fastest way to get all-zeroed memory.
(Often faster than explicitly zeroing the page out, courtesy of MMU
hardware) We don't do that any more so it's not nearly as much of an
issue.

Reply all
Reply to author
Forward
0 new messages