libdpf/thirdparty/portable-snippets/builtin
Ryan Henry e4e666f459 Initial import of libdpf.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-24 14:08:32 -06:00
..
builtin.h Initial import of libdpf. 2026-09-24 14:08:32 -06:00
README.md Initial import of libdpf. 2026-09-24 14:08:32 -06:00

Built-Ins

This module provides portable implementations of many compiler builtins and intrinsics, allowing you to use builtins and intrinsics on compilers which don't support them. This includes other compilers (e.g., GCC builtins on MSVC) and older versions of the same compiler.

We also provide exact-width variants of many builtins; no more calling different functions depending on the size of int, long, long long, etc. These are typically just aliases for the appropriate function, but if we can't find an appropriate type a portable implementation will be used.

If you define PSNIP_BUILTIN_EMULATE_NATIVE before builtin.h is included, this header will also define any missing native-style built-ins, allowing you to use the native names without regard for which compiler is actually in use (i.e., you can use __builtin_ffs directly in MSVC, or any other compiler, including GCC < 3.3).

If the compiler already has the builtin, the psnip function will simply be defined to that builtin (e.g., #define psnip_builtin_clz __builtin_clz). If the compiler does not have an implementation one will be provided using either a built-in/intrinsic the compiler does support (e.g., using an MSVC intrinsic to implement a GCC built-in), inline assembly, architecture-specific functions, or a fully-portable pure C implementation.

For example, for GCC's __builtin_ffs builtin, we provide implementations which work everywhere (including versions of GCC prior to 3.3, when __builtin_ffs was introduced) of the following functions:

int psnip_builtin_ffs(int);
int psnip_builtin_ffsl(long);
int psnip_builtin_ffsll(long long);
int psnip_builtin_ffs32(psnip_int32_t);
int psnip_builtin_ffs64(psnip_int64_t);

Additionally, when when PSNIP_BUILTIN_EMULATE_NATIVE is defined (and the compiler doesn't already provide them), we also provide

int __builtin_ffs(int);
int __builtin_ffsl(long);
int __builtin_ffsll(long long);

Note that these are often provided as macros, the prototypes are for documentation only.

Dependencies

To maximize portability you should #include the exact-int module before including builtin.h, but if you don't want to add the extra file to your project you can omit it and this module will simply rely on <stdint.h>. As an alternative you may define the following macros to appropriate values yourself:

  • psnip_int8_t
  • psnip_uint8_t
  • psnip_int16_t
  • psnip_uint16_t
  • psnip_int32_t
  • psnip_uint32_t
  • psnip_int64_t
  • psnip_uint64_t

Implementation Status

Virtually every generic builtin we can implement has been implemented. This should work almost everywhere, but every commit is tested before landing in the master branch on various versions of GCC, clang, MSVC, and PGI (thanks to Travis CI and AppVeyor). Sporadic testing is also done on ICC and Oracle Developer Studio.

GCC builtins:

  • ffs, ffsl, ffsll, ffs32, ffs64
  • clz, clzl, clzll, clz32, clz64
  • ctz, ctzl, ctzll, ctz32, ctz64
  • clrsb, clrsbl, clrsbll, clrsb32, clrsb64
  • popcount, popcountl, popcountll, popcount32, popcount64
  • parity, parityl, parityll, parity32, parity64
  • bswap16, bswap32, bswap64

Clang builtins:

  • bitreverse8, bitreverse16, bitreverse32, bitreverse64
  • addcb, addcs, addc, addcl, addcll, addc8, addc16, addc32, addc64
  • subcb, subcs, subc, subcl, subcll, subc8, subc16, subc32, subc64

MSVC intrinsics:

  • rotl8, rotl16, rotl, rotl64
  • rotr8, rotr16, rotr, rotr64
  • BitScanForward, BitScanForward64
  • BitScanReverse, BitScanReverse64
  • mul128, umul128
  • shiftleft128, shiftright128
  • mulh, umulh
  • byteswap_ushort, byteswap_ulong, byteswap_uint64
  • bittest, bittest64
  • bittestandcomplement, bittestandcomplement64
  • bittestandreset, bittestandreset64
  • bittestandset, bittestandset64

If we are missing a function you feel should be included, please file an issue. Please keep in mind that some things are simply impossible to implement without compiler support.

Alternatives & Supplements

For overflow-safe integer operations (i.e., __builtin_*_overflow), use safe-math.h.

For bswap/byteswap functions, you should really use endian.h, which depends on this module and handles endianness detection as well as providing easier to use APIs which integrate endianness detection logic.

For SIMD intrinsics (SSE, AVX, NEON, etc.), take a look at the SIMDe project.

For things which are effectively compiler hints (such as __builtin_expect) as opposed to data manipulation functions, see Hedley.

Areas for future work

Optimization

Performance should be pretty good but we're always open to shaving off a few operations, even if it means creating different variants for different compilers or architectures.

Creating implementations of one compiler's builtins using builtins from another is probably your best bet to improve performance. Another useful possibility is using architecture-specific builtins, or even embedded assembly, when they are available.

Architecture-specific builtins

GCC and MSVC both have lots of architecture-specific builtins. Especially GCC, which supports many architectures. If you come across one which is useful and could be implemented with a portable fallback, let us know.

Builtins from other compilers

We've looked at GCC, MSVC, and Clang, but we're happy to support builtins from other compilers, too.