diff options
author | Nathan Froyd <froydnj@gmail.com> | 2018-02-15 14:08:59 -0500 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2018-02-15 11:08:59 -0800 |
commit | 85ae8cc6ffeffa65ff30d17649a0d8589dab2b00 (patch) | |
tree | 9d87df46a85a6b37ca0e348bc3cdb7dea1dcd648 /src/wasm2asm.h | |
parent | e0f86a24bda5612fb798524df23b6071d2dccc14 (diff) | |
download | binaryen-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.h | 277 |
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)); } |