Steve Fink wrote:
IMCC doesn't handle bsr with non-constant args. A test program would be something like L: $I0 = addr L bsr $I0 It will complain that it can't fixup the label '$I0'.
Yep. That's missing. I'll hvae a look at it. (But you could invoke a Sub, which is ok IIRC).
In tracking this down, I also noticed that imcc seems to assume that
you will do a saveall/restoreall pair around bsr calls. (At least,
that's what a comment says.)
Yes, that's correct. Currently imcc does register allocation per compilation units (.sub/.end) and doesn't know anything about calling conventions and specially assumes, that "bsr" doesn't change registers.
This can of course be considered as a bug. It evolved in this direction due to the P6C code generator always did subroutines in this form.
So imcc has to learn somethin about calling conventions, and imcc has to get some information from the HL about these: Does the HL use pdd03_calling_convetions or do bsrs preserve all registers, or whatever.
It won't work, when you rely on the register allocator:... I haven't written a test case to see if this assumption matters, but the code I generate tends to use bsr specifically for lightweight situations where I do not want to preserve registers. (Or do a full invoke op.)
.sub _test
$I0 = 2
$I1 = 3
bsr L
print $I0
print $I1
print "\n"
end
L: $I2 = 4
$I3 = 5
ret
.end
25
($I2 and $I3 both get register I0)
This shouldn't be to hard to fix - from imcc.y:
if (!strcmp(name, "bsr") || !strcmp(name, "ret")) {
/* ignore subcalls and ret
* because they saveall
*/
}
else {
/* XXX: assume the jump is relative and to the last arg.
* usually true.
*/
ins->type = ITBRANCH | (1 << (nargs-1));
So "bsr" here is treated not as a branch (which of course it is) and no control flow is generated, so the register allocator will fail.
So, we need some definitions about calling conventions and a way how to tell imcc what the HL intended with "bsr"s and the like.
leo