summaryrefslogtreecommitdiff
path: root/src/passes/RemoveNonJSOps.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/RemoveNonJSOps.cpp')
-rw-r--r--src/passes/RemoveNonJSOps.cpp20
1 files changed, 16 insertions, 4 deletions
diff --git a/src/passes/RemoveNonJSOps.cpp b/src/passes/RemoveNonJSOps.cpp
index 7c0a0e2ce..5bbb9f701 100644
--- a/src/passes/RemoveNonJSOps.cpp
+++ b/src/passes/RemoveNonJSOps.cpp
@@ -252,17 +252,29 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> {
}
void rewriteCopysign(Binary* curr) {
+
+ // i32.copysign(x, y) => f32.reinterpret(
+ // (i32.reinterpret(x) & ~(1 << 31)) |
+ // (i32.reinterpret(y) & (1 << 31)
+ // )
+ //
+ // i64.copysign(x, y) => f64.reinterpret(
+ // (i64.reinterpret(x) & ~(1 << 63)) |
+ // (i64.reinterpret(y) & (1 << 63)
+ // )
+
Literal signBit, otherBits;
UnaryOp int2float, float2int;
BinaryOp bitAnd, bitOr;
+
switch (curr->op) {
case CopySignFloat32:
float2int = ReinterpretFloat32;
int2float = ReinterpretInt32;
bitAnd = AndInt32;
bitOr = OrInt32;
- signBit = Literal(uint32_t(1 << 31));
- otherBits = Literal(uint32_t(1 << 31) - 1);
+ signBit = Literal(uint32_t(1U << 31));
+ otherBits = Literal(~uint32_t(1U << 31));
break;
case CopySignFloat64:
@@ -270,8 +282,8 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> {
int2float = ReinterpretInt64;
bitAnd = AndInt64;
bitOr = OrInt64;
- signBit = Literal(uint64_t(1) << 63);
- otherBits = Literal((uint64_t(1) << 63) - 1);
+ signBit = Literal(uint64_t(1ULL << 63));
+ otherBits = Literal(~uint64_t(1ULL << 63));
break;
default: