Use long int builtins for xtensa (esp) targets (#26170)

Fixes #25200.

`xtensa-esp-elf-gcc` (the ESP-IDF toolchain for the Xtensa
ESP32/ESP32-S2/ESP32-S3) defines `int32_t` as `long int`, exactly like
`arm-none-eabi-gcc` and `riscv32-unknown-elf-gcc` do:

```console
$ xtensa-esp32s3-elf-gcc -dM -E -x c /dev/null | grep -E '__INT32_TYPE__|__SIZEOF_(INT|LONG)__|__xtensa__|__unix__'
#define __SIZEOF_INT__ 4
#define __SIZEOF_LONG__ 4
#define __xtensa__ 1
#define __INT32_TYPE__ long int
```

So with `--cpu:esp`, `NI`/`NI32` become `long int` while `nimAddInt`
still expands to `__builtin_sadd_overflow`, which expects `int*`:

```
error: passing argument 3 of '__builtin_sadd_overflow' from incompatible pointer type [-Wincompatible-pointer-types]
note: expected 'int *' but argument is of type 'NI32 *' {aka 'long int *'}
```

This is a warning on GCC 13 and below, but [a hard error since GCC
14](https://gcc.gnu.org/gcc-14/porting_to.html#incompatible-pointer-types)
— the log in #25200 shows the build failing outright with the
`esp-15.1.0` toolchain.

This applies the same fix that #23835 (arm-none-eabi), #24553 (riscv32)
and #26121 (limiting arm to non-`__unix__`) already applied, now for
Xtensa. The `!defined(__unix__)` guard mirrors #26121: the bare-metal
ESP toolchain does not define `__unix__` (verified above), so it is
unaffected, while a hypothetical `xtensa-*-linux` target keeps the
current `int` behaviour rather than being switched blindly.

### Verification

Compiling Nim-generated C for `--cpu:esp --os:standalone` with
`xtensa-esp32s3-elf-gcc 12.2.0` and `-Werror=incompatible-pointer-types`
(to reproduce the GCC 14+ default):

| `lib/nimbase.h` | exit code | `incompatible pointer` diagnostics |
|---|---|---|
| devel | 1 | 1 |
| this PR | 0 | 0 |

No effect on any other target: the change is inside the `NIM_INTBITS ==
32` branch and is gated on `__xtensa__`.
This commit is contained in:
Khronos31
2026-09-05 06:13:27 +09:00
committed by GitHub
parent c10438d264
commit 98211a2c69

View File

@@ -598,8 +598,9 @@ NIM_STATIC_ASSERT(sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8, "P
#define nimMulInt64(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res)
#if NIM_INTBITS == 32
#if ((defined(__arm__) && !defined(__unix__)) || defined(__riscv)) && defined(__GNUC__)
/* arm-none-eabi-gcc and riscv32-unknown-elf-gcc targets define int32_t as long int */
#if ((defined(__arm__) && !defined(__unix__)) || defined(__riscv) || (defined(__xtensa__) && !defined(__unix__))) && defined(__GNUC__)
/* arm-none-eabi-gcc, riscv32-unknown-elf-gcc and xtensa-esp-elf-gcc targets
define int32_t as long int */
#define nimAddInt(a, b, res) __builtin_saddl_overflow(a, b, res)
#define nimSubInt(a, b, res) __builtin_ssubl_overflow(a, b, res)
#define nimMulInt(a, b, res) __builtin_smull_overflow(a, b, res)