summaryrefslogtreecommitdiff
path: root/src/binaryen-c.cpp
diff options
context:
space:
mode:
authorDaniel Wirtz <dcode@dcode.io>2020-04-20 23:01:26 +0200
committerGitHub <noreply@github.com>2020-04-20 14:01:26 -0700
commit483d759230f4693abfca3a74a97b1c1db6d2a0d6 (patch)
treec37b39802b9e5791abb3e329b88ba7185557de49 /src/binaryen-c.cpp
parent1dc820c913712a2c50d05caee77e90a7ec49d2e1 (diff)
downloadbinaryen-483d759230f4693abfca3a74a97b1c1db6d2a0d6.tar.gz
binaryen-483d759230f4693abfca3a74a97b1c1db6d2a0d6.tar.bz2
binaryen-483d759230f4693abfca3a74a97b1c1db6d2a0d6.zip
Refactor expression runner so it can be used via the C and JS APIs (#2702)
Refactors most of the precompute pass's expression runner into its base class so it can also be used via the C and JS APIs. Also adds the option to populate the runner with known constant local and global values upfront, and remembers assigned intermediate values as well as traversing into functions if requested.
Diffstat (limited to 'src/binaryen-c.cpp')
-rw-r--r--src/binaryen-c.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 2ea4bd87f..d9d330082 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -135,6 +135,7 @@ std::map<BinaryenGlobalRef, size_t> globals;
std::map<BinaryenEventRef, size_t> events;
std::map<BinaryenExportRef, size_t> exports;
std::map<RelooperBlockRef, size_t> relooperBlocks;
+std::map<ExpressionRunnerRef, size_t> expressionRunners;
static bool isBasicAPIType(BinaryenType type) {
return type == BinaryenTypeAuto() || type <= Type::_last_value_type;
@@ -208,6 +209,26 @@ size_t noteExpression(BinaryenExpressionRef expression) {
return id;
}
+// Even though unlikely, it is possible that we are trying to use an id that is
+// still in use after wrapping around, which we must prevent.
+static std::unordered_set<size_t> usedExpressionRunnerIds;
+
+size_t noteExpressionRunner(ExpressionRunnerRef runner) {
+ // We would normally use the size of `expressionRunners` as the next index,
+ // but since we are going to delete runners the same address can become
+ // reused, which would result in unpredictable sizes (indexes) due to
+ // undefined behavior. Use a sequential id instead.
+ static size_t nextId = 0;
+
+ size_t id;
+ do {
+ id = nextId++;
+ } while (usedExpressionRunnerIds.find(id) != usedExpressionRunnerIds.end());
+ expressionRunners[runner] = id;
+ usedExpressionRunnerIds.insert(id);
+ return id;
+}
+
std::string getTemp() {
static size_t n = 0;
return "t" + std::to_string(n++);
@@ -604,6 +625,7 @@ void BinaryenModuleDispose(BinaryenModuleRef module) {
std::cout << " events.clear();\n";
std::cout << " exports.clear();\n";
std::cout << " relooperBlocks.clear();\n";
+ std::cout << " expressionRunners.clear();\n";
types.clear();
expressions.clear();
functions.clear();
@@ -4951,6 +4973,121 @@ BinaryenExpressionRef RelooperRenderAndDispose(RelooperRef relooper,
}
//
+// ========= ExpressionRunner =========
+//
+
+namespace wasm {
+
+class CExpressionRunner final : public ExpressionRunner<CExpressionRunner> {
+public:
+ CExpressionRunner(Module* module,
+ CExpressionRunner::Flags flags,
+ Index maxDepth,
+ Index maxLoopIterations)
+ : ExpressionRunner<CExpressionRunner>(
+ module, flags, maxDepth, maxLoopIterations) {}
+
+ void trap(const char* why) override { throw NonconstantException(); }
+};
+
+} // namespace wasm
+
+ExpressionRunnerFlags ExpressionRunnerFlagsDefault() {
+ return CExpressionRunner::FlagValues::DEFAULT;
+}
+
+ExpressionRunnerFlags ExpressionRunnerFlagsPreserveSideeffects() {
+ return CExpressionRunner::FlagValues::PRESERVE_SIDEEFFECTS;
+}
+
+ExpressionRunnerFlags ExpressionRunnerFlagsTraverseCalls() {
+ return CExpressionRunner::FlagValues::TRAVERSE_CALLS;
+}
+
+ExpressionRunnerRef ExpressionRunnerCreate(BinaryenModuleRef module,
+ ExpressionRunnerFlags flags,
+ BinaryenIndex maxDepth,
+ BinaryenIndex maxLoopIterations) {
+ auto* wasm = (Module*)module;
+ auto* runner = ExpressionRunnerRef(
+ new CExpressionRunner(wasm, flags, maxDepth, maxLoopIterations));
+ if (tracing) {
+ auto id = noteExpressionRunner(runner);
+ std::cout << " expressionRunners[" << id
+ << "] = ExpressionRunnerCreate(the_module, " << flags << ", "
+ << maxDepth << ", " << maxLoopIterations << ");\n";
+ }
+ return runner;
+}
+
+int ExpressionRunnerSetLocalValue(ExpressionRunnerRef runner,
+ BinaryenIndex index,
+ BinaryenExpressionRef value) {
+ if (tracing) {
+ std::cout << " ExpressionRunnerSetLocalValue(expressionRunners["
+ << expressionRunners[runner] << "], " << index << ", expressions["
+ << expressions[value] << "]);\n";
+ }
+
+ auto* R = (CExpressionRunner*)runner;
+ auto setFlow = R->visit(value);
+ if (!setFlow.breaking()) {
+ R->setLocalValue(index, setFlow.values);
+ return 1;
+ }
+ return 0;
+}
+
+int ExpressionRunnerSetGlobalValue(ExpressionRunnerRef runner,
+ const char* name,
+ BinaryenExpressionRef value) {
+ if (tracing) {
+ std::cout << " ExpressionRunnerSetGlobalValue(expressionRunners["
+ << expressionRunners[runner] << "], ";
+ traceNameOrNULL(name);
+ std::cout << ", expressions[" << expressions[value] << "]);\n";
+ }
+
+ auto* R = (CExpressionRunner*)runner;
+ auto setFlow = R->visit(value);
+ if (!setFlow.breaking()) {
+ R->setGlobalValue(name, setFlow.values);
+ return 1;
+ }
+ return 0;
+}
+
+BinaryenExpressionRef
+ExpressionRunnerRunAndDispose(ExpressionRunnerRef runner,
+ BinaryenExpressionRef expr) {
+ auto* R = (CExpressionRunner*)runner;
+ Expression* ret = nullptr;
+ try {
+ auto flow = R->visit(expr);
+ if (!flow.breaking() && !flow.values.empty()) {
+ ret = flow.getConstExpression(*R->getModule());
+ }
+ } catch (CExpressionRunner::NonconstantException&) {
+ }
+
+ if (tracing) {
+ if (ret != nullptr) {
+ auto id = noteExpression(ret);
+ std::cout << " expressions[" << id << "] = ";
+ } else {
+ std::cout << " ";
+ }
+ auto id = expressionRunners[runner];
+ std::cout << "ExpressionRunnerRunAndDispose(expressionRunners[" << id
+ << "], expressions[" << expressions[expr] << "]);\n";
+ usedExpressionRunnerIds.erase(id);
+ }
+
+ delete R;
+ return ret;
+}
+
+//
// ========= Other APIs =========
//
@@ -4970,6 +5107,7 @@ void BinaryenSetAPITracing(int on) {
" std::map<size_t, BinaryenEventRef> events;\n"
" std::map<size_t, BinaryenExportRef> exports;\n"
" std::map<size_t, RelooperBlockRef> relooperBlocks;\n"
+ " std::map<size_t, ExpressionRunnerRef> expressionRunners;\n"
" BinaryenModuleRef the_module = NULL;\n"
" RelooperRef the_relooper = NULL;\n";
} else {