Repository navigation
transpile: Implement __builtin_nans* and honor NaN payloads - #2049
Open
shashikanth-a wants to merge 2 commits into
Open
shashikanth-a wants to merge 2 commits into
shashikanth-a wants to merge 2 commits into
Conversation
`__builtin_nans`, `__builtin_nansf` and `__builtin_nansl` were unimplemented, and `__builtin_nan*` ignored their payload argument. Translate both to the bits clang's constant folding produces: the payload string is parsed like LLVM's `StringRef::getAsInteger` with an auto-detected radix, and the NaN is built like `APFloat::makeNaN`. `long double` uses binary128, matching its translation to `f128::f128`. Where clang doesn't fold (a non-literal or malformed payload), it emits a libm call instead. For the quiet variants, emit the default NaN with a warning, keeping the argument's side effects. libm has no `nans`, so an unfoldable signaling NaN is an error. Edition 2024 uses `f32::from_bits`/`f64::from_bits`. Older editions use `transmute`, as `from_bits` isn't `const` on their pinned toolchain and these can appear in `static` initializers. Fixes immunant#1800.
`__builtin_nanf128`, `__builtin_nansf128`, `__builtin_inff128` and `__builtin_huge_valf128` were unimplemented. `__float128` is translated to `f128::f128` like `long double`, so handle them like the `l` variants.
Rua
reviewed
Nov 1, 2026
|
|
||
| /// The IEEE format of the result of a `__builtin_nan*` builtin. | ||
| #[derive(Copy, Clone)] | ||
| enum NanFloat { |
Contributor
There was a problem hiding this comment.
This seems superfluous to the FloatingKind enum?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1800.
__builtin_nans{,f,l}were unimplemented,__builtin_nan*ignored their payload argument, and the__float128variants (__builtin_{nan,nans,inf,huge_val}f128) were unimplemented too.All NaN builtins now translate to the bits clang's constant folding produces:
StringRef::getAsIntegerwith an auto-detected radix ("", decimal, leading-0octal,0x,0b,0o), and the NaN is built likeAPFloat::makeNaN. A signaling NaN clears the quiet bit, and sets the next bit down if the payload is then empty.nans, so an unfoldable signaling NaN is an error.f64::from_bits(..). Older editions emittransmute, sincefrom_bitsisn'tconston their pinned toolchain (1.70) and these can appear instaticinitializers. The default quiet NaN still becomesf32::NAN/f64::NAN.long doubleand__float128usetransmute::<u128, f128::f128>, as thef128crate has no public bit-pattern constructor.One behaviour change:
__builtin_nanl("")used to bef128::f128::NAN, whose payload (all ones) differs from clang's. It now gets clang's bits.The second commit adds the
__float128builtins separately, in case you'd rather review or take it on its own.Testing
nan.candf128_builtins.c(translated forx86_64-unknown-linux-gnu), plus unit tests for payload parsing and NaN bits.nan,nans,nanfandnansf, I compiled and ran both the C and the translated Rust (editions 2021 and 2024) and compared the bits. Thef128variants were compared against clang's x86_64 constants, including payloads wider than 128 bits.f128output on x86_64 Linux against the realf128crate, and compared it with GCC.Limitations
long doubleis translated as binary128, so on x86 the bits differ from x87's 80-bit format. This is the existing mapping._Float16isn't supported by the transpiler at all, so__builtin_nanf16isn't handled here.