@@ -135,6 +135,7 @@ std::map<BinaryenGlobalRef, size_t> globals;
135
135
std::map<BinaryenEventRef, size_t > events;
136
136
std::map<BinaryenExportRef, size_t > exports;
137
137
std::map<RelooperBlockRef, size_t > relooperBlocks;
138
+ std::map<ExpressionRunnerRef, size_t > expressionRunners;
138
139
139
140
static bool isBasicAPIType (BinaryenType type) {
140
141
return type == BinaryenTypeAuto () || type <= Type::_last_value_type;
@@ -208,6 +209,26 @@ size_t noteExpression(BinaryenExpressionRef expression) {
208
209
return id;
209
210
}
210
211
212
+ // Even though unlikely, it is possible that we are trying to use an id that is
213
+ // still in use after wrapping around, which we must prevent.
214
+ static std::unordered_set<size_t > usedExpressionRunnerIds;
215
+
216
+ size_t noteExpressionRunner (ExpressionRunnerRef runner) {
217
+ // We would normally use the size of `expressionRunners` as the next index,
218
+ // but since we are going to delete runners the same address can become
219
+ // reused, which would result in unpredictable sizes (indexes) due to
220
+ // undefined behavior. Use a sequential id instead.
221
+ static size_t nextId = 0 ;
222
+
223
+ size_t id;
224
+ do {
225
+ id = nextId++;
226
+ } while (usedExpressionRunnerIds.find (id) != usedExpressionRunnerIds.end ());
227
+ expressionRunners[runner] = id;
228
+ usedExpressionRunnerIds.insert (id);
229
+ return id;
230
+ }
231
+
211
232
std::string getTemp () {
212
233
static size_t n = 0 ;
213
234
return " t" + std::to_string (n++);
@@ -604,6 +625,7 @@ void BinaryenModuleDispose(BinaryenModuleRef module) {
604
625
std::cout << " events.clear();\n " ;
605
626
std::cout << " exports.clear();\n " ;
606
627
std::cout << " relooperBlocks.clear();\n " ;
628
+ std::cout << " expressionRunners.clear();\n " ;
607
629
types.clear ();
608
630
expressions.clear ();
609
631
functions.clear ();
@@ -4950,6 +4972,121 @@ BinaryenExpressionRef RelooperRenderAndDispose(RelooperRef relooper,
4950
4972
return BinaryenExpressionRef (ret);
4951
4973
}
4952
4974
4975
+ //
4976
+ // ========= ExpressionRunner =========
4977
+ //
4978
+
4979
+ namespace wasm {
4980
+
4981
+ class CExpressionRunner final : public ExpressionRunner<CExpressionRunner> {
4982
+ public:
4983
+ CExpressionRunner (Module* module,
4984
+ CExpressionRunner::Flags flags,
4985
+ Index maxDepth,
4986
+ Index maxLoopIterations)
4987
+ : ExpressionRunner<CExpressionRunner>(
4988
+ module, flags, maxDepth, maxLoopIterations) {}
4989
+
4990
+ void trap (const char * why) override { throw NonconstantException (); }
4991
+ };
4992
+
4993
+ } // namespace wasm
4994
+
4995
+ ExpressionRunnerFlags ExpressionRunnerFlagsDefault () {
4996
+ return CExpressionRunner::FlagValues::DEFAULT;
4997
+ }
4998
+
4999
+ ExpressionRunnerFlags ExpressionRunnerFlagsPreserveSideeffects () {
5000
+ return CExpressionRunner::FlagValues::PRESERVE_SIDEEFFECTS;
5001
+ }
5002
+
5003
+ ExpressionRunnerFlags ExpressionRunnerFlagsTraverseCalls () {
5004
+ return CExpressionRunner::FlagValues::TRAVERSE_CALLS;
5005
+ }
5006
+
5007
+ ExpressionRunnerRef ExpressionRunnerCreate (BinaryenModuleRef module,
5008
+ ExpressionRunnerFlags flags,
5009
+ BinaryenIndex maxDepth,
5010
+ BinaryenIndex maxLoopIterations) {
5011
+ auto * wasm = (Module*)module;
5012
+ auto * runner = ExpressionRunnerRef (
5013
+ new CExpressionRunner (wasm, flags, maxDepth, maxLoopIterations));
5014
+ if (tracing) {
5015
+ auto id = noteExpressionRunner (runner);
5016
+ std::cout << " expressionRunners[" << id
5017
+ << " ] = ExpressionRunnerCreate(the_module, " << flags << " , "
5018
+ << maxDepth << " , " << maxLoopIterations << " );\n " ;
5019
+ }
5020
+ return runner;
5021
+ }
5022
+
5023
+ int ExpressionRunnerSetLocalValue (ExpressionRunnerRef runner,
5024
+ BinaryenIndex index,
5025
+ BinaryenExpressionRef value) {
5026
+ if (tracing) {
5027
+ std::cout << " ExpressionRunnerSetLocalValue(expressionRunners["
5028
+ << expressionRunners[runner] << " ], " << index << " , expressions["
5029
+ << expressions[value] << " ]);\n " ;
5030
+ }
5031
+
5032
+ auto * R = (CExpressionRunner*)runner;
5033
+ auto setFlow = R->visit (value);
5034
+ if (!setFlow.breaking ()) {
5035
+ R->setLocalValue (index , setFlow.values );
5036
+ return 1 ;
5037
+ }
5038
+ return 0 ;
5039
+ }
5040
+
5041
+ int ExpressionRunnerSetGlobalValue (ExpressionRunnerRef runner,
5042
+ const char * name,
5043
+ BinaryenExpressionRef value) {
5044
+ if (tracing) {
5045
+ std::cout << " ExpressionRunnerSetGlobalValue(expressionRunners["
5046
+ << expressionRunners[runner] << " ], " ;
5047
+ traceNameOrNULL (name);
5048
+ std::cout << " , expressions[" << expressions[value] << " ]);\n " ;
5049
+ }
5050
+
5051
+ auto * R = (CExpressionRunner*)runner;
5052
+ auto setFlow = R->visit (value);
5053
+ if (!setFlow.breaking ()) {
5054
+ R->setGlobalValue (name, setFlow.values );
5055
+ return 1 ;
5056
+ }
5057
+ return 0 ;
5058
+ }
5059
+
5060
+ BinaryenExpressionRef
5061
+ ExpressionRunnerRunAndDispose (ExpressionRunnerRef runner,
5062
+ BinaryenExpressionRef expr) {
5063
+ auto * R = (CExpressionRunner*)runner;
5064
+ Expression* ret = nullptr ;
5065
+ try {
5066
+ auto flow = R->visit (expr);
5067
+ if (!flow.breaking () && !flow.values .empty ()) {
5068
+ ret = flow.getConstExpression (*R->getModule ());
5069
+ }
5070
+ } catch (CExpressionRunner::NonconstantException&) {
5071
+ }
5072
+
5073
+ if (tracing) {
5074
+ if (ret != nullptr ) {
5075
+ auto id = noteExpression (ret);
5076
+ std::cout << " expressions[" << id << " ] = " ;
5077
+ } else {
5078
+ std::cout << " " ;
5079
+ }
5080
+ auto id = expressionRunners[runner];
5081
+ std::cout << " ExpressionRunnerRunAndDispose(expressionRunners[" << id
5082
+ << " ], expressions[" << expressions[expr] << " ]);\n " ;
5083
+ usedExpressionRunnerIds.erase (id);
5084
+ }
5085
+
5086
+ delete R;
5087
+ return ret;
5088
+ }
5089
+
4953
5090
//
4954
5091
// ========= Other APIs =========
4955
5092
//
@@ -4970,6 +5107,7 @@ void BinaryenSetAPITracing(int on) {
4970
5107
" std::map<size_t, BinaryenEventRef> events;\n "
4971
5108
" std::map<size_t, BinaryenExportRef> exports;\n "
4972
5109
" std::map<size_t, RelooperBlockRef> relooperBlocks;\n "
5110
+ " std::map<size_t, ExpressionRunnerRef> expressionRunners;\n "
4973
5111
" BinaryenModuleRef the_module = NULL;\n "
4974
5112
" RelooperRef the_relooper = NULL;\n " ;
4975
5113
} else {
0 commit comments