summaryrefslogtreecommitdiff
path: root/src/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes')
-rw-r--r--src/passes/I64ToI32Lowering.cpp17
-rw-r--r--src/passes/RemoveNonJSOps.cpp44
2 files changed, 60 insertions, 1 deletions
diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp
index f14f33027..e501107bd 100644
--- a/src/passes/I64ToI32Lowering.cpp
+++ b/src/passes/I64ToI32Lowering.cpp
@@ -449,6 +449,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
void visitLoad(Load* curr) {
if (curr->type != i64) return;
assert(!curr->isAtomic && "atomic load not implemented");
+ TempVar lowBits = getTemp();
TempVar highBits = getTemp();
TempVar ptrTemp = getTemp();
SetLocal* setPtr = builder->makeSetLocal(ptrTemp, curr->ptr);
@@ -465,6 +466,15 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
i32
)
);
+ } else if (curr->signed_) {
+ loadHigh = builder->makeSetLocal(
+ highBits,
+ builder->makeBinary(
+ ShrSInt32,
+ builder->makeGetLocal(lowBits, i32),
+ builder->makeConst(Literal(int32_t(31)))
+ )
+ );
} else {
loadHigh = builder->makeSetLocal(
highBits,
@@ -475,7 +485,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
curr->bytes = std::min(curr->bytes, uint8_t(4));
curr->align = std::min(uint32_t(curr->align), uint32_t(4));
curr->ptr = builder->makeGetLocal(ptrTemp, i32);
- Block* result = builder->blockify(setPtr, loadHigh, curr);
+ Block* result = builder->blockify(
+ setPtr,
+ builder->makeSetLocal(lowBits, curr),
+ loadHigh,
+ builder->makeGetLocal(lowBits, i32)
+ );
replaceCurrent(result);
setOutParam(result, std::move(highBits));
}
diff --git a/src/passes/RemoveNonJSOps.cpp b/src/passes/RemoveNonJSOps.cpp
index 4bd40a6c6..76c9528cb 100644
--- a/src/passes/RemoveNonJSOps.cpp
+++ b/src/passes/RemoveNonJSOps.cpp
@@ -113,6 +113,50 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> {
PostWalker<RemoveNonJSOpsPass>::doWalkFunction(func);
}
+ void visitLoad(Load *curr) {
+ if (curr->align == 0 || curr->align >= curr->bytes) {
+ return;
+ }
+
+ // Switch unaligned loads of floats to unaligned loads of integers (which we
+ // can actually implement) and then use reinterpretation to get the float
+ // back out.
+ switch (curr->type) {
+ case f32:
+ curr->type = i32;
+ replaceCurrent(builder->makeUnary(ReinterpretInt32, curr));
+ break;
+ case f64:
+ curr->type = i64;
+ replaceCurrent(builder->makeUnary(ReinterpretInt64, curr));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void visitStore(Store *curr) {
+ if (curr->align == 0 || curr->align >= curr->bytes) {
+ return;
+ }
+
+ // Switch unaligned stores of floats to unaligned stores of integers (which
+ // we can actually implement) and then use reinterpretation to store the
+ // right value.
+ switch (curr->valueType) {
+ case f32:
+ curr->valueType = i32;
+ curr->value = builder->makeUnary(ReinterpretFloat32, curr->value);
+ break;
+ case f64:
+ curr->valueType = i64;
+ curr->value = builder->makeUnary(ReinterpretFloat64, curr->value);
+ break;
+ default:
+ break;
+ }
+ }
+
void visitBinary(Binary *curr) {
Name name;
switch (curr->op) {