summaryrefslogtreecommitdiff
path: root/src/passes/SignatureRefining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/SignatureRefining.cpp')
-rw-r--r--src/passes/SignatureRefining.cpp25
1 files changed, 24 insertions, 1 deletions
diff --git a/src/passes/SignatureRefining.cpp b/src/passes/SignatureRefining.cpp
index 37ca091df..d094382c7 100644
--- a/src/passes/SignatureRefining.cpp
+++ b/src/passes/SignatureRefining.cpp
@@ -26,6 +26,7 @@
// type, and all call_refs using it).
//
+#include "ir/export-utils.h"
#include "ir/find_all.h"
#include "ir/lubs.h"
#include "ir/module-utils.h"
@@ -69,6 +70,10 @@ struct SignatureRefining : public Pass {
// A possibly improved LUB for the results.
LUBFinder resultsLUB;
+
+ // Normally we can optimize, but some cases prevent a particular signature
+ // type from being changed at all, see below.
+ bool canModify = true;
};
ModuleUtils::ParallelFunctionAnalysis<Info> analysis(
@@ -106,6 +111,20 @@ struct SignatureRefining : public Pass {
allInfo[func->type].resultsLUB.combine(info.resultsLUB);
}
+ // We cannot alter the signature of an exported function, as the outside may
+ // notice us doing so. For example, if we turn a parameter from nullable
+ // into non-nullable then callers sending a null will break. Put another
+ // way, we need to see all callers to refine types, and for exports we
+ // cannot do so.
+ // TODO If a function type is passed we should also mark the types used
+ // there, etc., recursively. For now this code just handles the top-
+ // level type, which is enough to keep the fuzzer from erroring. More
+ // generally, we need to decide about adding a "closed-world" flag of
+ // some kind.
+ for (auto* exportedFunc : ExportUtils::getExportedFunctions(*module)) {
+ allInfo[exportedFunc->type].canModify = false;
+ }
+
bool refinedResults = false;
// Compute optimal LUBs.
@@ -116,6 +135,11 @@ struct SignatureRefining : public Pass {
continue;
}
+ auto& info = allInfo[type];
+ if (!info.canModify) {
+ continue;
+ }
+
auto sig = type.getSignature();
auto numParams = sig.params.size();
@@ -127,7 +151,6 @@ struct SignatureRefining : public Pass {
}
};
- auto& info = allInfo[type];
for (auto* call : info.calls) {
updateLUBs(call->operands);
}