diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/s2wasm.h | 56 | ||||
-rw-r--r-- | src/wasm-linker.cpp | 13 |
2 files changed, 61 insertions, 8 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h index b17ed0702..3a7cf31db 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -554,7 +554,7 @@ class S2WasmBuilder { void parseFuncType() { auto decl = make_unique<FunctionType>(); - Name name = getCommaSeparated(); + Name rawName = getCommaSeparated(); skipComma(); if(match("void")) { decl->result = none; @@ -562,9 +562,11 @@ class S2WasmBuilder { decl->result = getType(); } while (*s && skipComma()) decl->params.push_back(getType()); - decl->name = "FUNCSIG$" + getSig(decl.get()); + std::string sig = getSig(decl.get()); + decl->name = "FUNCSIG$" + sig; FunctionType *ty = wasm->checkFunctionType(decl->name); + Name name = fixEmExceptionInvoke(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. @@ -876,14 +878,9 @@ class S2WasmBuilder { } else { // non-indirect call Name assign = getAssign(); - Name target = linkerObj->resolveAlias(cleanFunction(getCommaSeparated()), LinkerObject::Relocation::kFunction); - + Name rawTarget = cleanFunction(getCommaSeparated()); Call* curr = allocator->alloc<Call>(); - curr->target = target; curr->type = type; - if (!linkerObj->isFunctionImplemented(target)) { - linkerObj->addUndefinedFunctionCall(curr); - } skipWhitespace(); if (*s == ',') { skipComma(); @@ -893,6 +890,13 @@ class S2WasmBuilder { curr->operands.push_back(inputs[i]); } } + Name target = linkerObj->resolveAlias( + fixEmExceptionInvoke(rawTarget, curr->type, curr->operands), + LinkerObject::Relocation::kFunction); + curr->target = target; + if (!linkerObj->isFunctionImplemented(target)) { + linkerObj->addUndefinedFunctionCall(curr); + } setOutput(curr, assign); } }; @@ -1342,6 +1346,42 @@ class S2WasmBuilder { } } + // 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". + template<typename ListType> + Name fixEmExceptionInvoke(const Name &name, WasmType result, + const ListType &operands) { + return fixEmExceptionInvoke(name, getSig(result, operands)); + } + + 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); + } }; diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp index 45615fd59..d8bae7558 100644 --- a/src/wasm-linker.cpp +++ b/src/wasm-linker.cpp @@ -210,6 +210,19 @@ void Linker::layout() { auto* func = out.wasm.getFunction(name); func->type = ensureFunctionType(getSig(func), &out.wasm)->name; } + + // Export malloc and free whenever availble. JavsScript version of malloc has + // some issues and it cannot be called once _sbrk() is called. + // TODO This should get the list of exported functions from emcc.py - it has + // EXPORTED_FUNCTION metadata to keep track of this. Get the list of exported + // functions using a command-line argument from emcc.py and export all of + // them. + if (out.symbolInfo.implementedFunctions.count("malloc")) { + exportFunction("malloc", true); + } + if (out.symbolInfo.implementedFunctions.count("free")) { + exportFunction("free", true); + } } bool Linker::linkObject(S2WasmBuilder& builder) { |