diff options
-rw-r--r-- | src/ir/module-utils.h | 2 | ||||
-rw-r--r-- | src/passes/Asyncify.cpp | 62 | ||||
-rw-r--r-- | test/unit/test_asyncify.py | 19 |
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 [ |