diff options
author | Alon Zakai <alonzakai@gmail.com> | 2015-11-19 17:46:48 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2015-11-19 17:46:48 -0800 |
commit | f7070e21f92a2fedb61bdc9fa1f28a092852d7aa (patch) | |
tree | ac715be107efefc5a2198853ecef1c0820df7839 /src | |
parent | c233b37837dd8a1a768741b19ab8221384d4441e (diff) | |
download | binaryen-f7070e21f92a2fedb61bdc9fa1f28a092852d7aa.tar.gz binaryen-f7070e21f92a2fedb61bdc9fa1f28a092852d7aa.tar.bz2 binaryen-f7070e21f92a2fedb61bdc9fa1f28a092852d7aa.zip |
start to parse asm.js memory growth code
Diffstat (limited to 'src')
-rw-r--r-- | src/asm2wasm.h | 89 | ||||
-rw-r--r-- | src/wasm-js.cpp | 24 |
2 files changed, 94 insertions, 19 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index d34fe882f..7dcc0385b 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -473,6 +473,8 @@ void Asm2WasmBuilder::processAsm(Ref ast) { } }; + IString Int8Array, Int16Array, Int32Array, UInt8Array, UInt16Array, UInt32Array, Float32Array, Float64Array; + // first pass - do almost everything, but function imports and indirect calls for (unsigned i = 1; i < body->size(); i++) { @@ -508,34 +510,83 @@ void Asm2WasmBuilder::processAsm(Ref ast) { assert(value[1][0] == NAME && value[1][1] == Math_fround && value[2][0][0] == NUM && value[2][0][1]->getNumber() == 0); allocateGlobal(name, WasmType::f32, false); } else if (value[0] == DOT) { + // simple module.base import. can be a view, or a function. + if (value[1][0] == NAME) { + IString module = value[1][1]->getIString(); + IString base = value[2]->getIString(); + if (module == GLOBAL) { + if (base == INT8ARRAY) { + Int8Array = name; + } else if (base == INT16ARRAY) { + Int16Array = name; + } else if (base == INT32ARRAY) { + Int32Array = name; + } else if (base == UINT8ARRAY) { + UInt8Array = name; + } else if (base == UINT16ARRAY) { + UInt16Array = name; + } else if (base == UINT32ARRAY) { + UInt32Array = name; + } else if (base == FLOAT32ARRAY) { + Float32Array = name; + } else if (base == FLOAT64ARRAY) { + Float64Array = name; + } + } + } // function import addImport(name, value, WasmType::none); } else if (value[0] == NEW) { // ignore imports of typed arrays, but note the names of the arrays value = value[1]; assert(value[0] == CALL); - Ref constructor = value[1]; - assert(constructor[0] == DOT); // global.*Array - IString heap = constructor[2]->getIString(); unsigned bytes; bool integer, signed_; AsmType asmType; - if (heap == INT8ARRAY) { - bytes = 1; integer = true; signed_ = true; asmType = ASM_INT; - } else if (heap == INT16ARRAY) { - bytes = 2; integer = true; signed_ = true; asmType = ASM_INT; - } else if (heap == INT32ARRAY) { - bytes = 4; integer = true; signed_ = true; asmType = ASM_INT; - } else if (heap == UINT8ARRAY) { - bytes = 1; integer = true; signed_ = false; asmType = ASM_INT; - } else if (heap == UINT16ARRAY) { - bytes = 2; integer = true; signed_ = false; asmType = ASM_INT; - } else if (heap == UINT32ARRAY) { - bytes = 4; integer = true; signed_ = false; asmType = ASM_INT; - } else if (heap == FLOAT32ARRAY) { - bytes = 4; integer = false; signed_ = true; asmType = ASM_FLOAT; - } else if (heap == FLOAT64ARRAY) { - bytes = 8; integer = false; signed_ = true; asmType = ASM_DOUBLE; + Ref constructor = value[1]; + if (constructor[0] == DOT) { // global.*Array + IString heap = constructor[2]->getIString(); + if (heap == INT8ARRAY) { + bytes = 1; integer = true; signed_ = true; asmType = ASM_INT; + } else if (heap == INT16ARRAY) { + bytes = 2; integer = true; signed_ = true; asmType = ASM_INT; + } else if (heap == INT32ARRAY) { + bytes = 4; integer = true; signed_ = true; asmType = ASM_INT; + } else if (heap == UINT8ARRAY) { + bytes = 1; integer = true; signed_ = false; asmType = ASM_INT; + } else if (heap == UINT16ARRAY) { + bytes = 2; integer = true; signed_ = false; asmType = ASM_INT; + } else if (heap == UINT32ARRAY) { + bytes = 4; integer = true; signed_ = false; asmType = ASM_INT; + } else if (heap == FLOAT32ARRAY) { + bytes = 4; integer = false; signed_ = true; asmType = ASM_FLOAT; + } else if (heap == FLOAT64ARRAY) { + bytes = 8; integer = false; signed_ = true; asmType = ASM_DOUBLE; + } else { + abort_on("invalid view import", heap); + } + } else { // *ArrayView that was previously imported + assert(constructor[0] == NAME); + IString viewName = constructor[1]->getIString(); + if (viewName == Int8Array) { + bytes = 1; integer = true; signed_ = true; asmType = ASM_INT; + } else if (viewName == Int16Array) { + bytes = 2; integer = true; signed_ = true; asmType = ASM_INT; + } else if (viewName == Int32Array) { + bytes = 4; integer = true; signed_ = true; asmType = ASM_INT; + } else if (viewName == UInt8Array) { + bytes = 1; integer = true; signed_ = false; asmType = ASM_INT; + } else if (viewName == UInt16Array) { + bytes = 2; integer = true; signed_ = false; asmType = ASM_INT; + } else if (viewName == UInt32Array) { + bytes = 4; integer = true; signed_ = false; asmType = ASM_INT; + } else if (viewName == Float32Array) { + bytes = 4; integer = false; signed_ = true; asmType = ASM_FLOAT; + } else if (viewName == Float64Array) { + bytes = 8; integer = false; signed_ = true; asmType = ASM_DOUBLE; + } else { + abort_on("invalid short view import", viewName); + } } assert(views.find(name) == views.end()); views.emplace(name, View(bytes, integer, signed_, asmType)); diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp index 218fd993c..2f9ac639f 100644 --- a/src/wasm-js.cpp +++ b/src/wasm-js.cpp @@ -52,6 +52,30 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_asm(char *input) { end--; } + // asm.js memory growth uses a quite elaborate pattern. Instead of parsing and + // matching it, we do a simpler detection on emscripten's asm.js output format + bool memoryGrowth = false; + const char* START_FUNCS = "// EMSCRIPTEN_START_FUNCS"; + char *marker = strstr(input, START_FUNCS); + assert(marker && "must have '// EMSCRIPTEN_START_FUNCS' marker (for now)"); + *marker = 0; // look for memory growth code just up to here + char *growthSign = strstr(input, "return true;"); // this can only show up in growth code, as normal asm.js lacks "true" + if (growthSign) { + memoryGrowth = true; + // clean out this function, we don't need it + char *growthFuncStart = strstr(input, "function "); + assert(strstr(growthFuncStart + 1, "function ") == 0); // should be only this one function in this area, so no confusion for us + char *growthFuncEnd = strchr(growthSign, '}'); + assert(growthFuncEnd > growthFuncStart + 5); + growthFuncStart[0] = '/'; + growthFuncStart[1] = '*'; + growthFuncEnd--; + growthFuncEnd[0] = '*'; + growthFuncEnd[1] = '/'; + } + *marker = START_FUNCS[0]; + + // proceed to parse and wasmify if (wasmJSDebug) std::cerr << "parsing...\n"; cashew::Parser<Ref, DotZeroValueBuilder> builder; |