Skip to content

Commit 212a5e1

Browse files
authored
[builtins][arm64] Build __init_cpu_features_resolver on Apple platforms (#73685)
1 parent 6c12fd9 commit 212a5e1

File tree

1 file changed

+88
-6
lines changed

1 file changed

+88
-6
lines changed

compiler-rt/lib/builtins/cpu_model.c

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,8 @@ _Bool __aarch64_have_lse_atomics
948948
#if defined(__has_include)
949949
#if __has_include(<sys/auxv.h>)
950950
#include <sys/auxv.h>
951+
#define HAVE_SYS_AUXV
952+
#endif
951953

952954
#if __has_include(<sys/ifunc.h>)
953955
#include <sys/ifunc.h>
@@ -961,6 +963,8 @@ typedef struct __ifunc_arg_t {
961963

962964
#if __has_include(<asm/hwcap.h>)
963965
#include <asm/hwcap.h>
966+
#include HAVE_SYS_HWCAP
967+
#endif
964968

965969
#if defined(__ANDROID__)
966970
#include <string.h>
@@ -997,6 +1001,9 @@ typedef struct __ifunc_arg_t {
9971001
#ifndef HWCAP_SHA2
9981002
#define HWCAP_SHA2 (1 << 6)
9991003
#endif
1004+
#ifndef HWCAP_CRC32
1005+
#define HWCAP_CRC32 (1 << 7)
1006+
#endif
10001007
#ifndef HWCAP_ATOMICS
10011008
#define HWCAP_ATOMICS (1 << 8)
10021009
#endif
@@ -1149,6 +1156,7 @@ typedef struct __ifunc_arg_t {
11491156
if (__system_property_get("ro.arch", arch) > 0 && \
11501157
strncmp(arch, "exynos9810", sizeof("exynos9810") - 1) == 0)
11511158

1159+
#if !defined(__APPLE__)
11521160
static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics(void) {
11531161
#if defined(__FreeBSD__)
11541162
unsigned long hwcap;
@@ -1162,7 +1170,7 @@ static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics(void) {
11621170
zx_status_t status = _zx_system_get_features(ZX_FEATURE_KIND_CPU, &features);
11631171
__aarch64_have_lse_atomics =
11641172
status == ZX_OK && (features & ZX_ARM64_FEATURE_ISA_ATOMICS) != 0;
1165-
#else
1173+
#elif defined(HAVE_SYS_AUXV)
11661174
unsigned long hwcap = getauxval(AT_HWCAP);
11671175
_Bool result = (hwcap & HWCAP_ATOMICS) != 0;
11681176
#if defined(__ANDROID__)
@@ -1180,8 +1188,11 @@ static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics(void) {
11801188
}
11811189
#endif // defined(__ANDROID__)
11821190
__aarch64_have_lse_atomics = result;
1191+
#else
1192+
#error No support for checking for lse atomics on this platfrom yet.
11831193
#endif // defined(__FreeBSD__)
11841194
}
1195+
#endif // !defined(__APPLE__)
11851196

11861197
#if !defined(DISABLE_AARCH64_FMV)
11871198
// CPUFeatures must correspond to the same AArch64 features in
@@ -1259,6 +1270,76 @@ struct {
12591270
// As features grows new fields could be added
12601271
} __aarch64_cpu_features __attribute__((visibility("hidden"), nocommon));
12611272

1273+
#if defined(__APPLE__)
1274+
#include <TargetConditionals.h>
1275+
#if TARGET_OS_OSX || TARGET_OS_IPHONE
1276+
#include <dispatch/dispatch.h>
1277+
#include <sys/sysctl.h>
1278+
1279+
static bool isKnownAndSupported(const char *name) {
1280+
int32_t val = 0;
1281+
size_t size = sizeof(val);
1282+
if (sysctlbyname(name, &val, &size, NULL, 0))
1283+
return false;
1284+
return val;
1285+
}
1286+
1287+
void __init_cpu_features_resolver(void) {
1288+
// On Darwin platforms, this may be called concurrently by multiple threads
1289+
// because the resolvers that use it are called lazily at runtime (unlike on
1290+
// ELF platforms, where IFuncs are resolved serially at load time). This
1291+
// function's effect on __aarch64_cpu_features should be idempotent, but even
1292+
// so we need dispatch_once to resolve the race condition. Dispatch is
1293+
// available through libSystem, which we need anyway for the sysctl, so this
1294+
// does not add a new dependency.
1295+
1296+
static dispatch_once_t onceToken = 0;
1297+
dispatch_once(&onceToken, ^{
1298+
// https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
1299+
static struct {
1300+
const char *sysctl_name;
1301+
enum CPUFeatures feature;
1302+
} features[] = {
1303+
{"hw.optional.arm.FEAT_FlagM", FEAT_FLAGM},
1304+
{"hw.optional.arm.FEAT_FlagM2", FEAT_FLAGM2},
1305+
{"hw.optional.arm.FEAT_FHM", FEAT_FP16FML},
1306+
{"hw.optional.arm.FEAT_DotProd", FEAT_DOTPROD},
1307+
{"hw.optional.arm.FEAT_RDM", FEAT_RDM},
1308+
{"hw.optional.arm.FEAT_LSE", FEAT_LSE},
1309+
{"hw.optional.floatingpoint", FEAT_FP},
1310+
{"hw.optional.AdvSIMD", FEAT_SIMD},
1311+
{"hw.optional.armv8_crc32", FEAT_CRC},
1312+
{"hw.optional.arm.FEAT_SHA1", FEAT_SHA1},
1313+
{"hw.optional.arm.FEAT_SHA256", FEAT_SHA2},
1314+
{"hw.optional.arm.FEAT_SHA3", FEAT_SHA3},
1315+
{"hw.optional.arm.FEAT_AES", FEAT_AES},
1316+
{"hw.optional.arm.FEAT_PMULL", FEAT_PMULL},
1317+
{"hw.optional.arm.FEAT_FP16", FEAT_FP16},
1318+
{"hw.optional.arm.FEAT_DIT", FEAT_DIT},
1319+
{"hw.optional.arm.FEAT_DPB", FEAT_DPB},
1320+
{"hw.optional.arm.FEAT_DPB2", FEAT_DPB2},
1321+
{"hw.optional.arm.FEAT_JSCVT", FEAT_JSCVT},
1322+
{"hw.optional.arm.FEAT_FCMA", FEAT_FCMA},
1323+
{"hw.optional.arm.FEAT_LRCPC", FEAT_RCPC},
1324+
{"hw.optional.arm.FEAT_LRCPC2", FEAT_RCPC2},
1325+
{"hw.optional.arm.FEAT_FRINTTS", FEAT_FRINTTS},
1326+
{"hw.optional.arm.FEAT_I8MM", FEAT_I8MM},
1327+
{"hw.optional.arm.FEAT_BF16", FEAT_BF16},
1328+
{"hw.optional.arm.FEAT_SB", FEAT_SB},
1329+
{"hw.optional.arm.FEAT_SPECRES", FEAT_PREDRES},
1330+
{"hw.optional.arm.FEAT_SSBS", FEAT_SSBS2},
1331+
{"hw.optional.arm.FEAT_BTI", FEAT_BTI},
1332+
};
1333+
1334+
for (size_t I = 0, E = sizeof(features) / sizeof(features[0]); I != E; ++I)
1335+
if (isKnownAndSupported(features[I].sysctl_name))
1336+
__aarch64_cpu_features.features |= (1ULL << features[I].feature);
1337+
1338+
__aarch64_cpu_features.features |= (1ULL << FEAT_INIT);
1339+
});
1340+
}
1341+
#endif // TARGET_OS_OSX || TARGET_OS_IPHONE
1342+
#else // defined(__APPLE__)
12621343
static void __init_cpu_features_constructor(unsigned long hwcap,
12631344
const __ifunc_arg_t *arg) {
12641345
#define setCPUFeature(F) __aarch64_cpu_features.features |= 1ULL << F
@@ -1467,8 +1548,8 @@ void __init_cpu_features_resolver(unsigned long hwcap,
14671548
}
14681549

14691550
void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
1470-
unsigned long hwcap;
1471-
unsigned long hwcap2;
1551+
unsigned long hwcap = 0;
1552+
unsigned long hwcap2 = 0;
14721553
// CPU features already initialized.
14731554
if (__aarch64_cpu_features.features)
14741555
return;
@@ -1478,14 +1559,16 @@ void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
14781559
res |= elf_aux_info(AT_HWCAP2, &hwcap2, sizeof hwcap2);
14791560
if (res)
14801561
return;
1481-
#else
1562+
#elif defined(HAVE_SYS_AUXV)
14821563
#if defined(__ANDROID__)
14831564
// Don't set any CPU features,
14841565
// detection could be wrong on Exynos 9810.
14851566
IF_EXYNOS9810 return;
14861567
#endif // defined(__ANDROID__)
14871568
hwcap = getauxval(AT_HWCAP);
14881569
hwcap2 = getauxval(AT_HWCAP2);
1570+
#else
1571+
#error No support for checking hwcap on this platform yet.
14891572
#endif // defined(__FreeBSD__)
14901573
__ifunc_arg_t arg;
14911574
arg._size = sizeof(__ifunc_arg_t);
@@ -1497,8 +1580,7 @@ void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
14971580
#undef setCPUFeature
14981581
#undef IF_EXYNOS9810
14991582
}
1583+
#endif // defined(__APPLE__)
15001584
#endif // !defined(DISABLE_AARCH64_FMV)
15011585
#endif // defined(__has_include)
1502-
#endif // __has_include(<sys/auxv.h>)
1503-
#endif // __has_include(<asm/hwcap.h>)
15041586
#endif // defined(__aarch64__)

0 commit comments

Comments
 (0)