jasmin
jasmin copied to clipboard
Regalloc conflict produces internal error when function is inlined
The following gives internal compilation error in function main: Variable allocation: i (defined at "ble.jazz", line 16 (12-13)) and i (defined at "ble.jazz", line 16 (12-13)) : variable already set
fn f(reg ptr u8[1] p, reg u64 i) -> reg ptr u8[1] {
while (i < 1) {
p[(int) i] = 0;
i += 1;
}
return p;
}
export
fn main () -> reg u8 {
stack u8[1] c;
reg ptr u8[1] p;
p = c;
reg u64 i;
i = 0;
while (i < 1) {
#inline
p = f(p, i);
i += 1;
}
reg u8 tmp;
tmp = p[0];
return tmp;
}
I believe it's because f
increases i
but main
does not see this. If I remove the #inline
, then I get a register allocation error saying that these two i
s conflict, this is what I'd expect. Naturally, it works if I introduce i = i
at the beginning of f
, or return i
in f
.
Is this really an internal error, then?
Well spotted. Here is a smaller example:
inline fn f(reg u64 j) {
while (j < 1) {
j += 1;
}
}
export
fn main (reg u64 i) {
while (i < 1) {
f(i);
i += 1;
}
}
I think the issue is in the “renaming” step that blindly trusts the “rename” tag attached to assignments that are introduced by the “inlining” phase.
A simple workaround is to add an explicit assignment “i = i;” at the beginning of the inlined function.