diff options
author | Daniel Wirtz <dcode@dcode.io> | 2020-04-20 23:01:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-20 14:01:26 -0700 |
commit | 483d759230f4693abfca3a74a97b1c1db6d2a0d6 (patch) | |
tree | c37b39802b9e5791abb3e329b88ba7185557de49 /src/binaryen-c.cpp | |
parent | 1dc820c913712a2c50d05caee77e90a7ec49d2e1 (diff) | |
download | binaryen-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.cpp | 138 |
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 { |