diff options
Diffstat (limited to 'src/passes')
-rw-r--r-- | src/passes/I64ToI32Lowering.cpp | 17 | ||||
-rw-r--r-- | src/passes/RemoveNonJSOps.cpp | 44 |
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) { |