jasmin
jasmin copied to clipboard
Implicit arguments must be variables
We should check that implicit arguments are variables so that they can be allocated to their expected register or flag.
The instruction ADC
has the carry flag as an implicit argument: it's third argument (of type sbool
) must be allocated to the CF
flag. This is a valid program:
export
fn test(reg u64 arg0, reg u64 arg1) -> reg u64 {
reg u64 x;
x = arg0;
_, x = x + arg1 + true;
return x;
}
but can't be compiled to assembly. The problem is that it gives an internal error:
internal compilation error in function test:
asmgen: assemble_sopn : invalid op
because the Oaddcarry
wasn't be removed by lowering.
The following is also valid:
fn test(reg u64 arg0) -> reg u64 {
reg u64 x y;
reg bool cf zf;
x = arg0;
y = #CQO(0);
return x;
}
but gives an internal error
internal compilation error in function test:
asmgen: (compile_arg) bad implicit register
Same happens with _, x = #ADC(x, arg0, false);
.
When the argument is a variable that can't be allocated properly, register allocation fails, and that makes sense. When it's an immediate of the correct type, it falls through until assembly generation, where it gives an internal error.
The first example now gives a proper error message (after #313).
The second example is still bad. One possible fix would be to have a pass before lowering that checks that this kind of constraints are satisfied, and if kindly asked, introduces intermediate variables.
Two more examples, perhaps less artificial:
export
fn main() -> reg u64 {
reg u64 x;
x = 0;
x = 1 - x;
return x;
}
and
export
fn main() -> reg u64 {
reg u64 x;
x = 0;
x = #ADD(1, x);
return x;
}
both fail with an internal error for the same reason. (We could fix the first one in x86_lowering.v
.)