summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2019-04-08 17:23:02 -0700
committerGitHub <noreply@github.com>2019-04-08 17:23:02 -0700
commitc9eeaefbd839cc5176957e479475625fc8b2bcf0 (patch)
treeb0f903ac59d714b832b1dfbca1789966e6ba77ad
parentc5ad2e5ecc517030aa242c18fd738b9d79f11429 (diff)
downloadbinaryen-c9eeaefbd839cc5176957e479475625fc8b2bcf0.tar.gz
binaryen-c9eeaefbd839cc5176957e479475625fc8b2bcf0.tar.bz2
binaryen-c9eeaefbd839cc5176957e479475625fc8b2bcf0.zip
wasm-emscripten-finalize: rename function pointer getter functions (#1988)
Turns out there was already a precedent in emscripten for using `fp$` for these functions. Also, improve the heuristics for guessing the stack pointer global. There are cases where we don't use have an explicit stack pointer at all but *do* have both imported and exported globals.
-rw-r--r--src/wasm/wasm-emscripten.cpp29
-rw-r--r--test/lld/shared.wast.out6
2 files changed, 28 insertions, 7 deletions
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index 875212c44..95566f5b9 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -48,9 +48,19 @@ void addExportedFunction(Module& wasm, Function* function) {
wasm.addExport(export_);
}
+// TODO(sbc): There should probably be a better way to do this.
+bool isExported(Module& wasm, Name name) {
+ for (auto& ex : wasm.exports) {
+ if (ex->value == name) {
+ return true;
+ }
+ }
+ return false;
+}
+
Global* EmscriptenGlueGenerator::getStackPointerGlobal() {
// Assumption: The stack pointer is either imported as __stack_pointer or
- // its the first non-imported global.
+ // its the first non-imported and non-exported global.
// TODO(sbc): Find a better way to discover the stack pointer. Perhaps the
// linker could export it by name?
for (auto& g : wasm.globals) {
@@ -58,7 +68,7 @@ Global* EmscriptenGlueGenerator::getStackPointerGlobal() {
if (g->base == "__stack_pointer") {
return g.get();
}
- } else {
+ } else if (!isExported(wasm, g->name)) {
return g.get();
}
}
@@ -172,6 +182,17 @@ static Function* ensureFunctionImport(Module* module, Name name, std::string sig
return import;
}
+// Convert LLVM PIC ABI to emscripten ABI
+//
+// When generating -fPIC code llvm will generate imports call GOT.mem and
+// GOT.func in order to access the addresses of external global data and
+// functions.
+//
+// However emscripten uses a different ABI where function and data addresses
+// are available at runtime via special `g$foo` and `fp$bar` function calls.
+//
+// Here we internalize all such wasm globals and generte code that sets their
+// value based on the result of call `g$foo` and `fp$bar` functions at runtime.
Function* EmscriptenGlueGenerator::generateAssignGOTEntriesFunction() {
std::vector<Global*> got_entries_func;
std::vector<Global*> got_entries_mem;
@@ -209,7 +230,7 @@ Function* EmscriptenGlueGenerator::generateAssignGOTEntriesFunction() {
}
for (Global* g : got_entries_func) {
- Name getter(std::string("f$") + g->base.c_str());
+ Name getter(std::string("fp$") + g->base.c_str());
if (auto* f = wasm.getFunctionOrNull(g->base)) {
getter.set((getter.c_str() + std::string("$") + getSig(f)).c_str(), false);
}
@@ -244,7 +265,7 @@ void EmscriptenGlueGenerator::generatePostInstantiateFunction() {
if (Function* F = generateAssignGOTEntriesFunction()) {
// call __assign_got_enties from post_instantiate
Expression* call = builder.makeCall(F->name, {}, none);
- post_instantiate->body = builder.blockify(call);
+ post_instantiate->body = builder.blockify(post_instantiate->body, call);
}
// The names of standard imports/exports used by lld doesn't quite match that
diff --git a/test/lld/shared.wast.out b/test/lld/shared.wast.out
index 597d7086d..965ba326b 100644
--- a/test/lld/shared.wast.out
+++ b/test/lld/shared.wast.out
@@ -11,7 +11,7 @@
(import "env" "__table_base" (global $gimport$3 i32))
(import "env" "puts" (func $puts (param i32) (result i32)))
(import "env" "g$external_var" (func $g$external_var (result i32)))
- (import "env" "f$puts$ii" (func $f$puts$ii (result i32)))
+ (import "env" "fp$puts$ii" (func $fp$puts$ii (result i32)))
(global $gimport$5 (mut i32) (i32.const 0))
(global $gimport$6 (mut i32) (i32.const 0))
(export "print_message" (func $print_message))
@@ -42,7 +42,7 @@
(call $g$external_var)
)
(global.set $gimport$5
- (call $f$puts$ii)
+ (call $fp$puts$ii)
)
)
)
@@ -54,7 +54,7 @@
"declares": [
"puts",
"g$external_var",
- "f$puts$ii"
+ "fp$puts$ii"
],
"externs": [
"___memory_base",