summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Asyncify.cpp50
-rw-r--r--src/wasm-type.h5
-rw-r--r--src/wasm/wasm-type.cpp4
-rw-r--r--test/passes/asyncify_enable-multivalue.txt184
-rw-r--r--test/passes/asyncify_enable-multivalue.wast5
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))