summaryrefslogtreecommitdiff
path: root/src/wasm2asm.h
diff options
context:
space:
mode:
authorNathan Froyd <froydnj@gmail.com>2018-02-15 14:08:59 -0500
committerAlon Zakai <alonzakai@gmail.com>2018-02-15 11:08:59 -0800
commit85ae8cc6ffeffa65ff30d17649a0d8589dab2b00 (patch)
tree9d87df46a85a6b37ca0e348bc3cdb7dea1dcd648 /src/wasm2asm.h
parente0f86a24bda5612fb798524df23b6071d2dccc14 (diff)
downloadbinaryen-85ae8cc6ffeffa65ff30d17649a0d8589dab2b00.tar.gz
binaryen-85ae8cc6ffeffa65ff30d17649a0d8589dab2b00.tar.bz2
binaryen-85ae8cc6ffeffa65ff30d17649a0d8589dab2b00.zip
better handling of float ops in wasm2asm (#1427)
* explicitly handle binary float operations in processFunctionBody We weren't handling them before, but it wasn't obvious. Make the (non-) handling of them explicit in the code. We'll add handlers for them shortly. * add handling for simple binary float operations min, max, and copysign will require more sophisticated handling. * add handling for float comparisons * move float min/max handling to the correct place It was previously grouped with the i32 ops. * handle float promotion and demotion
Diffstat (limited to 'src/wasm2asm.h')
-rw-r--r--src/wasm2asm.h277
1 files changed, 176 insertions, 101 deletions
diff --git a/src/wasm2asm.h b/src/wasm2asm.h
index fd7a03234..346c1c677 100644
--- a/src/wasm2asm.h
+++ b/src/wasm2asm.h
@@ -1400,6 +1400,12 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) {
visit(curr->value, EXPRESSION_RESULT)
);
break;
+ case PromoteFloat32:
+ return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT),
+ ASM_DOUBLE);
+ case DemoteFloat64:
+ return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT),
+ ASM_FLOAT);
// TODO: more complex unary conversions
default:
std::cerr << "Unhandled unary float operator: " << curr
@@ -1438,112 +1444,181 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) {
Ref left = visit(curr->left, EXPRESSION_RESULT);
Ref right = visit(curr->right, EXPRESSION_RESULT);
Ref ret;
- switch (curr->op) {
- case AddInt32:
- ret = ValueBuilder::makeBinary(left, PLUS, right);
- break;
- case SubInt32:
- ret = ValueBuilder::makeBinary(left, MINUS, right);
- break;
- case MulInt32: {
- if (curr->type == i32) {
- // TODO: when one operand is a small int, emit a multiply
- return ValueBuilder::makeCall(MATH_IMUL, left, right);
- } else {
- return ValueBuilder::makeBinary(left, MUL, right);
+ switch (curr->type) {
+ case i32: {
+ switch (curr->op) {
+ case AddInt32:
+ ret = ValueBuilder::makeBinary(left, PLUS, right);
+ break;
+ case SubInt32:
+ ret = ValueBuilder::makeBinary(left, MINUS, right);
+ break;
+ case MulInt32: {
+ if (curr->type == i32) {
+ // TODO: when one operand is a small int, emit a multiply
+ return ValueBuilder::makeCall(MATH_IMUL, left, right);
+ } else {
+ return ValueBuilder::makeBinary(left, MUL, right);
+ }
+ }
+ case DivSInt32:
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), DIV,
+ makeSigning(right, ASM_SIGNED));
+ break;
+ case DivUInt32:
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), DIV,
+ makeSigning(right, ASM_UNSIGNED));
+ break;
+ case RemSInt32:
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), MOD,
+ makeSigning(right, ASM_SIGNED));
+ break;
+ case RemUInt32:
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), MOD,
+ makeSigning(right, ASM_UNSIGNED));
+ break;
+ case AndInt32:
+ ret = ValueBuilder::makeBinary(left, AND, right);
+ break;
+ case OrInt32:
+ ret = ValueBuilder::makeBinary(left, OR, right);
+ break;
+ case XorInt32:
+ ret = ValueBuilder::makeBinary(left, XOR, right);
+ break;
+ case ShlInt32:
+ ret = ValueBuilder::makeBinary(left, LSHIFT, right);
+ break;
+ case ShrUInt32:
+ ret = ValueBuilder::makeBinary(left, TRSHIFT, right);
+ break;
+ case ShrSInt32:
+ ret = ValueBuilder::makeBinary(left, RSHIFT, right);
+ break;
+ case EqInt32: {
+ // TODO: check if this condition is still valid/necessary
+ if (curr->left->type == i32) {
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), EQ,
+ makeSigning(right, ASM_SIGNED));
+ } else {
+ return ValueBuilder::makeBinary(left, EQ, right);
+ }
+ }
+ case NeInt32: {
+ if (curr->left->type == i32) {
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE,
+ makeSigning(right, ASM_SIGNED));
+ } else {
+ return ValueBuilder::makeBinary(left, NE, right);
+ }
+ }
+ case LtSInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LT,
+ makeSigning(right, ASM_SIGNED));
+ case LtUInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LT,
+ makeSigning(right, ASM_UNSIGNED));
+ case LeSInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LE,
+ makeSigning(right, ASM_SIGNED));
+ case LeUInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LE,
+ makeSigning(right, ASM_UNSIGNED));
+ case GtSInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GT,
+ makeSigning(right, ASM_SIGNED));
+ case GtUInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GT,
+ makeSigning(right, ASM_UNSIGNED));
+ case GeSInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GE,
+ makeSigning(right, ASM_SIGNED));
+ case GeUInt32:
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GE,
+ makeSigning(right, ASM_UNSIGNED));
+ case RotLInt32:
+ return makeSigning(ValueBuilder::makeCall(WASM_ROTL32, left, right),
+ ASM_SIGNED);
+ case RotRInt32:
+ return makeSigning(ValueBuilder::makeCall(WASM_ROTR32, left, right),
+ ASM_SIGNED);
+ case EqFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, EQ, right),
+ ASM_FLOAT);
+ case EqFloat64:
+ return ValueBuilder::makeBinary(left, EQ, right);
+ case NeFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, NE, right),
+ ASM_FLOAT);
+ case NeFloat64:
+ return ValueBuilder::makeBinary(left, NE, right);
+ case GeFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, GE, right),
+ ASM_FLOAT);
+ case GeFloat64:
+ return ValueBuilder::makeBinary(left, GE, right);
+ case GtFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, GT, right),
+ ASM_FLOAT);
+ case GtFloat64:
+ return ValueBuilder::makeBinary(left, GT, right);
+ case LeFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, LE, right),
+ ASM_FLOAT);
+ case LeFloat64:
+ return ValueBuilder::makeBinary(left, LE, right);
+ case LtFloat32:
+ return makeAsmCoercion(ValueBuilder::makeBinary(left, LT, right),
+ ASM_FLOAT);
+ case LtFloat64:
+ return ValueBuilder::makeBinary(left, LT, right);
+ default: {
+ std::cerr << "Unhandled i32 binary operator: " << curr << std::endl;
+ abort();
+ }
}
- }
- case DivSInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), DIV,
- makeSigning(right, ASM_SIGNED));
- break;
- case DivUInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), DIV,
- makeSigning(right, ASM_UNSIGNED));
- break;
- case RemSInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), MOD,
- makeSigning(right, ASM_SIGNED));
- break;
- case RemUInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), MOD,
- makeSigning(right, ASM_UNSIGNED));
- break;
- case AndInt32:
- ret = ValueBuilder::makeBinary(left, AND, right);
- break;
- case OrInt32:
- ret = ValueBuilder::makeBinary(left, OR, right);
- break;
- case XorInt32:
- ret = ValueBuilder::makeBinary(left, XOR, right);
- break;
- case ShlInt32:
- ret = ValueBuilder::makeBinary(left, LSHIFT, right);
break;
- case ShrUInt32:
- ret = ValueBuilder::makeBinary(left, TRSHIFT, right);
- break;
- case ShrSInt32:
- ret = ValueBuilder::makeBinary(left, RSHIFT, right);
- break;
- case MinFloat32:
- ret = ValueBuilder::makeCall(MATH_MIN, left, right);
- break;
- case MaxFloat32:
- ret = ValueBuilder::makeCall(MATH_MAX, left, right);
- break;
- case EqInt32: {
- // TODO: check if this condition is still valid/necessary
- if (curr->left->type == i32) {
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), EQ,
- makeSigning(right, ASM_SIGNED));
- } else {
- return ValueBuilder::makeBinary(left, EQ, right);
- }
}
- case NeInt32: {
- if (curr->left->type == i32) {
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE,
- makeSigning(right, ASM_SIGNED));
- } else {
- return ValueBuilder::makeBinary(left, NE, right);
+ case f32:
+ case f64:
+ switch (curr->op) {
+ case AddFloat32:
+ case AddFloat64:
+ ret = ValueBuilder::makeBinary(left, PLUS, right);
+ break;
+ case SubFloat32:
+ case SubFloat64:
+ ret = ValueBuilder::makeBinary(left, MINUS, right);
+ break;
+ case MulFloat32:
+ case MulFloat64:
+ ret = ValueBuilder::makeBinary(left, MUL, right);
+ break;
+ case DivFloat32:
+ case DivFloat64:
+ ret = ValueBuilder::makeBinary(left, DIV, right);
+ break;
+ case MinFloat32:
+ case MinFloat64:
+ ret = ValueBuilder::makeCall(MATH_MIN, left, right);
+ break;
+ case MaxFloat32:
+ case MaxFloat64:
+ ret = ValueBuilder::makeCall(MATH_MAX, left, right);
+ break;
+ case CopySignFloat32:
+ case CopySignFloat64:
+ default:
+ std::cerr << "Unhandled binary float operator: " << curr << std::endl;
+ abort();
}
- }
- case LtSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LT,
- makeSigning(right, ASM_SIGNED));
- case LtUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LT,
- makeSigning(right, ASM_UNSIGNED));
- case LeSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LE,
- makeSigning(right, ASM_SIGNED));
- case LeUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LE,
- makeSigning(right, ASM_UNSIGNED));
- case GtSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GT,
- makeSigning(right, ASM_SIGNED));
- case GtUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GT,
- makeSigning(right, ASM_UNSIGNED));
- case GeSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GE,
- makeSigning(right, ASM_SIGNED));
- case GeUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GE,
- makeSigning(right, ASM_UNSIGNED));
- case RotLInt32:
- return makeSigning(ValueBuilder::makeCall(WASM_ROTL32, left, right),
- ASM_SIGNED);
- case RotRInt32:
- return makeSigning(ValueBuilder::makeCall(WASM_ROTR32, left, right),
- ASM_SIGNED);
- default: {
- std::cerr << "Unhandled binary operator: " << curr << std::endl;
+ if (curr->type == f32) {
+ return makeAsmCoercion(ret, ASM_FLOAT);
+ }
+ return ret;
+ default:
+ std::cerr << "Unhandled type in binary: " << curr << std::endl;
abort();
- }
}
return makeAsmCoercion(ret, wasmToAsmType(curr->type));
}