diff options
Diffstat (limited to 'src/s2wasm.h')
-rw-r--r-- | src/s2wasm.h | 85 |
1 files changed, 7 insertions, 78 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h index 0efe0408e..3cb4c7139 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -253,6 +253,7 @@ class S2WasmBuilder { return new LinkerObject::Relocation( kind, target, fixEmLongjmp(cleanFunction(name)), offset); } + Expression* relocationToGetGlobal(LinkerObject::Relocation* relocation) { if (!relocation) { return nullptr; @@ -421,6 +422,7 @@ class S2WasmBuilder { bool isFunctionName(Name name) { return !!strstr(name.str, "@FUNCTION"); } + // Drop the @ and after it. Name cleanFunction(Name name) { if (!strchr(name.str, '@')) return name; @@ -615,7 +617,7 @@ class S2WasmBuilder { void parseFuncType() { auto decl = make_unique<FunctionType>(); - Name rawName = getCommaSeparated(); + Name name = getCommaSeparated(); skipComma(); if(match("void")) { decl->result = none; @@ -627,7 +629,6 @@ class S2WasmBuilder { decl->name = "FUNCSIG$" + sig; FunctionType *ty = wasm->getFunctionTypeOrNull(decl->name); - Name name = fixEmEHSjLjNames(rawName, sig); if (!ty) { // The wasm module takes ownership of the FunctionType if we insert it. // Otherwise it's already in the module and ours is freed. @@ -979,14 +980,11 @@ class S2WasmBuilder { if (*s == ',') { skipComma(); int num = getNumInputs(); - auto inputs = getInputs(num); - for (int i = 0; i < num; i++) { - curr->operands.push_back(inputs[i]); + for (Expression* input : getInputs(num)) { + curr->operands.push_back(input); } } - Name target = linkerObj->resolveAlias( - fixEmEHSjLjNames(rawTarget, curr->type, curr->operands), - LinkerObject::Relocation::kFunction); + Name target = linkerObj->resolveAlias(rawTarget, LinkerObject::Relocation::kFunction); curr->target = target; if (!linkerObj->isFunctionImplemented(target)) { linkerObj->addUndefinedFunctionCall(curr); @@ -1447,83 +1445,14 @@ class S2WasmBuilder { } } - // Fixes function name hacks caused by LLVM exception & setjmp/longjmp - // handling pass for wasm. - // This does two things: - // 1. Change emscripten_longjmp_jmpbuf to emscripten_longjmp. - // In setjmp/longjmp handling pass in wasm backend, what we want to do is - // to change all function calls to longjmp to calls to emscripten_longjmp. - // Because we replace all calls to longjmp to emscripten_longjmp, the - // signature of that function should be the same as longjmp: - // emscripten_longjmp(jmp_buf, int) - // But after calling a function that might longjmp, while we test whether - // a longjmp occurred, we have to load an int address value and call - // emscripten_longjmp again with that address as the first argument. (Refer - // to lib/Target/WebAssembly/WebAssemblyEmscriptenEHSjLj.cpp in LLVM for - // details.) - // In this case we need the signature of emscripten_longjmp to be (int, - // int). So we need two different kinds of emscripten_longjmp signatures in - // LLVM IR. Both signatures will be lowered to (int, int) eventually, but - // in LLVM IR, types are not lowered yet. - // So we declare two functions in LLVM: - // emscripten_longjmp_jmpbuf(jmp_buf, int) - // emscripten_longjmp(int, int) - // And we change the name of emscripten_longjmp_jmpbuf to - // emscripten_longjmp here. - // 2. Converts invoke wrapper names. - // Refer to the comments in fixEmExceptionInvoke below. - template<typename ListType> - Name fixEmEHSjLjNames(const Name &name, Type result, - const ListType &operands) { - return fixEmEHSjLjNames(name, getSig(result, operands)); - } - - Name fixEmEHSjLjNames(const Name &name, const std::string& sig) { - if (name == "emscripten_longjmp_jmpbuf") - return "emscripten_longjmp"; - return fixEmExceptionInvoke(name, sig); - } - // This version only converts emscripten_longjmp_jmpbuf and does not deal // with invoke wrappers. This is used when we only have a function name as // relocatable constant. - Name fixEmLongjmp(const Name &name) { + static Name fixEmLongjmp(const Name &name) { if (name == "emscripten_longjmp_jmpbuf") return "emscripten_longjmp"; return name; } - - // Converts invoke wrapper names generated by LLVM backend to real invoke - // wrapper names that are expected by JavaScript glue code. - // This is required to support wasm exception handling (asm.js style). - // - // LLVM backend lowers - // invoke @func(arg1, arg2) to label %invoke.cont unwind label %lpad - // into - // ... (some code) - // call @invoke_SIG(func, arg1, arg2) - // ... (some code) - // SIG is a mangled string generated based on the LLVM IR-level function - // signature. In LLVM IR, types are not lowered yet, so this mangling scheme - // simply takes LLVM's string representtion of parameter types and concatenate - // them with '_'. For example, the name of an invoke wrapper for function - // void foo(struct mystruct*, int) will be - // "__invoke_void_%struct.mystruct*_int". - // This function converts the names of invoke wrappers based on their lowered - // argument types and a return type. In the example above, the resulting new - // wrapper name becomes "invoke_vii". - Name fixEmExceptionInvoke(const Name &name, const std::string& sig) { - std::string nameStr = name.c_str(); - if (nameStr.front() == '"' && nameStr.back() == '"') { - nameStr = nameStr.substr(1, nameStr.size() - 2); - } - if (nameStr.find("__invoke_") != 0) { - return name; - } - std::string sigWoOrigFunc = sig.front() + sig.substr(2, sig.size() - 2); - return Name("invoke_" + sigWoOrigFunc); - } - }; } // namespace wasm |