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.cpp36
1 files changed, 26 insertions, 10 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index c03b404b0..f325f70c6 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -32,6 +32,7 @@
#include "ir/branch-utils.h"
#include "ir/debug.h"
+#include "ir/drop.h"
#include "ir/eh-utils.h"
#include "ir/element-utils.h"
#include "ir/literal-utils.h"
@@ -251,6 +252,10 @@ struct Updater : public PostWalker<Updater> {
Name returnName;
bool isReturn;
Builder* builder;
+ PassOptions& options;
+
+ Updater(PassOptions& options) : options(options) {}
+
void visitReturn(Return* curr) {
replaceCurrent(builder->makeBreak(returnName, curr->value));
}
@@ -259,7 +264,7 @@ struct Updater : public PostWalker<Updater> {
// achieve this, make the call a non-return call and add a break. This does
// not cause unbounded stack growth because inlining and return calling both
// avoid creating a new stack frame.
- template<typename T> void handleReturnCall(T* curr, HeapType targetType) {
+ template<typename T> void handleReturnCall(T* curr, Type results) {
if (isReturn) {
// If the inlined callsite was already a return_call, then we can keep
// return_calls in the inlined function rather than downgrading them.
@@ -269,7 +274,7 @@ struct Updater : public PostWalker<Updater> {
return;
}
curr->isReturn = false;
- curr->type = targetType.getSignature().results;
+ curr->type = results;
if (curr->type.isConcrete()) {
replaceCurrent(builder->makeBreak(returnName, curr));
} else {
@@ -278,17 +283,25 @@ struct Updater : public PostWalker<Updater> {
}
void visitCall(Call* curr) {
if (curr->isReturn) {
- handleReturnCall(curr, module->getFunction(curr->target)->type);
+ handleReturnCall(curr, module->getFunction(curr->target)->getResults());
}
}
void visitCallIndirect(CallIndirect* curr) {
if (curr->isReturn) {
- handleReturnCall(curr, curr->heapType);
+ handleReturnCall(curr, curr->heapType.getSignature().results);
}
}
void visitCallRef(CallRef* curr) {
+ Type targetType = curr->target->type;
+ if (targetType.isNull()) {
+ // We don't know what type the call should return, but we can't leave it
+ // as a potentially-invalid return_call_ref, either.
+ replaceCurrent(getDroppedChildrenAndAppend(
+ curr, *module, options, Builder(*module).makeUnreachable()));
+ return;
+ }
if (curr->isReturn) {
- handleReturnCall(curr, curr->target->type.getHeapType());
+ handleReturnCall(curr, targetType.getHeapType().getSignature().results);
}
}
void visitLocalGet(LocalGet* curr) {
@@ -301,8 +314,10 @@ 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, const InliningAction& action) {
+static Expression* doInlining(Module* module,
+ Function* into,
+ const InliningAction& action,
+ PassOptions& options) {
Function* from = action.contents;
auto* call = (*action.callSite)->cast<Call>();
// Works for return_call, too
@@ -337,7 +352,7 @@ doInlining(Module* module, Function* into, const InliningAction& action) {
*action.callSite = block;
}
// Prepare to update the inlined code's locals and other things.
- Updater updater;
+ Updater updater(options);
updater.module = module;
updater.returnName = block->name;
updater.isReturn = call->isReturn;
@@ -1002,7 +1017,7 @@ struct Inlining : public Pass {
action.contents = getActuallyInlinedFunction(action.contents);
// Perform the inlining and update counts.
- doInlining(module, func, action);
+ doInlining(module, func, action, getPassOptions());
inlinedUses[inlinedName]++;
inlinedInto.insert(func);
assert(inlinedUses[inlinedName] <= infos[inlinedName].refs);
@@ -1116,7 +1131,8 @@ struct InlineMainPass : public Pass {
// No call at all.
return;
}
- doInlining(module, main, InliningAction(callSite, originalMain));
+ doInlining(
+ module, main, InliningAction(callSite, originalMain), getPassOptions());
}
};