diff options
-rwxr-xr-x | scripts/test/wasm2js.py | 4 | ||||
-rw-r--r-- | src/tools/wasm2js.cpp | 5 | ||||
-rw-r--r-- | src/wasm2js.h | 65 | ||||
-rw-r--r-- | test/wasm2js/emscripten.2asm.js | 78 | ||||
-rw-r--r-- | test/wasm2js/emscripten.wast | 32 |
5 files changed, 180 insertions, 4 deletions
diff --git a/scripts/test/wasm2js.py b/scripts/test/wasm2js.py index afa399da2..2892da278 100755 --- a/scripts/test/wasm2js.py +++ b/scripts/test/wasm2js.py @@ -52,6 +52,8 @@ def test_wasm2js_output(): print '..', wasm cmd = WASM2JS + [os.path.join(options.binaryen_test, wasm)] + if 'emscripten' in wasm: + cmd += ['--emscripten'] out = run_command(cmd) fail_if_not_identical_to_file(out, expected_file) @@ -129,6 +131,8 @@ def update_wasm2js_tests(): print '..', wasm cmd = WASM2JS + [os.path.join('test', wasm)] + if 'emscripten' in wasm: + cmd += ['--emscripten'] out = run_command(cmd) with open(expected_file, 'w') as o: o.write(out) diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp index 76a724f86..8704dbf49 100644 --- a/src/tools/wasm2js.cpp +++ b/src/tools/wasm2js.cpp @@ -370,6 +370,11 @@ int main(int argc, const char *argv[]) { [&](Options* o, const std::string& argument) { flags.pedantic = true; }) + .add("--emscripten", "", "Emulate the glue in emscripten-compatible form (and not ES6 module form)", + Options::Arguments::Zero, + [&](Options* o, const std::string& argument) { + flags.emscripten = true; + }) .add_positional("INFILE", Options::Arguments::One, [](Options *o, const std::string& argument) { o->extra["infile"] = argument; diff --git a/src/wasm2js.h b/src/wasm2js.h index c6970e3e8..e93b3f273 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -142,6 +142,7 @@ public: bool debug = false; bool pedantic = false; bool allowAsserts = false; + bool emscripten = false; }; Wasm2JSBuilder(Flags f) : flags(f) {} @@ -358,6 +359,9 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) { generateFetchHighBits = true; } }); + if (flags.emscripten) { + asmFunc[3]->push_back(ValueBuilder::makeName("// EMSCRIPTEN_START_FUNCS")); + } // functions ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) { asmFunc[3]->push_back(processFunction(wasm, func)); @@ -379,6 +383,9 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) { e->kind = ExternalKind::Function; wasm->addExport(e); } + if (flags.emscripten) { + asmFunc[3]->push_back(ValueBuilder::makeName("// EMSCRIPTEN_END_FUNCS")); + } addTables(asmFunc[3], wasm); // memory XXX @@ -2002,9 +2009,26 @@ private: Output& out; Wasm2JSBuilder::Flags flags; Name moduleName; + + void emitPreEmscripten(); + void emitPreES6(); + void emitPostEmscripten(); + void emitPostES6(); }; void Wasm2JSGlue::emitPre() { + if (flags.emscripten) { + emitPreEmscripten(); + } else { + emitPreES6(); + } +} + +void Wasm2JSGlue::emitPreEmscripten() { + out << "function instantiate(asmLibraryArg, wasmMemory, wasmTable) {\n\n"; +} + +void Wasm2JSGlue::emitPreES6() { std::unordered_map<Name, Name> baseModuleMap; auto noteImport = [&](Name module, Name base) { @@ -2018,10 +2042,10 @@ void Wasm2JSGlue::emitPre() { baseModuleMap[base] = module; out << "import { " - << base.str - << " } from '" - << module.str - << "';\n"; + << base.str + << " } from '" + << module.str + << "';\n"; }; ImportInfo imports(wasm); @@ -2038,6 +2062,39 @@ void Wasm2JSGlue::emitPre() { } void Wasm2JSGlue::emitPost() { + if (flags.emscripten) { + emitPostEmscripten(); + } else { + emitPostES6(); + } +} + +void Wasm2JSGlue::emitPostEmscripten() { + out << "return asmFunc(\n" + << " {\n" + << " 'env': asmLibraryArg,\n" + << " 'global': {\n" + << " 'Int8Array': Int8Array,\n" + << " 'Int16Array': Int16Array,\n" + << " 'Int32Array': Int32Array,\n" + << " 'Uint8Array': Uint8Array,\n" + << " 'Uint16Array': Uint16Array,\n" + << " 'Uint32Array': Uint32Array,\n" + << " 'Float32Array': Float32Array,\n" + << " 'Float64Array': Float64Array,\n" + << " 'NaN': NaN,\n" + << " 'Infinity': Infinity,\n" + << " 'Math': Math\n" + << " }\n" + << " },\n" + << " wasmMemory.buffer\n" + << ")" + << "\n" + << "\n" + << "}"; +} + +void Wasm2JSGlue::emitPostES6() { // Create an initial `ArrayBuffer` and populate it with static data. // Currently we use base64 encoding to encode static data and we decode it at // instantiation time. diff --git a/test/wasm2js/emscripten.2asm.js b/test/wasm2js/emscripten.2asm.js new file mode 100644 index 000000000..d1fe55ffd --- /dev/null +++ b/test/wasm2js/emscripten.2asm.js @@ -0,0 +1,78 @@ +function instantiate(asmLibraryArg, wasmMemory, wasmTable) { + +function asmFunc(global, env, buffer) { + "use asm"; + var HEAP8 = new global.Int8Array(buffer); + var HEAP16 = new global.Int16Array(buffer); + var HEAP32 = new global.Int32Array(buffer); + var HEAPU8 = new global.Uint8Array(buffer); + var HEAPU16 = new global.Uint16Array(buffer); + var HEAPU32 = new global.Uint32Array(buffer); + var HEAPF32 = new global.Float32Array(buffer); + var HEAPF64 = new global.Float64Array(buffer); + var Math_imul = global.Math.imul; + var Math_fround = global.Math.fround; + var Math_abs = global.Math.abs; + var Math_clz32 = global.Math.clz32; + var Math_min = global.Math.min; + var Math_max = global.Math.max; + var Math_floor = global.Math.floor; + var Math_ceil = global.Math.ceil; + var Math_sqrt = global.Math.sqrt; + var abort = env.abort; + var nan = global.NaN; + var infinity = global.Infinity; + var syscall$6 = env.__syscall6; + var syscall$54 = env.__syscall54; + var global$0 = 5243904; + var i64toi32_i32$HIGH_BITS = 0; + // EMSCRIPTEN_START_FUNCS; + function main() { + var wasm2js_i32$0 = 0; + syscall$6(1 | 0, 2 | 0) | 0; + syscall$54(3 | 0, 4 | 0) | 0; + wasm2js_i32$0 = HEAP32[(0 + 1030 | 0) >> 2] | 0; + FUNCTION_TABLE_v[wasm2js_i32$0 & 3](); + } + + function other() { + main(); + } + + function foo() { + abort(); + } + + function bar() { + + } + + // EMSCRIPTEN_END_FUNCS; + var FUNCTION_TABLE_v = [foo, foo, bar, foo]; + return { + main: main, + other: other + }; +} + +return asmFunc( + { + 'env': asmLibraryArg, + 'global': { + 'Int8Array': Int8Array, + 'Int16Array': Int16Array, + 'Int32Array': Int32Array, + 'Uint8Array': Uint8Array, + 'Uint16Array': Uint16Array, + 'Uint32Array': Uint32Array, + 'Float32Array': Float32Array, + 'Float64Array': Float64Array, + 'NaN': NaN, + 'Infinity': Infinity, + 'Math': Math + } + }, + wasmMemory.buffer +) + +}
\ No newline at end of file diff --git a/test/wasm2js/emscripten.wast b/test/wasm2js/emscripten.wast new file mode 100644 index 000000000..82bf73548 --- /dev/null +++ b/test/wasm2js/emscripten.wast @@ -0,0 +1,32 @@ +(module + (type $0 (func)) + (import "env" "memory" (memory $8 256 256)) + (data (i32.const 1024) "hello, world!\n\00\00\9c\0c\00\00-+ 0X0x\00(null)\00\00\00\00\00\00\00\00\00\00\00\00\11\00\n\00\11\11\11\00\00\00\00\05\00\00\00\00\00\00\t\00\00\00\00\0b\00\00\00\00\00\00\00\00\11\00\0f\n\11\11\11\03\n\07\00\01\13\t\0b\0b\00\00\t\06\0b\00\00\0b\00\06\11\00\00\00\11\11\11\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0b\00\00\00\00\00\00\00\00\11\00\n\n\11\11\11\00\n\00\00\02\00\t\0b\00\00\00\t\00\0b\00\00\0b\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\0c\00\00\00\00\t\0c\00\00\00\00\00\0c\00\00\0c\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0e\00\00\00\00\00\00\00\00\00\00\00\0d\00\00\00\04\0d\00\00\00\00\t\0e\00\00\00\00\00\0e\00\00\0e\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\00\00\00\00\0f\00\00\00\00\0f\00\00\00\00\t\10\00\00\00\00\00\10\00\00\10\00\00\12\00\00\00\12\12\12\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\12\00\00\00\12\12\12\00\00\00\00\00\00\t\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0b\00\00\00\00\00\00\00\00\00\00\00\n\00\00\00\00\n\00\00\00\00\t\0b\00\00\00\00\00\0b\00\00\0b\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\00\00\00\00\00\00\00\0c\00\00\00\00\0c\00\00\00\00\t\0c\00\00\00\00\00\0c\00\00\0c\00\000123456789ABCDEF-0X+0X 0X-0x+0x 0x\00inf\00INF\00nan\00NAN\00.\00") + (data (i32.const 1600) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (import "env" "table" (table $timport$9 7 funcref)) + (elem (i32.const 1) $foo $bar) + (import "env" "__syscall6" (func $syscall$6 (param i32 i32) (result i32))) + (import "env" "__syscall54" (func $syscall$54 (param i32 i32) (result i32))) + (global $global$0 (mut i32) (i32.const 5243904)) + (export "main" (func $main)) + (export "other" (func $other)) + (func $main + (drop (call $syscall$6 (i32.const 1) (i32.const 2))) + (drop (call $syscall$54 (i32.const 3) (i32.const 4))) + (call_indirect (type $0) + (i32.load offset=1030 + (i32.const 0) + ) + ) + ) + (func $other + (call $main) + ) + (func $foo + (unreachable) + ) + (func $bar + (nop) + ) +) + |