summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/s2wasm.h56
-rw-r--r--src/wasm-linker.cpp13
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) {