summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild-js.sh1
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/Inlining.cpp4
-rw-r--r--src/passes/MergeBlocks.cpp2
-rw-r--r--src/passes/Metrics.cpp4
-rw-r--r--src/passes/NoExitRuntime.cpp60
-rw-r--r--src/passes/pass.cpp1
-rw-r--r--src/passes/passes.h1
-rw-r--r--test/passes/no-exit-runtime.txt32
-rw-r--r--test/passes/no-exit-runtime.wast15
10 files changed, 116 insertions, 5 deletions
diff --git a/build-js.sh b/build-js.sh
index 808329386..f9553e3e4 100755
--- a/build-js.sh
+++ b/build-js.sh
@@ -115,6 +115,7 @@ echo "building shared bitcode"
$BINARYEN_SRC/passes/Metrics.cpp \
$BINARYEN_SRC/passes/MinifyImportsAndExports.cpp \
$BINARYEN_SRC/passes/NameList.cpp \
+ $BINARYEN_SRC/passes/NoExitRuntime.cpp \
$BINARYEN_SRC/passes/OptimizeInstructions.cpp \
$BINARYEN_SRC/passes/PickLoadSigns.cpp \
$BINARYEN_SRC/passes/PostEmscripten.cpp \
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index b4e396750..0ad9dbf05 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -30,6 +30,7 @@ SET(passes_SOURCES
Metrics.cpp
MinifyImportsAndExports.cpp
NameList.cpp
+ NoExitRuntime.cpp
OptimizeInstructions.cpp
PickLoadSigns.cpp
PostEmscripten.cpp
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index ebc33bf97..35afc5776 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -349,11 +349,11 @@ struct Inlining : public Pass {
}
};
-Pass *createInliningPass() {
+Pass* createInliningPass() {
return new Inlining();
}
-Pass *createInliningOptimizingPass() {
+Pass* createInliningOptimizingPass() {
auto* ret = new Inlining();
ret->optimize = true;
return ret;
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index 57f8b7e41..38e9fc6a2 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -373,7 +373,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
Pass* create() override { return new MergeBlocks; }
- void visitBlock(Block *curr) {
+ void visitBlock(Block* curr) {
optimizeBlock(curr, getModule(), getPassOptions());
}
diff --git a/src/passes/Metrics.cpp b/src/passes/Metrics.cpp
index 5176f8762..b794ea32d 100644
--- a/src/passes/Metrics.cpp
+++ b/src/passes/Metrics.cpp
@@ -194,11 +194,11 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor<
}
};
-Pass *createMetricsPass() {
+Pass* createMetricsPass() {
return new Metrics(false);
}
-Pass *createFunctionMetricsPass() {
+Pass* createFunctionMetricsPass() {
return new Metrics(true);
}
diff --git a/src/passes/NoExitRuntime.cpp b/src/passes/NoExitRuntime.cpp
new file mode 100644
index 000000000..d76bb34ba
--- /dev/null
+++ b/src/passes/NoExitRuntime.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Assumes the program will never exit the runtime (as in the emscripten
+// NO_EXIT_RUNTIME option). That means that atexit()s do not need to be
+// run.
+//
+
+#include <pass.h>
+#include <wasm.h>
+#include <wasm-builder.h>
+#include <asmjs/shared-constants.h>
+
+using namespace std;
+
+namespace wasm {
+
+struct NoExitRuntime : public WalkerPass<PostWalker<NoExitRuntime>> {
+ bool isFunctionParallel() override { return true; }
+
+ Pass* create() override { return new NoExitRuntime; }
+
+ void visitCall(Call* curr) {
+ auto* import = getModule()->getFunctionOrNull(curr->target);
+ if (!import || !import->imported() || import->module != ENV) return;
+ // Remove all possible manifestations of atexit, across asm2wasm and llvm wasm backend.
+ for (auto* name : {
+ "___cxa_atexit",
+ "_atexit",
+ "__cxa_atexit",
+ "atexit",
+ }) {
+ if (strcmp(name, import->base.str) == 0) {
+ replaceCurrent(
+ Builder(*getModule()).replaceWithIdenticalType(curr)
+ );
+ }
+ }
+ }
+};
+
+Pass* createNoExitRuntimePass() {
+ return new NoExitRuntime();
+}
+
+} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index c42a3d144..f250b7de6 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -98,6 +98,7 @@ void PassRegistry::registerPasses() {
registerPass("minify-imports", "minifies import names (only those, and not export names), and emits a mapping to the minified ones", createMinifyImportsPass);
registerPass("minify-imports-and-exports", "minifies both import and export names, and emits a mapping to the minified ones", createMinifyImportsAndExportsPass);
registerPass("nm", "name list", createNameListPass);
+ registerPass("no-exit-runtime", "removes calls to atexit(), which is valid if the C runtime will never be exited", createNoExitRuntimePass);
registerPass("optimize-instructions", "optimizes instruction combinations", createOptimizeInstructionsPass);
registerPass("optimize-stack-ir", "optimize Stack IR", createOptimizeStackIRPass);
registerPass("pick-load-signs", "pick load signs based on their uses", createPickLoadSignsPass);
diff --git a/src/passes/passes.h b/src/passes/passes.h
index 8f5ca7e0a..df4322eee 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -55,6 +55,7 @@ Pass* createMinifyImportsPass();
Pass* createMinifyImportsAndExportsPass();
Pass* createMetricsPass();
Pass* createNameListPass();
+Pass* createNoExitRuntimePass();
Pass* createOptimizeInstructionsPass();
Pass* createOptimizeStackIRPass();
Pass* createPickLoadSignsPass();
diff --git a/test/passes/no-exit-runtime.txt b/test/passes/no-exit-runtime.txt
new file mode 100644
index 000000000..c8913d32a
--- /dev/null
+++ b/test/passes/no-exit-runtime.txt
@@ -0,0 +1,32 @@
+(module
+ (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
+ (type $1 (func))
+ (import "env" "atexit" (func $fimport$0 (param i32 i32) (result i32)))
+ (import "env" "__cxa_atexit" (func $fimport$1 (param i32 i32) (result i32)))
+ (import "env" "_atexit" (func $fimport$2 (param i32 i32) (result i32)))
+ (import "env" "___cxa_atexit" (func $fimport$3 (param i32 i32) (result i32)))
+ (import "env" "other" (func $fimport$4 (param i32 i32) (result i32)))
+ (func $caller (; 5 ;) (type $1)
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (call $fimport$4
+ (i32.const 0)
+ (i32.const 1)
+ )
+ )
+ (drop
+ (unreachable)
+ )
+ )
+)
diff --git a/test/passes/no-exit-runtime.wast b/test/passes/no-exit-runtime.wast
new file mode 100644
index 000000000..1afe5ef8d
--- /dev/null
+++ b/test/passes/no-exit-runtime.wast
@@ -0,0 +1,15 @@
+(module
+ (import "env" "atexit" (func $fimport$0 (param i32 i32) (result i32)))
+ (import "env" "__cxa_atexit" (func $fimport$1 (param i32 i32) (result i32)))
+ (import "env" "_atexit" (func $fimport$2 (param i32 i32) (result i32)))
+ (import "env" "___cxa_atexit" (func $fimport$3 (param i32 i32) (result i32)))
+ (import "env" "other" (func $fimport$4 (param i32 i32) (result i32)))
+ (func $caller
+ (drop (call $fimport$0 (i32.const 0) (i32.const 1)))
+ (drop (call $fimport$1 (i32.const 0) (i32.const 1)))
+ (drop (call $fimport$2 (i32.const 0) (i32.const 1)))
+ (drop (call $fimport$3 (i32.const 0) (i32.const 1)))
+ (drop (call $fimport$4 (i32.const 0) (i32.const 1)))
+ (drop (call $fimport$0 (unreachable) (i32.const 1)))
+ )
+)