diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asm_v_wasm.h | 1 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 72 |
2 files changed, 45 insertions, 28 deletions
diff --git a/src/asm_v_wasm.h b/src/asm_v_wasm.h index 9b2ee7695..d2089b569 100644 --- a/src/asm_v_wasm.h +++ b/src/asm_v_wasm.h @@ -26,7 +26,6 @@ namespace wasm { AsmType wasmToAsmType(Type type); char getSig(Type type); -std::string getSig(Function* func); std::string getSig(Type results, Type params); template<typename ListType> diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 26764c304..ba6f5d6ee 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -157,6 +157,10 @@ public: template<typename SubType> class ExpressionRunner : public OverriddenVisitor<SubType, Flow> { protected: + // Optional module context to search for globals and called functions. NULL if + // we are not interested in any context. + Module* module = nullptr; + // Maximum depth before giving up. Index maxDepth; Index depth = 0; @@ -183,9 +187,11 @@ public: // Indicates no limit of maxDepth or maxLoopIterations. static const Index NO_LIMIT = 0; - ExpressionRunner(Index maxDepth = NO_LIMIT, + ExpressionRunner(Module* module = nullptr, + Index maxDepth = NO_LIMIT, Index maxLoopIterations = NO_LIMIT) - : maxDepth(maxDepth), maxLoopIterations(maxLoopIterations) {} + : module(module), maxDepth(maxDepth), maxLoopIterations(maxLoopIterations) { + } Flow visit(Expression* curr) { depth++; @@ -210,6 +216,9 @@ public: return ret; } + // Gets the module this runner is operating on. + Module* getModule() { return module; } + Flow visitBlock(Block* curr) { NOTE_ENTER("Block"); // special-case Block, because Block nesting (in their first element) can be @@ -1426,24 +1435,38 @@ public: cast.outcome = cast.Null; return cast; } - // The input may not be a struct or an array; for example it could be an + // The input may not be GC data or a function; for example it could be an // anyref of null (already handled above) or anything else (handled here, // but this is for future use as atm the binaryen interpreter cannot // represent external references). - if (!cast.originalRef.isData()) { + if (!cast.originalRef.isData() && !cast.originalRef.isFunction()) { cast.outcome = cast.Failure; return cast; } - auto gcData = cast.originalRef.getGCData(); - auto refRtt = gcData->rtt; - auto intendedRtt = rtt.getSingleValue(); - if (!refRtt.isSubRtt(intendedRtt)) { - cast.outcome = cast.Failure; + Literal seenRtt; + Literal intendedRtt = rtt.getSingleValue(); + if (cast.originalRef.isFunction()) { + // Function casts are simple in that they have no RTT hierarchies; instead + // each reference has the canonical RTT for the signature. + // We must have a module in order to perform the cast, to get the type. + assert(module); + auto* func = module->getFunction(cast.originalRef.getFunc()); + seenRtt = Literal(Type(Rtt(0, func->sig))); + cast.castRef = + Literal(func->name, Type(intendedRtt.type.getHeapType(), Nullable)); } else { - cast.outcome = cast.Success; + // GC data store an RTT in each instance. + assert(cast.originalRef.isData()); + auto gcData = cast.originalRef.getGCData(); + seenRtt = gcData->rtt; cast.castRef = Literal(gcData, Type(intendedRtt.type.getHeapType(), Nullable)); } + if (!seenRtt.isSubRtt(intendedRtt)) { + cast.outcome = cast.Failure; + } else { + cast.outcome = cast.Success; + } return cast; } @@ -1788,10 +1811,6 @@ public: static const Index NO_LIMIT = 0; protected: - // Optional module context to search for globals and called functions. NULL if - // we are not interested in any context. - Module* module = nullptr; - // Flags indicating special requirements. See FlagValues. Flags flags = FlagValues::DEFAULT; @@ -1808,12 +1827,9 @@ public: Flags flags, Index maxDepth, Index maxLoopIterations) - : ExpressionRunner<SubType>(maxDepth, maxLoopIterations), module(module), + : ExpressionRunner<SubType>(module, maxDepth, maxLoopIterations), flags(flags) {} - // Gets the module this runner is operating on. - Module* getModule() { return module; } - // Sets a known local value to use. void setLocalValue(Index index, Literals& values) { assert(values.isConcrete()); @@ -1858,8 +1874,8 @@ public: Flow visitGlobalGet(GlobalGet* curr) { NOTE_ENTER("GlobalGet"); NOTE_NAME(curr->name); - if (module != nullptr) { - auto* global = module->getGlobal(curr->name); + if (this->module != nullptr) { + auto* global = this->module->getGlobal(curr->name); // Check if the global has an immutable value anyway if (!global->imported() && !global->mutable_) { return ExpressionRunner<SubType>::visit(global->init); @@ -1875,10 +1891,11 @@ public: Flow visitGlobalSet(GlobalSet* curr) { NOTE_ENTER("GlobalSet"); NOTE_NAME(curr->name); - if (!(flags & FlagValues::PRESERVE_SIDEEFFECTS) && module != nullptr) { + if (!(flags & FlagValues::PRESERVE_SIDEEFFECTS) && + this->module != nullptr) { // If we are evaluating and not replacing the expression, remember the // constant value set, if any, for subsequent gets. - auto* global = module->getGlobal(curr->name); + auto* global = this->module->getGlobal(curr->name); assert(global->mutable_); auto setFlow = ExpressionRunner<SubType>::visit(curr->value); if (!setFlow.breaking()) { @@ -1895,8 +1912,8 @@ public: // when replacing as long as the function does not have any side effects. // Might yield something useful for simple functions like `clamp`, sometimes // even if arguments are only partially constant or not constant at all. - if ((flags & FlagValues::TRAVERSE_CALLS) != 0 && module != nullptr) { - auto* func = module->getFunction(curr->target); + if ((flags & FlagValues::TRAVERSE_CALLS) != 0 && this->module != nullptr) { + auto* func = this->module->getFunction(curr->target); if (!func->imported()) { if (func->sig.results.isConcrete()) { auto numOperands = curr->operands.size(); @@ -2023,7 +2040,8 @@ class InitializerExpressionRunner public: InitializerExpressionRunner(GlobalManager& globals, Index maxDepth) - : ExpressionRunner<InitializerExpressionRunner<GlobalManager>>(maxDepth), + : ExpressionRunner<InitializerExpressionRunner<GlobalManager>>(nullptr, + maxDepth), globals(globals) {} Flow visitGlobalGet(GlobalGet* curr) { return Flow(globals[curr->name]); } @@ -2384,8 +2402,8 @@ private: RuntimeExpressionRunner(ModuleInstanceBase& instance, FunctionScope& scope, Index maxDepth) - : ExpressionRunner<RuntimeExpressionRunner>(maxDepth), instance(instance), - scope(scope) {} + : ExpressionRunner<RuntimeExpressionRunner>(&instance.wasm, maxDepth), + instance(instance), scope(scope) {} Flow visitCall(Call* curr) { NOTE_ENTER("Call"); |