diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2020-04-09 16:42:42 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-09 16:42:42 -0700 |
commit | c2760038591df9e67b49bb71c9aedb70eadb5b11 (patch) | |
tree | 8122128aaf9944800c8f6ad1107ca0da4b88ba92 | |
parent | 1cfaf2e723968443611b06895212d4328b4881de (diff) | |
download | binaryen-c2760038591df9e67b49bb71c9aedb70eadb5b11.tar.gz binaryen-c2760038591df9e67b49bb71c9aedb70eadb5b11.tar.bz2 binaryen-c2760038591df9e67b49bb71c9aedb70eadb5b11.zip |
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.
-rw-r--r-- | src/passes/Asyncify.cpp | 50 | ||||
-rw-r--r-- | src/wasm-type.h | 5 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 4 | ||||
-rw-r--r-- | test/passes/asyncify_enable-multivalue.txt | 184 | ||||
-rw-r--r-- | test/passes/asyncify_enable-multivalue.wast | 5 |
5 files changed, 239 insertions, 9 deletions
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<Type, Name> map; std::map<Name, Type> rev; + + // Collect the types returned from all calls for which call support globals + // may need to be generated. + using Types = std::unordered_set<Type>; + Types collectTypes() { + ModuleUtils::ParallelFunctionAnalysis<Types> analysis( + module, [&](Function* func, Types& types) { + if (!func->body) { + return; + } + struct TypeCollector : PostWalker<TypeCollector> { + 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<wasm::Type> { +public: + size_t operator()(const wasm::Type& type) const; +}; + template<> class std::hash<wasm::Signature> { 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<wasm::Type>::operator()(const wasm::Type& type) const { + return std::hash<uint32_t>{}(type.getID()); +} + size_t std::hash<wasm::Signature>:: operator()(const wasm::Signature& sig) const { return std::hash<uint64_t>{}(uint64_t(sig.params.getID()) << 32 | diff --git a/test/passes/asyncify_enable-multivalue.txt b/test/passes/asyncify_enable-multivalue.txt index 4c82fd62e..5aee73c7a 100644 --- a/test/passes/asyncify_enable-multivalue.txt +++ b/test/passes/asyncify_enable-multivalue.txt @@ -324,9 +324,11 @@ (type $i32_=>_none (func (param i32))) (type $none_=>_i32 (func (result i32))) (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32_i64 (func (result i32 i64))) (import "env" "import" (func $import)) (import "env" "import2" (func $import2 (result i32))) (import "env" "import3" (func $import3 (param i32))) + (import "env" "import-mv" (func $import-mv (result i32 i64))) (memory $0 1 2) (global $__asyncify_state (mut i32) (i32.const 0)) (global $__asyncify_data (mut i32) (i32.const 0)) @@ -1920,6 +1922,188 @@ ) (i32.const 0) ) + (func $calls-mv + (local $x (i32 i64)) + (local $1 (i32 i64)) + (local $2 i32) + (local $3 i32) + (local $4 (i32 i64)) + (local $5 i32) + (local $6 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -24) + ) + ) + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $x + (tuple.make + (i32.load + (local.get $5) + ) + (i64.load offset=4 align=4 + (local.get $5) + ) + ) + ) + (local.set $1 + (tuple.make + (i32.load offset=12 + (local.get $5) + ) + (i64.load offset=16 align=4 + (local.get $5) + ) + ) + ) + ) + ) + (local.set $2 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $3 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $3) + (i32.const 0) + ) + ) + (block + (local.set $4 + (call $import-mv) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $1 + (local.get $4) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $x + (local.get $1) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $2) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $6 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $6) + (tuple.extract 0 + (local.get $x) + ) + ) + (i64.store offset=4 align=4 + (local.get $6) + (tuple.extract 1 + (local.get $x) + ) + ) + (i32.store offset=12 + (local.get $6) + (tuple.extract 0 + (local.get $1) + ) + ) + (i64.store offset=16 align=4 + (local.get $6) + (tuple.extract 1 + (local.get $1) + ) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 24) + ) + ) + ) + ) (func $calls-loop (param $x i32) (local $1 i32) (local $2 i32) diff --git a/test/passes/asyncify_enable-multivalue.wast b/test/passes/asyncify_enable-multivalue.wast index b34338bd0..58734401a 100644 --- a/test/passes/asyncify_enable-multivalue.wast +++ b/test/passes/asyncify_enable-multivalue.wast @@ -55,6 +55,7 @@ (import "env" "import" (func $import)) (import "env" "import2" (func $import2 (result i32))) (import "env" "import3" (func $import3 (param i32))) + (import "env" "import-mv" (func $import-mv (result i32 i64))) (func $calls-import (call $import) ) @@ -109,6 +110,10 @@ ) (return (i32.const 3)) ) + (func $calls-mv + (local $x (i32 i64)) + (local.set $x (call $import-mv)) + ) (func $calls-loop (param $x i32) (loop $l (call $import3 (i32.const 1)) |