Estou brincando com um compilador WebAssembly. Estou olhando para o teste https://github.com/WebAssembly/spec/blob/634f0d9009404f498ef8d8bd510bd6f0941219cc/test/core/br_if.wast#L272 que se parece com isso expandiu um pouco:
(module
(func
$type-arg-void-vs-num-nested
(result i32)
block i32
(i32.const 0)
block
(i32.const 1)
(br_if 1)
end
end
)
)
O erro que recebo é:
Error: check failed:
test.wast:10:12
type stack size too small at br_if value. got 0, expected at least 1
(br_if 1)
^^^^^^^
Eu acho que o tamanho da pilha quando atinge br_if
é 2, o que significa que aparece 1 para o condicional e então tem uma sobra para satisfazer o bloco externo. Presumi que (i32.const 0)
cairia no bloco aninhado. Qual parte estou faltando? Desde já, obrigado.
Sim, o relatório de erros do wabt pode melhorar aqui. Mesmo que haja dois i32
s na pilha, os operadores nunca passarão do início de um bloco, portanto, há efetivamente apenas um.
Isso significa que cada bloco obtém sua própria pilha? Fiquei confuso com a seguinte declaração no documento de semântica:
A execução de uma instrução de bloco ou loop não tem efeito na pilha de valores.
Talvez isso deva mudar para:
A execução de uma instrução de bloco ou loop não tem efeito na pilha de valores, mas todos os valores da pilha fora do bloco em execução são inacessíveis.
Ou estou entendendo mal?
Isso significa que cada bloco obtém sua própria pilha?
Eu não diria que eles têm suas próprias pilhas, apenas que há um limite para o que pode ser estourado. É assim que é implementado no wabt, há uma pilha de valores e uma pilha de "rótulos". Cada rótulo armazena um "limite" que é o tamanho da pilha de valores quando o rótulo é empurrado. Então, sempre que você estourar, você verifica o limite do rótulo principal.
A execução de uma instrução de bloco ou loop não tem efeito na pilha de valores.
Talvez isso deva mudar para:
A execução de um bloco ou instrução de loop não tem efeito na pilha de valores, mas todos os valores da pilha fora do bloco em execução são inacessíveis.
Ou estou entendendo mal?
Sim, provavelmente vale a pena mencionar algo assim em Semantics.md. Embora eu deva mencionar que há um trabalho em uma especificação de prosa formal também.
>
Isso significa que cada bloco obtém sua própria pilha?
Eu não diria que eles têm suas próprias pilhas, só que há um limite
para o que pode ser estourado. É assim que é implementado no wabt,
é uma pilha de valores e uma pilha de "rótulos". Cada etiqueta armazena um "limite" que é
o tamanho da pilha de valores quando o rótulo é empurrado. Então, sempre que você
pop, você verifica o limite do rótulo superior.
Ambos são pontos de vista válidos. Semanticamente, a visualização "block-local stack" tem o
vantagem de não requerer invariantes extras. Com "pilha única"
suposições de correção adicionais são necessárias, como todos os limites
que ocorre na pilha de rótulos deve estar dentro dos limites da pilha de operandos atuais
altura, eles devem ocorrer em (não necessariamente estritamente) ordem crescente, e
a pilha de etiquetas nunca deve estar vazia.
Obrigado pela informação. Estou encerrando isso porque não há nada acionável para sair dele e especificações mais formais estão chegando para esclarecer isso.
Comentários muito úteis
>
Ambos são pontos de vista válidos. Semanticamente, a visualização "block-local stack" tem o
vantagem de não requerer invariantes extras. Com "pilha única"
suposições de correção adicionais são necessárias, como todos os limites
que ocorre na pilha de rótulos deve estar dentro dos limites da pilha de operandos atuais
altura, eles devem ocorrer em (não necessariamente estritamente) ordem crescente, e
a pilha de etiquetas nunca deve estar vazia.