Fix long double width on FreeBSD/PowerPC - #9148
Conversation
|
I appreciate that this will fix the assertion failure. However, please keep in mind that this code path is designed to allow "cross-architecture verification", much like "cross compilation". I would hence set the width to a constant based on the OS. |
|
That is not really possible.
If you want it hardcoded, is it OK if I first check for powerpc64le on a recent 16.0 and set 128b if true and fall back to 64b on anything else? |
Indeed not easy to fix. I am ok with dropping cross-verification support for FreeBSD prior to 16.0; i.e., you'd add a branch to the case where a) you are targeting FreeBSD, and b) running on FreeBSD, and then you use what Cross-verification would use the FreeBSD 16.0 value. |
set_arch_spec_power() sets long_double_width to 16*8 for every PowerPC subarchitecture. That matches Linux, where long double is 128-bit IBM double-double, but not FreeBSD, where long double on PowerPC is the same as double -- except on powerpc64le since FreeBSD 16.0, which uses IEEE binary128. Because the width does not match the host, verifying natively on FreeBSD/powerpc64le aborts as soon as any tool configures itself: --- begin invariant violation report --- Invariant check failed File: src/util/config.cpp function: set Condition: ansi_c.long_double_width == sizeof(long double) * CHAR_BIT Reason: long double width shall be equal to the system long double width --- end invariant violation report --- Abort trap (core dumped) This is not hypothetical for a build either: the regression tests run the freshly built goto-gcc, so the build itself fails. The width is a property of the FreeBSD release, which a target triple does not carry, so neither constant is correct on its own. Follow the toolchain when verifying natively and assume FreeBSD >= 16.0 when cross-verifying. The native case reuses the existing `arch == this_arch && os == this_os` predicate that already guards the type-width invariants below, so the two can never disagree. Note this is deliberately stricter than "running on FreeBSD": on FreeBSD/amd64 targeting FreeBSD/ppc64 big-endian, sizeof(long double) is 128 (x87 80-bit padded to 16 bytes) while the correct width is 64, so the architecture has to match too.
|
Done - native path uses sizeof, cross-verification uses the FreeBSD 16.0 value (128-bit for ppc64le, 64-bit for powerpc/ppc64), so pre-16.0 cross-verification is dropped as you suggested. One refinement: rather than checking "running on FreeBSD", I reused the existing arch == this_arch && os == this_os predicate that already guards the type-width invariants a few lines below. An OS-only check would misfire on |
|
Looks good, thank you |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #9148 +/- ##
=========================================
Coverage 80.83% 80.83%
=========================================
Files 1715 1717 +2
Lines 189957 190069 +112
Branches 73 73
=========================================
+ Hits 153549 153644 +95
- Misses 36408 36425 +17 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
set_arch_spec_power() sets long_double_width to 16*8 for every PowerPC subarchitecture. That matches Linux, where long double is 128-bit IBM double-double, but not FreeBSD, where long double on PowerPC is the same as double -- with the exception of powerpc64le since FreeBSD 16.0, which uses IEEE binary128.
Because the width does not match the host, verifying natively on FreeBSD/powerpc64le aborts as soon as any tool configures itself:
--- begin invariant violation report ---
Invariant check failed
File: src/util/config.cpp:1132 function: set
Condition: ansi_c.long_double_width == sizeof(long double) * CHAR_BIT
Reason: long double width shall be equal to the system long double width
--- end invariant violation report ---
Abort trap (core dumped)
This is not hypothetical for a build either: the regression tests run the freshly built goto-gcc, so the build itself fails.
Neither constant is right for FreeBSD, as the width depends on the release:
FreeBSD 15.1, powerpc64le: sizeof(long double) * CHAR_BIT == 64
(LDBL_MANT_DIG 53)
FreeBSD 16.0, powerpc64le: sizeof(long double) * CHAR_BIT == 128
(LDBL_MANT_DIG 113, LONG_DOUBLE_IEEE128)
Take the width from the toolchain instead of hard-coding it, which is exactly the quantity the invariant compares against and stays correct across that transition. The override lives in configt::set() rather than in set_arch_spec_power(), which only receives the subarchitecture and has no way to know the target operating system; the neighbouring macos/arm64 case already sets long_double_width the same way.