diff --git a/src/ir/import-name.h b/src/ir/import-name.h index 81fd0a3e768..04e141c3bc5 100644 --- a/src/ir/import-name.h +++ b/src/ir/import-name.h @@ -19,6 +19,7 @@ #include +#include "support/hash.h" #include "support/name.h" namespace wasm { @@ -26,8 +27,24 @@ namespace wasm { struct ImportNames { Name module; Name name; + + bool operator==(const ImportNames& other) const { + return module == other.module && name == other.name; + } }; } // namespace wasm +namespace std { + +template<> struct hash { + std::size_t operator()(const wasm::ImportNames& importNames) const noexcept { + size_t val = hash{}(importNames.module); + wasm::rehash(val, importNames.name); + return val; + } +}; + +} // namespace std + #endif // wasm_ir_import_name_h diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index ac8045e547b..1c8f0c5216f 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -84,14 +84,22 @@ class EvallingImportResolver : public ImportResolver { 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 { - Fatal() << "getTagOrNull not implemented in ctor-eval."; - return nullptr; + 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 { diff --git a/test/ctor-eval/tag-import.wast b/test/ctor-eval/tag-import.wast new file mode 100644 index 00000000000..dca27d75206 --- /dev/null +++ b/test/ctor-eval/tag-import.wast @@ -0,0 +1,16 @@ +(module + ;; an imported tag that isn't accessed doesn't stop us from optimizing + (import "import" "tag" (tag $imported)) + (global $g (mut i32) (i32.const 0)) + (func $setg (export "setg") + (drop (i32.const 1)) + (global.set $g + (i32.add (i32.const 1) (i32.const 2)) + ) + ) + + (func $keepalive (export "keepalive") (result i32) + ;; Keep the global alive so we can see its value. + (global.get $g) + ) +) diff --git a/test/ctor-eval/tag-import.wast.ctors b/test/ctor-eval/tag-import.wast.ctors new file mode 100644 index 00000000000..9b1821d1b2d --- /dev/null +++ b/test/ctor-eval/tag-import.wast.ctors @@ -0,0 +1 @@ +setg diff --git a/test/ctor-eval/tag-import.wast.out b/test/ctor-eval/tag-import.wast.out new file mode 100644 index 00000000000..89271eee388 --- /dev/null +++ b/test/ctor-eval/tag-import.wast.out @@ -0,0 +1,8 @@ +(module + (type $0 (func (result i32))) + (global $g (mut i32) (i32.const 3)) + (export "keepalive" (func $keepalive)) + (func $keepalive (type $0) (result i32) + (global.get $g) + ) +)