summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-11-11 15:39:45 -0800
committerGitHub <noreply@github.com>2019-11-11 15:39:45 -0800
commite83a9e2a21b35f19fe56a0d375191369b9b67148 (patch)
tree7a167721fbf38ff6ff8202b9ca900cd2c168529a /src
parent63ddbc04cf75a45a05a2b1f11564563915ebdbec (diff)
downloadbinaryen-e83a9e2a21b35f19fe56a0d375191369b9b67148.tar.gz
binaryen-e83a9e2a21b35f19fe56a0d375191369b9b67148.tar.bz2
binaryen-e83a9e2a21b35f19fe56a0d375191369b9b67148.zip
When legalizing, optionally export the original function too with orig$X (#2427)
The original is necessary if we want to pass it to wasm, where it will be called directly, without JS legalization. For example the JS dynamic loader in emscripten needs this, emscripten-core/emscripten#9562
Diffstat (limited to 'src')
-rw-r--r--src/passes/LegalizeJSInterface.cpp29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/passes/LegalizeJSInterface.cpp b/src/passes/LegalizeJSInterface.cpp
index 1404f6894..4dc680972 100644
--- a/src/passes/LegalizeJSInterface.cpp
+++ b/src/passes/LegalizeJSInterface.cpp
@@ -50,17 +50,42 @@ struct LegalizeJSInterface : public Pass {
LegalizeJSInterface(bool full) : full(full) {}
void run(PassRunner* runner, Module* module) override {
+ auto exportOriginals =
+ !runner->options
+ .getArgumentOrDefault("legalize-js-interface-export-originals", "")
+ .empty();
// for each illegal export, we must export a legalized stub instead
+ std::vector<Export*> newExports;
for (auto& ex : module->exports) {
if (ex->kind == ExternalKind::Function) {
// if it's an import, ignore it
auto* func = module->getFunction(ex->value);
if (isIllegal(func) && shouldBeLegalized(ex.get(), func)) {
+ // Provide a legal function for the export.
auto legalName = makeLegalStub(func, module);
ex->value = legalName;
+ if (exportOriginals) {
+ // Also export the original function, before legalization. This is
+ // not normally useful for JS, except in cases like dynamic linking
+ // where the JS loader code must copy exported wasm functions into
+ // the table, and they must not be legalized as other wasm code will
+ // do an indirect call to them. However, don't do this for imported
+ // functions, as those would be legalized in their actual module
+ // anyhow. It also makes no sense to do this for dynCalls, as they
+ // are only called from JS.
+ if (!func->imported() && !isDynCall(ex->name)) {
+ Builder builder(*module);
+ Name newName = std::string("orig$") + ex->name.str;
+ newExports.push_back(builder.makeExport(
+ newName, func->name, ExternalKind::Function));
+ }
+ }
}
}
}
+ for (auto* ex : newExports) {
+ module->addExport(ex);
+ }
// Avoid iterator invalidation later.
std::vector<Function*> originalFunctions;
for (auto& func : module->functions) {
@@ -136,13 +161,15 @@ private:
return t->result == i64;
}
+ bool isDynCall(Name name) { return name.startsWith("dynCall_"); }
+
// Check if an export should be legalized.
bool shouldBeLegalized(Export* ex, Function* func) {
if (full) {
return true;
}
// We are doing minimal legalization - just what JS needs.
- return ex->name.startsWith("dynCall_");
+ return isDynCall(ex->name);
}
// Check if an import should be legalized.