infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
platform.c
Go to the documentation of this file.
1
26#include "common/platform.h"
27#include <infix/infix.h>
28#include <stdint.h>
29
37
38#if defined(INFIX_ARCH_X64)
39#if defined(_MSC_VER)
40#include <intrin.h>
41#elif defined(__GNUC__) || defined(__clang__)
42#include <cpuid.h>
43#endif
44
45// Helper to execute XGETBV and return XCR0
46static uint64_t _infix_xgetbv(void) {
47#if defined(_MSC_VER)
48 return _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
49#elif defined(__GNUC__) || defined(__clang__)
50 uint32_t eax, edx;
51 __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
52 return ((uint64_t)edx << 32) | eax;
53#else
54 return 0;
55#endif
56}
57
58// XCR0 Bit Masks
59#define XCR0_SSE (1 << 1)
60#define XCR0_AVX (1 << 2)
61#define XCR0_OPMASK (1 << 5)
62#define XCR0_ZMM_Hi256 (1 << 6)
63#define XCR0_Hi16_ZMM (1 << 7)
64
65#endif
66
67#if defined(INFIX_ARCH_AARCH64) && defined(__has_include)
68#if __has_include(<sys/auxv.h>) && defined(__linux__)
69#include <sys/auxv.h>
70#ifndef HWCAP_SVE
71#define HWCAP_SVE (1 << 22)
72#endif
73#elif __has_include(<sys/sysctl.h>) && defined(__APPLE__)
74#include <sys/sysctl.h>
75#endif
76#endif
77
78#if defined(INFIX_ARCH_X64)
79bool infix_cpu_has_avx2(void) {
80 // 1. Check CPUID for OSXSAVE bit (ECX bit 27 of leaf 1)
81 // If this is 0, we can't use XGETBV.
82 bool osxsave = false;
83 bool avx2_hardware = false;
84
85#if defined(_MSC_VER)
86 int cpuInfo[4];
87 __cpuid(cpuInfo, 1);
88 osxsave = (cpuInfo[2] & (1 << 27)) != 0;
89
90 __cpuidex(cpuInfo, 7, 0);
91 avx2_hardware = (cpuInfo[1] & (1 << 5)) != 0;
92#elif defined(__GNUC__) || defined(__clang__)
93 unsigned int eax, ebx, ecx, edx;
94 __cpuid(1, eax, ebx, ecx, edx);
95 osxsave = (ecx & (1 << 27)) != 0;
96
97 if (__get_cpuid_max(0, NULL) >= 7) {
98 __cpuid_count(7, 0, eax, ebx, ecx, edx);
99 avx2_hardware = (ebx & (1 << 5)) != 0;
100 }
101#endif
102
103 if (!osxsave || !avx2_hardware)
104 return false;
105
106 // 2. Check XCR0 to ensure OS has enabled YMM state saving.
107 // Must have SSE(1) and AVX(2) bits set.
108 uint64_t xcr0 = _infix_xgetbv();
109 return (xcr0 & (XCR0_SSE | XCR0_AVX)) == (XCR0_SSE | XCR0_AVX);
110}
111
112bool infix_cpu_has_avx512f(void) {
113 bool osxsave = false;
114 bool avx512f_hardware = false;
115
116#if defined(_MSC_VER)
117 int cpuInfo[4];
118 __cpuid(cpuInfo, 1);
119 osxsave = (cpuInfo[2] & (1 << 27)) != 0;
120
121 __cpuidex(cpuInfo, 7, 0);
122 avx512f_hardware = (cpuInfo[1] & (1 << 16)) != 0;
123#elif defined(__GNUC__) || defined(__clang__)
124 unsigned int eax, ebx, ecx, edx;
125 __cpuid(1, eax, ebx, ecx, edx);
126 osxsave = (ecx & (1 << 27)) != 0;
127
128 if (__get_cpuid_max(0, NULL) >= 7) {
129 __cpuid_count(7, 0, eax, ebx, ecx, edx);
130 avx512f_hardware = (ebx & (1 << 16)) != 0;
131 }
132#endif
133
134 if (!osxsave || !avx512f_hardware)
135 return false;
136
137 // 2. Check XCR0 for ZMM support.
138 // Need SSE(1) | AVX(2) | opmask(5) | ZMM_Hi256(6) | Hi16_ZMM(7)
139 uint64_t xcr0 = _infix_xgetbv();
140 uint64_t required = XCR0_SSE | XCR0_AVX | XCR0_OPMASK | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM;
141 return (xcr0 & required) == required;
142}
143#endif
144
145#if defined(INFIX_ARCH_AARCH64)
146bool infix_cpu_has_sve(void) {
147#if defined(__linux__) && defined(HWCAP_SVE)
148 return (getauxval(AT_HWCAP) & HWCAP_SVE) != 0;
149#elif defined(__APPLE__)
150 int sve_present = 0;
151 size_t size = sizeof(sve_present);
152 if (sysctlbyname("hw.optional.arm.FEAT_SVE", &sve_present, &size, NULL, 0) == 0)
153 return sve_present == 1;
154 return false;
155#else
156 // Add checks for other OS (e.g., Windows on ARM) if needed.
157 return false;
158#endif
159}
160#endif
#define INFIX_PATCH
Definition infix.h:85
#define INFIX_NODISCARD
A compatibility macro for the C23 [[nodiscard]] attribute.
Definition infix.h:140
#define INFIX_MAJOR
Definition infix.h:83
#define INFIX_MINOR
Definition infix.h:84
#define INFIX_API
Symbol visibility macro.
Definition infix.h:114
The public interface for the infix FFI library.
INFIX_API INFIX_NODISCARD infix_version_t infix_get_version(void)
Retrieves the version of the infix library linked at runtime.
Definition platform.c:34
Declares internal, runtime CPU/OS feature detection functions.
A structure representing the semantic version of the library.
Definition infix.h:148