summaryrefslogtreecommitdiff
path: root/src/passes/Inlining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/Inlining.cpp')
-rw-r--r--src/passes/Inlining.cpp38
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