summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/empty.txt0
-rw-r--r--scripts/fuzz_relooper.py12
-rw-r--r--src/asm2wasm.h73
-rw-r--r--src/binaryen-c.cpp109
-rw-r--r--src/binaryen-c.h109
-rw-r--r--src/cfg/Relooper.cpp2
-rw-r--r--src/cfg/Relooper.h2
-rw-r--r--src/passes/OptimizeInstructions.cpp42
-rw-r--r--src/passes/PostEmscripten.cpp2
-rw-r--r--src/passes/Print.cpp115
-rw-r--r--src/s2wasm.h69
-rw-r--r--src/wasm-binary.h162
-rw-r--r--src/wasm-interpreter.h126
-rw-r--r--src/wasm-s-parser.h53
-rw-r--r--src/wasm.h66
-rw-r--r--test/example/c-api-hello-world.c2
-rw-r--r--test/example/c-api-kitchen-sink.c74
-rw-r--r--test/example/find_div0s.cpp2
-rw-r--r--test/example/relooper-fuzz.c26
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))
),