diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 1c8f0c5216f..9ede99b79ff 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -68,40 +68,6 @@ bool isNullableAndMutable(Expression* ref, Index fieldIndex) { // the output. #define RECOMMENDATION "\n recommendation: " -class EvallingImportResolver : public ImportResolver { -public: - EvallingImportResolver() : stubLiteral({Literal(0)}) {}; - - // Return an unused stub value. We throw FailToEvalException on reading any - // imported globals. We ignore the type and return an i32 literal since some - // types can't be created anyway (e.g. ref none). - Literals* getGlobalOrNull(ImportNames name, Type type) const override { - return &stubLiteral; - } - - RuntimeTable* getTableOrNull(ImportNames name, - const Table& type) const override { - throw FailToEvalException{"Imported table access."}; - } - - // We assume that each tag import is distinct. This is wrong if the same tag - // instantiation is imported twice with different import names. - Tag* getTagOrNull(ImportNames name, - const Signature& signature) const override { - auto [it, inserted] = importedTags.try_emplace(name, Tag{}); - if (inserted) { - auto& tag = it->second; - tag.type = HeapType(signature); - } - - return &it->second; - } - -private: - mutable Literals stubLiteral; - mutable std::unordered_map importedTags; -}; - class EvallingRuntimeTable : public RuntimeTable { public: // TODO: putting EvallingModuleRunner into its own header would allow us to @@ -180,6 +146,53 @@ class EvallingRuntimeTable : public RuntimeTable { const std::function makeFuncData; }; +class EvallingImportResolver : public ImportResolver { +public: + EvallingImportResolver(const bool& instanceInitialized, + const Module& wasm, + std::function makeFuncData) + : stubLiteral({Literal(0)}), instanceInitialized(instanceInitialized), + wasm(wasm), makeFuncData(makeFuncData) {}; + + // Return an unused stub value. We throw FailToEvalException on reading any + // imported globals. We ignore the type and return an i32 literal since some + // types can't be created anyway (e.g. ref none). + Literals* getGlobalOrNull(ImportNames name, Type type) const override { + return &stubLiteral; + } + + RuntimeTable* getTableOrNull(ImportNames name, + const Table& type) const override { + auto [it, inserted] = + tables.emplace(name, + std::make_unique( + type, instanceInitialized, wasm, makeFuncData)); + return it->second.get(); + } + + // We assume that each tag import is distinct. This is wrong if the same tag + // instantiation is imported twice with different import names. + Tag* getTagOrNull(ImportNames name, + const Signature& signature) const override { + auto [it, inserted] = importedTags.try_emplace(name, Tag{}); + if (inserted) { + auto& tag = it->second; + tag.type = HeapType(signature); + } + + return &it->second; + } + +private: + mutable Literals stubLiteral; + mutable std::unordered_map> + tables; + const bool& instanceInitialized; + const Module& wasm; + const std::function makeFuncData; + mutable std::unordered_map importedTags; +}; + class EvallingModuleRunner : public ModuleRunnerBase { public: EvallingModuleRunner( @@ -190,17 +203,11 @@ class EvallingModuleRunner : public ModuleRunnerBase { : ModuleRunnerBase( wasm, externalInterface, - std::make_shared(), - linkedInstances_, - // TODO: Only use EvallingRuntimeTable for table imports. We can use - // RealRuntimeTable for non-imported tables. - [this, &instanceInitialized](Literal initial, Table table) { - return std::make_unique( - table, - instanceInitialized, - this->wasm, - [this](Name name, Type type) { return makeFuncData(name, type); }); - }) {} + std::make_shared( + instanceInitialized, + wasm, + [this](Name name, Type type) { return makeFuncData(name, type); }), + linkedInstances_) {} Flow visitGlobalGet(GlobalGet* curr) { // Error on reads of imported globals. @@ -1166,6 +1173,11 @@ EvalCtorOutcome evalCtor(EvallingModuleRunner& instance, std::cout << " ...stopping due to non-constant func\n"; } break; + } catch (TrapException& trap) { + if (!quiet) { + std::cout << " ...stopping due to trap\n"; + } + break; } if (flow.breakTo == NONCONSTANT_FLOW) { diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index a8033a8fca5..807c55eea0d 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -3177,25 +3177,15 @@ class ModuleRunnerBase : public ExpressionRunner { std::unordered_map allTags; - using CreateTableFunc = std::unique_ptr(Literal, Table); - ModuleRunnerBase( Module& wasm, ExternalInterface* externalInterface, std::shared_ptr importResolver, - std::map> linkedInstances_ = {}, - std::function createTable = {}) + std::map> linkedInstances_ = {}) : ExpressionRunner(&wasm), wasm(wasm), externalInterface(externalInterface), linkedInstances(std::move(linkedInstances_)), - importResolver(std::move(importResolver)), - createTable( - createTable != nullptr - ? std::move(createTable) - : static_cast>( - [](Literal initial, Table t) -> std::unique_ptr { - return std::make_unique(initial, t); - })) { + importResolver(std::move(importResolver)) { // Set up a single shared CurrContinuations for all these linked instances, // reusing one if it exists. std::shared_ptr shared; @@ -3533,8 +3523,8 @@ class ModuleRunnerBase : public ExpressionRunner { "We only support nullable tables today"); auto null = Literal::makeNull(table->type.getHeapType()); - auto& runtimeTable = - definedTables.emplace_back(createTable(null, *table)); + auto& runtimeTable = definedTables.emplace_back( + std::make_unique(null, *table)); [[maybe_unused]] auto [_, inserted] = allTables.try_emplace(table->name, runtimeTable.get()); assert(inserted && "Unexpected repeated table name"); @@ -5245,7 +5235,6 @@ class ModuleRunnerBase : public ExpressionRunner { ExternalInterface* externalInterface; std::map> linkedInstances; std::shared_ptr importResolver; - std::function createTable; }; class ModuleRunner : public ModuleRunnerBase { diff --git a/test/lit/ctor-eval/table.init.wat b/test/lit/ctor-eval/table.init.wat index 7af2a09c6e1..f6d7b63dcec 100644 --- a/test/lit/ctor-eval/table.init.wat +++ b/test/lit/ctor-eval/table.init.wat @@ -11,7 +11,6 @@ ;; CHECK: (elem $init (i32.const 0) $nop) (elem $init (i32.const 0) $nop) - ;; CHECK: (elem $later func $trap) (elem $later $trap) (export "run" (func $run)) @@ -43,19 +42,11 @@ (nop) ) - ;; CHECK: (func $trap (type $none_=>_none) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) (func $trap (type $none_=>_none) (unreachable) ) ) ;; CHECK: (func $run_3 (type $none_=>_none) -;; CHECK-NEXT: (table.init $table $later -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) ;; CHECK-NEXT: (call_indirect $table (type $none_=>_none) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) diff --git a/test/lit/ctor-eval/table.wat b/test/lit/ctor-eval/table.wat index 0954faeea7d..ab74d38eead 100644 --- a/test/lit/ctor-eval/table.wat +++ b/test/lit/ctor-eval/table.wat @@ -32,8 +32,6 @@ ;; CHECK: (elem $0 (i32.const 0) $nop) - ;; CHECK: (elem declare func $trap) - ;; CHECK: (export "run" (func $run_3)) ;; CHECK: (func $nop (type $none_=>_none) @@ -43,18 +41,11 @@ (nop) ) - ;; CHECK: (func $trap (type $none_=>_none) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) (func $trap (type $none_=>_none) (unreachable) ) ) ;; CHECK: (func $run_3 (type $none_=>_none) -;; CHECK-NEXT: (table.set $0 -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: (ref.func $trap) -;; CHECK-NEXT: ) ;; CHECK-NEXT: (call_indirect $0 (type $none_=>_none) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: )