summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-12-07 13:59:59 -0800
committerAlon Zakai <alonzakai@gmail.com>2015-12-07 14:03:43 -0800
commit09771ea21a3f30ade4a8abb7482fdd3b6eaaba7a (patch)
tree6b4ce653edc13318b758db60417d68f714623bae /src
parent43ddf341c47350db98618c49a5d0acb0af6960ab (diff)
downloadbinaryen-09771ea21a3f30ade4a8abb7482fdd3b6eaaba7a.tar.gz
binaryen-09771ea21a3f30ade4a8abb7482fdd3b6eaaba7a.tar.bz2
binaryen-09771ea21a3f30ade4a8abb7482fdd3b6eaaba7a.zip
emit function table calls in wasm2asm
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h14
-rw-r--r--src/asm_v_wasm.h20
-rw-r--r--src/wasm2asm.h27
3 files changed, 47 insertions, 14 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 {