@@ -50,17 +50,42 @@ struct LegalizeJSInterface : public Pass {
5050 LegalizeJSInterface (bool full) : full(full) {}
5151
5252 void run (PassRunner* runner, Module* module ) override {
53+ auto exportOriginals =
54+ !runner->options
55+ .getArgumentOrDefault (" legalize-js-interface-export-originals" , " " )
56+ .empty ();
5357 // for each illegal export, we must export a legalized stub instead
58+ std::vector<Export*> newExports;
5459 for (auto & ex : module ->exports ) {
5560 if (ex->kind == ExternalKind::Function) {
5661 // if it's an import, ignore it
5762 auto * func = module ->getFunction (ex->value );
5863 if (isIllegal (func) && shouldBeLegalized (ex.get (), func)) {
64+ // Provide a legal function for the export.
5965 auto legalName = makeLegalStub (func, module );
6066 ex->value = legalName;
67+ if (exportOriginals) {
68+ // Also export the original function, before legalization. This is
69+ // not normally useful for JS, except in cases like dynamic linking
70+ // where the JS loader code must copy exported wasm functions into
71+ // the table, and they must not be legalized as other wasm code will
72+ // do an indirect call to them. However, don't do this for imported
73+ // functions, as those would be legalized in their actual module
74+ // anyhow. It also makes no sense to do this for dynCalls, as they
75+ // are only called from JS.
76+ if (!func->imported () && !isDynCall (ex->name )) {
77+ Builder builder (*module );
78+ Name newName = std::string (" orig$" ) + ex->name .str ;
79+ newExports.push_back (builder.makeExport (
80+ newName, func->name , ExternalKind::Function));
81+ }
82+ }
6183 }
6284 }
6385 }
86+ for (auto * ex : newExports) {
87+ module ->addExport (ex);
88+ }
6489 // Avoid iterator invalidation later.
6590 std::vector<Function*> originalFunctions;
6691 for (auto & func : module ->functions ) {
@@ -136,13 +161,15 @@ struct LegalizeJSInterface : public Pass {
136161 return t->result == i64 ;
137162 }
138163
164+ bool isDynCall (Name name) { return name.startsWith (" dynCall_" ); }
165+
139166 // Check if an export should be legalized.
140167 bool shouldBeLegalized (Export* ex, Function* func) {
141168 if (full) {
142169 return true ;
143170 }
144171 // We are doing minimal legalization - just what JS needs.
145- return ex->name . startsWith ( " dynCall_ " );
172+ return isDynCall ( ex->name );
146173 }
147174
148175 // Check if an import should be legalized.
0 commit comments