summaryrefslogtreecommitdiff
path: root/src/wasm-js.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-10-31 17:11:04 -0700
committerAlon Zakai <alonzakai@gmail.com>2015-10-31 17:13:51 -0700
commit3e618d9570b278ca9e94663240cf33d4f3cb22a9 (patch)
treedf52ab3eb814ab7274703680bfb1b09bc093ce41 /src/wasm-js.cpp
parent2635938b578aa55419bd2a59b837dfaeb546ddcc (diff)
downloadbinaryen-3e618d9570b278ca9e94663240cf33d4f3cb22a9.tar.gz
binaryen-3e618d9570b278ca9e94663240cf33d4f3cb22a9.tar.bz2
binaryen-3e618d9570b278ca9e94663240cf33d4f3cb22a9.zip
call from js into wasm
Diffstat (limited to 'src/wasm-js.cpp')
-rw-r--r--src/wasm-js.cpp50
1 files changed, 47 insertions, 3 deletions
diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp
index cd9e427a3..a0c9a0f13 100644
--- a/src/wasm-js.cpp
+++ b/src/wasm-js.cpp
@@ -15,11 +15,15 @@
using namespace cashew;
using namespace wasm;
+ModuleInstance* instance = nullptr;
+
// receives asm.js code, parses into wasm and returns an instance handle.
// this creates a module, an external interface, and a module instance,
// all of which are then the responsibility of the caller to free.
// note: this modifies the input.
-extern "C" ModuleInstance* EMSCRIPTEN_KEEPALIVE load_asm(char *input) {
+extern "C" void EMSCRIPTEN_KEEPALIVE load_asm(char *input) {
+ assert(instance == nullptr); // singleton
+
// emcc --separate-asm modules look like
//
// Module["asm"] = (function(global, env, buffer) {
@@ -54,7 +58,21 @@ extern "C" ModuleInstance* EMSCRIPTEN_KEEPALIVE load_asm(char *input) {
if (debug) std::cerr << "optimizing...\n";
asm2wasm.optimize();
- if (debug) std::cerr << "returning instance.\n";
+ if (debug) std::cerr << "generating exports...\n";
+ EM_ASM({
+ Module['asmExports'] = {};
+ });
+ for (auto& curr : wasm->exports) {
+ EM_ASM_({
+ var name = Pointer_stringify($0);
+ Module['asmExports'][name] = function() {
+ Module['tempArguments'] = Array.prototype.slice.call(arguments);
+ return Module['_call_from_js']($0);
+ };
+ }, curr.name.str);
+ }
+
+ if (debug) std::cerr << "creating instance...\n";
struct JSExternalInterface : ModuleInstance::ExternalInterface {
Literal callImport(Import *import, ModuleInstance::LiteralList& arguments) override {
@@ -136,6 +154,32 @@ extern "C" ModuleInstance* EMSCRIPTEN_KEEPALIVE load_asm(char *input) {
}
};
- return new ModuleInstance(*wasm, new JSExternalInterface());
+ instance = new ModuleInstance(*wasm, new JSExternalInterface());
+}
+
+// Does a call from js into an export of the module.
+extern "C" double EMSCRIPTEN_KEEPALIVE call_from_js(const char *target) {
+ IString name(target);
+ assert(instance->functions.find(name) != instance->functions.end());
+ Function *function = instance->functions[name];
+ size_t num = EM_ASM_INT_V({ return Module['tempArguments'].length });
+ assert(num == function->params.size()); // TODO: fake missing/extra args?
+
+ ModuleInstance::LiteralList arguments;
+ for (size_t i = 0; i < num; i++) {
+ WasmType type = function->params[i].type;
+ if (type == i32) {
+ arguments.push_back(Literal(EM_ASM_INT({ return Module['tempArguments'][$0] }, i)));
+ } else if (type == f64) {
+ arguments.push_back(Literal(EM_ASM_DOUBLE({ return Module['tempArguments'][$0] }, i)));
+ } else {
+ abort();
+ }
+ }
+
+ Literal ret = instance->callFunction(name, arguments);
+ if (ret.type == i32) return ret.i32;
+ if (ret.type == f64) return ret.f64;
+ abort();
}