diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-05-18 17:32:43 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-05-18 18:28:16 -0700 |
commit | 9070ff54453bec5e90727cc586b4a702b54628d4 (patch) | |
tree | ddf944ba236f25ed8a839ffba8827dd31c9b9979 | |
parent | b88e9de7df6a8b2ba9381e27dff3aa3dff64f764 (diff) | |
download | binaryen-9070ff54453bec5e90727cc586b4a702b54628d4.tar.gz binaryen-9070ff54453bec5e90727cc586b4a702b54628d4.tar.bz2 binaryen-9070ff54453bec5e90727cc586b4a702b54628d4.zip |
use separate internal opcodes for binary variants
-rw-r--r-- | lib/empty.txt | 0 | ||||
-rw-r--r-- | scripts/fuzz_relooper.py | 12 | ||||
-rw-r--r-- | src/asm2wasm.h | 73 | ||||
-rw-r--r-- | src/binaryen-c.cpp | 109 | ||||
-rw-r--r-- | src/binaryen-c.h | 109 | ||||
-rw-r--r-- | src/cfg/Relooper.cpp | 2 | ||||
-rw-r--r-- | src/cfg/Relooper.h | 2 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 42 | ||||
-rw-r--r-- | src/passes/PostEmscripten.cpp | 2 | ||||
-rw-r--r-- | src/passes/Print.cpp | 115 | ||||
-rw-r--r-- | src/s2wasm.h | 69 | ||||
-rw-r--r-- | src/wasm-binary.h | 162 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 126 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 53 | ||||
-rw-r--r-- | src/wasm.h | 66 | ||||
-rw-r--r-- | test/example/c-api-hello-world.c | 2 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.c | 74 | ||||
-rw-r--r-- | test/example/find_div0s.cpp | 2 | ||||
-rw-r--r-- | test/example/relooper-fuzz.c | 26 |
19 files changed, 635 insertions, 411 deletions
diff --git a/lib/empty.txt b/lib/empty.txt deleted file mode 100644 index e69de29bb..000000000 --- a/lib/empty.txt +++ /dev/null diff --git a/scripts/fuzz_relooper.py b/scripts/fuzz_relooper.py index e09f252b7..8a67b067b 100644 --- a/scripts/fuzz_relooper.py +++ b/scripts/fuzz_relooper.py @@ -96,7 +96,7 @@ int main() { // if the end, halt BinaryenExpressionRef halter = BinaryenIf(module, BinaryenBinary(module, - BinaryenEq(), + BinaryenEqInt32(), BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * %d)) // jumps of 4 bytes @@ -109,7 +109,7 @@ int main() { 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAdd(), + BinaryenAddInt32(), BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4)) @@ -119,7 +119,7 @@ int main() { // optionally, print the return value BinaryenExpressionRef args[] = { BinaryenBinary(module, - BinaryenSub(), + BinaryenSubInt32(), BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, 4, 0, 4, 0, BinaryenInt32(), @@ -186,9 +186,9 @@ int main() { for j in range(len(b)): fast += ''' RelooperAddBranch(b%d, b%d, BinaryenBinary(module, - BinaryenEq(), + BinaryenEqInt32(), BinaryenBinary(module, - BinaryenRemU(), + BinaryenRemUInt32(), BinaryenGetLocal(module, 0, BinaryenInt32()), BinaryenConst(module, BinaryenLiteralInt32(%d)) ), @@ -265,7 +265,7 @@ int main() { print '.' cmd = [os.environ.get('CC') or 'gcc', 'fuzz.c', '-Isrc', - '-lbinaryen-c', '-lasmjs', + '-lbinaryen', '-lasmjs', '-lsupport', '-Llib/.', '-pthread', '-o', 'fuzz'] subprocess.check_call(cmd) print '^' diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 74b1aa8c4..d1959b918 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -307,63 +307,58 @@ private: } BinaryOp parseAsmBinaryOp(IString op, Ref left, Ref right, AsmData *asmData) { - if (op == PLUS) return BinaryOp::Add; - if (op == MINUS) return BinaryOp::Sub; - if (op == MUL) return BinaryOp::Mul; - if (op == AND) return BinaryOp::And; - if (op == OR) return BinaryOp::Or; - if (op == XOR) return BinaryOp::Xor; - if (op == LSHIFT) return BinaryOp::Shl; - if (op == RSHIFT) return BinaryOp::ShrS; - if (op == TRSHIFT) return BinaryOp::ShrU; - if (op == EQ) return BinaryOp::Eq; - if (op == NE) return BinaryOp::Ne; WasmType leftType = detectWasmType(left, asmData); -#if 0 - std::cout << "CHECK\n"; - left->stringify(std::cout); - std::cout << " => " << printWasmType(leftType); - std::cout << '\n'; - right->stringify(std::cout); - std::cout << " => " << printWasmType(detectWasmType(right, asmData)) << "\n"; -#endif bool isInteger = leftType == WasmType::i32; + + if (op == PLUS) return isInteger ? BinaryOp::AddInt32 : (leftType == f32 ? BinaryOp::AddFloat32 : BinaryOp::AddFloat64); + if (op == MINUS) return isInteger ? BinaryOp::SubInt32 : (leftType == f32 ? BinaryOp::SubFloat32 : BinaryOp::SubFloat64); + if (op == MUL) return isInteger ? BinaryOp::MulInt32 : (leftType == f32 ? BinaryOp::MulFloat32 : BinaryOp::MulFloat64); + if (op == AND) return BinaryOp::AndInt32; + if (op == OR) return BinaryOp::OrInt32; + if (op == XOR) return BinaryOp::XorInt32; + if (op == LSHIFT) return BinaryOp::ShlInt32; + if (op == RSHIFT) return BinaryOp::ShrSInt32; + if (op == TRSHIFT) return BinaryOp::ShrUInt32; + if (op == EQ) return isInteger ? BinaryOp::EqInt32 : (leftType == f32 ? BinaryOp::EqFloat32 : BinaryOp::EqFloat64); + if (op == NE) return isInteger ? BinaryOp::NeInt32 : (leftType == f32 ? BinaryOp::NeFloat32 : BinaryOp::NeFloat64); + bool isUnsigned = isUnsignedCoercion(left) || isUnsignedCoercion(right); + if (op == DIV) { if (isInteger) { - return isUnsigned ? BinaryOp::DivU : BinaryOp::DivS; + return isUnsigned ? BinaryOp::DivUInt32 : BinaryOp::DivSInt32; } - return BinaryOp::Div; + return leftType == f32 ? BinaryOp::DivFloat32 : BinaryOp::DivFloat64; } if (op == MOD) { if (isInteger) { - return isUnsigned ? BinaryOp::RemU : BinaryOp::RemS; + return isUnsigned ? BinaryOp::RemUInt32 : BinaryOp::RemSInt32; } - return BinaryOp::RemS; // XXX no floating-point remainder op, this must be handled by the caller + return BinaryOp::RemSInt32; // XXX no floating-point remainder op, this must be handled by the caller } if (op == GE) { if (isInteger) { - return isUnsigned ? BinaryOp::GeU : BinaryOp::GeS; + return isUnsigned ? BinaryOp::GeUInt32 : BinaryOp::GeSInt32; } - return BinaryOp::Ge; + return leftType == f32 ? BinaryOp::GeFloat32 : BinaryOp::GeFloat64; } if (op == GT) { if (isInteger) { - return isUnsigned ? BinaryOp::GtU : BinaryOp::GtS; + return isUnsigned ? BinaryOp::GtUInt32 : BinaryOp::GtSInt32; } - return BinaryOp::Gt; + return leftType == f32 ? BinaryOp::GtFloat32 : BinaryOp::GtFloat64; } if (op == LE) { if (isInteger) { - return isUnsigned ? BinaryOp::LeU : BinaryOp::LeS; + return isUnsigned ? BinaryOp::LeUInt32 : BinaryOp::LeSInt32; } - return BinaryOp::Le; + return leftType == f32 ? BinaryOp::LeFloat32 : BinaryOp::LeFloat64; } if (op == LT) { if (isInteger) { - return isUnsigned ? BinaryOp::LtU : BinaryOp::LtS; + return isUnsigned ? BinaryOp::LtUInt32 : BinaryOp::LtSInt32; } - return BinaryOp::Lt; + return leftType == f32 ? BinaryOp::LtFloat32 : BinaryOp::LtFloat64; } abort_on("bad wasm binary op", op); abort(); // avoid warning @@ -733,7 +728,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) { assert(functionTableStarts.find(tableName) != functionTableStarts.end()); auto sub = allocator.alloc<Binary>(); // note that the target is already masked, so we just offset it, we don't need to guard against overflow (which would be an error anyhow) - sub->op = Add; + sub->op = AddInt32; sub->left = call->target; sub->right = allocator.alloc<Const>()->set(Literal((int32_t)functionTableStarts[tableName])); sub->type = WasmType::i32; @@ -1008,7 +1003,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { ret->left = process(ast[2]); ret->right = process(ast[3]); ret->finalize(); - if (binary == BinaryOp::RemS && isWasmTypeFloat(ret->type)) { + if (binary == BinaryOp::RemSInt32 && isWasmTypeFloat(ret->type)) { // WebAssembly does not have floating-point remainder, we have to emit a call to a special import of ours CallImport *call = allocator.alloc<CallImport>(); call->target = F64_REM; @@ -1126,7 +1121,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { if (asmType == ASM_INT) { // wasm has no unary negation for int, so do 0- auto ret = allocator.alloc<Binary>(); - ret->op = Sub; + ret->op = SubInt32; ret->left = allocator.alloc<Const>()->set(Literal((int32_t)0)); ret->right = process(ast[2]); ret->type = WasmType::i32; @@ -1182,7 +1177,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } // no bitwise unary not, so do xor with -1 auto ret = allocator.alloc<Binary>(); - ret->op = Xor; + ret->op = XorInt32; ret->left = process(ast[2]); ret->right = allocator.alloc<Const>()->set(Literal(int32_t(-1))); ret->type = WasmType::i32; @@ -1207,7 +1202,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { if (name == Math_imul) { assert(ast[2]->size() == 2); auto ret = allocator.alloc<Binary>(); - ret->op = Mul; + ret->op = MulInt32; ret->left = process(ast[2][0]); ret->right = process(ast[2][1]); ret->type = WasmType::i32; @@ -1263,14 +1258,14 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { return ret; }; auto isNegative = allocator.alloc<Binary>(); - isNegative->op = LtS; + isNegative->op = LtSInt32; isNegative->left = get(); isNegative->right = allocator.alloc<Const>()->set(Literal(0)); isNegative->finalize(); auto block = allocator.alloc<Block>(); block->list.push_back(set); auto flip = allocator.alloc<Binary>(); - flip->op = Sub; + flip->op = SubInt32; flip->left = allocator.alloc<Const>()->set(Literal(0)); flip->right = get(); flip->type = i32; @@ -1631,7 +1626,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } } Binary* offsetor = allocator.alloc<Binary>(); - offsetor->op = BinaryOp::Sub; + offsetor->op = BinaryOp::SubInt32; offsetor->left = br->condition; offsetor->right = allocator.alloc<Const>()->set(Literal(min)); offsetor->type = i32; diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 8f94c4ec5..7fb39ffe4 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -145,39 +145,82 @@ BinaryenOp BinaryenPromoteFloat32(void) { return PromoteFloat32; } BinaryenOp BinaryenDemoteFloat64(void) { return DemoteFloat64; } BinaryenOp BinaryenReinterpretInt32(void) { return ReinterpretInt32; } BinaryenOp BinaryenReinterpretInt64(void) { return ReinterpretInt64; } -BinaryenOp BinaryenAdd(void) { return Add; } -BinaryenOp BinaryenSub(void) { return Sub; } -BinaryenOp BinaryenMul(void) { return Mul; } -BinaryenOp BinaryenDivS(void) { return DivS; } -BinaryenOp BinaryenDivU(void) { return DivU; } -BinaryenOp BinaryenRemS(void) { return RemS; } -BinaryenOp BinaryenRemU(void) { return RemU; } -BinaryenOp BinaryenAnd(void) { return And; } -BinaryenOp BinaryenOr(void) { return Or; } -BinaryenOp BinaryenXor(void) { return Xor; } -BinaryenOp BinaryenShl(void) { return Shl; } -BinaryenOp BinaryenShrU(void) { return ShrU; } -BinaryenOp BinaryenShrS(void) { return ShrS; } -BinaryenOp BinaryenRotL(void) { return RotL; } -BinaryenOp BinaryenRotR(void) { return RotR; } -BinaryenOp BinaryenDiv(void) { return Div; } -BinaryenOp BinaryenCopySign(void) { return CopySign; } -BinaryenOp BinaryenMin(void) { return Min; } -BinaryenOp BinaryenMax(void) { return Max; } -BinaryenOp BinaryenEq(void) { return Eq; } -BinaryenOp BinaryenNe(void) { return Ne; } -BinaryenOp BinaryenLtS(void) { return LtS; } -BinaryenOp BinaryenLtU(void) { return LtU; } -BinaryenOp BinaryenLeS(void) { return LeS; } -BinaryenOp BinaryenLeU(void) { return LeU; } -BinaryenOp BinaryenGtS(void) { return GtS; } -BinaryenOp BinaryenGtU(void) { return GtU; } -BinaryenOp BinaryenGeS(void) { return GeS; } -BinaryenOp BinaryenGeU(void) { return GeU; } -BinaryenOp BinaryenLt(void) { return Lt; } -BinaryenOp BinaryenLe(void) { return Le; } -BinaryenOp BinaryenGt(void) { return Gt; } -BinaryenOp BinaryenGe(void) { return Ge; } +BinaryenOp BinaryenAddInt32(void) { return AddInt32; } +BinaryenOp BinaryenSubInt32(void) { return SubInt32; } +BinaryenOp BinaryenMulInt32(void) { return MulInt32; } +BinaryenOp BinaryenDivSInt32(void) { return DivSInt32; } +BinaryenOp BinaryenDivUInt32(void) { return DivUInt32; } +BinaryenOp BinaryenRemSInt32(void) { return RemSInt32; } +BinaryenOp BinaryenRemUInt32(void) { return RemUInt32; } +BinaryenOp BinaryenAndInt32(void) { return AndInt32; } +BinaryenOp BinaryenOrInt32(void) { return OrInt32; } +BinaryenOp BinaryenXorInt32(void) { return XorInt32; } +BinaryenOp BinaryenShlInt32(void) { return ShlInt32; } +BinaryenOp BinaryenShrUInt32(void) { return ShrUInt32; } +BinaryenOp BinaryenShrSInt32(void) { return ShrSInt32; } +BinaryenOp BinaryenRotLInt32(void) { return RotLInt32; } +BinaryenOp BinaryenRotRInt32(void) { return RotRInt32; } +BinaryenOp BinaryenEqInt32(void) { return EqInt32; } +BinaryenOp BinaryenNeInt32(void) { return NeInt32; } +BinaryenOp BinaryenLtSInt32(void) { return LtSInt32; } +BinaryenOp BinaryenLtUInt32(void) { return LtUInt32; } +BinaryenOp BinaryenLeSInt32(void) { return LeSInt32; } +BinaryenOp BinaryenLeUInt32(void) { return LeUInt32; } +BinaryenOp BinaryenGtSInt32(void) { return GtSInt32; } +BinaryenOp BinaryenGtUInt32(void) { return GtUInt32; } +BinaryenOp BinaryenGeSInt32(void) { return GeSInt32; } +BinaryenOp BinaryenGeUInt32(void) { return GeUInt32; } +BinaryenOp BinaryenAddInt64(void) { return AddInt64; } +BinaryenOp BinaryenSubInt64(void) { return SubInt64; } +BinaryenOp BinaryenMulInt64(void) { return MulInt64; } +BinaryenOp BinaryenDivSInt64(void) { return DivSInt64; } +BinaryenOp BinaryenDivUInt64(void) { return DivUInt64; } +BinaryenOp BinaryenRemSInt64(void) { return RemSInt64; } +BinaryenOp BinaryenRemUInt64(void) { return RemUInt64; } +BinaryenOp BinaryenAndInt64(void) { return AndInt64; } +BinaryenOp BinaryenOrInt64(void) { return OrInt64; } +BinaryenOp BinaryenXorInt64(void) { return XorInt64; } +BinaryenOp BinaryenShlInt64(void) { return ShlInt64; } +BinaryenOp BinaryenShrUInt64(void) { return ShrUInt64; } +BinaryenOp BinaryenShrSInt64(void) { return ShrSInt64; } +BinaryenOp BinaryenRotLInt64(void) { return RotLInt64; } +BinaryenOp BinaryenRotRInt64(void) { return RotRInt64; } +BinaryenOp BinaryenEqInt64(void) { return EqInt64; } +BinaryenOp BinaryenNeInt64(void) { return NeInt64; } +BinaryenOp BinaryenLtSInt64(void) { return LtSInt64; } +BinaryenOp BinaryenLtUInt64(void) { return LtUInt64; } +BinaryenOp BinaryenLeSInt64(void) { return LeSInt64; } +BinaryenOp BinaryenLeUInt64(void) { return LeUInt64; } +BinaryenOp BinaryenGtSInt64(void) { return GtSInt64; } +BinaryenOp BinaryenGtUInt64(void) { return GtUInt64; } +BinaryenOp BinaryenGeSInt64(void) { return GeSInt64; } +BinaryenOp BinaryenGeUInt64(void) { return GeUInt64; } +BinaryenOp BinaryenAddFloat32(void) { return AddFloat32; } +BinaryenOp BinaryenSubFloat32(void) { return SubFloat32; } +BinaryenOp BinaryenMulFloat32(void) { return MulFloat32; } +BinaryenOp BinaryenDivFloat32(void) { return DivFloat32; } +BinaryenOp BinaryenCopySignFloat32(void) { return CopySignFloat32; } +BinaryenOp BinaryenMinFloat32(void) { return MinFloat32; } +BinaryenOp BinaryenMaxFloat32(void) { return MaxFloat32; } +BinaryenOp BinaryenEqFloat32(void) { return EqFloat32; } +BinaryenOp BinaryenNeFloat32(void) { return NeFloat32; } +BinaryenOp BinaryenLtFloat32(void) { return LtFloat32; } +BinaryenOp BinaryenLeFloat32(void) { return LeFloat32; } +BinaryenOp BinaryenGtFloat32(void) { return GtFloat32; } +BinaryenOp BinaryenGeFloat32(void) { return GeFloat32; } +BinaryenOp BinaryenAddFloat64(void) { return AddFloat64; } +BinaryenOp BinaryenSubFloat64(void) { return SubFloat64; } +BinaryenOp BinaryenMulFloat64(void) { return MulFloat64; } +BinaryenOp BinaryenDivFloat64(void) { return DivFloat64; } +BinaryenOp BinaryenCopySignFloat64(void) { return CopySignFloat64; } +BinaryenOp BinaryenMinFloat64(void) { return MinFloat64; } +BinaryenOp BinaryenMaxFloat64(void) { return MaxFloat64; } +BinaryenOp BinaryenEqFloat64(void) { return EqFloat64; } +BinaryenOp BinaryenNeFloat64(void) { return NeFloat64; } +BinaryenOp BinaryenLtFloat64(void) { return LtFloat64; } +BinaryenOp BinaryenLeFloat64(void) { return LeFloat64; } +BinaryenOp BinaryenGtFloat64(void) { return GtFloat64; } +BinaryenOp BinaryenGeFloat64(void) { return GeFloat64; } BinaryenOp BinaryenPageSize(void) { return PageSize; } BinaryenOp BinaryenCurrentMemory(void) { return CurrentMemory; } BinaryenOp BinaryenGrowMemory(void) { return GrowMemory; } diff --git a/src/binaryen-c.h b/src/binaryen-c.h index dbaf65b0e..d3858489c 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -161,39 +161,82 @@ BinaryenOp BinaryenPromoteFloat32(void); BinaryenOp BinaryenDemoteFloat64(void); BinaryenOp BinaryenReinterpretInt32(void); BinaryenOp BinaryenReinterpretInt64(void); -BinaryenOp BinaryenAdd(void); -BinaryenOp BinaryenSub(void); -BinaryenOp BinaryenMul(void); -BinaryenOp BinaryenDivS(void); -BinaryenOp BinaryenDivU(void); -BinaryenOp BinaryenRemS(void); -BinaryenOp BinaryenRemU(void); -BinaryenOp BinaryenAnd(void); -BinaryenOp BinaryenOr(void); -BinaryenOp BinaryenXor(void); -BinaryenOp BinaryenShl(void); -BinaryenOp BinaryenShrU(void); -BinaryenOp BinaryenShrS(void); -BinaryenOp BinaryenRotL(void); -BinaryenOp BinaryenRotR(void); -BinaryenOp BinaryenDiv(void); -BinaryenOp BinaryenCopySign(void); -BinaryenOp BinaryenMin(void); -BinaryenOp BinaryenMax(void); -BinaryenOp BinaryenEq(void); -BinaryenOp BinaryenNe(void); -BinaryenOp BinaryenLtS(void); -BinaryenOp BinaryenLtU(void); -BinaryenOp BinaryenLeS(void); -BinaryenOp BinaryenLeU(void); -BinaryenOp BinaryenGtS(void); -BinaryenOp BinaryenGtU(void); -BinaryenOp BinaryenGeS(void); -BinaryenOp BinaryenGeU(void); -BinaryenOp BinaryenLt(void); -BinaryenOp BinaryenLe(void); -BinaryenOp BinaryenGt(void); -BinaryenOp BinaryenGe(void); +BinaryenOp BinaryenAddInt32(void); +BinaryenOp BinaryenSubInt32(void); +BinaryenOp BinaryenMulInt32(void); +BinaryenOp BinaryenDivSInt32(void); +BinaryenOp BinaryenDivUInt32(void); +BinaryenOp BinaryenRemSInt32(void); +BinaryenOp BinaryenRemUInt32(void); +BinaryenOp BinaryenAndInt32(void); +BinaryenOp BinaryenOrInt32(void); +BinaryenOp BinaryenXorInt32(void); +BinaryenOp BinaryenShlInt32(void); +BinaryenOp BinaryenShrUInt32(void); +BinaryenOp BinaryenShrSInt32(void); +BinaryenOp BinaryenRotLInt32(void); +BinaryenOp BinaryenRotRInt32(void); +BinaryenOp BinaryenEqInt32(void); +BinaryenOp BinaryenNeInt32(void); +BinaryenOp BinaryenLtSInt32(void); +BinaryenOp BinaryenLtUInt32(void); +BinaryenOp BinaryenLeSInt32(void); +BinaryenOp BinaryenLeUInt32(void); +BinaryenOp BinaryenGtSInt32(void); +BinaryenOp BinaryenGtUInt32(void); +BinaryenOp BinaryenGeSInt32(void); +BinaryenOp BinaryenGeUInt32(void); +BinaryenOp BinaryenAddInt64(void); +BinaryenOp BinaryenSubInt64(void); +BinaryenOp BinaryenMulInt64(void); +BinaryenOp BinaryenDivSInt64(void); +BinaryenOp BinaryenDivUInt64(void); +BinaryenOp BinaryenRemSInt64(void); +BinaryenOp BinaryenRemUInt64(void); +BinaryenOp BinaryenAndInt64(void); +BinaryenOp BinaryenOrInt64(void); +BinaryenOp BinaryenXorInt64(void); +BinaryenOp BinaryenShlInt64(void); +BinaryenOp BinaryenShrUInt64(void); +BinaryenOp BinaryenShrSInt64(void); +BinaryenOp BinaryenRotLInt64(void); +BinaryenOp BinaryenRotRInt64(void); +BinaryenOp BinaryenEqInt64(void); +BinaryenOp BinaryenNeInt64(void); +BinaryenOp BinaryenLtSInt64(void); +BinaryenOp BinaryenLtUInt64(void); +BinaryenOp BinaryenLeSInt64(void); +BinaryenOp BinaryenLeUInt64(void); +BinaryenOp BinaryenGtSInt64(void); +BinaryenOp BinaryenGtUInt64(void); +BinaryenOp BinaryenGeSInt64(void); +BinaryenOp BinaryenGeUInt64(void); +BinaryenOp BinaryenAddFloat32(void); +BinaryenOp BinaryenSubFloat32(void); +BinaryenOp BinaryenMulFloat32(void); +BinaryenOp BinaryenDivFloat32(void); +BinaryenOp BinaryenCopySignFloat32(void); +BinaryenOp BinaryenMinFloat32(void); +BinaryenOp BinaryenMaxFloat32(void); +BinaryenOp BinaryenEqFloat32(void); +BinaryenOp BinaryenNeFloat32(void); +BinaryenOp BinaryenLtFloat32(void); +BinaryenOp BinaryenLeFloat32(void); +BinaryenOp BinaryenGtFloat32(void); +BinaryenOp BinaryenGeFloat32(void); +BinaryenOp BinaryenAddFloat64(void); +BinaryenOp BinaryenSubFloat64(void); +BinaryenOp BinaryenMulFloat64(void); +BinaryenOp BinaryenDivFloat64(void); +BinaryenOp BinaryenCopySignFloat64(void); +BinaryenOp BinaryenMinFloat64(void); +BinaryenOp BinaryenMaxFloat64(void); +BinaryenOp BinaryenEqFloat64(void); +BinaryenOp BinaryenNeFloat64(void); +BinaryenOp BinaryenLtFloat64(void); +BinaryenOp BinaryenLeFloat64(void); +BinaryenOp BinaryenGtFloat64(void); +BinaryenOp BinaryenGeFloat64(void); BinaryenOp BinaryenPageSize(void); BinaryenOp BinaryenCurrentMemory(void); BinaryenOp BinaryenGrowMemory(void); diff --git a/src/cfg/Relooper.cpp b/src/cfg/Relooper.cpp index d830caa67..06867c748 100644 --- a/src/cfg/Relooper.cpp +++ b/src/cfg/Relooper.cpp @@ -201,7 +201,7 @@ wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { } else { auto* Now = Builder.makeUnary(wasm::EqZInt32, Details->Condition); if (RemainingConditions) { - RemainingConditions = Builder.makeBinary(wasm::And, RemainingConditions, Now); + RemainingConditions = Builder.makeBinary(wasm::AndInt32, RemainingConditions, Now); } else { RemainingConditions = Now; } diff --git a/src/cfg/Relooper.h b/src/cfg/Relooper.h index 706b3d065..3040b0fc2 100644 --- a/src/cfg/Relooper.h +++ b/src/cfg/Relooper.h @@ -50,7 +50,7 @@ public: return makeSetLocal(labelHelper, makeConst(wasm::Literal(int32_t(value)))); } wasm::Binary* makeCheckLabel(wasm::Index value) { - return makeBinary(wasm::Eq, makeGetLabel(), makeConst(wasm::Literal(int32_t(value)))); + return makeBinary(wasm::EqInt32, makeGetLabel(), makeConst(wasm::Literal(int32_t(value)))); } wasm::Break* makeBreak(int id) { return wasm::Builder::makeBreak(getBreakName(id)); diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 3c88c830b..3d98d0a67 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -44,16 +44,38 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, auto* child = curr->value->dynCast<Binary>(); if (child && (child->type == i32 || child->type == i64)) { switch (child->op) { - case Eq: child->op = Ne; break; - case Ne: child->op = Eq; break; - case LtS: child->op = GeS; break; - case LtU: child->op = GeU; break; - case LeS: child->op = GtS; break; - case LeU: child->op = GtU; break; - case GtS: child->op = LeS; break; - case GtU: child->op = LeU; break; - case GeS: child->op = LtS; break; - case GeU: child->op = LtU; break; + case EqInt32: child->op = NeInt32; break; + case NeInt32: child->op = EqInt32; break; + case LtSInt32: child->op = GeSInt32; break; + case LtUInt32: child->op = GeUInt32; break; + case LeSInt32: child->op = GtSInt32; break; + case LeUInt32: child->op = GtUInt32; break; + case GtSInt32: child->op = LeSInt32; break; + case GtUInt32: child->op = LeUInt32; break; + case GeSInt32: child->op = LtSInt32; break; + case GeUInt32: child->op = LtUInt32; break; + case EqInt64: child->op = NeInt64; break; + case NeInt64: child->op = EqInt64; break; + case LtSInt64: child->op = GeSInt64; break; + case LtUInt64: child->op = GeUInt64; break; + case LeSInt64: child->op = GtSInt64; break; + case LeUInt64: child->op = GtUInt64; break; + case GtSInt64: child->op = LeSInt64; break; + case GtUInt64: child->op = LeUInt64; break; + case GeSInt64: child->op = LtSInt64; break; + case GeUInt64: child->op = LtUInt64; break; + case EqFloat32: child->op = NeFloat32; break; + case NeFloat32: child->op = EqFloat32; break; + case LtFloat32: child->op = GeFloat32; break; + case LeFloat32: child->op = GtFloat32; break; + case GtFloat32: child->op = LeFloat32; break; + case GeFloat32: child->op = LtFloat32; break; + case EqFloat64: child->op = NeFloat64; break; + case NeFloat64: child->op = EqFloat64; break; + case LtFloat64: child->op = GeFloat64; break; + case LeFloat64: child->op = GtFloat64; break; + case GtFloat64: child->op = LeFloat64; break; + case GeFloat64: child->op = LtFloat64; break; default: return; } replaceCurrent(child); diff --git a/src/passes/PostEmscripten.cpp b/src/passes/PostEmscripten.cpp index 43fd1b2bc..4bd828a00 100644 --- a/src/passes/PostEmscripten.cpp +++ b/src/passes/PostEmscripten.cpp @@ -47,7 +47,7 @@ struct PostEmscripten : public WalkerPass<PostWalker<PostEmscripten, Visitor<Pos if (curr->offset) return; Expression* ptr = curr->ptr; auto add = ptr->dynCast<Binary>(); - if (!add || add->op != Add) return; + if (!add || add->op != AddInt32) return; assert(add->type == i32); auto c = add->right->dynCast<Const>(); if (!c) { diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 4559a5ce6..04b1d0edb 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -340,41 +340,88 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } void visitBinary(Binary *curr) { o << '('; - prepareColor(o) << printWasmType(curr->isRelational() ? curr->left->type : curr->type) << '.'; + prepareColor(o); switch (curr->op) { - case Add: o << "add"; break; - case Sub: o << "sub"; break; - case Mul: o << "mul"; break; - case DivS: o << "div_s"; break; - case DivU: o << "div_u"; break; - case RemS: o << "rem_s"; break; - case RemU: o << "rem_u"; break; - case And: o << "and"; break; - case Or: o << "or"; break; - case Xor: o << "xor"; break; - case Shl: o << "shl"; break; - case ShrU: o << "shr_u"; break; - case ShrS: o << "shr_s"; break; - case RotL: o << "rotl"; break; - case RotR: o << "rotr"; break; - case Div: o << "div"; break; - case CopySign: o << "copysign"; break; - case Min: o << "min"; break; - case Max: o << "max"; break; - case Eq: o << "eq"; break; - case Ne: o << "ne"; break; - case LtS: o << "lt_s"; break; - case LtU: o << "lt_u"; break; - case LeS: o << "le_s"; break; - case LeU: o << "le_u"; break; - case GtS: o << "gt_s"; break; - case GtU: o << "gt_u"; break; - case GeS: o << "ge_s"; break; - case GeU: o << "ge_u"; break; - case Lt: o << "lt"; break; - case Le: o << "le"; break; - case Gt: o << "gt"; break; - case Ge: o << "ge"; break; + case AddInt32: o << "i32.add"; break; + case SubInt32: o << "i32.sub"; break; + case MulInt32: o << "i32.mul"; break; + case DivSInt32: o << "i32.div_s"; break; + case DivUInt32: o << "i32.div_u"; break; + case RemSInt32: o << "i32.rem_s"; break; + case RemUInt32: o << "i32.rem_u"; break; + case AndInt32: o << "i32.and"; break; + case OrInt32: o << "i32.or"; break; + case XorInt32: o << "i32.xor"; break; + case ShlInt32: o << "i32.shl"; break; + case ShrUInt32: o << "i32.shr_u"; break; + case ShrSInt32: o << "i32.shr_s"; break; + case RotLInt32: o << "i32.rotl"; break; + case RotRInt32: o << "i32.rotr"; break; + case EqInt32: o << "i32.eq"; break; + case NeInt32: o << "i32.ne"; break; + case LtSInt32: o << "i32.lt_s"; break; + case LtUInt32: o << "i32.lt_u"; break; + case LeSInt32: o << "i32.le_s"; break; + case LeUInt32: o << "i32.le_u"; break; + case GtSInt32: o << "i32.gt_s"; break; + case GtUInt32: o << "i32.gt_u"; break; + case GeSInt32: o << "i32.ge_s"; break; + case GeUInt32: o << "i32.ge_u"; break; + + case AddInt64: o << "i64.add"; break; + case SubInt64: o << "i64.sub"; break; + case MulInt64: o << "i64.mul"; break; + case DivSInt64: o << "i64.div_s"; break; + case DivUInt64: o << "i64.div_u"; break; + case RemSInt64: o << "i64.rem_s"; break; + case RemUInt64: o << "i64.rem_u"; break; + case AndInt64: o << "i64.and"; break; + case OrInt64: o << "i64.or"; break; + case XorInt64: o << "i64.xor"; break; + case ShlInt64: o << "i64.shl"; break; + case ShrUInt64: o << "i64.shr_u"; break; + case ShrSInt64: o << "i64.shr_s"; break; + case RotLInt64: o << "i64.rotl"; break; + case RotRInt64: o << "i64.rotr"; break; + case EqInt64: o << "i64.eq"; break; + case NeInt64: o << "i64.ne"; break; + case LtSInt64: o << "i64.lt_s"; break; + case LtUInt64: o << "i64.lt_u"; break; + case LeSInt64: o << "i64.le_s"; break; + case LeUInt64: o << "i64.le_u"; break; + case GtSInt64: o << "i64.gt_s"; break; + case GtUInt64: o << "i64.gt_u"; break; + case GeSInt64: o << "i64.ge_s"; break; + case GeUInt64: o << "i64.ge_u"; break; + + case AddFloat32: o << "f32.add"; break; + case SubFloat32: o << "f32.sub"; break; + case MulFloat32: o << "f32.mul"; break; + case DivFloat32: o << "f32.div"; break; + case CopySignFloat32: o << "f32.copysign"; break; + case MinFloat32: o << "f32.min"; break; + case MaxFloat32: o << "f32.max"; break; + case EqFloat32: o << "f32.eq"; break; + case NeFloat32: o << "f32.ne"; break; + case LtFloat32: o << "f32.lt"; break; + case LeFloat32: o << "f32.le"; break; + case GtFloat32: o << "f32.gt"; break; + case GeFloat32: o << "f32.ge"; break; + + case AddFloat64: o << "f64.add"; break; + case SubFloat64: o << "f64.sub"; break; + case MulFloat64: o << "f64.mul"; break; + case DivFloat64: o << "f64.div"; break; + case CopySignFloat64: o << "f64.copysign"; break; + case MinFloat64: o << "f64.min"; break; + case MaxFloat64: o << "f64.max"; break; + case EqFloat64: o << "f64.eq"; break; + case NeFloat64: o << "f64.ne"; break; + case LtFloat64: o << "f64.lt"; break; + case LeFloat64: o << "f64.le"; break; + case GtFloat64: o << "f64.gt"; break; + case GeFloat64: o << "f64.ge"; break; + default: abort(); } restoreNormalColor(o); diff --git a/src/s2wasm.h b/src/s2wasm.h index 68a7c5b62..79ba4c138 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -740,11 +740,14 @@ class S2WasmBuilder { setOutput(curr, assign); } }; + #define BINARY_INT_OR_FLOAT(op) (type == i32 ? BinaryOp::op##Int32 : (type == i64 ? BinaryOp::op##Int64 : (type == f32 ? BinaryOp::op##Float32 : BinaryOp::op##Float64))) + #define BINARY_INT(op) (type == i32 ? BinaryOp::op##Int32 : BinaryOp::op##Int64) + #define BINARY_FLOAT(op) (type == f32 ? BinaryOp::op##Float32 : BinaryOp::op##Float64) auto handleTyped = [&](WasmType type) { switch (*s) { case 'a': { - if (match("add")) makeBinary(BinaryOp::Add, type); - else if (match("and")) makeBinary(BinaryOp::And, type); + if (match("add")) makeBinary(BINARY_INT_OR_FLOAT(Add), type); + else if (match("and")) makeBinary(BINARY_INT(And), type); else if (match("abs")) makeUnary(type == f32 ? UnaryOp::AbsFloat32 : UnaryOp::AbsFloat64, type); else abort_on("type.a"); break; @@ -770,22 +773,22 @@ class S2WasmBuilder { else if (match("convert_u/i64")) makeUnary(type == f32 ? UnaryOp::ConvertUInt64ToFloat32 : UnaryOp::ConvertUInt64ToFloat64, type); else if (match("clz")) makeUnary(type == i32 ? UnaryOp::ClzInt32 : UnaryOp::ClzInt64, type); else if (match("ctz")) makeUnary(type == i32 ? UnaryOp::CtzInt32 : UnaryOp::CtzInt64, type); - else if (match("copysign")) makeBinary(BinaryOp::CopySign, type); + else if (match("copysign")) makeBinary(BINARY_FLOAT(CopySign), type); else if (match("ceil")) makeUnary(type == f32 ? UnaryOp::CeilFloat32 : UnaryOp::CeilFloat64, type); else abort_on("type.c"); break; } case 'd': { if (match("demote/f64")) makeUnary(UnaryOp::DemoteFloat64, type); - else if (match("div_s")) makeBinary(BinaryOp::DivS, type); - else if (match("div_u")) makeBinary(BinaryOp::DivU, type); - else if (match("div")) makeBinary(BinaryOp::Div, type); + else if (match("div_s")) makeBinary(BINARY_INT(DivS), type); + else if (match("div_u")) makeBinary(BINARY_INT(DivU), type); + else if (match("div")) makeBinary(BINARY_FLOAT(Div), type); else abort_on("type.g"); break; } case 'e': { if (match("eqz")) makeUnary(type == i32 ? UnaryOp::EqZInt32 : UnaryOp::EqZInt64, type); - else if (match("eq")) makeBinary(BinaryOp::Eq, i32); + else if (match("eq")) makeBinary(BINARY_INT_OR_FLOAT(Eq), i32); else if (match("extend_s/i32")) makeUnary(UnaryOp::ExtendSInt32, type); else if (match("extend_u/i32")) makeUnary(UnaryOp::ExtendUInt32, type); else abort_on("type.e"); @@ -797,42 +800,42 @@ class S2WasmBuilder { break; } case 'g': { - if (match("gt_s")) makeBinary(BinaryOp::GtS, i32); - else if (match("gt_u")) makeBinary(BinaryOp::GtU, i32); - else if (match("ge_s")) makeBinary(BinaryOp::GeS, i32); - else if (match("ge_u")) makeBinary(BinaryOp::GeU, i32); - else if (match("gt")) makeBinary(BinaryOp::Gt, i32); - else if (match("ge")) makeBinary(BinaryOp::Ge, i32); + if (match("gt_s")) makeBinary(BINARY_INT(GtS), i32); + else if (match("gt_u")) makeBinary(BINARY_INT(GtU), i32); + else if (match("ge_s")) makeBinary(BINARY_INT(GeS), i32); + else if (match("ge_u")) makeBinary(BINARY_INT(GeU), i32); + else if (match("gt")) makeBinary(BINARY_FLOAT(Gt), i32); + else if (match("ge")) makeBinary(BINARY_FLOAT(Ge), i32); else abort_on("type.g"); break; } case 'l': { - if (match("lt_s")) makeBinary(BinaryOp::LtS, i32); - else if (match("lt_u")) makeBinary(BinaryOp::LtU, i32); - else if (match("le_s")) makeBinary(BinaryOp::LeS, i32); - else if (match("le_u")) makeBinary(BinaryOp::LeU, i32); + if (match("lt_s")) makeBinary(BINARY_INT(LtS), i32); + else if (match("lt_u")) makeBinary(BINARY_INT(LtU), i32); + else if (match("le_s")) makeBinary(BINARY_INT(LeS), i32); + else if (match("le_u")) makeBinary(BINARY_INT(LeU), i32); else if (match("load")) makeLoad(type); - else if (match("lt")) makeBinary(BinaryOp::Lt, i32); - else if (match("le")) makeBinary(BinaryOp::Le, i32); + else if (match("lt")) makeBinary(BINARY_FLOAT(Lt), i32); + else if (match("le")) makeBinary(BINARY_FLOAT(Le), i32); else abort_on("type.g"); break; } case 'm': { - if (match("mul")) makeBinary(BinaryOp::Mul, type); - else if (match("min")) makeBinary(BinaryOp::Min, type); - else if (match("max")) makeBinary(BinaryOp::Max, type); + if (match("mul")) makeBinary(BINARY_INT_OR_FLOAT(Mul), type); + else if (match("min")) makeBinary(BINARY_FLOAT(Min), type); + else if (match("max")) makeBinary(BINARY_FLOAT(Max), type); else abort_on("type.m"); break; } case 'n': { if (match("neg")) makeUnary(type == f32 ? UnaryOp::NegFloat32 : UnaryOp::NegFloat64, type); else if (match("nearest")) makeUnary(type == f32 ? UnaryOp::NearestFloat32 : UnaryOp::NearestFloat64, type); - else if (match("ne")) makeBinary(BinaryOp::Ne, i32); + else if (match("ne")) makeBinary(BINARY_INT_OR_FLOAT(Ne), i32); else abort_on("type.n"); break; } case 'o': { - if (match("or")) makeBinary(BinaryOp::Or, type); + if (match("or")) makeBinary(BINARY_INT(Or), type); else abort_on("type.o"); break; } @@ -843,22 +846,22 @@ class S2WasmBuilder { break; } case 'r': { - if (match("rem_s")) makeBinary(BinaryOp::RemS, type); - else if (match("rem_u")) makeBinary(BinaryOp::RemU, type); + if (match("rem_s")) makeBinary(BINARY_INT(RemS), type); + else if (match("rem_u")) makeBinary(BINARY_INT(RemU), type); else if (match("reinterpret/i32")) makeUnary(UnaryOp::ReinterpretInt32, type); else if (match("reinterpret/i64")) makeUnary(UnaryOp::ReinterpretInt64, type); else if (match("reinterpret/f32")) makeUnary(UnaryOp::ReinterpretFloat32, type); else if (match("reinterpret/f64")) makeUnary(UnaryOp::ReinterpretFloat64, type); - else if (match("rotl")) makeBinary(BinaryOp::RotL, type); - else if (match("rotr")) makeBinary(BinaryOp::RotR, type); + else if (match("rotl")) makeBinary(BINARY_INT(RotL), type); + else if (match("rotr")) makeBinary(BINARY_INT(RotR), type); else abort_on("type.r"); break; } case 's': { - if (match("shr_s")) makeBinary(BinaryOp::ShrS, type); - else if (match("shr_u")) makeBinary(BinaryOp::ShrU, type); - else if (match("shl")) makeBinary(BinaryOp::Shl, type); - else if (match("sub")) makeBinary(BinaryOp::Sub, type); + if (match("shr_s")) makeBinary(BINARY_INT(ShrS), type); + else if (match("shr_u")) makeBinary(BINARY_INT(ShrU), type); + else if (match("shl")) makeBinary(BINARY_INT(Shl), type); + else if (match("sub")) makeBinary(BINARY_INT_OR_FLOAT(Sub), type); else if (match("store")) makeStore(type); else if (match("select")) makeSelect(type); else if (match("sqrt")) makeUnary(type == f32 ? UnaryOp::SqrtFloat32 : UnaryOp::SqrtFloat64, type); @@ -880,7 +883,7 @@ class S2WasmBuilder { break; } case 'x': { - if (match("xor")) makeBinary(BinaryOp::Xor, type); + if (match("xor")) makeBinary(BINARY_INT(Xor), type); else abort_on("type.x"); break; } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index a2ea93605..9f061db47 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1065,72 +1065,89 @@ public: if (debug) std::cerr << "zz node: Binary" << std::endl; recurse(curr->left); recurse(curr->right); - #define TYPED_CODE(code) { \ - switch (getReachableWasmType(curr->left->type, curr->right->type)) { \ - case i32: o << int8_t(BinaryConsts::I32##code); break; \ - case i64: o << int8_t(BinaryConsts::I64##code); break; \ - case f32: o << int8_t(BinaryConsts::F32##code); break; \ - case f64: o << int8_t(BinaryConsts::F64##code); break; \ - default: abort(); \ - } \ - break; \ - } - #define INT_TYPED_CODE(code) { \ - switch (getReachableWasmType(curr->left->type, curr->right->type)) { \ - case i32: o << int8_t(BinaryConsts::I32##code); break; \ - case i64: o << int8_t(BinaryConsts::I64##code); break; \ - default: abort(); \ - } \ - break; \ - } - #define FLOAT_TYPED_CODE(code) { \ - switch (getReachableWasmType(curr->left->type, curr->right->type)) { \ - case f32: o << int8_t(BinaryConsts::F32##code); break; \ - case f64: o << int8_t(BinaryConsts::F64##code); break; \ - default: abort(); \ - } \ - break; \ - } switch (curr->op) { - case Add: TYPED_CODE(Add); - case Sub: TYPED_CODE(Sub); - case Mul: TYPED_CODE(Mul); - case DivS: INT_TYPED_CODE(DivS); - case DivU: INT_TYPED_CODE(DivU); - case RemS: INT_TYPED_CODE(RemS); - case RemU: INT_TYPED_CODE(RemU); - case And: INT_TYPED_CODE(And); - case Or: INT_TYPED_CODE(Or); - case Xor: INT_TYPED_CODE(Xor); - case Shl: INT_TYPED_CODE(Shl);; - case ShrU: INT_TYPED_CODE(ShrU); - case ShrS: INT_TYPED_CODE(ShrS); - case RotL: INT_TYPED_CODE(RotL); - case RotR: INT_TYPED_CODE(RotR); - case Div: FLOAT_TYPED_CODE(Div); - case CopySign: FLOAT_TYPED_CODE(CopySign); - case Min: FLOAT_TYPED_CODE(Min); - case Max: FLOAT_TYPED_CODE(Max); - case Eq: TYPED_CODE(Eq); - case Ne: TYPED_CODE(Ne); - case LtS: INT_TYPED_CODE(LtS); - case LtU: INT_TYPED_CODE(LtU); - case LeS: INT_TYPED_CODE(LeS); - case LeU: INT_TYPED_CODE(LeU); - case GtS: INT_TYPED_CODE(GtS); - case GtU: INT_TYPED_CODE(GtU); - case GeS: INT_TYPED_CODE(GeS); - case GeU: INT_TYPED_CODE(GeU); - case Lt: FLOAT_TYPED_CODE(Lt); - case Le: FLOAT_TYPED_CODE(Le); - case Gt: FLOAT_TYPED_CODE(Gt); - case Ge: FLOAT_TYPED_CODE(Ge); - default: abort(); + case AddInt32: o << int8_t(BinaryConsts::I32Add); break; + case SubInt32: o << int8_t(BinaryConsts::I32Sub); break; + case MulInt32: o << int8_t(BinaryConsts::I32Mul); break; + case DivSInt32: o << int8_t(BinaryConsts::I32DivS); break; + case DivUInt32: o << int8_t(BinaryConsts::I32DivU); break; + case RemSInt32: o << int8_t(BinaryConsts::I32RemS); break; + case RemUInt32: o << int8_t(BinaryConsts::I32RemU); break; + case AndInt32: o << int8_t(BinaryConsts::I32And); break; + case OrInt32: o << int8_t(BinaryConsts::I32Or); break; + case XorInt32: o << int8_t(BinaryConsts::I32Xor); break; + case ShlInt32: o << int8_t(BinaryConsts::I32Shl); break; + case ShrUInt32: o << int8_t(BinaryConsts::I32ShrU); break; + case ShrSInt32: o << int8_t(BinaryConsts::I32ShrS); break; + case RotLInt32: o << int8_t(BinaryConsts::I32RotL); break; + case RotRInt32: o << int8_t(BinaryConsts::I32RotR); break; + case EqInt32: o << int8_t(BinaryConsts::I32Eq); break; + case NeInt32: o << int8_t(BinaryConsts::I32Ne); break; + case LtSInt32: o << int8_t(BinaryConsts::I32LtS); break; + case LtUInt32: o << int8_t(BinaryConsts::I32LtU); break; + case LeSInt32: o << int8_t(BinaryConsts::I32LeS); break; + case LeUInt32: o << int8_t(BinaryConsts::I32LeU); break; + case GtSInt32: o << int8_t(BinaryConsts::I32GtS); break; + case GtUInt32: o << int8_t(BinaryConsts::I32GtU); break; + case GeSInt32: o << int8_t(BinaryConsts::I32GeS); break; + case GeUInt32: o << int8_t(BinaryConsts::I32GeU); break; + + case AddInt64: o << int8_t(BinaryConsts::I64Add); break; + case SubInt64: o << int8_t(BinaryConsts::I64Sub); break; + case MulInt64: o << int8_t(BinaryConsts::I64Mul); break; + case DivSInt64: o << int8_t(BinaryConsts::I64DivS); break; + case DivUInt64: o << int8_t(BinaryConsts::I64DivU); break; + case RemSInt64: o << int8_t(BinaryConsts::I64RemS); break; + case RemUInt64: o << int8_t(BinaryConsts::I64RemU); break; + case AndInt64: o << int8_t(BinaryConsts::I64And); break; + case OrInt64: o << int8_t(BinaryConsts::I64Or); break; + case XorInt64: o << int8_t(BinaryConsts::I64Xor); break; + case ShlInt64: o << int8_t(BinaryConsts::I64Shl); break; + case ShrUInt64: o << int8_t(BinaryConsts::I64ShrU); break; + case ShrSInt64: o << int8_t(BinaryConsts::I64ShrS); break; + case RotLInt64: o << int8_t(BinaryConsts::I64RotL); break; + case RotRInt64: o << int8_t(BinaryConsts::I64RotR); break; + case EqInt64: o << int8_t(BinaryConsts::I64Eq); break; + case NeInt64: o << int8_t(BinaryConsts::I64Ne); break; + case LtSInt64: o << int8_t(BinaryConsts::I64LtS); break; + case LtUInt64: o << int8_t(BinaryConsts::I64LtU); break; + case LeSInt64: o << int8_t(BinaryConsts::I64LeS); break; + case LeUInt64: o << int8_t(BinaryConsts::I64LeU); break; + case GtSInt64: o << int8_t(BinaryConsts::I64GtS); break; + case GtUInt64: o << int8_t(BinaryConsts::I64GtU); break; + case GeSInt64: o << int8_t(BinaryConsts::I64GeS); break; + case GeUInt64: o << int8_t(BinaryConsts::I64GeU); break; + + case AddFloat32: o << int8_t(BinaryConsts::F32Add); break; + case SubFloat32: o << int8_t(BinaryConsts::F32Sub); break; + case MulFloat32: o << int8_t(BinaryConsts::F32Mul); break; + case DivFloat32: o << int8_t(BinaryConsts::F32Div); break; + case CopySignFloat32: o << int8_t(BinaryConsts::F32CopySign);break; + case MinFloat32: o << int8_t(BinaryConsts::F32Min); break; + case MaxFloat32: o << int8_t(BinaryConsts::F32Max); break; + case EqFloat32: o << int8_t(BinaryConsts::F32Eq); break; + case NeFloat32: o << int8_t(BinaryConsts::F32Ne); break; + case LtFloat32: o << int8_t(BinaryConsts::F32Lt); break; + case LeFloat32: o << int8_t(BinaryConsts::F32Le); break; + case GtFloat32: o << int8_t(BinaryConsts::F32Gt); break; + case GeFloat32: o << int8_t(BinaryConsts::F32Ge); break; + + case AddFloat64: o << int8_t(BinaryConsts::F64Add); break; + case SubFloat64: o << int8_t(BinaryConsts::F64Sub); break; + case MulFloat64: o << int8_t(BinaryConsts::F64Mul); break; + case DivFloat64: o << int8_t(BinaryConsts::F64Div); break; + case CopySignFloat64: o << int8_t(BinaryConsts::F64CopySign);break; + case MinFloat64: o << int8_t(BinaryConsts::F64Min); break; + case MaxFloat64: o << int8_t(BinaryConsts::F64Max); break; + case EqFloat64: o << int8_t(BinaryConsts::F64Eq); break; + case NeFloat64: o << int8_t(BinaryConsts::F64Ne); break; + case LtFloat64: o << int8_t(BinaryConsts::F64Lt); break; + case LeFloat64: o << int8_t(BinaryConsts::F64Le); break; + case GtFloat64: o << int8_t(BinaryConsts::F64Gt); break; + case GeFloat64: o << int8_t(BinaryConsts::F64Ge); break; + default: abort(); } - #undef TYPED_CODE - #undef INT_TYPED_CODE - #undef FLOAT_TYPED_CODE } void visitSelect(Select *curr) { if (debug) std::cerr << "zz node: Select" << std::endl; @@ -1968,20 +1985,19 @@ public: } bool maybeVisitBinary(Expression*& out, uint8_t code) { Binary* curr; - #define TYPED_CODE(code) { \ - case BinaryConsts::I32##code: curr = allocator.alloc<Binary>(); curr->op = code; curr->type = i32; break; \ - case BinaryConsts::I64##code: curr = allocator.alloc<Binary>(); curr->op = code; curr->type = i64; break; \ - case BinaryConsts::F32##code: curr = allocator.alloc<Binary>(); curr->op = code; curr->type = f32; break; \ - case BinaryConsts::F64##code: curr = allocator.alloc<Binary>(); curr->op = code; curr->type = f64; break; \ - } #define INT_TYPED_CODE(code) { \ - case BinaryConsts::I32##code: curr = allocator.alloc<Binary>(); curr->op = code; curr->type = i32; break; \ - case BinaryConsts::I64##code: curr = allocator.alloc<Binary>(); curr->op = code; curr->type = i64; break; \ + case BinaryConsts::I32##code: curr = allocator.alloc<Binary>(); curr->op = code##Int32; curr->type = i32; break; \ + case BinaryConsts::I64##code: curr = allocator.alloc<Binary>(); curr->op = code##Int64; curr->type = i64; break; \ } #define FLOAT_TYPED_CODE(code) { \ - case BinaryConsts::F32##code: curr = allocator.alloc<Binary>(); curr->op = code; curr->type = f32; break; \ - case BinaryConsts::F64##code: curr = allocator.alloc<Binary>(); curr->op = code; curr->type = f64; break; \ + case BinaryConsts::F32##code: curr = allocator.alloc<Binary>(); curr->op = code##Float32; curr->type = f32; break; \ + case BinaryConsts::F64##code: curr = allocator.alloc<Binary>(); curr->op = code##Float64; curr->type = f64; break; \ } + #define TYPED_CODE(code) { \ + INT_TYPED_CODE(code) \ + FLOAT_TYPED_CODE(code) \ + } + switch (code) { TYPED_CODE(Add); TYPED_CODE(Sub); diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 21ccd7a47..3ac3cf1e4 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -489,105 +489,105 @@ private: assert(isConcreteWasmType(curr->right->type) ? right.type == curr->right->type : true); if (left.type == i32) { switch (curr->op) { - case Add: return left.add(right); - case Sub: return left.sub(right); - case Mul: return left.mul(right); - case DivS: { + case AddInt32: return left.add(right); + case SubInt32: return left.sub(right); + case MulInt32: return left.mul(right); + case DivSInt32: { if (right.getInteger() == 0) trap("i32.div_s by 0"); if (left.getInteger() == std::numeric_limits<int32_t>::min() && right.getInteger() == -1) trap("i32.div_s overflow"); // signed division overflow return left.divS(right); } - case DivU: { + case DivUInt32: { if (right.getInteger() == 0) trap("i32.div_u by 0"); return left.divU(right); } - case RemS: { + case RemSInt32: { if (right.getInteger() == 0) trap("i32.rem_s by 0"); if (left.getInteger() == std::numeric_limits<int32_t>::min() && right.getInteger() == -1) return Literal(int32_t(0)); return left.remS(right); } - case RemU: { + case RemUInt32: { if (right.getInteger() == 0) trap("i32.rem_u by 0"); return left.remU(right); } - case And: return left.and_(right); - case Or: return left.or_(right); - case Xor: return left.xor_(right); - case Shl: return left.shl(right.and_(Literal(int32_t(31)))); - case ShrU: return left.shrU(right.and_(Literal(int32_t(31)))); - case ShrS: return left.shrS(right.and_(Literal(int32_t(31)))); - case RotL: return left.rotL(right); - case RotR: return left.rotR(right); - case Eq: return left.eq(right); - case Ne: return left.ne(right); - case LtS: return left.ltS(right); - case LtU: return left.ltU(right); - case LeS: return left.leS(right); - case LeU: return left.leU(right); - case GtS: return left.gtS(right); - case GtU: return left.gtU(right); - case GeS: return left.geS(right); - case GeU: return left.geU(right); + case AndInt32: return left.and_(right); + case OrInt32: return left.or_(right); + case XorInt32: return left.xor_(right); + case ShlInt32: return left.shl(right.and_(Literal(int32_t(31)))); + case ShrUInt32: return left.shrU(right.and_(Literal(int32_t(31)))); + case ShrSInt32: return left.shrS(right.and_(Literal(int32_t(31)))); + case RotLInt32: return left.rotL(right); + case RotRInt32: return left.rotR(right); + case EqInt32: return left.eq(right); + case NeInt32: return left.ne(right); + case LtSInt32: return left.ltS(right); + case LtUInt32: return left.ltU(right); + case LeSInt32: return left.leS(right); + case LeUInt32: return left.leU(right); + case GtSInt32: return left.gtS(right); + case GtUInt32: return left.gtU(right); + case GeSInt32: return left.geS(right); + case GeUInt32: return left.geU(right); default: abort(); } } else if (left.type == i64) { switch (curr->op) { - case Add: return left.add(right); - case Sub: return left.sub(right); - case Mul: return left.mul(right); - case DivS: { + case AddInt64: return left.add(right); + case SubInt64: return left.sub(right); + case MulInt64: return left.mul(right); + case DivSInt64: { if (right.getInteger() == 0) trap("i64.div_s by 0"); if (left.getInteger() == LLONG_MIN && right.getInteger() == -1LL) trap("i64.div_s overflow"); // signed division overflow return left.divS(right); } - case DivU: { + case DivUInt64: { if (right.getInteger() == 0) trap("i64.div_u by 0"); return left.divU(right); } - case RemS: { + case RemSInt64: { if (right.getInteger() == 0) trap("i64.rem_s by 0"); if (left.getInteger() == LLONG_MIN && right.getInteger() == -1LL) return Literal(int64_t(0)); return left.remS(right); } - case RemU: { + case RemUInt64: { if (right.getInteger() == 0) trap("i64.rem_u by 0"); return left.remU(right); } - case And: return left.and_(right); - case Or: return left.or_(right); - case Xor: return left.xor_(right); - case Shl: return left.shl(right.and_(Literal(int64_t(63)))); - case ShrU: return left.shrU(right.and_(Literal(int64_t(63)))); - case ShrS: return left.shrS(right.and_(Literal(int64_t(63)))); - case RotL: return left.rotL(right); - case RotR: return left.rotR(right); - case Eq: return left.eq(right); - case Ne: return left.ne(right); - case LtS: return left.ltS(right); - case LtU: return left.ltU(right); - case LeS: return left.leS(right); - case LeU: return left.leU(right); - case GtS: return left.gtS(right); - case GtU: return left.gtU(right); - case GeS: return left.geS(right); - case GeU: return left.geU(right); + case AndInt64: return left.and_(right); + case OrInt64: return left.or_(right); + case XorInt64: return left.xor_(right); + case ShlInt64: return left.shl(right.and_(Literal(int64_t(63)))); + case ShrUInt64: return left.shrU(right.and_(Literal(int64_t(63)))); + case ShrSInt64: return left.shrS(right.and_(Literal(int64_t(63)))); + case RotLInt64: return left.rotL(right); + case RotRInt64: return left.rotR(right); + case EqInt64: return left.eq(right); + case NeInt64: return left.ne(right); + case LtSInt64: return left.ltS(right); + case LtUInt64: return left.ltU(right); + case LeSInt64: return left.leS(right); + case LeUInt64: return left.leU(right); + case GtSInt64: return left.gtS(right); + case GtUInt64: return left.gtU(right); + case GeSInt64: return left.geS(right); + case GeUInt64: return left.geU(right); default: abort(); } } else if (left.type == f32 || left.type == f64) { switch (curr->op) { - case Add: return left.add(right); - case Sub: return left.sub(right); - case Mul: return left.mul(right); - case Div: return left.div(right); - case CopySign: return left.copysign(right); - case Min: return left.min(right); - case Max: return left.max(right); - case Eq: return left.eq(right); - case Ne: return left.ne(right); - case Lt: return left.lt(right); - case Le: return left.le(right); - case Gt: return left.gt(right); - case Ge: return left.ge(right); + case AddFloat32: case AddFloat64: return left.add(right); + case SubFloat32: case SubFloat64: return left.sub(right); + case MulFloat32: case MulFloat64: return left.mul(right); + case DivFloat32: case DivFloat64: return left.div(right); + case CopySignFloat32: case CopySignFloat64: return left.copysign(right); + case MinFloat32: case MinFloat64: return left.min(right); + case MaxFloat32: case MaxFloat64: return left.max(right); + case EqFloat32: case EqFloat64: return left.eq(right); + case NeFloat32: case NeFloat64: return left.ne(right); + case LtFloat32: case LtFloat64: return left.lt(right); + case LeFloat32: case LeFloat64: return left.le(right); + case GtFloat32: case GtFloat64: return left.gt(right); + case GeFloat32: case GeFloat64: return left.ge(right); default: abort(); } } diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 0ffbfe989..42c1ce88e 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -527,18 +527,21 @@ public: enum { maxNameSize = 15 }; char op[maxNameSize + 1] = {'\0'}; strncpy(op, dot + 1, maxNameSize); + #define BINARY_INT_OR_FLOAT(op) (type == i32 ? BinaryOp::op##Int32 : (type == i64 ? BinaryOp::op##Int64 : (type == f32 ? BinaryOp::op##Float32 : BinaryOp::op##Float64))) + #define BINARY_INT(op) (type == i32 ? BinaryOp::op##Int32 : BinaryOp::op##Int64) + #define BINARY_FLOAT(op) (type == f32 ? BinaryOp::op##Float32 : BinaryOp::op##Float64) switch (op[0]) { case 'a': { if (op[1] == 'b') return makeUnary(s, type == f32 ? UnaryOp::AbsFloat32 : UnaryOp::AbsFloat64, type); - if (op[1] == 'd') return makeBinary(s, BinaryOp::Add, type); - if (op[1] == 'n') return makeBinary(s, BinaryOp::And, type); + if (op[1] == 'd') return makeBinary(s, BINARY_INT_OR_FLOAT(Add), type); + if (op[1] == 'n') return makeBinary(s, BINARY_INT(And), type); abort_on(op); } case 'c': { if (op[1] == 'e') return makeUnary(s, type == f32 ? UnaryOp::CeilFloat32 : UnaryOp::CeilFloat64, type); if (op[1] == 'l') return makeUnary(s, type == i32 ? UnaryOp::ClzInt32 : UnaryOp::ClzInt64, type); if (op[1] == 'o') { - if (op[2] == 'p') return makeBinary(s, BinaryOp::CopySign, type); + if (op[2] == 'p') return makeBinary(s, BINARY_FLOAT(CopySign), type); if (op[2] == 'n') { if (op[3] == 'v') { if (op[8] == 's') return makeUnary(s, op[11] == '3' ? (type == f32 ? UnaryOp::ConvertSInt32ToFloat32 : UnaryOp::ConvertSInt32ToFloat64) : (type == f32 ? UnaryOp::ConvertSInt64ToFloat32 : UnaryOp::ConvertSInt64ToFloat64), type); @@ -552,15 +555,15 @@ public: } case 'd': { if (op[1] == 'i') { - if (op[3] == '_') return makeBinary(s, op[4] == 'u' ? BinaryOp::DivU : BinaryOp::DivS, type); - if (op[3] == 0) return makeBinary(s, BinaryOp::Div, type); + if (op[3] == '_') return makeBinary(s, op[4] == 'u' ? BINARY_INT(DivU) : BINARY_INT(DivS), type); + if (op[3] == 0) return makeBinary(s, BINARY_FLOAT(Div), type); } if (op[1] == 'e') return makeUnary(s, UnaryOp::DemoteFloat64, type); abort_on(op); } case 'e': { if (op[1] == 'q') { - if (op[2] == 0) return makeBinary(s, BinaryOp::Eq, type); + if (op[2] == 0) return makeBinary(s, BINARY_INT_OR_FLOAT(Eq), type); if (op[2] == 'z') return makeUnary(s, type == i32 ? UnaryOp::EqZInt32 : UnaryOp::EqZInt64, type); } if (op[1] == 'x') return makeUnary(s, op[7] == 'u' ? UnaryOp::ExtendUInt32 : UnaryOp::ExtendSInt32, type); @@ -572,43 +575,43 @@ public: } case 'g': { if (op[1] == 't') { - if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BinaryOp::GtU : BinaryOp::GtS, type); - if (op[2] == 0) return makeBinary(s, BinaryOp::Gt, type); + if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BINARY_INT(GtU) : BINARY_INT(GtS), type); + if (op[2] == 0) return makeBinary(s, BINARY_FLOAT(Gt), type); } if (op[1] == 'e') { - if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BinaryOp::GeU : BinaryOp::GeS, type); - if (op[2] == 0) return makeBinary(s, BinaryOp::Ge, type); + if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BINARY_INT(GeU) : BINARY_INT(GeS), type); + if (op[2] == 0) return makeBinary(s, BINARY_FLOAT(Ge), type); } abort_on(op); } case 'l': { if (op[1] == 't') { - if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BinaryOp::LtU : BinaryOp::LtS, type); - if (op[2] == 0) return makeBinary(s, BinaryOp::Lt, type); + if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BINARY_INT(LtU) : BINARY_INT(LtS), type); + if (op[2] == 0) return makeBinary(s, BINARY_FLOAT(Lt), type); } if (op[1] == 'e') { - if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BinaryOp::LeU : BinaryOp::LeS, type); - if (op[2] == 0) return makeBinary(s, BinaryOp::Le, type); + if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BINARY_INT(LeU) : BINARY_INT(LeS), type); + if (op[2] == 0) return makeBinary(s, BINARY_FLOAT(Le), type); } if (op[1] == 'o') return makeLoad(s, type); abort_on(op); } case 'm': { - if (op[1] == 'i') return makeBinary(s, BinaryOp::Min, type); - if (op[1] == 'a') return makeBinary(s, BinaryOp::Max, type); - if (op[1] == 'u') return makeBinary(s, BinaryOp::Mul, type); + if (op[1] == 'i') return makeBinary(s, BINARY_FLOAT(Min), type); + if (op[1] == 'a') return makeBinary(s, BINARY_FLOAT(Max), type); + if (op[1] == 'u') return makeBinary(s, BINARY_INT_OR_FLOAT(Mul), type); abort_on(op); } case 'n': { if (op[1] == 'e') { - if (op[2] == 0) return makeBinary(s, BinaryOp::Ne, type); + if (op[2] == 0) return makeBinary(s, BINARY_INT_OR_FLOAT(Ne), type); if (op[2] == 'a') return makeUnary(s, type == f32 ? UnaryOp::NearestFloat32 : UnaryOp::NearestFloat64, type); if (op[2] == 'g') return makeUnary(s, type == f32 ? UnaryOp::NegFloat32 : UnaryOp::NegFloat64, type); } abort_on(op); } case 'o': { - if (op[1] == 'r') return makeBinary(s, BinaryOp::Or, type); + if (op[1] == 'r') return makeBinary(s, BINARY_INT(Or), type); abort_on(op); } case 'p': { @@ -618,20 +621,20 @@ public: } case 'r': { if (op[1] == 'e') { - if (op[2] == 'm') return makeBinary(s, op[4] == 'u' ? BinaryOp::RemU : BinaryOp::RemS, type); + if (op[2] == 'm') return makeBinary(s, op[4] == 'u' ? BINARY_INT(RemU) : BINARY_INT(RemS), type); if (op[2] == 'i') return makeUnary(s, isWasmTypeFloat(type) ? (type == f32 ? UnaryOp::ReinterpretInt32 : UnaryOp::ReinterpretInt64) : (type == i32 ? UnaryOp::ReinterpretFloat32 : UnaryOp::ReinterpretFloat64), type); } if (op[1] == 'o' && op[2] == 't') { - return makeBinary(s, op[3] == 'l' ? BinaryOp::RotL : BinaryOp::RotR, type); + return makeBinary(s, op[3] == 'l' ? BINARY_INT(RotL) : BINARY_INT(RotR), type); } abort_on(op); } case 's': { if (op[1] == 'h') { - if (op[2] == 'l') return makeBinary(s, BinaryOp::Shl, type); - return makeBinary(s, op[4] == 'u' ? BinaryOp::ShrU : BinaryOp::ShrS, type); + if (op[2] == 'l') return makeBinary(s, BINARY_INT(Shl), type); + return makeBinary(s, op[4] == 'u' ? BINARY_INT(ShrU) : BINARY_INT(ShrS), type); } - if (op[1] == 'u') return makeBinary(s, BinaryOp::Sub, type); + if (op[1] == 'u') return makeBinary(s, BINARY_INT_OR_FLOAT(Sub), type); if (op[1] == 'q') return makeUnary(s, type == f32 ? UnaryOp::SqrtFloat32 : UnaryOp::SqrtFloat64, type); if (op[1] == 't') return makeStore(s, type); abort_on(op); @@ -649,7 +652,7 @@ public: abort_on(op); } case 'x': { - if (op[1] == 'o') return makeBinary(s, BinaryOp::Xor, type); + if (op[1] == 'o') return makeBinary(s, BINARY_INT(Xor), type); abort_on(op); } default: abort_on(op); diff --git a/src/wasm.h b/src/wasm.h index 6e7ca18ce..fc0337700 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -791,13 +791,29 @@ enum UnaryOp { }; enum BinaryOp { - Add, Sub, Mul, // int or float - DivS, DivU, RemS, RemU, And, Or, Xor, Shl, ShrU, ShrS, RotL, RotR, // int - Div, CopySign, Min, Max, // float + AddInt32, SubInt32, MulInt32, // int or float + DivSInt32, DivUInt32, RemSInt32, RemUInt32, AndInt32, OrInt32, XorInt32, ShlInt32, ShrUInt32, ShrSInt32, RotLInt32, RotRInt32, // int // relational ops - Eq, Ne, // int or float - LtS, LtU, LeS, LeU, GtS, GtU, GeS, GeU, // int - Lt, Le, Gt, Ge // float + EqInt32, NeInt32, // int or float + LtSInt32, LtUInt32, LeSInt32, LeUInt32, GtSInt32, GtUInt32, GeSInt32, GeUInt32, // int + + AddInt64, SubInt64, MulInt64, // int or float + DivSInt64, DivUInt64, RemSInt64, RemUInt64, AndInt64, OrInt64, XorInt64, ShlInt64, ShrUInt64, ShrSInt64, RotLInt64, RotRInt64, // int + // relational ops + EqInt64, NeInt64, // int or float + LtSInt64, LtUInt64, LeSInt64, LeUInt64, GtSInt64, GtUInt64, GeSInt64, GeUInt64, // int + + AddFloat32, SubFloat32, MulFloat32, // int or float + DivFloat32, CopySignFloat32, MinFloat32, MaxFloat32, // float + // relational ops + EqFloat32, NeFloat32, // int or float + LtFloat32, LeFloat32, GtFloat32, GeFloat32, // float + + AddFloat64, SubFloat64, MulFloat64, // int or float + DivFloat64, CopySignFloat64, MinFloat64, MaxFloat64, // float + // relational ops + EqFloat64, NeFloat64, // int or float + LtFloat64, LeFloat64, GtFloat64, GeFloat64, // float }; enum HostOp { @@ -1182,7 +1198,43 @@ public: // the type is always the type of the operands, // except for relationals - bool isRelational() { return op >= Eq; } + bool isRelational() { + switch (op) { + case EqFloat64: + case NeFloat64: + case LtFloat64: + case LeFloat64: + case GtFloat64: + case GeFloat64: + case EqInt32: + case NeInt32: + case LtSInt32: + case LtUInt32: + case LeSInt32: + case LeUInt32: + case GtSInt32: + case GtUInt32: + case GeSInt32: + case GeUInt32: + case EqInt64: + case NeInt64: + case LtSInt64: + case LtUInt64: + case LeSInt64: + case LeUInt64: + case GtSInt64: + case GtUInt64: + case GeSInt64: + case GeUInt64: + case EqFloat32: + case NeFloat32: + case LtFloat32: + case LeFloat32: + case GtFloat32: + case GeFloat32: return true; + default: return false; + } + } void finalize() { if (isRelational()) { diff --git a/test/example/c-api-hello-world.c b/test/example/c-api-hello-world.c index 016c2404b..e4a8a1cad 100644 --- a/test/example/c-api-hello-world.c +++ b/test/example/c-api-hello-world.c @@ -13,7 +13,7 @@ int main() { // Get the 0 and 1 arguments, and add them BinaryenExpressionRef x = BinaryenGetLocal(module, 0, BinaryenInt32()), y = BinaryenGetLocal(module, 1, BinaryenInt32()); - BinaryenExpressionRef add = BinaryenBinary(module, BinaryenAdd(), x, y); + BinaryenExpressionRef add = BinaryenBinary(module, BinaryenAddInt32(), x, y); // Create the add function // Note: no additional local variables diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index dcf1e78ff..4e0bd5af4 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -91,7 +91,7 @@ void test_core() { makeUnary(module, BinaryenCeilFloat32(), 3), makeUnary(module, BinaryenFloorFloat64(), 4), makeUnary(module, BinaryenTruncFloat32(), 3), - makeUnary(module, BinaryenNearestFloat64(), 3), + makeUnary(module, BinaryenNearestFloat32(), 3), makeUnary(module, BinaryenSqrtFloat64(), 4), makeUnary(module, BinaryenEqZInt32(), 1), makeUnary(module, BinaryenExtendSInt32(), 1), @@ -120,38 +120,38 @@ void test_core() { makeUnary(module, BinaryenReinterpretInt32(), 1), makeUnary(module, BinaryenReinterpretInt64(), 2), // Binary - makeBinary(module, BinaryenAdd(), 1), - makeBinary(module, BinaryenSub(), 4), - makeBinary(module, BinaryenDivS(), 1), - makeBinary(module, BinaryenDivU(), 2), - makeBinary(module, BinaryenRemS(), 2), - makeBinary(module, BinaryenRemU(), 1), - makeBinary(module, BinaryenAnd(), 1), - makeBinary(module, BinaryenOr(), 2), - makeBinary(module, BinaryenXor(), 1), - makeBinary(module, BinaryenShl(), 2), - makeBinary(module, BinaryenShrU(), 2), - makeBinary(module, BinaryenShrS(), 1), - makeBinary(module, BinaryenRotL(), 1), - makeBinary(module, BinaryenRotR(), 2), - makeBinary(module, BinaryenDiv(), 3), - makeBinary(module, BinaryenCopySign(), 4), - makeBinary(module, BinaryenMin(), 3), - makeBinary(module, BinaryenMax(), 4), - makeBinary(module, BinaryenEq(), 1), - makeBinary(module, BinaryenNe(), 3), - makeBinary(module, BinaryenLtS(), 1), - makeBinary(module, BinaryenLtU(), 2), - makeBinary(module, BinaryenLeS(), 2), - makeBinary(module, BinaryenLeU(), 1), - makeBinary(module, BinaryenGtS(), 2), - makeBinary(module, BinaryenGtU(), 1), - makeBinary(module, BinaryenGeS(), 1), - makeBinary(module, BinaryenGeU(), 2), - makeBinary(module, BinaryenLt(), 3), - makeBinary(module, BinaryenLe(), 4), - makeBinary(module, BinaryenGt(), 4), - makeBinary(module, BinaryenGe(), 3), + makeBinary(module, BinaryenAddInt32(), 1), + makeBinary(module, BinaryenSubFloat64(), 4), + makeBinary(module, BinaryenDivSInt32(), 1), + makeBinary(module, BinaryenDivUInt64(), 2), + makeBinary(module, BinaryenRemSInt64(), 2), + makeBinary(module, BinaryenRemUInt32(), 1), + makeBinary(module, BinaryenAndInt32(), 1), + makeBinary(module, BinaryenOrInt64(), 2), + makeBinary(module, BinaryenXorInt32(), 1), + makeBinary(module, BinaryenShlInt64(), 2), + makeBinary(module, BinaryenShrUInt64(), 2), + makeBinary(module, BinaryenShrSInt32(), 1), + makeBinary(module, BinaryenRotLInt32(), 1), + makeBinary(module, BinaryenRotRInt64(), 2), + makeBinary(module, BinaryenDivFloat32(), 3), + makeBinary(module, BinaryenCopySignFloat64(), 4), + makeBinary(module, BinaryenMinFloat32(), 3), + makeBinary(module, BinaryenMaxFloat64(), 4), + makeBinary(module, BinaryenEqInt32(), 1), + makeBinary(module, BinaryenNeFloat32(), 3), + makeBinary(module, BinaryenLtSInt32(), 1), + makeBinary(module, BinaryenLtUInt64(), 2), + makeBinary(module, BinaryenLeSInt64(), 2), + makeBinary(module, BinaryenLeUInt32(), 1), + makeBinary(module, BinaryenGtSInt64(), 2), + makeBinary(module, BinaryenGtUInt32(), 1), + makeBinary(module, BinaryenGeSInt32(), 1), + makeBinary(module, BinaryenGeUInt64(), 2), + makeBinary(module, BinaryenLtFloat32(), 3), + makeBinary(module, BinaryenLeFloat64(), 4), + makeBinary(module, BinaryenGtFloat64(), 4), + makeBinary(module, BinaryenGeFloat32(), 3), // All the rest BinaryenBlock(module, NULL, NULL, 0), // block with no name BinaryenIf(module, makeInt32(module, 1), makeInt32(module, 2), makeInt32(module, 3)), @@ -165,16 +165,16 @@ void test_core() { BinaryenBreak(module, "the-nothing", NULL, NULL), BinaryenSwitch(module, switchValueNames, 1, "the-value", makeInt32(module, 0), makeInt32(module, 1)), BinaryenSwitch(module, switchBodyNames, 1, "the-nothing", makeInt32(module, 2), NULL), - BinaryenUnary(module, BinaryenEqZ(), // check the output type of the call node + BinaryenUnary(module, BinaryenEqZInt32(), // check the output type of the call node BinaryenCall(module, "kitchen-sinker", callOperands4, 4, BinaryenInt32()) ), - BinaryenUnary(module, BinaryenEqZ(), // check the output type of the call node + BinaryenUnary(module, BinaryenEqZInt32(), // check the output type of the call node BinaryenUnary(module, BinaryenTruncSFloat32ToInt32(), BinaryenCallImport(module, "an-imported", callOperands2, 2, BinaryenFloat32()) ) ), - BinaryenUnary(module, BinaryenEqZ(), // check the output type of the call node + BinaryenUnary(module, BinaryenEqZInt32(), // check the output type of the call node BinaryenCallIndirect(module, makeInt32(module, 2449), callOperands4, 4, iiIfF) ), BinaryenGetLocal(module, 0, BinaryenInt32()), @@ -401,7 +401,7 @@ void test_binaries() { BinaryenFunctionTypeRef iii = BinaryenAddFunctionType(module, "iii", BinaryenInt32(), params, 2); BinaryenExpressionRef x = BinaryenGetLocal(module, 0, BinaryenInt32()), y = BinaryenGetLocal(module, 1, BinaryenInt32()); - BinaryenExpressionRef add = BinaryenBinary(module, BinaryenAdd(), x, y); + BinaryenExpressionRef add = BinaryenBinary(module, BinaryenAddInt32(), x, y); BinaryenFunctionRef adder = BinaryenAddFunction(module, "adder", iii, NULL, 0, add); size = BinaryenModuleWrite(module, buffer, 1024); // write out the module BinaryenModuleDispose(module); diff --git a/test/example/find_div0s.cpp b/test/example/find_div0s.cpp index c3a2c0750..45e7f4633 100644 --- a/test/example/find_div0s.cpp +++ b/test/example/find_div0s.cpp @@ -42,7 +42,7 @@ int main() { struct DivZeroSeeker : public PostWalker<DivZeroSeeker, Visitor<DivZeroSeeker>> { void visitBinary(Binary* curr) { // In every Binary, look for integer divisions - if (curr->op == BinaryOp::DivS || curr->op == BinaryOp::DivU) { + if (curr->op == BinaryOp::DivSInt32 || curr->op == BinaryOp::DivUInt32) { // Check if the right operand is a constant, and if it is 0 auto right = curr->right->dynCast<Const>(); if (right && right->value.getInteger() == 0) { diff --git a/test/example/relooper-fuzz.c b/test/example/relooper-fuzz.c index cfd10a9b3..ecb204347 100644 --- a/test/example/relooper-fuzz.c +++ b/test/example/relooper-fuzz.c @@ -16,7 +16,7 @@ int main() { // if the end, halt BinaryenExpressionRef halter = BinaryenIf(module, BinaryenBinary(module, - BinaryenEq(), + BinaryenEqInt32(), BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 27)) // jumps of 4 bytes ), @@ -28,7 +28,7 @@ int main() { 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAdd(), + BinaryenAddInt32(), BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4)) ) @@ -37,7 +37,7 @@ int main() { // optionally, print the return value BinaryenExpressionRef args[] = { BinaryenBinary(module, - BinaryenSub(), + BinaryenSubInt32(), BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, 4, 0, 4, 0, BinaryenInt32(), @@ -155,9 +155,9 @@ int main() { } RelooperAddBranch(b0, b5, BinaryenBinary(module, - BinaryenEq(), + BinaryenEqInt32(), BinaryenBinary(module, - BinaryenRemU(), + BinaryenRemUInt32(), BinaryenGetLocal(module, 0, BinaryenInt32()), BinaryenConst(module, BinaryenLiteralInt32(2)) ), @@ -171,9 +171,9 @@ int main() { RelooperAddBranch(b2, b5, NULL, NULL); RelooperAddBranch(b3, b5, BinaryenBinary(module, - BinaryenEq(), + BinaryenEqInt32(), BinaryenBinary(module, - BinaryenRemU(), + BinaryenRemUInt32(), BinaryenGetLocal(module, 0, BinaryenInt32()), BinaryenConst(module, BinaryenLiteralInt32(2)) ), @@ -183,9 +183,9 @@ int main() { RelooperAddBranch(b3, b8, NULL, NULL); RelooperAddBranch(b4, b4, BinaryenBinary(module, - BinaryenEq(), + BinaryenEqInt32(), BinaryenBinary(module, - BinaryenRemU(), + BinaryenRemUInt32(), BinaryenGetLocal(module, 0, BinaryenInt32()), BinaryenConst(module, BinaryenLiteralInt32(3)) ), @@ -193,9 +193,9 @@ int main() { ), NULL); RelooperAddBranch(b4, b5, BinaryenBinary(module, - BinaryenEq(), + BinaryenEqInt32(), BinaryenBinary(module, - BinaryenRemU(), + BinaryenRemUInt32(), BinaryenGetLocal(module, 0, BinaryenInt32()), BinaryenConst(module, BinaryenLiteralInt32(3)) ), @@ -205,9 +205,9 @@ int main() { RelooperAddBranch(b4, b2, NULL, NULL); RelooperAddBranch(b5, b4, BinaryenBinary(module, - BinaryenEq(), + BinaryenEqInt32(), BinaryenBinary(module, - BinaryenRemU(), + BinaryenRemUInt32(), BinaryenGetLocal(module, 0, BinaryenInt32()), BinaryenConst(module, BinaryenLiteralInt32(2)) ), |