summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/LogExecution.cpp77
-rw-r--r--src/passes/pass.cpp1
-rw-r--r--src/passes/passes.h2
-rw-r--r--test/passes/log-execution.txt88
-rw-r--r--test/passes/log-execution.wast35
6 files changed, 203 insertions, 1 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index 876a71d74..75e634c16 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -8,6 +8,7 @@ SET(passes_SOURCES
Inlining.cpp
LegalizeJSInterface.cpp
LocalCSE.cpp
+ LogExecution.cpp
MemoryPacking.cpp
MergeBlocks.cpp
Metrics.cpp
diff --git a/src/passes/LogExecution.cpp b/src/passes/LogExecution.cpp
new file mode 100644
index 000000000..8d555fefe
--- /dev/null
+++ b/src/passes/LogExecution.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2017 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.
+ */
+
+//
+// Instruments the build with code to log execution at each function
+// entry and loop header. This can be useful in debugging, to log out
+// a trace, and diff it to another (running in another browser, to
+// check for bugs, for example).
+//
+// The logging is performed by calling an ffi with an id for each
+// call site. You need to provide that import on the JS side.
+//
+
+#include <wasm.h>
+#include <wasm-builder.h>
+#include <pass.h>
+#include "shared-constants.h"
+#include "asmjs/shared-constants.h"
+#include "asm_v_wasm.h"
+
+namespace wasm {
+
+Name LOGGER("log_execution");
+
+struct LogExecution : public WalkerPass<PostWalker<LogExecution>> {
+ void visitLoop(Loop* curr) {
+ curr->body = makeLogCall(curr->body);
+ }
+
+ void visitFunction(Function* curr) {
+ curr->body = makeLogCall(curr->body);
+ }
+
+ void visitModule(Module *curr) {
+ // Add the import
+ auto import = new Import;
+ import->name = LOGGER;
+ import->module = ENV;
+ import->base = LOGGER;
+ import->functionType = ensureFunctionType("vi", curr)->name;
+ import->kind = ExternalKind::Function;
+ curr->addImport(import);
+ }
+
+private:
+ Expression* makeLogCall(Expression* curr) {
+ static Index id = 0;
+ Builder builder(*getModule());
+ return builder.makeSequence(
+ builder.makeCallImport(
+ LOGGER,
+ { builder.makeConst(Literal(int32_t(id++))) },
+ none
+ ),
+ curr
+ );
+ }
+};
+
+Pass *createLogExecutionPass() {
+ return new LogExecution();
+}
+
+} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index a82b2fa58..577a460cb 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -72,6 +72,7 @@ void PassRegistry::registerPasses() {
registerPass("inlining", "inlines functions (currently only ones with a single use)", createInliningPass);
registerPass("legalize-js-interface", "legalizes i64 types on the import/export boundary", createLegalizeJSInterfacePass);
registerPass("local-cse", "common subexpression elimination inside basic blocks", createLocalCSEPass);
+ registerPass("log-execution", "instrument the build with logging of where execution goes", createLogExecutionPass);
registerPass("memory-packing", "packs memory into separate segments, skipping zeros", createMemoryPackingPass);
registerPass("merge-blocks", "merges blocks to their parents", createMergeBlocksPass);
registerPass("metrics", "reports metrics", createMetricsPass);
diff --git a/src/passes/passes.h b/src/passes/passes.h
index c3660b048..f8156d4fe 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -32,7 +32,7 @@ Pass *createFullPrinterPass();
Pass *createInliningPass();
Pass *createLegalizeJSInterfacePass();
Pass *createLocalCSEPass();
-Pass *createLowerIfElsePass();
+Pass *createLogExecutionPass();
Pass *createMemoryPackingPass();
Pass *createMergeBlocksPass();
Pass *createMinifiedPrinterPass();
diff --git a/test/passes/log-execution.txt b/test/passes/log-execution.txt
new file mode 100644
index 000000000..32bbd88eb
--- /dev/null
+++ b/test/passes/log-execution.txt
@@ -0,0 +1,88 @@
+(module
+ (type $0 (func))
+ (type $1 (func (result i32)))
+ (type $FUNCSIG$vi (func (param i32)))
+ (import "env" "log_execution" (func $log_execution (param i32)))
+ (memory $0 0)
+ (func $nopp (type $0)
+ (call $log_execution
+ (i32.const 0)
+ )
+ (nop)
+ )
+ (func $intt (type $1) (result i32)
+ (call $log_execution
+ (i32.const 1)
+ )
+ (i32.const 10)
+ )
+ (func $workk (type $0)
+ (call $log_execution
+ (i32.const 2)
+ )
+ (block
+ (if
+ (i32.const 0)
+ (nop)
+ )
+ (drop
+ (i32.const 1)
+ )
+ )
+ )
+ (func $loops (type $0)
+ (call $log_execution
+ (i32.const 6)
+ )
+ (block
+ (loop $x
+ (call $log_execution
+ (i32.const 3)
+ )
+ (block
+ (call $loops)
+ (br $x)
+ )
+ )
+ (if
+ (call $intt)
+ (loop $y
+ (call $log_execution
+ (i32.const 4)
+ )
+ (call $loops)
+ )
+ )
+ (loop $loop-in
+ (call $log_execution
+ (i32.const 5)
+ )
+ (block
+ (drop
+ (i32.const 10)
+ )
+ (drop
+ (i32.const 20)
+ )
+ (drop
+ (i32.const 30)
+ )
+ )
+ )
+ )
+ )
+ (func $loops-similar (type $0)
+ (call $log_execution
+ (i32.const 8)
+ )
+ (loop $x
+ (call $log_execution
+ (i32.const 7)
+ )
+ (block
+ (call $loops)
+ (br $x)
+ )
+ )
+ )
+)
diff --git a/test/passes/log-execution.wast b/test/passes/log-execution.wast
new file mode 100644
index 000000000..12175fbcb
--- /dev/null
+++ b/test/passes/log-execution.wast
@@ -0,0 +1,35 @@
+(module
+ (func $nopp
+ (nop)
+ )
+ (func $intt (result i32)
+ (i32.const 10)
+ )
+ (func $workk
+ (if (i32.const 0) (nop))
+ (drop (i32.const 1))
+ )
+ (func $loops
+ (loop $x
+ (call $loops)
+ (br $x)
+ )
+ (if (call $intt)
+ (loop $y
+ (call $loops)
+ )
+ )
+ (loop
+ (drop (i32.const 10))
+ (drop (i32.const 20))
+ (drop (i32.const 30))
+ )
+ )
+ (func $loops-similar
+ (loop $x
+ (call $loops)
+ (br $x)
+ )
+ )
+)
+