Closed
Description
I could be wrong about this one because Wasm control flow is confusing, but I'm 85% sure this C function compiles to something it shouldn't:
intmax_t make_power_of_10_int(int p)
{
intmax_t v = 1;
while (p >= 5) { v *= 100000; p -= 5; }
while (p >= 1) { v *= 10; p -= 1; }
return v;
}
Using -Oz
this compiles to:
make_power_of_10_int:
i64.const 1
local.set 1
loop i64
block
local.get 0
i32.const 4
i32.gt_s
br_if 0
block
loop
local.get 0
i32.const 1
i32.lt_s
br_if 1
local.get 0
i32.const -1
i32.add
local.set 0
local.get 1
i64.const 10
i64.mul
local.set 1
br 0
end_loop
end_block
local.get 1
return
end_block
local.get 0
i32.const -5
i32.add
local.set 0
local.get 1
i64.const 100000
i64.mul
local.set 1
br 0
end_loop
end_function
The problem is that:
- The first (outermost) loop has a
i64
return type, but at the 4th line from the bottomlocal.set 1
empties the stack. - This loop branches unconditionally with
br 0
, so even if there was something in the stack it could never be used. - This loop and the whole function can only end through
return
. - The result is stored in
local1
anyway, I can't see why the loop would need a return type.
Therefore the most immediately obvious conclusion is that giving that loop a return type is a mistake because it doesn't actually return anything (due to empty stack) and it can never exit normally anyway. I guess it would make sense if at the end of the loop the last local.set
was treated as a local.tee
, but I see no reason to believe things are supposed to work like this.
This problem seems specific to -Oz
as the other optimisation settings produce totally different Wasm.