diff options
author | Alon Zakai <alonzakai@gmail.com> | 2015-12-01 16:17:19 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2015-12-01 16:53:19 -0800 |
commit | e7707396ea86ded822848b0fb40b8b1180ac4a84 (patch) | |
tree | cedae051586df3505db1d66546edbae8d7ce4855 | |
parent | e0cff3c71ffa5683173f968641bd78e6014cd5e3 (diff) | |
download | binaryen-e7707396ea86ded822848b0fb40b8b1180ac4a84.tar.gz binaryen-e7707396ea86ded822848b0fb40b8b1180ac4a84.tar.bz2 binaryen-e7707396ea86ded822848b0fb40b8b1180ac4a84.zip |
refactoring, and wasm2asm arags and locals
-rw-r--r-- | src/asm2wasm.h | 24 | ||||
-rw-r--r-- | src/asm_v_wasm.h | 33 | ||||
-rw-r--r-- | src/emscripten-optimizer/optimizer-shared.cpp | 52 | ||||
-rw-r--r-- | src/emscripten-optimizer/optimizer.h | 3 | ||||
-rw-r--r-- | src/emscripten-optimizer/simple_ast.h | 67 | ||||
-rw-r--r-- | src/wasm2asm.h | 33 |
6 files changed, 177 insertions, 35 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 51536663d..7785ece5a 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -8,6 +8,7 @@ #include "emscripten-optimizer/optimizer.h" #include "mixed_arena.h" #include "shared-constants.h" +#include "asm_v_wasm.h" namespace wasm { @@ -271,29 +272,6 @@ public: void optimize(); private: - WasmType asmToWasmType(AsmType asmType) { - switch (asmType) { - case ASM_INT: return WasmType::i32; - case ASM_DOUBLE: return WasmType::f64; - case ASM_FLOAT: return WasmType::f32; - case ASM_NONE: return WasmType::none; - default: {} - } - abort_on("confused asmType", asmType); - return (WasmType)-1; // avoid warning - } - AsmType wasmToAsmType(WasmType type) { - switch (type) { - case WasmType::i32: return ASM_INT; - case WasmType::f32: return ASM_FLOAT; - case WasmType::f64: return ASM_DOUBLE; - case WasmType::none: return ASM_NONE; - default: {} - } - abort_on("confused wasmType", type); - return (AsmType)-1; // avoid warning - } - AsmType detectAsmType(Ref ast, AsmData *data) { if (ast[0] == NAME) { IString name = ast[1]->getIString(); diff --git a/src/asm_v_wasm.h b/src/asm_v_wasm.h new file mode 100644 index 000000000..f59d51d25 --- /dev/null +++ b/src/asm_v_wasm.h @@ -0,0 +1,33 @@ +#ifndef _asm_v_wasm_h_ +#define _asm_v_wasm_h_ + +#include "emscripten-optimizer/optimizer.h" + +namespace wasm { + +WasmType asmToWasmType(AsmType asmType) { + switch (asmType) { + case ASM_INT: return WasmType::i32; + case ASM_DOUBLE: return WasmType::f64; + case ASM_FLOAT: return WasmType::f32; + case ASM_NONE: return WasmType::none; + default: {} + } + abort(); +} + +AsmType wasmToAsmType(WasmType type) { + switch (type) { + case WasmType::i32: return ASM_INT; + case WasmType::f32: return ASM_FLOAT; + case WasmType::f64: return ASM_DOUBLE; + case WasmType::none: return ASM_NONE; + default: {} + } + abort(); +} + +} + +#endif // _asm_v_wasm_h_ + diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp index 6a8bbf9b5..09b458138 100644 --- a/src/emscripten-optimizer/optimizer-shared.cpp +++ b/src/emscripten-optimizer/optimizer-shared.cpp @@ -176,3 +176,55 @@ AsmSign detectSign(Ref node, IString minifiedFround) { abort(); // avoid warning } +Ref makeAsmCoercedZero(AsmType type) { + switch (type) { + case ASM_INT: return ValueBuilder::makeNum(0); break; + case ASM_DOUBLE: return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeNum(0)); break; + case ASM_FLOAT: { + if (!ASM_FLOAT_ZERO.isNull()) { + return ValueBuilder::makeName(ASM_FLOAT_ZERO); + } else { + return ValueBuilder::makeCall(MATH_FROUND, ValueBuilder::makeNum(0)); + } + break; + } + case ASM_FLOAT32X4: { + return ValueBuilder::makeCall(SIMD_FLOAT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + break; + } + case ASM_FLOAT64X2: { + return ValueBuilder::makeCall(SIMD_FLOAT64X2, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + break; + } + case ASM_INT8X16: { + return ValueBuilder::makeCall(SIMD_INT8X16, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + break; + } + case ASM_INT16X8: { + return ValueBuilder::makeCall(SIMD_INT16X8, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + break; + } + case ASM_INT32X4: { + return ValueBuilder::makeCall(SIMD_INT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); + break; + } + default: assert(0); + } + abort(); +} + +Ref makeAsmCoercion(Ref node, AsmType type) { + switch (type) { + case ASM_INT: return ValueBuilder::makeBinary(node, OR, ValueBuilder::makeNum(0)); + case ASM_DOUBLE: return ValueBuilder::makeUnary(PLUS, node); + case ASM_FLOAT: return ValueBuilder::makeCall(MATH_FROUND, node); + case ASM_FLOAT32X4: return ValueBuilder::makeCall(SIMD_FLOAT32X4_CHECK, node); + case ASM_FLOAT64X2: return ValueBuilder::makeCall(SIMD_FLOAT64X2_CHECK, node); + case ASM_INT8X16: return ValueBuilder::makeCall(SIMD_INT8X16_CHECK, node); + case ASM_INT16X8: return ValueBuilder::makeCall(SIMD_INT16X8_CHECK, node); + case ASM_INT32X4: return ValueBuilder::makeCall(SIMD_INT32X4_CHECK, node); + case ASM_NONE: + default: return node; // non-validating code, emit nothing XXX this is dangerous, we should only allow this when we know we are not validating + } +} + diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h index 12d0671eb..00303aee9 100644 --- a/src/emscripten-optimizer/optimizer.h +++ b/src/emscripten-optimizer/optimizer.h @@ -137,5 +137,8 @@ inline cashew::Ref deStat(cashew::Ref node) { return node; } +cashew::Ref makeAsmCoercedZero(AsmType type); +cashew::Ref makeAsmCoercion(cashew::Ref node, AsmType type); + #endif // __optimizer_h__ diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h index f2607315a..e4964ce50 100644 --- a/src/emscripten-optimizer/simple_ast.h +++ b/src/emscripten-optimizer/simple_ast.h @@ -1289,15 +1289,15 @@ class ValueBuilder { return &arena.alloc()->setString(s); } - static Ref makeRawArray(int size_hint=0) { - return &arena.alloc()->setArray(size_hint); - } - static Ref makeNull() { return &arena.alloc()->setNull(); } public: + static Ref makeRawArray(int size_hint=0) { + return &arena.alloc()->setArray(size_hint); + } + static Ref makeToplevel() { return &makeRawArray(2)->push_back(makeRawString(TOPLEVEL)) .push_back(makeRawArray()); @@ -1345,16 +1345,62 @@ public: static Ref makeCall(IString target, Ref arg) { Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL)) .push_back(makeName(target)) - .push_back(makeRawArray()); + .push_back(makeRawArray(1)); ret[2]->push_back(arg); return ret; } static Ref makeCall(IString target, Ref arg1, Ref arg2) { Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL)) .push_back(makeName(target)) - .push_back(makeRawArray()); + .push_back(makeRawArray(2)); + ret[2]->push_back(arg1); + ret[2]->push_back(arg2); + return ret; + } + static Ref makeCall(IString target, Ref arg1, Ref arg2, Ref arg3, Ref arg4) { + Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL)) + .push_back(makeName(target)) + .push_back(makeRawArray(4)); + ret[2]->push_back(arg1); + ret[2]->push_back(arg2); + ret[2]->push_back(arg3); + ret[2]->push_back(arg4); + return ret; + } + static Ref makeCall(IString target, Ref arg1, Ref arg2, Ref arg3, Ref arg4, Ref arg5, Ref arg6, Ref arg7, Ref arg8) { + Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL)) + .push_back(makeName(target)) + .push_back(makeRawArray(8)); ret[2]->push_back(arg1); ret[2]->push_back(arg2); + ret[2]->push_back(arg3); + ret[2]->push_back(arg4); + ret[2]->push_back(arg5); + ret[2]->push_back(arg6); + ret[2]->push_back(arg7); + ret[2]->push_back(arg8); + return ret; + } + static Ref makeCall(IString target, Ref arg1, Ref arg2, Ref arg3, Ref arg4, Ref arg5, Ref arg6, Ref arg7, Ref arg8, Ref arg9, Ref arg10, Ref arg11, Ref arg12, Ref arg13, Ref arg14, Ref arg15, Ref arg16) { + Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL)) + .push_back(makeName(target)) + .push_back(makeRawArray(16)); + ret[2]->push_back(arg1); + ret[2]->push_back(arg2); + ret[2]->push_back(arg3); + ret[2]->push_back(arg4); + ret[2]->push_back(arg5); + ret[2]->push_back(arg6); + ret[2]->push_back(arg7); + ret[2]->push_back(arg8); + ret[2]->push_back(arg9); + ret[2]->push_back(arg10); + ret[2]->push_back(arg11); + ret[2]->push_back(arg12); + ret[2]->push_back(arg13); + ret[2]->push_back(arg14); + ret[2]->push_back(arg15); + ret[2]->push_back(arg16); return ret; } @@ -1379,6 +1425,15 @@ public: static Ref makeInt(uint32_t num) { return makeDouble(double(num)); } + static Ref makeNum(double num) { + return makeDouble(num); + } + + static Ref makeUnary(IString op, Ref value) { + return &makeRawArray(3)->push_back(makeRawString(UNARY_PREFIX)) + .push_back(makeRawString(op)) + .push_back(value); + } static Ref makeBinary(Ref left, IString op, Ref right) { if (op == SET) { diff --git a/src/wasm2asm.h b/src/wasm2asm.h index ce9f378ac..a52de4de1 100644 --- a/src/wasm2asm.h +++ b/src/wasm2asm.h @@ -7,6 +7,7 @@ #include "wasm.h" #include "emscripten-optimizer/optimizer.h" #include "mixed_arena.h" +#include "asm_v_wasm.h" namespace wasm { @@ -65,11 +66,7 @@ IString ASM_FUNC("asmFunc"), class Wasm2AsmBuilder { - MixedArena& allocator; - public: - Asm2WasmBuilder(MixedArena& allocator) : allocator(allocator) {} - Ref processWasm(Module* wasm); Ref processFunction(Function* func); @@ -155,13 +152,37 @@ Ref Wasm2AsmBuilder::processFunction(Function* func) { temps.clear(); temps.resize(std::max(i32, std::max(f32, f64))); temps[i32] = temps[f32] = temps[f64] = 0; - // arguments XXX + // arguments + for (auto& param : func->params) { + IString name = fromName(param.name) + ret[2]->push_back(name); + ret[3]->push_back( + ValueBuilder::makeAssign( + ValueBuilder::makeName(name), + makeAsmCoercion(ValueBuilder::makeName(name), wasmToAsmType(param.type)) + ) + ); + } + Ref theVar = ValueBuilder::makeVar(); + ret[3]->push_back(theVar); // body scanFunctionBody(func->body); IString result = func->result != none ? getTemp(func->result) : NO_RESULT; ret[3]->push_back(processFunctionBody(func->body, result)); if (result != NO_RESULT) freeTemp(func->result, result); - // locals, including new temp locals XXX + // locals, including new temp locals + for (auto& local : func->locals) { + ValueBuilder::appendToVar(theVar, fromName(local.name), makeAsmCoercedZero(wasmToAsmType(param.type)); + } + for (auto free : frees[i32]) { + ValueBuilder::appendToVar(theVar, free, makeAsmCoercedZero(i32)); + } + for (auto free : frees[f32]) { + ValueBuilder::appendToVar(theVar, free, makeAsmCoercedZero(f32)); + } + for (auto free : frees[f64]) { + ValueBuilder::appendToVar(theVar, free, makeAsmCoercedZero(f64)); + } // checks assert(frees[i32].size() == temps[i32]); // all temp vars should be free at the end assert(frees[f32].size() == temps[f32]); // all temp vars should be free at the end |