summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm-main.cpp6
-rw-r--r--src/asm2wasm.h19
-rw-r--r--src/js/post.js9
-rw-r--r--src/wasm-js.cpp54
4 files changed, 65 insertions, 23 deletions
diff --git a/src/asm2wasm-main.cpp b/src/asm2wasm-main.cpp
index c8a5a4c30..b2b490965 100644
--- a/src/asm2wasm-main.cpp
+++ b/src/asm2wasm-main.cpp
@@ -15,6 +15,7 @@ int main(int argc, char **argv) {
debug = getenv("ASM2WASM_DEBUG") ? getenv("ASM2WASM_DEBUG")[0] - '0' : 0;
char *infile = argv[1];
+ char *mappedGlobals = argc < 3 ? nullptr : argv[2];
if (debug) std::cerr << "loading '" << infile << "'...\n";
FILE *f = fopen(argv[1], "r");
@@ -50,6 +51,11 @@ int main(int argc, char **argv) {
if (debug) std::cerr << "printing...\n";
std::cout << wasm;
+ if (mappedGlobals) {
+ if (debug) std::cerr << "serializing mapped globals...\n";
+ asm2wasm.serializeMappedGlobals(mappedGlobals);
+ }
+
if (debug) std::cerr << "done.\n";
}
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index ed376f576..8dcefec0e 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -143,6 +143,25 @@ class Asm2WasmBuilder {
public:
std::map<IString, MappedGlobal> mappedGlobals;
+ // the global mapping info is not present in the output wasm. We need to save it on the side
+ // if we intend to load and run this module's wasm.
+ void serializeMappedGlobals(const char *filename) {
+ FILE *f = fopen(filename, "w");
+ assert(f);
+ fprintf(f, "{\n");
+ bool first = true;
+ for (auto& pair : mappedGlobals) {
+ auto name = pair.first;
+ auto& global = pair.second;
+ if (first) first = false;
+ else fprintf(f, ",");
+ fprintf(f, "\"%s\": { \"address\": %d, \"type\": %d, \"import\": %d, \"module\": \"%s\", \"base\": \"%s\" }\n",
+ name.str, global.address, global.type, global.import, global.module.str, global.base.str);
+ }
+ fprintf(f, "}");
+ fclose(f);
+ }
+
private:
void allocateGlobal(IString name, WasmType type, bool import, IString module = IString(), IString base = IString()) {
assert(mappedGlobals.find(name) == mappedGlobals.end());
diff --git a/src/js/post.js b/src/js/post.js
index 4377ed797..2ef25e30c 100644
--- a/src/js/post.js
+++ b/src/js/post.js
@@ -84,6 +84,9 @@ function integrateWasmJS(Module) {
Module['asm'] = function(global, env, providedBuffer) {
assert(providedBuffer === Module['buffer']); // we should not even need to pass it as a 3rd arg for wasm, but that's the asm.js way.
+ info.global = global;
+ info.env = env;
+
// wasm code would create its own buffer, at this time. But static init code might have
// written to the buffer already, and we must copy it over. We could just avoid
// this copy in wasm.js polyfilling, but to be as close as possible to real wasm,
@@ -112,16 +115,12 @@ function integrateWasmJS(Module) {
if (method == 'asm2wasm') {
wasmJS['_load_asm2wasm'](temp);
} else {
- wasmJS['_load_s_expr2wasm'](temp);
+ wasmJS['_load_s_expr2wasm'](temp, Module['read'](Module['wasmCodeFile'] + '.mappedGlobals'));
}
wasmJS['_free'](temp);
wasmJS['_instantiate'](temp);
- // write the provided data to a location the wasm instance can get at it.
- info.global = global;
- info.env = env;
- wasmJS['_load_mapped_globals'](); // now that we have global and env, we can ready the provided imported globals, copying them to their mapped locations.
return wasmJS['asmExports'];
};
}
diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp
index e822da66a..fb3d5dd5a 100644
--- a/src/wasm-js.cpp
+++ b/src/wasm-js.cpp
@@ -62,10 +62,25 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_asm2wasm(char *input) {
if (wasmJSDebug) std::cerr << "optimizing...\n";
asm2wasm->optimize();
+
+ if (wasmJSDebug) std::cerr << "mapping globals...\n";
+ for (auto& pair : asm2wasm->mappedGlobals) {
+ auto name = pair.first;
+ auto& global = pair.second;
+ if (!global.import) continue; // non-imports are initialized to zero in the typed array anyhow, so nothing to do here
+ double value = EM_ASM_DOUBLE({ return Module['lookupImport'](Pointer_stringify($0), Pointer_stringify($1)) }, global.module.str, global.base.str);
+ unsigned address = global.address;
+ switch (global.type) {
+ case i32: EM_ASM_({ Module['info'].parent['HEAP32'][$0 >> 2] = $1 }, address, value); break;
+ case f32: EM_ASM_({ Module['info'].parent['HEAPF32'][$0 >> 2] = $1 }, address, value); break;
+ case f64: EM_ASM_({ Module['info'].parent['HEAPF64'][$0 >> 3] = $1 }, address, value); break;
+ default: abort();
+ }
+ }
}
// loads wasm code in s-expression format
-extern "C" void EMSCRIPTEN_KEEPALIVE load_s_expr2wasm(char *input) {
+extern "C" void EMSCRIPTEN_KEEPALIVE load_s_expr2wasm(char *input, char *mappedGlobals) {
prepare2wasm();
if (wasmJSDebug) std::cerr << "wasm-s-expression parsing...\n";
@@ -82,6 +97,26 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_s_expr2wasm(char *input) {
std::cerr << "error in parsing s-expressions to wasm\n";
abort();
});
+
+ if (wasmJSDebug) std::cerr << "mapping globals...\n";
+ EM_ASM_({
+ var mappedGlobals = JSON.parse($0);
+ var i32 = $1;
+ var f32 = $2;
+ var f64 = $3;
+ for (var name in mappedGlobals) {
+ var global = mappedGlobals[name];
+ if (!global.import) continue; // non-imports are initialized to zero in the typed array anyhow, so nothing to do here
+ var value = Module['lookupImport'](global.module, global.base);
+ var address = global.address;
+ switch (global.type) {
+ case i32: Module['info'].parent['HEAP32'][address >> 2] = value; break;
+ case f32: Module['info'].parent['HEAPF32'][address >> 2] = value; break;
+ case f64: Module['info'].parent['HEAPF64'][address >> 3] = value; break;
+ default: abort();
+ }
+ }
+ }, mappedGlobals, i32, f32, f64);
}
// instantiates the loaded wasm (which might be from asm2wasm, or
@@ -228,23 +263,6 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
instance = new ModuleInstance(*module, new JSExternalInterface());
}
-// Ready the provided imported globals, copying them to their mapped locations.
-extern "C" void EMSCRIPTEN_KEEPALIVE load_mapped_globals() {
- for (auto& pair : asm2wasm->mappedGlobals) {
- auto name = pair.first;
- auto& global = pair.second;
- if (!global.import) continue; // non-imports are initialized to zero in the typed array anyhow, so nothing to do here
- double value = EM_ASM_DOUBLE({ return Module['lookupImport'](Pointer_stringify($0), Pointer_stringify($1)) }, global.module.str, global.base.str);
- unsigned address = global.address;
- switch (global.type) {
- case i32: EM_ASM_({ Module['info'].parent['HEAP32'][$0 >> 2] = $1 }, address, value); break;
- case f32: EM_ASM_({ Module['info'].parent['HEAPF32'][$0 >> 2] = $1 }, address, value); break;
- case f64: EM_ASM_({ Module['info'].parent['HEAPF64'][$0 >> 3] = $1 }, address, value); break;
- default: abort();
- }
- }
-}
-
// Does a call from js into an export of the module.
extern "C" void EMSCRIPTEN_KEEPALIVE call_from_js(const char *target) {
if (wasmJSDebug) std::cout << "call_from_js " << target << '\n';