summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/export-utils.h36
-rw-r--r--src/passes/SignatureRefining.cpp25
2 files changed, 60 insertions, 1 deletions
diff --git a/src/ir/export-utils.h b/src/ir/export-utils.h
new file mode 100644
index 000000000..245365fbc
--- /dev/null
+++ b/src/ir/export-utils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2022 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_ir_export_h
+#define wasm_ir_export_h
+
+#include "wasm.h"
+
+namespace wasm::ExportUtils {
+
+inline std::vector<Function*> getExportedFunctions(Module& wasm) {
+ std::vector<Function*> ret;
+ for (auto& ex : wasm.exports) {
+ if (ex->kind == ExternalKind::Function) {
+ ret.push_back(wasm.getFunction(ex->value));
+ }
+ }
+ return ret;
+}
+
+} // namespace wasm::ExportUtils
+
+#endif // wasm_ir_export_h
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);
}