summaryrefslogtreecommitdiff
path: root/src/s2wasm.h
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2016-06-02 14:30:30 -0700
committerDerek Schuff <dschuff@chromium.org>2016-06-02 14:30:30 -0700
commitd4dc216888d5028f41e6189e65001694e49a66c2 (patch)
tree35ac5962bedb07fa732b34b62f7b7c3d68280ce4 /src/s2wasm.h
parentd595e89003dc3636952de4c561679e3a077e6015 (diff)
downloadbinaryen-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.h30
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');