summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/I64ToI32Lowering.cpp37
-rw-r--r--src/wasm2asm.h24
2 files changed, 58 insertions, 3 deletions
diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp
index 759e5e265..657df4896 100644
--- a/src/passes/I64ToI32Lowering.cpp
+++ b/src/passes/I64ToI32Lowering.cpp
@@ -587,6 +587,37 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
replaceCurrent(curr->value);
}
+ void lowerReinterpretFloat64(Unary* curr) {
+ // Assume that the wasm file assumes the address 0 is invalid and roundtrip
+ // our f64 through memory at address 0
+ Expression* zero = builder->makeConst(Literal(int32_t(0)));
+ TempVar highBits = getTemp();
+ Block *result = builder->blockify(
+ builder->makeStore(8, 0, 8, zero, curr->value, f64),
+ builder->makeSetLocal(
+ highBits,
+ builder->makeLoad(4, true, 4, 4, zero, i32)
+ ),
+ builder->makeLoad(4, true, 0, 4, zero, i32)
+ );
+ setOutParam(result, std::move(highBits));
+ replaceCurrent(result);
+ }
+
+ void lowerReinterpretInt64(Unary* curr) {
+ // Assume that the wasm file assumes the address 0 is invalid and roundtrip
+ // our i64 through memory at address 0
+ TempVar highBits = fetchOutParam(curr->value);
+ TempVar lowBits = getTemp();
+ Expression* zero = builder->makeConst(Literal(int32_t(0)));
+ Block *result = builder->blockify(
+ builder->makeStore(4, 0, 4, zero, curr->value, i32),
+ builder->makeStore(4, 4, 4, zero, builder->makeGetLocal(highBits, i32), i32),
+ builder->makeLoad(8, true, 0, 8, zero, f64)
+ );
+ replaceCurrent(result);
+ }
+
void lowerPopcnt64(Unary* curr) {
TempVar highBits = fetchOutParam(curr->value);
TempVar lowBits = getTemp();
@@ -701,7 +732,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
replaceCurrent(curr->value);
return;
}
- assert(hasOutParam(curr->value) || curr->type == i64);
+ assert(hasOutParam(curr->value) || curr->type == i64 || curr->type == f64);
switch (curr->op) {
case ClzInt64:
case CtzInt64: lowerCountZeros(curr); break;
@@ -710,16 +741,16 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
case ExtendSInt32: lowerExtendSInt32(curr); break;
case ExtendUInt32: lowerExtendUInt32(curr); break;
case WrapInt64: lowerWrapInt64(curr); break;
+ case ReinterpretFloat64: lowerReinterpretFloat64(curr); break;
+ case ReinterpretInt64: lowerReinterpretInt64(curr); break;
case TruncSFloat32ToInt64:
case TruncUFloat32ToInt64:
case TruncSFloat64ToInt64:
case TruncUFloat64ToInt64:
- case ReinterpretFloat64:
case ConvertSInt64ToFloat32:
case ConvertSInt64ToFloat64:
case ConvertUInt64ToFloat32:
case ConvertUInt64ToFloat64:
- case ReinterpretInt64:
default:
std::cerr << "Unhandled unary operator: " << curr->op << std::endl;
abort();
diff --git a/src/wasm2asm.h b/src/wasm2asm.h
index dce91dacb..ea8fd8142 100644
--- a/src/wasm2asm.h
+++ b/src/wasm2asm.h
@@ -1376,6 +1376,19 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) {
makeAsmCoercion(visit(curr->value,
EXPRESSION_RESULT), ASM_INT), EQ,
makeAsmCoercion(ValueBuilder::makeInt(0), ASM_INT));
+ case ReinterpretFloat32: {
+ // Naively assume that the address 0 and the next 4 bytes are
+ // permanently unused by the source program, which is definitely
+ // true for languages like C/C++/Rust
+ Ref zero = ValueBuilder::makeInt(0);
+ Ref ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF32), zero);
+ Ref value = visit(curr->value, EXPRESSION_RESULT);
+ Ref store = ValueBuilder::makeBinary(ret, SET, value);
+ return ValueBuilder::makeSeq(
+ store,
+ ValueBuilder::makeSub(ValueBuilder::makeName(HEAP32), zero)
+ );
+ }
default: {
std::cerr << "Unhandled unary i32 operator: " << curr
<< std::endl;
@@ -1442,6 +1455,17 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) {
case DemoteFloat64:
return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT),
ASM_FLOAT);
+ case ReinterpretInt32: {
+ // Like above, assume address 0 is unused.
+ Ref zero = ValueBuilder::makeInt(0);
+ Ref ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAP32), zero);
+ Ref value = visit(curr->value, EXPRESSION_RESULT);
+ Ref store = ValueBuilder::makeBinary(ret, SET, value);
+ return ValueBuilder::makeSeq(
+ store,
+ ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF32), zero)
+ );
+ }
// TODO: more complex unary conversions
default:
std::cerr << "Unhandled unary float operator: " << curr