diff options
-rw-r--r-- | src/asm2wasm.h | 14 | ||||
-rw-r--r-- | src/asm_v_wasm.h | 20 | ||||
-rw-r--r-- | src/wasm2asm.h | 27 | ||||
-rw-r--r-- | test/emcc_O2_hello_world.2asm.js | 16 | ||||
-rw-r--r-- | test/unit.2asm.js | 2 |
5 files changed, 56 insertions, 23 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 27f7edffb..dbf142fd3 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -233,23 +233,13 @@ private: } } - char getSigFromType(WasmType type) { - switch (type) { - case i32: return 'i'; - case f32: return 'f'; - case f64: return 'd'; - case none: return 'v'; - default: abort(); - } - } - FunctionType *getFunctionType(Ref parent, ExpressionList& operands) { // generate signature WasmType result = detectWasmType(parent, nullptr); std::string str = "FUNCSIG$"; - str += getSigFromType(result); + str += getSig(result); for (auto operand : operands) { - str += getSigFromType(operand->type); + str += getSig(operand->type); } IString sig(str.c_str(), false); if (wasm.functionTypesMap.find(sig) == wasm.functionTypesMap.end()) { diff --git a/src/asm_v_wasm.h b/src/asm_v_wasm.h index f59d51d25..323d255ee 100644 --- a/src/asm_v_wasm.h +++ b/src/asm_v_wasm.h @@ -27,7 +27,27 @@ AsmType wasmToAsmType(WasmType type) { abort(); } +char getSig(WasmType type) { + switch (type) { + case i32: return 'i'; + case f32: return 'f'; + case f64: return 'd'; + case none: return 'v'; + default: abort(); + } +} + +std::string getSig(FunctionType *type) { + // generate signature + std::string ret; + ret += getSig(type->result); + for (auto param : type->params) { + ret += getSig(param); + } + return ret; } +} // namespace wasm + #endif // _asm_v_wasm_h_ diff --git a/src/wasm2asm.h b/src/wasm2asm.h index 8f8025dfa..4fab55f86 100644 --- a/src/wasm2asm.h +++ b/src/wasm2asm.h @@ -143,6 +143,10 @@ public: return breakedWithValue.find(name) != breakedWithValue.end(); } + size_t getTableSize() { + return tableSize; + } + private: // How many temp vars we need std::vector<int> temps; // type => num temps @@ -155,6 +159,9 @@ private: // Label names to which we break with a value aka spooky-return-at-a-distance std::set<Name> breakedWithValue; + // All our function tables have the same size TODO: optimize? + size_t tableSize; + void addHeaps(Ref ast); }; @@ -166,7 +173,15 @@ Ref Wasm2AsmBuilder::processWasm(Module* wasm) { ValueBuilder::appendArgumentToFunction(asmFunc, ENV); ValueBuilder::appendArgumentToFunction(asmFunc, BUFFER); asmFunc[3]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeString(USE_ASM))); + // create heaps addHeaps(asmFunc[3]); + // figure out the table size + tableSize = wasm->table.names.size(); + size_t pow2ed = 1; + while (pow2ed < tableSize) { + pow2ed <<= 1; + } + tableSize = pow2ed; // imports XXX // exports XXX // functions @@ -638,9 +653,17 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { return visitCall(curr); } Ref visitCallIndirect(CallIndirect *curr) override { + std::string stable = std::string("FUNCTION_TABLE_") + getSig(curr->fullType); + IString table = IString(stable.c_str(), false); + auto makeTableCall = [&](Ref target) { + return ValueBuilder::makeCall(ValueBuilder::makeSub( + ValueBuilder::makeName(table), + ValueBuilder::makeBinary(target, AND, ValueBuilder::makeInt(parent->getTableSize()-1)) + )); + }; if (!isStatement(curr)) { // none of our operands is a statement; go right ahead and create a simple expression - Ref theCall = ValueBuilder::makeCall(ValueBuilder::makeSub(ValueBuilder::makeName(FUNCTION_TABLE), visit(curr->target, EXPRESSION_RESULT))); + Ref theCall = makeTableCall(visit(curr->target, EXPRESSION_RESULT)); for (auto operand : curr->operands) { theCall[2]->push_back(makeAsmCoercion(visit(operand, EXPRESSION_RESULT), wasmToAsmType(operand->type))); } @@ -650,7 +673,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { Ref ret = ValueBuilder::makeBlock(); ScopedTemp temp(i32, parent); flattenAppend(ret, visit(curr->target, temp)); - Ref theCall = ValueBuilder::makeCall(ValueBuilder::makeSub(ValueBuilder::makeName(FUNCTION_TABLE), temp.getAstName())); + Ref theCall = makeTableCall(temp.getAstName()); return makeStatementizedCall(curr->operands, ret, theCall, result, curr->type); } Ref visitGetLocal(GetLocal *curr) override { diff --git a/test/emcc_O2_hello_world.2asm.js b/test/emcc_O2_hello_world.2asm.js index 8d0394b7b..3c153067c 100644 --- a/test/emcc_O2_hello_world.2asm.js +++ b/test/emcc_O2_hello_world.2asm.js @@ -1896,7 +1896,7 @@ function asmFunc(global, env, buffer) { i4 = HEAPU32[i5 >> 2] | 0; i9 = i4; if (((i6 - i4 | 0) >>> 0 | 0) >>> 0 < (i2 >>> 0 | 0) >>> 0) { - i8 = FUNCTION_TABLE[((HEAPU32[(i3 + 36 | 0) >> 2] | 0) & 7 | 0) + 2 | 0](i3 | 0, i1 | 0, i2 | 0) | 0; + i8 = FUNCTION_TABLE_iiii[(((HEAPU32[(i3 + 36 | 0) >> 2] | 0) & 7 | 0) + 2 | 0) & 31](i3 | 0, i1 | 0, i2 | 0) | 0; break label$break$L5; } label$break$L10 : { @@ -1917,7 +1917,7 @@ function asmFunc(global, env, buffer) { } else i4 = i14; continue while_out$0; } while (0); - if (((FUNCTION_TABLE[((HEAPU32[(i3 + 36 | 0) >> 2] | 0) & 7 | 0) + 2 | 0](i3 | 0, i1 | 0, i15 | 0) | 0) >>> 0 | 0) >>> 0 < (i15 >>> 0 | 0) >>> 0) { + if (((FUNCTION_TABLE_iiii[(((HEAPU32[(i3 + 36 | 0) >> 2] | 0) & 7 | 0) + 2 | 0) & 31](i3 | 0, i1 | 0, i15 | 0) | 0) >>> 0 | 0) >>> 0 < (i15 >>> 0 | 0) >>> 0) { i8 = i15; break label$break$L5; } @@ -2076,7 +2076,7 @@ function asmFunc(global, env, buffer) { i10 = i11; break do_once$0; } - if ((FUNCTION_TABLE[((HEAPU32[(i1 + 36 | 0) >> 2] | 0) & 7 | 0) + 2 | 0](i1 | 0, i4 | 0, 1 | 0) | 0 | 0) == (1 | 0)) i10 = HEAPU8[i4 >> 0] | 0; else i10 = 4294967295; + if ((FUNCTION_TABLE_iiii[(((HEAPU32[(i1 + 36 | 0) >> 2] | 0) & 7 | 0) + 2 | 0) & 31](i1 | 0, i4 | 0, 1 | 0) | 0 | 0) == (1 | 0)) i10 = HEAPU8[i4 >> 0] | 0; else i10 = 4294967295; } } HEAP32[8 >> 2] = i3; @@ -2092,7 +2092,7 @@ function asmFunc(global, env, buffer) { i2 = i1 + 20 | 0; i3 = i1 + 28 | 0; if (((HEAPU32[i2 >> 2] | 0) >>> 0 | 0) >>> 0 > ((HEAPU32[i3 >> 2] | 0) >>> 0 | 0) >>> 0) { - FUNCTION_TABLE[((HEAPU32[(i1 + 36 | 0) >> 2] | 0) & 7 | 0) + 2 | 0](i1 | 0, 0 | 0, 0 | 0) | 0; + FUNCTION_TABLE_iiii[(((HEAPU32[(i1 + 36 | 0) >> 2] | 0) & 7 | 0) + 2 | 0) & 31](i1 | 0, 0 | 0, 0 | 0) | 0; wasm2asm_i32$1 = (HEAPU32[i2 >> 2] | 0 | 0) == (0 | 0); } else wasm2asm_i32$1 = 0; if (wasm2asm_i32$1) i4 = 4294967295; else { @@ -2100,7 +2100,7 @@ function asmFunc(global, env, buffer) { i6 = HEAPU32[i5 >> 2] | 0; i7 = i1 + 8 | 0; i8 = HEAPU32[i7 >> 2] | 0; - if ((i6 >>> 0 | 0) >>> 0 < (i8 >>> 0 | 0) >>> 0) FUNCTION_TABLE[((HEAPU32[(i1 + 40 | 0) >> 2] | 0) & 7 | 0) + 2 | 0](i1 | 0, i6 - i8 | 0 | 0, 1 | 0) | 0; + if ((i6 >>> 0 | 0) >>> 0 < (i8 >>> 0 | 0) >>> 0) FUNCTION_TABLE_iiii[(((HEAPU32[(i1 + 40 | 0) >> 2] | 0) & 7 | 0) + 2 | 0) & 31](i1 | 0, i6 - i8 | 0 | 0, 1 | 0) | 0; HEAP32[(i1 + 16 | 0) >> 2] = 0; HEAP32[i3 >> 2] = 0; HEAP32[i2 >> 2] = 0; @@ -2379,7 +2379,7 @@ function asmFunc(global, env, buffer) { i2 = i2 | 0; i3 = i3 | 0; i4 = i4 | 0; - return FUNCTION_TABLE[(i1 & 7 | 0) + 2 | 0](i2 | 0, i3 | 0, i4 | 0) | 0 | 0; + return FUNCTION_TABLE_iiii[((i1 & 7 | 0) + 2 | 0) & 31](i2 | 0, i3 | 0, i4 | 0) | 0 | 0; } function stackAlloc(i1) { @@ -2421,7 +2421,7 @@ function asmFunc(global, env, buffer) { function dynCall_ii(i1, i2) { i1 = i1 | 0; i2 = i2 | 0; - return FUNCTION_TABLE[(i1 & 1 | 0) + 0 | 0](i2 | 0) | 0 | 0; + return FUNCTION_TABLE_ii[((i1 & 1 | 0) + 0 | 0) & 31](i2 | 0) | 0 | 0; } function _cleanup_418(i1) { @@ -2442,7 +2442,7 @@ function asmFunc(global, env, buffer) { function dynCall_vi(i1, i2) { i1 = i1 | 0; i2 = i2 | 0; - FUNCTION_TABLE[(i1 & 7 | 0) + 10 | 0](i2 | 0) + FUNCTION_TABLE_vi[((i1 & 7 | 0) + 10 | 0) & 31](i2 | 0) } function b1(i1, i2, i3) { diff --git a/test/unit.2asm.js b/test/unit.2asm.js index c33736a61..1dfc7f32b 100644 --- a/test/unit.2asm.js +++ b/test/unit.2asm.js @@ -193,7 +193,7 @@ function asmFunc(global, env, buffer) { function neg() { var x = Math_fround(0); x = Math_fround(-x); - FUNCTION_TABLE[(1 & 7 | 0) + 8 | 0](Math_fround(x)); + FUNCTION_TABLE_vf[((1 & 7 | 0) + 8 | 0) & 15](Math_fround(x)); } function ___syscall_ret() { |