summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-11-19 17:46:48 -0800
committerAlon Zakai <alonzakai@gmail.com>2015-11-19 17:46:48 -0800
commitf7070e21f92a2fedb61bdc9fa1f28a092852d7aa (patch)
treeac715be107efefc5a2198853ecef1c0820df7839 /src
parentc233b37837dd8a1a768741b19ab8221384d4441e (diff)
downloadbinaryen-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.h89
-rw-r--r--src/wasm-js.cpp24
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;