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)
+ )
)