Skip to content

Commit f4d074f

Browse files
authored
Rename Emscripten EHSjLj functions in wasm backend (#3191)
Now that we are renaming invoke wrappers and `emscripten_longjmp_jmpbuf` in the wasm backend, this deletes all related renaming routines and relevant tests. Depends on #3192. Addresses: #3043 and #3081 Companions: https://reviews.llvm.org/D88697 emscripten-core/emscripten#12399
1 parent caf624d commit f4d074f

File tree

6 files changed

+3
-174
lines changed

6 files changed

+3
-174
lines changed

src/passes/GenerateDynCalls.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ struct GenerateDynCalls : public WalkerPass<PostWalker<GenerateDynCalls>> {
5555

5656
void visitFunction(Function* func) {
5757
// Generate dynCalls for invokes
58-
if (func->imported() && func->base.startsWith("invoke_")) {
58+
if (func->imported() && func->module == ENV &&
59+
func->base.startsWith("invoke_")) {
5960
Signature sig = func->sig;
6061
// The first parameter is a pointer to the original function that's called
6162
// by the invoke, so skip it

src/passes/PostEmscripten.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,31 +78,13 @@ struct OptimizeCalls : public WalkerPass<PostWalker<OptimizeCalls>> {
7878

7979
struct PostEmscripten : public Pass {
8080
void run(PassRunner* runner, Module* module) override {
81-
// Optimize imports
82-
optimizeImports(runner, module);
83-
8481
// Optimize calls
8582
OptimizeCalls().run(runner, module);
8683

8784
// Optimize exceptions
8885
optimizeExceptions(runner, module);
8986
}
9087

91-
void optimizeImports(PassRunner* runner, Module* module) {
92-
// Calling emscripten_longjmp_jmpbuf is the same as emscripten_longjmp.
93-
Name EMSCRIPTEN_LONGJMP("emscripten_longjmp");
94-
Name EMSCRIPTEN_LONGJMP_JMPBUF("emscripten_longjmp_jmpbuf");
95-
ImportInfo info(*module);
96-
auto* emscripten_longjmp =
97-
info.getImportedFunction(ENV, EMSCRIPTEN_LONGJMP);
98-
auto* emscripten_longjmp_jmpbuf =
99-
info.getImportedFunction(ENV, EMSCRIPTEN_LONGJMP_JMPBUF);
100-
if (emscripten_longjmp && emscripten_longjmp_jmpbuf) {
101-
// Both exist, so it is worth renaming so that we have only one.
102-
emscripten_longjmp_jmpbuf->base = EMSCRIPTEN_LONGJMP;
103-
}
104-
}
105-
10688
// Optimize exceptions (and setjmp) by removing unnecessary invoke* calls.
10789
// An invoke is a call to JS with a function pointer; JS does a try-catch
10890
// and calls the pointer, catching and reporting any error. If we know no

src/tools/wasm-emscripten-finalize.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,6 @@ int main(int argc, const char* argv[]) {
259259
generator.onlyI64DynCalls = onlyI64DynCalls;
260260
generator.noDynCalls = noDynCalls;
261261

262-
generator.fixInvokeFunctionNames();
263-
264262
std::vector<Name> initializerFunctions;
265263

266264
// The wasm backend emits "__indirect_function_table" as the import name for

src/wasm/wasm-emscripten.cpp

Lines changed: 1 addition & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -487,134 +487,6 @@ EmJsWalker fixEmJsFuncsAndReturnWalker(Module& wasm) {
487487
return walker;
488488
}
489489

490-
// Fixes function name hacks caused by LLVM exception & setjmp/longjmp
491-
// handling pass for wasm.
492-
// This does two things:
493-
// 1. Change emscripten_longjmp_jmpbuf to emscripten_longjmp.
494-
// In setjmp/longjmp handling pass in wasm backend, what we want to do is
495-
// to change all function calls to longjmp to calls to emscripten_longjmp.
496-
// Because we replace all calls to longjmp to emscripten_longjmp, the
497-
// signature of that function should be the same as longjmp:
498-
// emscripten_longjmp(jmp_buf, int)
499-
// But after calling a function that might longjmp, while we test whether
500-
// a longjmp occurred, we have to load an int address value and call
501-
// emscripten_longjmp again with that address as the first argument. (Refer
502-
// to lib/Target/WebAssembly/WebAssemblyEmscriptenEHSjLj.cpp in LLVM for
503-
// details.)
504-
// In this case we need the signature of emscripten_longjmp to be (int,
505-
// int). So we need two different kinds of emscripten_longjmp signatures in
506-
// LLVM IR. Both signatures will be lowered to (int, int) eventually, but
507-
// in LLVM IR, types are not lowered yet.
508-
// So we declare two functions in LLVM:
509-
// emscripten_longjmp_jmpbuf(jmp_buf, int)
510-
// emscripten_longjmp(int, int)
511-
// And we change the name of emscripten_longjmp_jmpbuf to
512-
// emscripten_longjmp here.
513-
// 2. Converts invoke wrapper names.
514-
// Refer to the comments in fixEmExceptionInvoke below.
515-
struct FixInvokeFunctionNamesWalker
516-
: public PostWalker<FixInvokeFunctionNamesWalker> {
517-
Module& wasm;
518-
std::vector<Name> toRemove;
519-
std::map<Name, Name> importRenames;
520-
std::map<Name, Name> functionRenames;
521-
std::set<Signature> invokeSigs;
522-
ImportInfo imports;
523-
524-
FixInvokeFunctionNamesWalker(Module& _wasm) : wasm(_wasm), imports(wasm) {}
525-
526-
// Converts invoke wrapper names generated by LLVM backend to real invoke
527-
// wrapper names that are expected by JavaScript glue code.
528-
// This is required to support wasm exception handling (asm.js style).
529-
//
530-
// LLVM backend lowers
531-
// invoke @func(arg1, arg2) to label %invoke.cont unwind label %lpad
532-
// into
533-
// ... (some code)
534-
// call @invoke_SIG(func, arg1, arg2)
535-
// ... (some code)
536-
// SIG is a mangled string generated based on the LLVM IR-level function
537-
// signature. In LLVM IR, types are not lowered yet, so this mangling scheme
538-
// simply takes LLVM's string representtion of parameter types and concatenate
539-
// them with '_'. For example, the name of an invoke wrapper for function
540-
// void foo(struct mystruct*, int) will be
541-
// "__invoke_void_%struct.mystruct*_int".
542-
// This function converts the names of invoke wrappers based on their lowered
543-
// argument types and a return type. In the example above, the resulting new
544-
// wrapper name becomes "invoke_vii".
545-
Name fixEmExceptionInvoke(const Name& name, Signature sig) {
546-
std::string nameStr = name.c_str();
547-
if (nameStr.front() == '"' && nameStr.back() == '"') {
548-
nameStr = nameStr.substr(1, nameStr.size() - 2);
549-
}
550-
if (nameStr.find("__invoke_") != 0) {
551-
return name;
552-
}
553-
554-
std::vector<Type> newParams(sig.params.begin() + 1, sig.params.end());
555-
Signature sigWoOrigFunc = Signature(Type(newParams), sig.results);
556-
invokeSigs.insert(sigWoOrigFunc);
557-
return Name("invoke_" +
558-
getSig(sigWoOrigFunc.results, sigWoOrigFunc.params));
559-
}
560-
561-
void visitFunction(Function* curr) {
562-
if (!curr->imported()) {
563-
return;
564-
}
565-
566-
Name newname = fixEmExceptionInvoke(curr->base, curr->sig);
567-
if (newname == curr->base) {
568-
return;
569-
}
570-
571-
BYN_TRACE("renaming import: " << curr->module << "." << curr->base << " ("
572-
<< curr->name << ") -> " << newname << "\n");
573-
574-
if (auto* f = imports.getImportedFunction(curr->module, newname)) {
575-
BYN_TRACE("remove redundant import: " << curr->base << "\n");
576-
toRemove.push_back(curr->name);
577-
// Make sure the existing import has the correct internal name.
578-
if (f->name != newname) {
579-
functionRenames[f->name] = newname;
580-
}
581-
} else {
582-
BYN_TRACE("rename import: " << curr->base << "\n");
583-
curr->base = newname;
584-
}
585-
586-
functionRenames[curr->name] = newname;
587-
588-
// Ensure that an imported functions of this name exists.
589-
importRenames[curr->base] = newname;
590-
}
591-
592-
void visitModule(Module* curr) {
593-
for (auto name : toRemove) {
594-
wasm.removeFunction(name);
595-
}
596-
597-
// Rename all uses of the old function to the new import name
598-
ModuleUtils::renameFunctions(wasm, functionRenames);
599-
600-
// For imports that for renamed, update any associated GOT.func imports.
601-
for (auto& pair : importRenames) {
602-
BYN_TRACE("looking for: GOT.func." << pair.first << "\n");
603-
if (auto g = imports.getImportedGlobal("GOT.func", pair.first)) {
604-
BYN_TRACE("renaming corresponding GOT entry: " << g->base << " -> "
605-
<< pair.second << "\n");
606-
g->base = pair.second;
607-
}
608-
}
609-
}
610-
};
611-
612-
void EmscriptenGlueGenerator::fixInvokeFunctionNames() {
613-
BYN_TRACE("fixInvokeFunctionNames\n");
614-
FixInvokeFunctionNamesWalker walker(wasm);
615-
walker.walkModule(&wasm);
616-
}
617-
618490
void printSignatures(std::ostream& o, const std::set<Signature>& c) {
619491
o << "[";
620492
bool first = true;
@@ -746,7 +618,7 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
746618
meta << " \"invokeFuncs\": [";
747619
commaFirst = true;
748620
ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
749-
if (import->base.startsWith("invoke_")) {
621+
if (import->module == ENV && import->base.startsWith("invoke_")) {
750622
if (invokeFuncs.insert(import->base.str).second) {
751623
meta << nextElement() << '"' << import->base.str << '"';
752624
}

test/passes/post-emscripten.txt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -176,16 +176,3 @@
176176
)
177177
)
178178
)
179-
(module
180-
(type $i32_i32_=>_none (func (param i32 i32)))
181-
(import "env" "emscripten_longjmp" (func $a (param i32 i32)))
182-
(import "env" "emscripten_longjmp" (func $b (param i32 i32)))
183-
)
184-
(module
185-
(type $i32_i32_=>_none (func (param i32 i32)))
186-
(import "env" "emscripten_longjmp_jmpbuf" (func $b (param i32 i32)))
187-
)
188-
(module
189-
(type $i32_i32_=>_none (func (param i32 i32)))
190-
(import "env" "emscripten_longjmp" (func $a (param i32 i32)))
191-
)

test/passes/post-emscripten.wast

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,3 @@
148148
)
149149
)
150150
)
151-
;; longjmp renaming
152-
(module
153-
(import "env" "emscripten_longjmp" (func $a (param i32 i32)))
154-
(import "env" "emscripten_longjmp_jmpbuf" (func $b (param i32 i32)))
155-
)
156-
(module
157-
(import "env" "emscripten_longjmp_jmpbuf" (func $b (param i32 i32)))
158-
)
159-
(module
160-
(import "env" "emscripten_longjmp" (func $a (param i32 i32)))
161-
)

0 commit comments

Comments
 (0)