summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Wirtz <dcode@dcode.io>2020-01-17 18:43:45 +0100
committerAlon Zakai <azakai@google.com>2020-01-17 09:43:44 -0800
commit98f5507c508d6fde326347df3fcad70740b634ea (patch)
tree3b8a7f1420ba81ca8e8df5b10a9e744a3602e6b4
parente873e2a84db3fda3c8df5ed8e0b39578a1fb2f2d (diff)
downloadbinaryen-98f5507c508d6fde326347df3fcad70740b634ea.tar.gz
binaryen-98f5507c508d6fde326347df3fcad70740b634ea.tar.bz2
binaryen-98f5507c508d6fde326347df3fcad70740b634ea.zip
Expose ExpressionAnalyzer in C-/JS-API (#2585)
Instead of reinventing the wheel on our side, this adds ExpressionAnalyzer bindings to the C- and JS-APIs, which can be useful for generators. For example, a generator may decide to simplify a compilation step if a subexpression doesn't have any side effects, or simply skip emitting something that is likely to compile to a drop or an empty block right away.
-rw-r--r--src/binaryen-c.cpp59
-rw-r--r--src/binaryen-c.h22
-rw-r--r--src/ir/effects.h51
-rw-r--r--src/js/binaryen.js-post.js23
-rw-r--r--test/binaryen.js/sideffects.js94
-rw-r--r--test/binaryen.js/sideffects.js.txt12
6 files changed, 261 insertions, 0 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 79571bd96..d0c672abd 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -4449,6 +4449,65 @@ void BinaryenAddCustomSection(BinaryenModuleRef module,
}
//
+// ========= Effect analyzer =========
+//
+
+BinaryenSideEffects BinaryenSideEffectNone(void) {
+ return static_cast<BinaryenSideEffects>(EffectAnalyzer::SideEffects::None);
+}
+BinaryenSideEffects BinaryenSideEffectBranches(void) {
+ return static_cast<BinaryenSideEffects>(
+ EffectAnalyzer::SideEffects::Branches);
+}
+BinaryenSideEffects BinaryenSideEffectCalls(void) {
+ return static_cast<BinaryenSideEffects>(EffectAnalyzer::SideEffects::Calls);
+}
+BinaryenSideEffects BinaryenSideEffectReadsLocal(void) {
+ return static_cast<BinaryenSideEffects>(
+ EffectAnalyzer::SideEffects::ReadsLocal);
+}
+BinaryenSideEffects BinaryenSideEffectWritesLocal(void) {
+ return static_cast<BinaryenSideEffects>(
+ EffectAnalyzer::SideEffects::WritesLocal);
+}
+BinaryenSideEffects BinaryenSideEffectReadsGlobal(void) {
+ return static_cast<BinaryenSideEffects>(
+ EffectAnalyzer::SideEffects::ReadsGlobal);
+}
+BinaryenSideEffects BinaryenSideEffectWritesGlobal(void) {
+ return static_cast<BinaryenSideEffects>(
+ EffectAnalyzer::SideEffects::WritesGlobal);
+}
+BinaryenSideEffects BinaryenSideEffectReadsMemory(void) {
+ return static_cast<BinaryenSideEffects>(
+ EffectAnalyzer::SideEffects::ReadsMemory);
+}
+BinaryenSideEffects BinaryenSideEffectWritesMemory(void) {
+ return static_cast<BinaryenSideEffects>(
+ EffectAnalyzer::SideEffects::WritesMemory);
+}
+BinaryenSideEffects BinaryenSideEffectImplicitTrap(void) {
+ return static_cast<BinaryenSideEffects>(
+ EffectAnalyzer::SideEffects::ImplicitTrap);
+}
+BinaryenSideEffects BinaryenSideEffectIsAtomic(void) {
+ return static_cast<BinaryenSideEffects>(
+ EffectAnalyzer::SideEffects::IsAtomic);
+}
+BinaryenSideEffects BinaryenSideEffectAny(void) {
+ return static_cast<BinaryenSideEffects>(EffectAnalyzer::SideEffects::Any);
+}
+
+BinaryenSideEffects
+BinaryenExpressionGetSideEffects(BinaryenExpressionRef expr) {
+ if (tracing) {
+ std::cout << " BinaryenExpressionGetSideEffects(expressions["
+ << expressions[expr] << "]);\n";
+ }
+ return EffectAnalyzer(globalPassOptions, (Expression*)expr).getSideEffects();
+}
+
+//
// ========== CFG / Relooper ==========
//
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 36d82ecb0..067812438 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -1479,6 +1479,28 @@ BINARYEN_API void BinaryenAddCustomSection(BinaryenModuleRef module,
BinaryenIndex contentsSize);
//
+// ========= Effect analyzer =========
+//
+
+typedef uint32_t BinaryenSideEffects;
+
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectNone(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectBranches(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectCalls(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectReadsLocal(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectWritesLocal(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectReadsGlobal(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectWritesGlobal(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectReadsMemory(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectWritesMemory(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectImplicitTrap(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectIsAtomic(void);
+BINARYEN_API BinaryenSideEffects BinaryenSideEffectAny(void);
+
+BINARYEN_API BinaryenSideEffects
+BinaryenExpressionGetSideEffects(BinaryenExpressionRef expr);
+
+//
// ========== CFG / Relooper ==========
//
// General usage is (1) create a relooper, (2) create blocks, (3) add
diff --git a/src/ir/effects.h b/src/ir/effects.h
index 9c8887333..0d1e2c2b1 100644
--- a/src/ir/effects.h
+++ b/src/ir/effects.h
@@ -408,6 +408,57 @@ struct EffectAnalyzer
EffectAnalyzer bEffects(passOptions, b);
return !aEffects.invalidates(bEffects);
}
+
+ // C-API
+
+ enum SideEffects : uint32_t {
+ None = 0,
+ Branches = 1 << 0,
+ Calls = 1 << 1,
+ ReadsLocal = 1 << 2,
+ WritesLocal = 1 << 3,
+ ReadsGlobal = 1 << 4,
+ WritesGlobal = 1 << 5,
+ ReadsMemory = 1 << 6,
+ WritesMemory = 1 << 7,
+ ImplicitTrap = 1 << 8,
+ IsAtomic = 1 << 9,
+ Any = (1 << 10) - 1
+ };
+ uint32_t getSideEffects() const {
+ uint32_t effects = 0;
+ if (branches) {
+ effects |= SideEffects::Branches;
+ }
+ if (calls) {
+ effects |= SideEffects::Calls;
+ }
+ if (localsRead.size() > 0) {
+ effects |= SideEffects::ReadsLocal;
+ }
+ if (localsWritten.size() > 0) {
+ effects |= SideEffects::WritesLocal;
+ }
+ if (globalsRead.size() > 0) {
+ effects |= SideEffects::ReadsGlobal;
+ }
+ if (globalsWritten.size() > 0) {
+ effects |= SideEffects::WritesGlobal;
+ }
+ if (readsMemory) {
+ effects |= SideEffects::ReadsMemory;
+ }
+ if (writesMemory) {
+ effects |= SideEffects::WritesMemory;
+ }
+ if (implicitTrap) {
+ effects |= SideEffects::ImplicitTrap;
+ }
+ if (isAtomic) {
+ effects |= SideEffects::IsAtomic;
+ }
+ return effects;
+ }
};
} // namespace wasm
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index 2993573d1..54f21ed07 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -457,6 +457,24 @@ function initializeConstants() {
].forEach(function(name) {
Module['Operations'][name] = Module[name] = Module['_Binaryen' + name]();
});
+
+ // Expression side effects
+ Module['SideEffects'] = {};
+ [ 'None',
+ 'Branches',
+ 'Calls',
+ 'ReadsLocal',
+ 'WritesLocal',
+ 'ReadsGlobal',
+ 'WritesGlobal',
+ 'ReadsMemory',
+ 'WritesMemory',
+ 'ImplicitTrap',
+ 'IsAtomic',
+ 'Any'
+ ].forEach(function(name) {
+ Module['SideEffects'][name] = Module['_BinaryenSideEffect' + name]();
+ });
}
// 'Module' interface
@@ -2739,6 +2757,11 @@ Module['getExpressionInfo'] = function(expr) {
}
};
+// Gets the side effects of the specified expression
+Module['getSideEffects'] = function(expr) {
+ return Module['_BinaryenExpressionGetSideEffects'](expr);
+};
+
Module['createType'] = function(types) {
return preserveStack(function() {
var array = i32sToStack(types);
diff --git a/test/binaryen.js/sideffects.js b/test/binaryen.js/sideffects.js
new file mode 100644
index 000000000..a486099dc
--- /dev/null
+++ b/test/binaryen.js/sideffects.js
@@ -0,0 +1,94 @@
+console.log("SideEffects.None=" + binaryen.SideEffects.None);
+console.log("SideEffects.Branches=" + binaryen.SideEffects.Branches);
+console.log("SideEffects.Calls=" + binaryen.SideEffects.Calls);
+console.log("SideEffects.ReadsLocal=" + binaryen.SideEffects.ReadsLocal);
+console.log("SideEffects.WritesLocal=" + binaryen.SideEffects.WritesLocal);
+console.log("SideEffects.ReadsGlobal=" + binaryen.SideEffects.ReadsGlobal);
+console.log("SideEffects.WritesGlobal=" + binaryen.SideEffects.WritesGlobal);
+console.log("SideEffects.ReadsMemory=" + binaryen.SideEffects.ReadsMemory);
+console.log("SideEffects.WritesMemory=" + binaryen.SideEffects.WritesMemory);
+console.log("SideEffects.ImplicitTrap=" + binaryen.SideEffects.ImplicitTrap);
+console.log("SideEffects.IsAtomic=" + binaryen.SideEffects.IsAtomic);
+console.log("SideEffects.Any=" + binaryen.SideEffects.Any);
+
+var module = new binaryen.Module();
+assert(
+ binaryen.getSideEffects(
+ module.i32.const(1)
+ )
+ ==
+ binaryen.SideEffects.None
+);
+assert(
+ binaryen.getSideEffects(
+ module.br("test")
+ )
+ ==
+ binaryen.SideEffects.Branches
+);
+assert(
+ binaryen.getSideEffects(
+ module.call("test", [], binaryen.i32)
+ )
+ ==
+ binaryen.SideEffects.Calls
+);
+assert(
+ binaryen.getSideEffects(
+ module.local.get("test", binaryen.i32)
+ )
+ ==
+ binaryen.SideEffects.ReadsLocal
+);
+assert(
+ binaryen.getSideEffects(
+ module.local.set("test",
+ module.i32.const(1)
+ )
+ )
+ ==
+ binaryen.SideEffects.WritesLocal
+);
+assert(
+ binaryen.getSideEffects(
+ module.global.get("test", binaryen.i32)
+ )
+ ==
+ binaryen.SideEffects.ReadsGlobal
+);
+assert(
+ binaryen.getSideEffects(
+ module.global.set("test", module.i32.const(1))
+ )
+ ==
+ binaryen.SideEffects.WritesGlobal
+);
+assert(
+ binaryen.getSideEffects(
+ module.i32.load(0, 0,
+ module.i32.const(0)
+ )
+ )
+ ==
+ binaryen.SideEffects.ReadsMemory | binaryen.SideEffects.ImplicitTrap
+);
+assert(
+ binaryen.getSideEffects(
+ module.i32.store(0, 0,
+ module.i32.const(0),
+ module.i32.const(1)
+ )
+ )
+ ==
+ binaryen.SideEffects.WritesMemory | binaryen.SideEffects.ImplicitTrap
+);
+assert(
+ binaryen.getSideEffects(
+ module.i32.div_s(
+ module.i32.const(1),
+ module.i32.const(0)
+ )
+ )
+ ==
+ binaryen.SideEffects.ImplicitTrap
+);
diff --git a/test/binaryen.js/sideffects.js.txt b/test/binaryen.js/sideffects.js.txt
new file mode 100644
index 000000000..54a1e14bc
--- /dev/null
+++ b/test/binaryen.js/sideffects.js.txt
@@ -0,0 +1,12 @@
+SideEffects.None=0
+SideEffects.Branches=1
+SideEffects.Calls=2
+SideEffects.ReadsLocal=4
+SideEffects.WritesLocal=8
+SideEffects.ReadsGlobal=16
+SideEffects.WritesGlobal=32
+SideEffects.ReadsMemory=64
+SideEffects.WritesMemory=128
+SideEffects.ImplicitTrap=256
+SideEffects.IsAtomic=512
+SideEffects.Any=1023