casaroli opened a new pull request, #21505:
URL: https://github.com/apache/nuttx/pull/21505

   depends-on: apache/nuttx/pull/21493
   
   This branch holds the 19 commits of #21474, the 10 commits of #21493 and 8 
commits of its own, because these commits change the same code. **Review only 
the last 8 commits.** It stays a draft until #21493 merges. Part of #21467, 
step 3.
   
   ## Summary
   
   This PR fixes the output of correct calls that #21474 only made safe, and 
adds the missing conversions behind options:
   
   - **-0.0 prints its sign**, a fix in all profiles. It tests the sign bit in 
place of a compare: +0 on Cortex-M0, +8 on Cortex-M3, +24 on rv32 and -4 on 
arm64. A NaN with its sign bit set now prints `-nan`, as C23 requires.
   - **`%a` and `%A`**, behind `LIBC_PRINTF_HEXFLOAT`, off in Minimal and 
Default, on in Full. With the option off, `printf` reads the argument and 
prints `?`, as in #21474. The code works on the bits, with no floating point 
operation and no big numbers, so the option does not need `LIBC_FLOATINGPOINT` 
and pulls in no soft-float code. A `long double` has its own digits where it 
has more bits than a `double`.
   - **C23 `%b`, `%B`, `wN` and `wfN`**, behind `LIBC_PRINTF_C23`, same 
defaults. With the option off, they stay unknown conversions, as in #21474: the 
rest of the format prints as text.
   - **`%n` with a store**, behind `LIBC_PRINTF_PERCENT_N`, off in all 
profiles, also in Full. The prompt and the help say that it is dangerous. With 
the option off, `%n` reads its pointer, stores nothing and prints `?`, as in 
#21474.
   - **`scanf` with `%L`** stores a `long double`. `%Ld` stores a `long long`, 
as in GNU libc. It adds code only where `long double` differs from `double`, 
and only in an image that links `sscanf()` with floating point.
   
   Two commits only fix style, because the check reads all of a file that a 
commit changes. The one for `lib_libvscanf.c` indents the `case` labels: read 
it with `git show -w`.
   
   ## What is not fixed
   
   - More than 15 significant digits, and correct rounding of `%e`, `%f`, `%g`. 
That is step 4 of #21467, after a discussion there.
   - `%#g` drops trailing zeros: 917 tests of the suite.
   - The rest of `scanf`.
   
   ## Impact
   
   Default: the only output that changes is the sign of -0.0 and of a negative 
NaN. A config with `LIBC_FLOATINGPOINT` off has the same image text as #21493. 
No ABI change. Not a breaking change. No architecture code. Flat, protected and 
kernel builds.
   
   The Kconfig help has the text of the options. Step 5 of #21467 is the 
documentation page.
   
   Image text, each board's defaults; rv32 and arm64 have float on by default.  
Boards: `nucleo-f072rb:nsh`, `nucleo-f103rb:nsh`, `rv-virt:nsh`, 
`qemu-armv8a:nsh`:
   
   | | Cortex-M0 | Cortex-M3 | rv32 | arm64 |
   |---|---:|---:|---:|---:|
   | #21493 | 46,724 | 34,436 | 230,438 | 328,272 |
   | Minimal | 46,380 | 33,860 | 227,988 | 325,584 |
   | Default | 46,724 | 34,436 | 230,462 | 328,268 |
   | Full | 58,856 | 40,460 | 233,046 | 331,896 |
   | Default - #21493 | +0 | +0 | +24 | -4 |
   
   The cost of `-0.0`, image text, float on in both builds:
   
   | | Cortex-M0 | Cortex-M3 | rv32 | arm64 |
   |---|---:|---:|---:|---:|
   | #21493 | 56,856 | 38,596 | 230,438 | 328,272 |
   | With `-0.0` | 56,856 | 38,604 | 230,462 | 328,268 |
   | Delta | +0 | +8 | +24 | -4 |
   | All of this PR, Default | +0 | +8 | +24 | -4 |
   
   Image text with float off is the same as #21493 on all four boards in 
Default:
   
   | | Cortex-M0 | Cortex-M3 | rv32 | arm64 |
   |---|---:|---:|---:|---:|
   | #21493 | 46,724 | 34,436 | 228,362 | 326,044 |
   | This PR | 46,724 | 34,436 | 228,362 | 326,044 |
   
   One option added, image text:
   
   | | Cortex-M0 | Cortex-M3 | rv32 | arm64 |
   |---|---:|---:|---:|---:|
   | Default, float off, + `LIBC_PRINTF_HEXFLOAT` | +816 | +776 | +1112 | +1580 
