Я пишу анализатор байт-кода WebAssembly и натолкнулся на некоторое поведение, связанное с тем, как различные компиляторы WebAssembly обрабатывают l oop инструкции, которые мне трудно согласовать со спецификацией WebAssembly.
Следующий фрагмент кода ( взятый из WebAssembly l oop тестовых случаев ) показывает вложенный l oop, который, как ожидается, вернет целое число i32.
(module
(type $t0 (func (result i32)))
(func $cont-inner (export "cont-inner") (type $t0) (result i32)
(local $l0 i32)
i32.const 0
local.set $l0
local.get $l0
loop $L0 (result i32)
loop $L1 (result i32)
br $L0
end
end
i32.add
local.set $l0
Визуальный анализ вышеизложенного показывает, что этот синтаксис не полностью соответствует спецификации (насколько я понимаю), поскольку тело цикла не имеет значений стека для возврата.
Конечно, вышеприведенные циклы образуют бесконечный l oop, и поэтому во время выполнения программа фактически не выйдет из самого внешнего l oop.
Но некоторые из компиляторов, которые я пытался скомпилировать, без проблем, например, webassembly.studio. И наоборот, если безусловная ветвь заменяется условной ветвью, компиляторы фактически ведут себя так, как я ожидаю, и жалуются на отсутствующее возвращаемое значение.
Я что-то упустил в спецификации WebAssembly о том, как работают циклы? Или компиляторы неявно проводят анализ достижимости?