@@ -648,6 +648,16 @@ void WasmBinaryWriter::visitBreak(Break *curr) {
648648 if (curr->condition ) recurse (curr->condition );
649649 o << int8_t (curr->condition ? BinaryConsts::BrIf : BinaryConsts::Br)
650650 << U32LEB (getBreakIndex (curr->name ));
651+ if (curr->condition && curr->type == unreachable) {
652+ // a br_if is normally none or emits a value. if it is unreachable,
653+ // then either the condition or the value is unreachable, which is
654+ // extremely rare, and may require us to make the stack polymorphic
655+ // (if the block we branch to has a value, we may lack one as we
656+ // are not a taken branch; the wasm spec on the other hand does
657+ // presume the br_if emits a value of the right type, even if it
658+ // popped unreachable)
659+ o << int8_t (BinaryConsts::Unreachable);
660+ }
651661}
652662
653663void WasmBinaryWriter::visitSwitch (Switch *curr) {
@@ -669,6 +679,9 @@ void WasmBinaryWriter::visitCall(Call *curr) {
669679 recurse (operand);
670680 }
671681 o << int8_t (BinaryConsts::CallFunction) << U32LEB (getFunctionIndex (curr->target ));
682+ if (curr->type == unreachable) {
683+ o << int8_t (BinaryConsts::Unreachable);
684+ }
672685}
673686
674687void WasmBinaryWriter::visitCallImport (CallImport *curr) {
@@ -689,6 +702,9 @@ void WasmBinaryWriter::visitCallIndirect(CallIndirect *curr) {
689702 o << int8_t (BinaryConsts::CallIndirect)
690703 << U32LEB (getFunctionTypeIndex (curr->fullType ))
691704 << U32LEB (0 ); // Reserved flags field
705+ if (curr->type == unreachable) {
706+ o << int8_t (BinaryConsts::Unreachable);
707+ }
692708}
693709
694710void WasmBinaryWriter::visitGetLocal (GetLocal *curr) {
@@ -700,6 +716,9 @@ void WasmBinaryWriter::visitSetLocal(SetLocal *curr) {
700716 if (debug) std::cerr << " zz node: Set|TeeLocal" << std::endl;
701717 recurse (curr->value );
702718 o << int8_t (curr->isTee () ? BinaryConsts::TeeLocal : BinaryConsts::SetLocal) << U32LEB (mappedLocals[curr->index ]);
719+ if (curr->type == unreachable) {
720+ o << int8_t (BinaryConsts::Unreachable);
721+ }
703722}
704723
705724void WasmBinaryWriter::visitGetGlobal (GetGlobal *curr) {
@@ -986,6 +1005,9 @@ void WasmBinaryWriter::visitUnary(Unary *curr) {
9861005 case ReinterpretInt64: o << int8_t (BinaryConsts::F64ReinterpretI64); break ;
9871006 default : abort ();
9881007 }
1008+ if (curr->type == unreachable) {
1009+ o << int8_t (BinaryConsts::Unreachable);
1010+ }
9891011}
9901012
9911013void WasmBinaryWriter::visitBinary (Binary *curr) {
@@ -1075,6 +1097,9 @@ void WasmBinaryWriter::visitBinary(Binary *curr) {
10751097 case GeFloat64: o << int8_t (BinaryConsts::F64Ge); break ;
10761098 default : abort ();
10771099 }
1100+ if (curr->type == unreachable) {
1101+ o << int8_t (BinaryConsts::Unreachable);
1102+ }
10781103}
10791104
10801105void WasmBinaryWriter::visitSelect (Select *curr) {
@@ -1083,6 +1108,9 @@ void WasmBinaryWriter::visitSelect(Select *curr) {
10831108 recurse (curr->ifFalse );
10841109 recurse (curr->condition );
10851110 o << int8_t (BinaryConsts::Select);
1111+ if (curr->type == unreachable) {
1112+ o << int8_t (BinaryConsts::Unreachable);
1113+ }
10861114}
10871115
10881116void WasmBinaryWriter::visitReturn (Return *curr) {
@@ -1771,7 +1799,11 @@ Expression* WasmBinaryBuilder::popExpression() {
17711799 throw ParseException (" attempted pop from empty stack" );
17721800 }
17731801 auto ret = expressionStack.back ();
1774- expressionStack.pop_back ();
1802+ // to simulate the wasm polymorphic stack mode, leave a final
1803+ // unreachable, don't empty the stack in that case
1804+ if (!(expressionStack.size () == 1 && ret->type == unreachable)) {
1805+ expressionStack.pop_back ();
1806+ }
17751807 return ret;
17761808}
17771809
0 commit comments