Strange generated wasm

I have a small test program which I'm compiling to wasm32-unknown-unknown

fn main() {
    let mut a: u64 = 1;
    let mut b = 1;
    for i in 1..=1000 {
        let c = a.wrapping_add(b);
        a = b;
        b = c;
        println!("{}: {}", i, a);
    }
}

But, when compiled, core::ops::function::FnOnce::call_once becomes:

(func $_ZN4core3ops8function6FnOnce9call_once17h2ab86767ec17c50dE (type $t3) (param $p0 i32) (param $p1 i32) (result i32)
    local.get $p0
    i32.load
    drop
    loop $L0 (result i32)
      br $L0
    end)

This doesn't seem right, as it:

  1. Loads the first parameter onto the stack
  2. Reads from that location in memory
  3. Gets rid of the value it just read
  4. Enters a loop of type i32
  5. Gets an i32 from the top of the stack and teturns to the start of the loop

But there is nothing on the stack to take back in the loop! Is this output therefore invalid, or have I missed/misunderstood something?

What happens when you run it?

With my own wasm interpeter, it sees the issue and fails to even instantiate. With wasmtime, it runs fine (as far as I can tell). I'm inclined to believe wasmtime is right, but I can't figure out why

edit: I am currently in the process of writing my interpreter (this is a test case for it) so it wouldn't be that much of a surprise if I got the handling of it wrong

Yep, misunderstood the spec. Breaking in a loop is supposed to take the input to the loop from the stack before looping, not the output.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.