summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/module-utils.h2
-rw-r--r--src/passes/Asyncify.cpp62
-rw-r--r--test/unit/test_asyncify.py19
3 files changed, 54 insertions, 29 deletions
diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h
index 368af71a5..0e18266e8 100644
--- a/src/ir/module-utils.h
+++ b/src/ir/module-utils.h
@@ -154,7 +154,7 @@ template<typename T> inline void renameFunctions(Module& wasm, T& map) {
// Update the function itself.
for (auto& pair : map) {
if (Function* F = wasm.getFunctionOrNull(pair.first)) {
- assert(!wasm.getFunctionOrNull(pair.second));
+ assert(!wasm.getFunctionOrNull(pair.second) || F->name == pair.second);
F->name = pair.second;
}
}
diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp
index c1cec4a36..f8fd6085b 100644
--- a/src/passes/Asyncify.cpp
+++ b/src/passes/Asyncify.cpp
@@ -445,6 +445,27 @@ public:
PatternMatcher blacklist("black", module, blacklistInput);
PatternMatcher whitelist("white", module, whitelistInput);
+ // Rename the asyncify imports so their internal name matches the
+ // convention. This makes replacing them with the implementations
+ // later easier.
+ std::map<Name, Name> renamings;
+ for (auto& func : module.functions) {
+ if (func->module == ASYNCIFY) {
+ if (func->base == START_UNWIND) {
+ renamings[func->name] = ASYNCIFY_START_UNWIND;
+ } else if (func->base == STOP_UNWIND) {
+ renamings[func->name] = ASYNCIFY_STOP_UNWIND;
+ } else if (func->base == START_REWIND) {
+ renamings[func->name] = ASYNCIFY_START_REWIND;
+ } else if (func->base == STOP_REWIND) {
+ renamings[func->name] = ASYNCIFY_STOP_REWIND;
+ } else {
+ Fatal() << "call to unidenfied asyncify import: " << func->base;
+ }
+ }
+ }
+ ModuleUtils::renameFunctions(module, renamings);
+
// Scan to see which functions can directly change the state.
// Also handle the asyncify imports, removing them (as we will implement
// them later), and replace calls to them with calls to the later proper
@@ -463,30 +484,33 @@ public:
return;
}
struct Walker : PostWalker<Walker> {
+ Info& info;
+ Module& module;
+ bool canIndirectChangeState;
+
+ Walker(Info& info, Module& module, bool canIndirectChangeState)
+ : info(info), module(module),
+ canIndirectChangeState(canIndirectChangeState) {}
+
void visitCall(Call* curr) {
if (curr->isReturn) {
Fatal() << "tail calls not yet supported in asyncify";
}
- auto* target = module->getFunction(curr->target);
+ auto* target = module.getFunction(curr->target);
if (target->imported() && target->module == ASYNCIFY) {
// Redirect the imports to the functions we'll add later.
if (target->base == START_UNWIND) {
- curr->target = ASYNCIFY_START_UNWIND;
- info->canChangeState = true;
- info->isTopMostRuntime = true;
+ info.canChangeState = true;
+ info.isTopMostRuntime = true;
} else if (target->base == STOP_UNWIND) {
- curr->target = ASYNCIFY_STOP_UNWIND;
- info->isBottomMostRuntime = true;
+ info.isBottomMostRuntime = true;
} else if (target->base == START_REWIND) {
- curr->target = ASYNCIFY_START_REWIND;
- info->isBottomMostRuntime = true;
+ info.isBottomMostRuntime = true;
} else if (target->base == STOP_REWIND) {
- curr->target = ASYNCIFY_STOP_REWIND;
- info->canChangeState = true;
- info->isTopMostRuntime = true;
+ info.canChangeState = true;
+ info.isTopMostRuntime = true;
} else {
- Fatal() << "call to unidenfied asyncify import: "
- << target->base;
+ WASM_UNREACHABLE("call to unidenfied asyncify import");
}
}
}
@@ -495,20 +519,12 @@ public:
Fatal() << "tail calls not yet supported in asyncify";
}
if (canIndirectChangeState) {
- info->canChangeState = true;
+ info.canChangeState = true;
}
// TODO optimize the other case, at least by type
}
- Info* info;
- Module* module;
- ModuleAnalyzer* analyzer;
- bool canIndirectChangeState;
};
- Walker walker;
- walker.info = &info;
- walker.module = &module;
- walker.analyzer = this;
- walker.canIndirectChangeState = canIndirectChangeState;
+ Walker walker(info, module, canIndirectChangeState);
walker.walk(func->body);
if (info.isBottomMostRuntime) {
diff --git a/test/unit/test_asyncify.py b/test/unit/test_asyncify.py
index 356a4935a..331e1a9e2 100644
--- a/test/unit/test_asyncify.py
+++ b/test/unit/test_asyncify.py
@@ -24,11 +24,20 @@ class AsyncifyTest(utils.BinaryenTestCase):
test(['-Os', '-g'])
def test_asyncify_pure_wasm(self):
- shared.run_process(shared.WASM_OPT + [self.input_path('asyncify-pure.wat'), '--asyncify', '-o', 'a.wasm'])
- shared.run_process(shared.WASM_DIS + ['a.wasm', '-o', 'a.wat'])
- output = shared.run_process(shared.WASM_SHELL + ['a.wat'], capture_output=True).stdout
- with open(self.input_path('asyncify-pure.txt'), 'r') as f:
- self.assertEqual(f.read(), output)
+ def test(input_file):
+ shared.run_process(shared.WASM_OPT + [input_file, '--asyncify', '-o', 'a.wasm'])
+ shared.run_process(shared.WASM_DIS + ['a.wasm', '-o', 'a.wat'])
+ output = shared.run_process(shared.WASM_SHELL + ['a.wat'], capture_output=True).stdout
+ with open(self.input_path('asyncify-pure.txt'), 'r') as f:
+ self.assertEqual(f.read(), output)
+
+ # test wat input
+ wat = self.input_path('asyncify-pure.wat')
+ test(wat)
+
+ # test wasm input
+ shared.run_process(shared.WASM_AS + [wat, '-o', 'a.wasm'])
+ test('a.wasm')
def test_asyncify_list_bad(self):
for arg, warning in [