{u}int_fastN_t Types and Preprocessor Defines

Hi cfe-dev!

I am currently investigating an ABI incompatibility for RISC-V between Clang and GCC.

GCC defines `{u}int_fast8_t` and `{u}int_fast16_t` to be the same sizes as `{u}int32_t` or `{u}int64_t`, depending on the underlying hardware register length (RISC-V has a 32-bit architecture and a 64-bit architecture). This, to me, makes sense, as there are no sub-registers in the architecture. The `{u}int_least8_t` and `{u}int_least16_t` match their bitwidths.

However, in Clang, I believe we cannot have `{u}int_fastN_t` different from the equivalent `{u}int_leastN_t`, as the codebase currently stands, due to both `DefineFastIntType` and the definitions in `clang/lib/Headers/stdint.h`.

Point one is while investigating this, Luis discovered that on x86 these types *do* differ in size: Compiler Explorer
I cannot work out how x86 manages this, because my reading of stdint.h and the clang codebase do not show any codepaths where this would work. Any help to shed light on how this is done would be useful.

Point two is that I have started a patch to add a `getFastIntTypeByWidth` hook for Clang, which by default defers to `getLeastIntTypeByWidth`, to match the current behaviour. The comment in `DefineFastIntType` points to me having to update `stdint.h` to ensure these match, and any guidance about doing so would be appreciated. The patch is here: ⚙ D80963 [WIP][clang] Allow {u}int_fastN_t to be different to {u}int_leastN_t

I know psABIs are a minefield (to say nothing of preprocessors :wink: ), so I'm keen to see if we can add this functionality for RISC-V without breaking any other architectures. psABIs are hard enough to verify at the best of times.

Thanks In Advance,


I think for X86, clang’s stdint.h is ignored due to this part of stdint.h. You’ll get different sizes if you pass -ffreestanding.

/* If we’re hosted, fall back to the system’s stdint.h, which might have

  • additional definitions.
    #if STDC_HOSTED && __has_include_next(<stdint.h>)

The test in your godbolt link is using the system stdint.h, not the one shipped by clang. So it's ignoring whatever clang thinks the size of the types should be.

clang's stdint.h should probably be changed to use the __INT_LEAST* and __INT_FAST* macros. I think the reason it currently doesn't use them is that the macros didn't exist when clang's stdint.h was originally written.