次の2つはどちらもコンパイルが通る
(module
(func (export "test") (param $i i32) (result i32)
(block (result i32)
i32.const 1
br 0
;;i32.const 2
)
)
)
(module
(func (export "test") (param $i i32) (result i32)
(block (result i32)
i32.const 1
br 0
i32.const 2
)
)
)
バグかと思ったが、仕様に書いてあった。
stack-polymorphicというのがよくわからないのですが、後続の命令の引数に対して「齟齬がない限り」どんな型とでも考えてもらっていいよ、ということのようです。
このblockの返り値が[i32]であれば良いので、こちらであればbrの型は[i32]->[i32]となり、
(block (result i32)
i32.const 1
br 0
)
こちらであればbrの型は[i32]->[]となる。
(block (result i32)
i32.const 1
br 0
i32.const 2
)
unconditional control transfer(問答無用でジャンプする)のときにしか使われないようなので、実質的にはその後の命令は型チェックだけすれば良くて、実装はしなくて良い。