fix
diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp index c5b1524..39fbdfe 100644 --- a/src/passes/StackIR.cpp +++ b/src/passes/StackIR.cpp
@@ -251,12 +251,13 @@ // rid of it, which might not be worth it. // TODO: the case of 2 seems optimizable, by replacing the old value // with a drop. + assert(!valueStack.empty()); auto droppedIndex = valueStack.back(); valueStack.pop_back(); auto* droppedInst = insts[droppedIndex]; // TODO: handle drops of control flow elements like blocks, which show // up as multiple insts. - if (!isControlFlow(droppedInst)) { + if (droppedInst && !isControlFlow(droppedInst)) { auto consumedByDropped = getNumConsumedValues(droppedInst); if (consumedByDropped < 2) { EffectAnalyzer effects(passOptions, module->features); @@ -279,10 +280,13 @@ // to handle unreachable code here - it's ok to pop multiple values // there even if the stack is at size 0. while (consumed > 0) { + assert(!valueStack.empty()); valueStack.pop_back(); consumed--; } - if (isBegin(inst) && inst->type.isConcrete()) { + // Push a value on the stack if there is one (note the convention in stack + // IR where the end of a block etc. represents the value). + if (inst->type.isConcrete() && isEnd(inst)) { valueStack.push_back(i); } } @@ -358,6 +362,10 @@ return inst->op == StackInst::Basic || isControlFlowBegin(inst); } + bool isEnd(StackInst* inst) { + return inst->op == StackInst::Basic || isControlFlowEnd(inst); + } + // Remove the instruction at index i. If the instruction // is control flow, and so has been expanded to multiple // instructions, remove them as well.
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 2e4cd43..15e457d 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp
@@ -1753,7 +1753,7 @@ stackType = Type::none; } else if (op != StackInst::BlockEnd && op != StackInst::IfEnd && op != StackInst::LoopEnd && op != StackInst::TryEnd) { - // If a concrete type is returned, we mark the end of the construct has + // If a concrete type is returned, we mark the end of the construct as // having that type (as it is pushed to the value stack at that point), // other parts are marked as none). stackType = Type::none;
diff --git a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt b/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt index bb031c4..394cdac 100644 --- a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt +++ b/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt
@@ -1,6 +1,7 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i64 (func (result i64))) (event $e0 (attr 0) (param i32)) (func $eh (; 0 ;) (local $exn exnref) @@ -18,10 +19,14 @@ drop end ) + (func $drop_unreachable_block (; 1 ;) (result i64) + unreachable + ) ) (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i64 (func (result i64))) (event $e0 (attr 0) (param i32)) (func $eh (; 0 ;) (; has Stack IR ;) (local $exn exnref) @@ -45,4 +50,12 @@ ) ) ) + (func $drop_unreachable_block (; 1 ;) (; has Stack IR ;) (result i64) + (drop + (block $label$1 (result i32) + (unreachable) + ) + ) + (i64.const 1) + ) )
diff --git a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast b/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast index c355a2b..c9fbf8b 100644 --- a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast +++ b/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast
@@ -1,6 +1,5 @@ (module (event $e0 (attr 0) (param i32)) - (func $eh (local $exn exnref) (try (throw $e0 (i32.const 0)) @@ -16,4 +15,12 @@ ) ) ) + (func $drop_unreachable_block (result i64) + (drop + (block $label$1 (result i32) + (unreachable) + ) + ) + (i64.const 1) + ) )