FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[i64-to-i32-lowering] Document non-trapping float truncation behavior… · WebAssembly/binaryen@de0d99f · GitHub

Commit de0d99f

Browse files
committed
[i64-to-i32-lowering] Document non-trapping float truncation behavior (NFC)
Document that `I64ToI32Lowering` is designed for the `wasm2js` pipeline and does not preserve strict WebAssembly trapping semantics for float-to-int conversions. Also add comments in `lowerTruncFloatToInt` noting that the emitted 32-bit truncations are translated to JavaScript bitwise operations in `wasm2js` and thus do not trap on out-of-range values, NaN, or infinity. See: #9017
1 parent daf26d2 commit de0d99f

1 file changed

Lines changed: 25 additions & 8 deletions

File tree

‎src/passes/I64ToI32Lowering.cpp‎

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,17 @@
1515
*/
1616

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

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

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

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

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

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL