summaryrefslogtreecommitdiff
path: root/src/asm2wasm.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/asm2wasm.h')
-rw-r--r--src/asm2wasm.h174
1 files changed, 105 insertions, 69 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index fa3a3dd4c..f413cbe9e 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -57,8 +57,6 @@ Name I64("i64"),
I64_SHL("i64_shl"),
I64_ASHR("i64_ashr"),
I64_LSHR("i64_lshr"),
- I64_LOAD("i64_load"),
- I64_STORE("i64_store"),
I64_EQ("i64_eq"),
I64_NE("i64_ne"),
I64_ULE("i64_ule"),
@@ -87,7 +85,21 @@ Name I64("i64"),
I64S_REM("i64s-rem"),
I64U_REM("i64u-rem"),
I64S_DIV("i64s-div"),
- I64U_DIV("i64u-div");
+ I64U_DIV("i64u-div"),
+ LOAD1("load1"),
+ LOAD2("load2"),
+ LOAD4("load4"),
+ LOAD8("load8"),
+ LOADF("loadf"),
+ LOADD("loadd"),
+ STORE1("store1"),
+ STORE2("store2"),
+ STORE4("store4"),
+ STORE8("store8"),
+ STOREF("storef"),
+ STORED("stored"),
+ I32_BC2F("i32_bc2f"),
+ I32_BC2I("i32_bc2i");
// Utilities
@@ -421,10 +433,6 @@ private:
return -1; // avoid warning
}
- bool maybeWasmInt64Intrinsic(Name name) {
- return strncmp(name.str, "i64", 3) == 0;
- }
-
std::map<unsigned, Ref> tempNums;
Literal checkLiteral(Ref ast) {
@@ -806,7 +814,6 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
} else if (key == GET_TEMP_RET0) {
getTempRet0 = value;
}
- assert(wasm.checkFunction(value));
if (exported.count(key) > 0) {
// asm.js allows duplicate exports, but not wasm. use the last, like asm.js
exported[key]->value = value;
@@ -874,10 +881,6 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
void visitCall(Call* curr) {
if (!getModule()->checkFunction(curr->target)) {
std::cerr << "invalid call target: " << curr->target << '\n';
- if (parent->maybeWasmInt64Intrinsic(curr->target)) {
- std::cerr << " - perhaps this is a wasm-only i64() method, and you should run asm2wasm with --wasm-only?\n";
- if (parent->wasmOnly) std::cerr << " - wait, you *did*. so this is an internal compiler error, please file an issue!\n";
- }
WASM_UNREACHABLE();
}
auto result = getModule()->getFunction(curr->target)->result;
@@ -1532,66 +1535,99 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
}
return ret;
}
- if (wasmOnly && maybeWasmInt64Intrinsic(name)) {
+ if (wasmOnly) {
auto num = ast[2]->size();
- if (num == 1) {
- auto* value = process(ast[2][0]);
- if (name == I64) {
- // no-op "coercion" / "cast", although we also tolerate i64(0) for constants that fit in i32
- if (value->type == i32) {
- return builder.makeConst(Literal(int64_t(value->cast<Const>()->value.geti32())));
- } else {
- fixCallType(value, i64);
- return value;
+ switch (name.str[0]) {
+ case 'l': {
+ auto align = num == 2 ? ast[2][1][1]->getInteger() : 0;
+ if (name == LOAD1) return builder.makeLoad(1, true, 0, 1, process(ast[2][0]), i32);
+ if (name == LOAD2) return builder.makeLoad(2, true, 0, indexOr(align, 2), process(ast[2][0]), i32);
+ if (name == LOAD4) return builder.makeLoad(4, true, 0, indexOr(align, 4), process(ast[2][0]), i32);
+ if (name == LOAD8) return builder.makeLoad(8, true, 0, indexOr(align, 8), process(ast[2][0]), i64);
+ if (name == LOADF) return builder.makeLoad(4, true, 0, indexOr(align, 4), process(ast[2][0]), f32);
+ if (name == LOADD) return builder.makeLoad(8, true, 0, indexOr(align, 8), process(ast[2][0]), f64);
+ break;
+ }
+ case 's': {
+ auto align = num == 3 ? ast[2][2][1]->getInteger() : 0;
+ if (name == STORE1) return builder.makeStore(1, 0, 1, process(ast[2][0]), process(ast[2][1]), i32);
+ if (name == STORE2) return builder.makeStore(2, 0, indexOr(align, 2), process(ast[2][0]), process(ast[2][1]), i32);
+ if (name == STORE4) return builder.makeStore(4, 0, indexOr(align, 4), process(ast[2][0]), process(ast[2][1]), i32);
+ if (name == STORE8) return builder.makeStore(8, 0, indexOr(align, 8), process(ast[2][0]), process(ast[2][1]), i64);
+ if (name == STOREF) {
+ auto* value = process(ast[2][1]);
+ if (value->type == f64) {
+ // asm.js allows storing a double to HEAPF32, we must cast here
+ value = builder.makeUnary(DemoteFloat64, value);
+ }
+ return builder.makeStore(4, 0, indexOr(align, 4), process(ast[2][0]), value, f32);
}
+ if (name == STORED) return builder.makeStore(8, 0, indexOr(align, 8), process(ast[2][0]), process(ast[2][1]), f64);
+ break;
+ }
+ case 'i': {
+ if (num == 1) {
+ auto* value = process(ast[2][0]);
+ if (name == I64) {
+ // no-op "coercion" / "cast", although we also tolerate i64(0) for constants that fit in i32
+ if (value->type == i32) {
+ return builder.makeConst(Literal(int64_t(value->cast<Const>()->value.geti32())));
+ } else {
+ fixCallType(value, i64);
+ return value;
+ }
+ }
+ if (name == I32_BC2F) return builder.makeUnary(UnaryOp::ReinterpretInt32, value);
+ if (name == I32_BC2I) return builder.makeUnary(UnaryOp::ReinterpretFloat32, value);
+
+ if (name == I64_TRUNC) return builder.makeUnary(UnaryOp::WrapInt64, value);
+ if (name == I64_SEXT) return builder.makeUnary(UnaryOp::ExtendSInt32, value);
+ if (name == I64_ZEXT) return builder.makeUnary(UnaryOp::ExtendUInt32, value);
+ if (name == I64_S2F) return builder.makeUnary(UnaryOp::ConvertSInt64ToFloat32, value);
+ if (name == I64_S2D) return builder.makeUnary(UnaryOp::ConvertSInt64ToFloat64, value);
+ if (name == I64_U2F) return builder.makeUnary(UnaryOp::ConvertUInt64ToFloat32, value);
+ if (name == I64_U2D) return builder.makeUnary(UnaryOp::ConvertUInt64ToFloat64, value);
+ if (name == I64_F2S) return builder.makeUnary(UnaryOp::TruncSFloat32ToInt64, value);
+ if (name == I64_D2S) return builder.makeUnary(UnaryOp::TruncSFloat64ToInt64, value);
+ if (name == I64_F2U) return builder.makeUnary(UnaryOp::TruncUFloat32ToInt64, value);
+ if (name == I64_D2U) return builder.makeUnary(UnaryOp::TruncUFloat64ToInt64, value);
+ if (name == I64_BC2D) return builder.makeUnary(UnaryOp::ReinterpretInt64, value);
+ if (name == I64_BC2I) return builder.makeUnary(UnaryOp::ReinterpretFloat64, value);
+ if (name == I64_CTTZ) return builder.makeUnary(UnaryOp::CtzInt64, value);
+ if (name == I64_CTLZ) return builder.makeUnary(UnaryOp::ClzInt64, value);
+ } else if (num == 2) { // 2 params,binary
+ if (name == I64_CONST) return builder.makeConst(getLiteral(ast));
+ auto* left = process(ast[2][0]);
+ auto* right = process(ast[2][1]);
+ // maths
+ if (name == I64_ADD) return builder.makeBinary(BinaryOp::AddInt64, left, right);
+ if (name == I64_SUB) return builder.makeBinary(BinaryOp::SubInt64, left, right);
+ if (name == I64_MUL) return builder.makeBinary(BinaryOp::MulInt64, left, right);
+ if (name == I64_UDIV) return makeDangerousI64Binary(BinaryOp::DivUInt64, left, right);
+ if (name == I64_SDIV) return makeDangerousI64Binary(BinaryOp::DivSInt64, left, right);
+ if (name == I64_UREM) return makeDangerousI64Binary(BinaryOp::RemUInt64, left, right);
+ if (name == I64_SREM) return makeDangerousI64Binary(BinaryOp::RemSInt64, left, right);
+ if (name == I64_AND) return builder.makeBinary(BinaryOp::AndInt64, left, right);
+ if (name == I64_OR) return builder.makeBinary(BinaryOp::OrInt64, left, right);
+ if (name == I64_XOR) return builder.makeBinary(BinaryOp::XorInt64, left, right);
+ if (name == I64_SHL) return builder.makeBinary(BinaryOp::ShlInt64, left, right);
+ if (name == I64_ASHR) return builder.makeBinary(BinaryOp::ShrSInt64, left, right);
+ if (name == I64_LSHR) return builder.makeBinary(BinaryOp::ShrUInt64, left, right);
+ // comps
+ if (name == I64_EQ) return builder.makeBinary(BinaryOp::EqInt64, left, right);
+ if (name == I64_NE) return builder.makeBinary(BinaryOp::NeInt64, left, right);
+ if (name == I64_ULE) return builder.makeBinary(BinaryOp::LeUInt64, left, right);
+ if (name == I64_SLE) return builder.makeBinary(BinaryOp::LeSInt64, left, right);
+ if (name == I64_UGE) return builder.makeBinary(BinaryOp::GeUInt64, left, right);
+ if (name == I64_SGE) return builder.makeBinary(BinaryOp::GeSInt64, left, right);
+ if (name == I64_ULT) return builder.makeBinary(BinaryOp::LtUInt64, left, right);
+ if (name == I64_SLT) return builder.makeBinary(BinaryOp::LtSInt64, left, right);
+ if (name == I64_UGT) return builder.makeBinary(BinaryOp::GtUInt64, left, right);
+ if (name == I64_SGT) return builder.makeBinary(BinaryOp::GtSInt64, left, right);
+ }
+ break;
}
- if (name == I64_TRUNC) return builder.makeUnary(UnaryOp::WrapInt64, value);
- if (name == I64_SEXT) return builder.makeUnary(UnaryOp::ExtendSInt32, value);
- if (name == I64_ZEXT) return builder.makeUnary(UnaryOp::ExtendUInt32, value);
- if (name == I64_S2F) return builder.makeUnary(UnaryOp::ConvertSInt64ToFloat32, value);
- if (name == I64_S2D) return builder.makeUnary(UnaryOp::ConvertSInt64ToFloat64, value);
- if (name == I64_U2F) return builder.makeUnary(UnaryOp::ConvertUInt64ToFloat32, value);
- if (name == I64_U2D) return builder.makeUnary(UnaryOp::ConvertUInt64ToFloat64, value);
- if (name == I64_F2S) return builder.makeUnary(UnaryOp::TruncSFloat32ToInt64, value);
- if (name == I64_D2S) return builder.makeUnary(UnaryOp::TruncSFloat64ToInt64, value);
- if (name == I64_F2U) return builder.makeUnary(UnaryOp::TruncUFloat32ToInt64, value);
- if (name == I64_D2U) return builder.makeUnary(UnaryOp::TruncUFloat64ToInt64, value);
- if (name == I64_BC2D) return builder.makeUnary(UnaryOp::ReinterpretInt64, value);
- if (name == I64_BC2I) return builder.makeUnary(UnaryOp::ReinterpretFloat64, value);
- if (name == I64_CTTZ) return builder.makeUnary(UnaryOp::CtzInt64, value);
- if (name == I64_CTLZ) return builder.makeUnary(UnaryOp::ClzInt64, value);
- } else if (num == 2) { // 2 params,binary
- if (name == I64_CONST) return builder.makeConst(getLiteral(ast));
- if (name == I64_LOAD) return builder.makeLoad(8, true, 0, indexOr(ast[2][1][1]->getInteger(), 8), process(ast[2][0]), i64);
- auto* left = process(ast[2][0]);
- auto* right = process(ast[2][1]);
- // maths
- if (name == I64_ADD) return builder.makeBinary(BinaryOp::AddInt64, left, right);
- if (name == I64_SUB) return builder.makeBinary(BinaryOp::SubInt64, left, right);
- if (name == I64_MUL) return builder.makeBinary(BinaryOp::MulInt64, left, right);
- if (name == I64_UDIV) return makeDangerousI64Binary(BinaryOp::DivUInt64, left, right);
- if (name == I64_SDIV) return makeDangerousI64Binary(BinaryOp::DivSInt64, left, right);
- if (name == I64_UREM) return makeDangerousI64Binary(BinaryOp::RemUInt64, left, right);
- if (name == I64_SREM) return makeDangerousI64Binary(BinaryOp::RemSInt64, left, right);
- if (name == I64_AND) return builder.makeBinary(BinaryOp::AndInt64, left, right);
- if (name == I64_OR) return builder.makeBinary(BinaryOp::OrInt64, left, right);
- if (name == I64_XOR) return builder.makeBinary(BinaryOp::XorInt64, left, right);
- if (name == I64_SHL) return builder.makeBinary(BinaryOp::ShlInt64, left, right);
- if (name == I64_ASHR) return builder.makeBinary(BinaryOp::ShrSInt64, left, right);
- if (name == I64_LSHR) return builder.makeBinary(BinaryOp::ShrUInt64, left, right);
- // comps
- if (name == I64_EQ) return builder.makeBinary(BinaryOp::EqInt64, left, right);
- if (name == I64_NE) return builder.makeBinary(BinaryOp::NeInt64, left, right);
- if (name == I64_ULE) return builder.makeBinary(BinaryOp::LeUInt64, left, right);
- if (name == I64_SLE) return builder.makeBinary(BinaryOp::LeSInt64, left, right);
- if (name == I64_UGE) return builder.makeBinary(BinaryOp::GeUInt64, left, right);
- if (name == I64_SGE) return builder.makeBinary(BinaryOp::GeSInt64, left, right);
- if (name == I64_ULT) return builder.makeBinary(BinaryOp::LtUInt64, left, right);
- if (name == I64_SLT) return builder.makeBinary(BinaryOp::LtSInt64, left, right);
- if (name == I64_UGT) return builder.makeBinary(BinaryOp::GtUInt64, left, right);
- if (name == I64_SGT) return builder.makeBinary(BinaryOp::GtSInt64, left, right);
- } else if (num == 3) { // 3 params
- if (name == I64_STORE) return builder.makeStore(8, 0, indexOr(ast[2][2][1]->getInteger(), 8), process(ast[2][0]), process(ast[2][1]), i64);
+ default: {}
}
}
Expression* ret;