summaryrefslogtreecommitdiff
path: root/src/passes/StackIR.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-07-22 09:11:12 -0700
committerGitHub <noreply@github.com>2021-07-22 09:11:12 -0700
commit556381b41aa95b56a77e9217afb2e2d7ecb230f5 (patch)
tree8bd8f1dd5083427e6c2024ea7af25ae487247b68 /src/passes/StackIR.cpp
parented97c68294a8d95c57972eae22906cc0bea1aae8 (diff)
downloadbinaryen-556381b41aa95b56a77e9217afb2e2d7ecb230f5.tar.gz
binaryen-556381b41aa95b56a77e9217afb2e2d7ecb230f5.tar.bz2
binaryen-556381b41aa95b56a77e9217afb2e2d7ecb230f5.zip
[Wasm GC] Avoid dangerous StackIR opts on GC (#4007)
removeUnneededBlocks() can force us to use a local when we load the emitted wasm, which can't work for something nondefaultable like an RTT. For now, just don't run that optimization if GC is enabled. Eventually, perhaps we'll want to enable this optimization in a different way.
Diffstat (limited to 'src/passes/StackIR.cpp')
-rw-r--r--src/passes/StackIR.cpp44
1 files changed, 40 insertions, 4 deletions
diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp
index fbb990fe0..a3d9442bf 100644
--- a/src/passes/StackIR.cpp
+++ b/src/passes/StackIR.cpp
@@ -51,10 +51,14 @@ class StackIROptimizer {
Function* func;
PassOptions& passOptions;
StackIR& insts;
+ FeatureSet features;
public:
- StackIROptimizer(Function* func, PassOptions& passOptions)
- : func(func), passOptions(passOptions), insts(*func->stackIR.get()) {
+ StackIROptimizer(Function* func,
+ PassOptions& passOptions,
+ FeatureSet features)
+ : func(func), passOptions(passOptions), insts(*func->stackIR.get()),
+ features(features) {
assert(func->stackIR);
}
@@ -65,7 +69,39 @@ public:
if (passOptions.optimizeLevel >= 3 || passOptions.shrinkLevel >= 1) {
local2Stack();
}
- removeUnneededBlocks();
+ // Removing unneeded blocks is dangerous with GC, as if we do this:
+ //
+ // (call
+ // (rtt)
+ // (block
+ // (nop)
+ // (i32)
+ // )
+ // )
+ // === remove inner block ==>
+ // (call
+ // (rtt)
+ // (nop)
+ // (i32)
+ // )
+ //
+ // Then we end up with a nop that forces us to emit this during load:
+ //
+ // (call
+ // (block
+ // (local.set
+ // (rtt)
+ // )
+ // (nop)
+ // (local.get)
+ // )
+ // (i32)
+ // )
+ //
+ // However, that is not valid as an rtt cannot be set to a local.
+ if (!features.hasGC()) {
+ removeUnneededBlocks();
+ }
dce();
}
@@ -340,7 +376,7 @@ struct OptimizeStackIR : public WalkerPass<PostWalker<OptimizeStackIR>> {
if (!func->stackIR) {
return;
}
- StackIROptimizer(func, getPassOptions()).run();
+ StackIROptimizer(func, getPassOptions(), getModule()->features).run();
}
};