Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions src/passes/I64ToI32Lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,17 @@
*/

//
// Lowers i64s to i32s by splitting variables and arguments
// into pairs of i32s. i64 return values are lowered by
// returning the low half and storing the high half into a
// global.
// Lowers i64s to i32s by splitting variables and arguments into pairs of i32s.
// i64 return values are lowered by returning the low half and storing the high
// half into a global.
//
// Note: This pass is designed primarily as an internal part of the wasm2js
// pipeline rather than a general-purpose lowering pass for standard WebAssembly
// runtimes. As such, it does not strictly preserve all WebAssembly trapping
// semantics. In particular, float-to-int conversions are lowered using float
// arithmetic and 32-bit truncations that do not trap on out-of-range values,
// NaN, or infinity, relying on the fact that wasm2js maps 32-bit truncations
// to non-trapping JavaScript bitwise operations (~~ and >>>).
//

#include "abi/js.h"
Expand Down Expand Up @@ -623,8 +630,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}

void lowerReinterpretFloat64(Unary* curr) {
// Assume that the wasm file assumes the address 0 is invalid and roundtrip
// our f64 through memory at address 0
// Roundtrip the f64 through a scratch buffer via wasm2js helper functions
// to extract the low and high 32-bit integer halves.
TempVar highBits = getTemp();
Block* result = builder->blockify(
builder->makeCall(
Expand All @@ -643,8 +650,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}

void lowerReinterpretInt64(Unary* curr) {
// Assume that the wasm file assumes the address 0 is invalid and roundtrip
// our i64 through memory at address 0
// Roundtrip the low and high 32-bit integer halves through a scratch buffer
// via wasm2js helper functions to reconstruct the f64 value.
TempVar highBits = fetchOutParam(curr->value);
Block* result = builder->blockify(
builder->makeCall(ABI::wasm2js::SCRATCH_STORE_I32,
Expand All @@ -661,6 +668,16 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}

void lowerTruncFloatToInt(Unary* curr) {
// Lowers 64-bit float-to-int truncations into 32-bit float arithmetic and
// 32-bit truncations.
//
// Note that this lowering is non-trapping: in wasm2js, the emitted
// 32-bit truncations are translated to JavaScript bitwise operations
// ((~~expr) >>> 0), so out-of-range values, NaN, and +/-infinity do not
// trap. Both signed and unsigned operations share the same logic because
// the two's complement bit representation is identical for in-range values.
//
// Pseudocode:
// hiBits = if abs(f) >= 1.0 {
// if f > 0.0 {
// (unsigned) min(
Expand Down
Loading