|
   | Minimal + `LIBC_PRINTF_HEXFLOAT` | +836 | +820 | +1048 | +1472 |
   | Default, float off, + `LIBC_PRINTF_C23` | +184 | +180 | +220 | +232 |
   | Minimal + `LIBC_PRINTF_C23` | +160 | +228 | +166 | +192 |
   | Default, float off, + `LIBC_PRINTF_PERCENT_N` | +28 | +48 | +48 | +36 |
   
   `vsprintf_internal` frame:
   
   | | Cortex-M0 | Cortex-M3 | rv32 | arm64 |
   |---|---:|---:|---:|---:|
   | #21493, Default | 88 | 72 | 144 | 160 |
   | Default | 88 | 72 | 144 | 160 |
   | Minimal | 80 | 72 | 96 | 160 |
   | Full | 184 | 176 | 208 | 256 |
   | Default, float off, + `%a` | 112 | 104 | 144 | 192 |
   | Default, float off, + C23 | 128 | 112 | 112 | 176 |
   | Minimal + `%a` | 112 | 104 | 128 | 192 |
   
   The growth with the options on comes from new code: `lib_hexfloat.c`, its 
output in `vsprintf_puthex()`, and the parser of `wN`. With `LIBC_PRINTF_C23` 
on, the conversion buffer holds all bits of an integer, so the frame of 
`vsprintf_internal` grows by up to 42 bytes. With `LIBC_PRINTF_HEXFLOAT` on, 
the frame holds the digits, and `lib_vsprintf()` with numbered arguments holds 
a `long double` for each argument where that is larger than a `double`.
   
   Image text of an image with `sscanf()` of `%lf`, the `%L` commit: rv32 +178, 
arm64 +176. A CPU where `long double` is `double` has no new code.
   
   ## Testing
   
   The suite at https://github.com/casaroli/printf-report on sim arm64, against 
#21493:
   
   | | C99 required | Correctly rounded | C23 | POSIX | XSI | Bit-exact | Crash 
+ hang |
   |---|---:|---:|---:|---:|---:|---:|---:|
   | #21493 | 67.81% | 63.11% | 1.08% | 92.68% | 36.36% | 61.46% | 0 |
   | This PR, options off | 73.84% | 69.14% | 2.15% | 92.68% | 36.36% | 68.96% 
| 0 |
   | This PR, `%a` and C23 on | 94.85% | 90.08% | 92.47% | 95.12% | 36.36% | 
90.08% | 0 |
   | The same, `%n` on | 94.89% | 90.12% | 96.77% | 100% | 36.36% | 90.14% | 0 |
   | Full profile | 94.85% | 90.08% | 92.47% | 95.12% | 36.36% | 90.08% | 0 |
   | Minimal | 5.50% | 5.50% | 1.08% | 27.91% | 33.33% | 5.52% | 0 |
   | Minimal, `%a` and C23 on | 24.17% | 24.17% | 75.27% | 27.91% | 33.33% | 
24.32% | 0 |
   
   No test goes from pass to fail. 540 tests go from "allowed alternative" to 
"pass": a NaN with a sign bit prints its sign. The 3 `%wf16` tests that fail 
are not `printf`: `int_fast16_t` is `int`, and `INT_FAST16_MAX` in 
`include/stdint.h` is `INT16_MAX`. The `%n` tests fail by design with the 
option off.
   
   - `%a` against GNU libc 2.41: 3,123,276 conversions with precision none and 
0 to 32, flags and widths, on boundary, tie, subnormal and random values of 
`double` and binary128: 0 differences. 471,276 of them also on big-endian 
s390x: 0 differences. macOS libc does not round ties to even and normalizes 
subnormal values, so it is not a reference. The 80-bit format of x86: 0 value 
differences without a precision, and with a precision not compared, because GNU 
libc has another first digit.
   - Host harness under ASan and UBSan, 49 builds, clang on macOS and gcc on 
Linux arm64: each profile, each option added or removed: clang on macOS, 49 
builds: 49 builds correct usage: 0 reports, 0 timeouts, 0 bad returns, 0 
sentinel errors, 49 builds wrong usage: 0 reports, 0 timeouts, 0 bad returns, 0 
sentinel errors.  gcc on Linux arm64, 49 builds: 49 builds correct usage: 0 
reports, 0 timeouts, 0 bad returns, 0 sentinel errors, 49 builds wrong usage: 0 
reports, 0 timeouts, 0 bad returns, 0 sentinel errors..
   - Runtime: ostest with the new cases of the test in nuttx-apps, and a test 
program: `rv-virt:nsh` (flat) and `qemu-armv8a:knsh` (kernel), each with 
Default, Full, Minimal, Minimal with `%a` and C23, Default with `%a`, Default 
with C23, Full with `%n`: all exit 0 with 0 failures.
   - Builds with `EXTRAFLAGS="-Wno-cpp -Werror"`: Minimal, Default, Full on the 
four flat boards (12 of 12), each option added on them.  `mps2-an500:knsh` 
(protected), `qemu-armv8a:knsh`, `rv-virt:knsh` (kernel), each profile and 
Minimal with all options: 12 of 12 on this head.
   
   Not run: - Cortex-M0 at run time.
   - A CMake build.
   - The suite on a 32-bit target: only the sim runs it here.
   
   `tools/checkpatch.sh -c -u -m -g` passes.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to