diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/I64ToI32Lowering.cpp | 37 | ||||
-rw-r--r-- | src/wasm2asm.h | 24 |
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 |