Skip to content

Commit cb5b957

Browse files
kjg0724mr-c
authored andcommitted
math: extend non-glibc guard to Clang and add exp10 guard
The previous fix (#1398) guarded __builtin_roundeven only for GCC 10+, assuming Clang always lowers it to an inline llvm.roundeven.* intrinsic. That assumption is wrong: Clang emits a roundeven()/roundevenf() libm call on targets without a native rounding instruction (x86 without SSE4.1, powerpc, sparc, i386, etc.). On non-glibc systems (musl, OpenBSD, FreeBSD, MinGW) the symbol is absent, causing: undefined reference to 'roundevenf' Fix: drop the GCC-only restriction and apply the glibc >= 2.25 guard to all compilers. Non-glibc platforms fall through to the existing portable inline fallback. Also guard __builtin_exp10 / __builtin_exp10f: exp10() is a GNU extension present only in glibc, so the builtin produces the same class of link error on musl and other non-glibc libcs. The fallback simde_math_pow(10.0, v) / simde_math_powf(10.0f, v) is already present and correct. Reported by brad0 in issue #1396.
1 parent df69d38 commit cb5b957

1 file changed

Lines changed: 17 additions & 14 deletions

File tree

simde/simde-math.h

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -973,13 +973,18 @@ simde_math_fpclass(double v, const int imm8) {
973973
#endif
974974
#endif
975975

976-
#if HEDLEY_HAS_BUILTIN(__builtin_exp10) || HEDLEY_GCC_VERSION_CHECK(3,4,0)
976+
/* __builtin_exp10 lowers to exp10() which is a GNU extension available
977+
* only in glibc. Other libcs (musl, OpenBSD, FreeBSD, MinGW, etc.)
978+
* lack the symbol and produce a link error. Fall back to pow(10, v). */
979+
#if (HEDLEY_HAS_BUILTIN(__builtin_exp10) || HEDLEY_GCC_VERSION_CHECK(3,4,0)) && \
980+
defined(__GLIBC__)
977981
# define simde_math_exp10(v) __builtin_exp10(v)
978982
#else
979983
# define simde_math_exp10(v) simde_math_pow(10.0, (v))
980984
#endif
981985

982-
#if HEDLEY_HAS_BUILTIN(__builtin_exp10f) || HEDLEY_GCC_VERSION_CHECK(3,4,0)
986+
#if (HEDLEY_HAS_BUILTIN(__builtin_exp10f) || HEDLEY_GCC_VERSION_CHECK(3,4,0)) && \
987+
defined(__GLIBC__)
983988
# define simde_math_exp10f(v) __builtin_exp10f(v)
984989
#else
985990
# define simde_math_exp10f(v) simde_math_powf(10.0f, (v))
@@ -1266,17 +1271,16 @@ simde_math_fpclass(double v, const int imm8) {
12661271
#endif
12671272

12681273
#if !defined(simde_math_roundeven)
1269-
/* GCC 10+ lowers __builtin_roundeven to a libm roundeven() call when
1270-
* the target has no native instruction. roundeven() is C23 and only
1271-
* available in glibc >= 2.25; other platforms (musl, OpenBSD, MinGW,
1272-
* etc.) lack the symbol and produce a link error. Clang lowers the
1273-
* builtin to an llvm.roundeven.* intrinsic which is always emitted
1274-
* inline (no libm dependency), so the GCC guard is not needed there. */
1274+
/* __builtin_roundeven lowers to a roundeven() libm call on targets
1275+
* without a native rounding instruction (x86 without SSE4.1,
1276+
* powerpc, sparc, i386, etc.). roundeven() is C23 and only
1277+
* available in glibc >= 2.25; other libcs (musl, OpenBSD, FreeBSD,
1278+
* MinGW, etc.) lack the symbol and produce a link error. Guard for
1279+
* all compilers: non-glibc platforms use the inline fallback below. */
12751280
#if \
12761281
((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && \
12771282
HEDLEY_HAS_BUILTIN(__builtin_roundeven) && \
1278-
(!HEDLEY_GCC_VERSION_CHECK(10,0,0) || \
1279-
(defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)))))
1283+
(defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))))
12801284
#define simde_math_roundeven(v) __builtin_roundeven(v)
12811285
#elif defined(simde_math_round) && defined(simde_math_fabs)
12821286
static HEDLEY_INLINE
@@ -1295,13 +1299,12 @@ simde_math_fpclass(double v, const int imm8) {
12951299

12961300
#if !defined(simde_math_roundevenf)
12971301
/* Same rationale as simde_math_roundeven above; applies to the float
1298-
* variant. GCC 10+ requires glibc >= 2.25 for roundevenf(); Clang
1299-
* is always safe via llvm.roundeven.f32 inline expansion. */
1302+
* variant. Both GCC and Clang emit a roundevenf() libm call on
1303+
* targets without a native instruction. */
13001304
#if \
13011305
((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && \
13021306
HEDLEY_HAS_BUILTIN(__builtin_roundevenf) && \
1303-
(!HEDLEY_GCC_VERSION_CHECK(10,0,0) || \
1304-
(defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)))))
1307+
(defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))))
13051308
#define simde_math_roundevenf(v) __builtin_roundevenf(v)
13061309
#elif defined(simde_math_roundf) && defined(simde_math_fabsf)
13071310
static HEDLEY_INLINE

0 commit comments

Comments
 (0)