diff options
Diffstat (limited to 'src/passes/Inlining.cpp')
-rw-r--r-- | src/passes/Inlining.cpp | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp index 9ba01c4c1..53a57cfeb 100644 --- a/src/passes/Inlining.cpp +++ b/src/passes/Inlining.cpp @@ -217,7 +217,7 @@ struct Updater : public PostWalker<Updater> { // Core inlining logic. Modifies the outside function (adding locals as // needed), and returns the inlined code. static Expression* -doInlining(Module* module, Function* into, InliningAction& action) { +doInlining(Module* module, Function* into, const InliningAction& action) { Function* from = action.contents; auto* call = (*action.callSite)->cast<Call>(); // Works for return_call, too @@ -415,4 +415,40 @@ Pass* createInliningOptimizingPass() { return ret; } +static const char* MAIN = "main"; +static const char* ORIGINAL_MAIN = "__original_main"; + +// Inline __original_main into main, if they exist. This works around the odd +// thing that clang/llvm currently do, where __original_main contains the user's +// actual main (this is done as a workaround for main having two different +// possible signatures). +struct InlineMainPass : public Pass { + void run(PassRunner* runner, Module* module) override { + auto* main = module->getFunctionOrNull(MAIN); + auto* originalMain = module->getFunctionOrNull(ORIGINAL_MAIN); + if (!main || main->imported() || !originalMain || + originalMain->imported()) { + return; + } + FindAllPointers<Call> calls(main->body); + Expression** callSite = nullptr; + for (auto* call : calls.list) { + if ((*call)->cast<Call>()->target == ORIGINAL_MAIN) { + if (callSite) { + // More than one call site. + return; + } + callSite = call; + } + } + if (!callSite) { + // No call at all. + return; + } + doInlining(module, main, InliningAction(callSite, originalMain)); + } +}; + +Pass* createInlineMainPass() { return new InlineMainPass(); } + } // namespace wasm |