diff options
author | Derek Schuff <dschuff@chromium.org> | 2016-06-02 14:30:30 -0700 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2016-06-02 14:30:30 -0700 |
commit | d4dc216888d5028f41e6189e65001694e49a66c2 (patch) | |
tree | 35ac5962bedb07fa732b34b62f7b7c3d68280ce4 /src/s2wasm.h | |
parent | d595e89003dc3636952de4c561679e3a077e6015 (diff) | |
download | binaryen-d4dc216888d5028f41e6189e65001694e49a66c2.tar.gz binaryen-d4dc216888d5028f41e6189e65001694e49a66c2.tar.bz2 binaryen-d4dc216888d5028f41e6189e65001694e49a66c2.zip |
Generate thunks for address-taken imports (#554)
Under emscripten, C code can take the address of a function implemented
in Javascript (which is exposed via an import in wasm). Because imports
do not have linear memory address in wasm, we need to generate a thunk
to be the target of the indirect call; it call the import directly.
This is facilited by a new .s directive (.functype) which declares the
types of functions which are declared but not defined.
Fixes https://github.com/WebAssembly/binaryen/issues/392
Diffstat (limited to 'src/s2wasm.h')
-rw-r--r-- | src/s2wasm.h | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h index 2228ae900..d24f5ef46 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -88,6 +88,11 @@ class S2WasmBuilder { } } + void skipToEOL() { + s = strchr(s, '\n'); + assert(s); + } + bool skipComma() { skipWhitespace(); if (*s != ',') return false; @@ -397,10 +402,11 @@ class S2WasmBuilder { else if (match("weak") || match("hidden") || match("protected") || match("internal")) getStr(); // contents are in the content that follows else if (match("imports")) skipImports(); else if (match("data")) {} - else if (match("ident")) {} + else if (match("ident")) skipToEOL(); else if (match("section")) parseToplevelSection(); - else if (match("align") || match("p2align")) s = strchr(s, '\n'); + else if (match("align") || match("p2align")) skipToEOL(); else if (match("globl")) parseGlobl(); + else if (match("functype")) parseFuncType(); else abort_on("process"); } } @@ -423,11 +429,11 @@ class S2WasmBuilder { void parseInitializer() { // Ignore the rest of the .section line - s = strchr(s, '\n'); + skipToEOL(); skipWhitespace(); // The section may start with .p2align if (match(".p2align")) { - s = strchr(s, '\n'); + skipToEOL(); skipWhitespace(); } mustMatch(".int32"); @@ -480,6 +486,22 @@ class S2WasmBuilder { skipWhitespace(); } + void parseFuncType() { + auto decl = make_unique<FunctionType>(); + Name name = getCommaSeparated(); + skipComma(); + if(match("void")) { + decl->result = none; + } else { + decl->result = getType(); + } + while (*s && skipComma()) decl->params.push_back(getType()); + + FunctionType *ty = wasm->checkFunctionType(getSig(decl.get())); + if (!ty) ty = decl.release(); + linkerObj->addExternType(name, ty); + } + bool parseVersionMin() { if (match("watchos_version_min") || match("tvos_version_min") || match("ios_version_min") || match("macosx_version_min")) { s = strchr(s, '\n'); |