From c2760038591df9e67b49bb71c9aedb70eadb5b11 Mon Sep 17 00:00:00 2001 From: Thomas Lively <7121787+tlively@users.noreply.github.com> Date: Thu, 9 Apr 2020 16:42:42 -0700 Subject: Handle tuples in Asyncify call support (#2743) Instead of adding globals for hardcoded basic types, traverse the module to collect all call types that might need to be handled and emit a global for each of them. Adapted from #2712. --- src/passes/Asyncify.cpp | 50 ++++++++++++++++++++++++++++++++++++++++--------- src/wasm-type.h | 5 +++++ src/wasm/wasm-type.cpp | 4 ++++ 3 files changed, 50 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp index a6afd3444..62b14531a 100644 --- a/src/passes/Asyncify.cpp +++ b/src/passes/Asyncify.cpp @@ -312,17 +312,14 @@ class FakeGlobalHelper { public: FakeGlobalHelper(Module& module) : module(module) { - map[Type::i32] = "asyncify_fake_call_global_i32"; - map[Type::i64] = "asyncify_fake_call_global_i64"; - map[Type::f32] = "asyncify_fake_call_global_f32"; - map[Type::f64] = "asyncify_fake_call_global_f64"; Builder builder(module); - for (auto& pair : map) { - auto type = pair.first; - auto name = pair.second; - rev[name] = type; + std::string prefix = "asyncify_fake_call_global_"; + for (auto type : collectTypes()) { + auto global = prefix + Type(type).toString(); + map[type] = global; + rev[global] = type; module.addGlobal(builder.makeGlobal( - name, type, LiteralUtils::makeZero(type, module), Builder::Mutable)); + global, type, LiteralUtils::makeZero(type, module), Builder::Mutable)); } } @@ -346,6 +343,41 @@ public: private: std::map map; std::map rev; + + // Collect the types returned from all calls for which call support globals + // may need to be generated. + using Types = std::unordered_set; + Types collectTypes() { + ModuleUtils::ParallelFunctionAnalysis analysis( + module, [&](Function* func, Types& types) { + if (!func->body) { + return; + } + struct TypeCollector : PostWalker { + Types& types; + TypeCollector(Types& types) : types(types) {} + void visitCall(Call* curr) { + if (curr->type.isConcrete()) { + types.insert(curr->type); + } + } + void visitCallIndirect(CallIndirect* curr) { + if (curr->type.isConcrete()) { + types.insert(curr->type); + } + } + }; + TypeCollector(types).walk(func->body); + }); + Types types; + for (auto& pair : analysis.map) { + Types& functionTypes = pair.second; + for (auto t : functionTypes) { + types.insert(t); + } + } + return types; + } }; class PatternMatcher { diff --git a/src/wasm-type.h b/src/wasm-type.h index f3db912d1..05cfeaef5 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -175,6 +175,11 @@ std::ostream& operator<<(std::ostream& os, Signature t); } // namespace wasm +template<> class std::hash { +public: + size_t operator()(const wasm::Type& type) const; +}; + template<> class std::hash { public: size_t operator()(const wasm::Signature& sig) const; diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index da7fb50b6..aed13b6d1 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -35,6 +35,10 @@ public: } }; +size_t std::hash::operator()(const wasm::Type& type) const { + return std::hash{}(type.getID()); +} + size_t std::hash:: operator()(const wasm::Signature& sig) const { return std::hash{}(uint64_t(sig.params.getID()) << 32 | -- cgit v1.2.3