summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asm2wasm.h14
-rw-r--r--src/asm_v_wasm.h20
-rw-r--r--src/wasm2asm.h27
-rw-r--r--test/emcc_O2_hello_world.2asm.js16
-rw-r--r--test/unit.2asm.js2
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() {