libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
platform.h
Go to the documentation of this file.
1
9#pragma once
10
11
12#include <promeki/config.h>
13#if PROMEKI_ENABLE_CORE
14// ============================================================================
15// Operating system detection
16// ============================================================================
17
18#if defined(__EMSCRIPTEN__)
19#define PROMEKI_PLATFORM_EMSCRIPTEN 1
20#define PROMEKI_PLATFORM "Emscripten"
21#elif defined(_WIN64)
22#define PROMEKI_PLATFORM_WINDOWS 64
23#define PROMEKI_PLATFORM "Win64"
24#elif defined(_WIN32)
25#define PROMEKI_PLATFORM_WINDOWS 32
26#define PROMEKI_PLATFORM "Win32"
27#elif defined(__APPLE__)
28#define PROMEKI_PLATFORM_APPLE 1
29#define PROMEKI_PLATFORM "MacOS"
30#elif defined(__linux__)
31#define PROMEKI_PLATFORM_LINUX 1
32#define PROMEKI_PLATFORM "Linux"
33#elif defined(__FreeBSD__)
34#define PROMEKI_PLATFORM_FREEBSD 1
35#define PROMEKI_PLATFORM "FreeBSD"
36#elif defined(__OpenBSD__)
37#define PROMEKI_PLATFORM_OPENBSD 1
38#define PROMEKI_PLATFORM "OpenBSD"
39#else
40#define PROMEKI_PLATFORM_UNKNOWN 1
41#define PROMEKI_PLATFORM "Unknown"
42#endif
43
44// Convenience macro for any POSIX-like system (not Windows)
45#if defined(PROMEKI_PLATFORM_LINUX) || defined(PROMEKI_PLATFORM_APPLE) || defined(PROMEKI_PLATFORM_FREEBSD) || \
46 defined(PROMEKI_PLATFORM_OPENBSD)
47#define PROMEKI_PLATFORM_POSIX 1
48#endif
49
50// Convenience macro for any BSD-derived system
51#if defined(PROMEKI_PLATFORM_FREEBSD) || defined(PROMEKI_PLATFORM_OPENBSD) || defined(PROMEKI_PLATFORM_APPLE)
52#define PROMEKI_PLATFORM_BSD 1
53#endif
54
55// ============================================================================
56// CPU architecture detection
57// ============================================================================
58//
59// Exactly one of PROMEKI_ARCH_* is set for each build, plus PROMEKI_ARCH_64
60// when the target ABI is 64-bit. PROMEKI_ARCH_NAME is a short string suitable
61// for logging / build banners. See the ISA-capability macros below for
62// SIMD-feature gating — never key SIMD code paths off the arch macros
63// directly, since e.g. an x86_64 build may still be compiled without SSE
64// enabled, and an arm32 build may or may not have NEON.
65
66#if defined(__x86_64__) || defined(_M_X64)
67#define PROMEKI_ARCH_X86_64 1
68#define PROMEKI_ARCH_64 1
69#define PROMEKI_ARCH_NAME "x86_64"
70#elif defined(__i386__) || defined(_M_IX86)
71#define PROMEKI_ARCH_X86 1
72#define PROMEKI_ARCH_NAME "x86"
73#elif defined(__aarch64__) || defined(_M_ARM64)
74#define PROMEKI_ARCH_AARCH64 1
75#define PROMEKI_ARCH_64 1
76#define PROMEKI_ARCH_NAME "aarch64"
77#elif defined(__arm__) || defined(_M_ARM)
78#define PROMEKI_ARCH_ARM 1
79#define PROMEKI_ARCH_NAME "arm"
80#elif defined(__riscv) && (__riscv_xlen == 64)
81#define PROMEKI_ARCH_RISCV64 1
82#define PROMEKI_ARCH_64 1
83#define PROMEKI_ARCH_NAME "riscv64"
84#elif defined(__riscv)
85#define PROMEKI_ARCH_RISCV 1
86#define PROMEKI_ARCH_NAME "riscv"
87#elif defined(__powerpc64__) || defined(__ppc64__)
88#define PROMEKI_ARCH_PPC64 1
89#define PROMEKI_ARCH_64 1
90#define PROMEKI_ARCH_NAME "ppc64"
91#elif defined(__wasm__) || defined(__wasm32__) || defined(__wasm64__)
92#define PROMEKI_ARCH_WASM 1
93#if defined(__wasm64__)
94#define PROMEKI_ARCH_64 1
95#endif
96#define PROMEKI_ARCH_NAME "wasm"
97#else
98#define PROMEKI_ARCH_UNKNOWN 1
99#define PROMEKI_ARCH_NAME "Unknown"
100#endif
101
102// ============================================================================
103// ISA capability detection
104// ============================================================================
105//
106// Each PROMEKI_HAS_<FEATURE> is set to 1 when the corresponding instruction
107// set is available at compile time and the matching intrinsics header has
108// been pre-included by this header (or is safe to include). Code that wants
109// to gate a SIMD path keys off these rather than off the arch macros — the
110// arch is necessary but not sufficient (e.g. -march=armv8-a always has NEON,
111// but armv7a builds may be compiled with or without -mfpu=neon).
112//
113// On x86, GCC / Clang define __SSE2__ / __SSE4_2__ / __AVX__ / __AVX2__ when
114// the compiler has been told to target those. SSE2 is part of the x86_64
115// ABI so it is always available on x86_64. On aarch64, NEON is part of the
116// base ABI so it is always available; on arm32, __ARM_NEON gates it.
117
118#if defined(__SSE2__) || defined(PROMEKI_ARCH_X86_64)
119#define PROMEKI_HAS_SSE2 1
120#endif
121#if defined(__SSE3__)
122#define PROMEKI_HAS_SSE3 1
123#endif
124#if defined(__SSSE3__)
125#define PROMEKI_HAS_SSSE3 1
126#endif
127#if defined(__SSE4_1__)
128#define PROMEKI_HAS_SSE4_1 1
129#endif
130#if defined(__SSE4_2__)
131#define PROMEKI_HAS_SSE4_2 1
132#endif
133#if defined(__AVX__)
134#define PROMEKI_HAS_AVX 1
135#endif
136#if defined(__AVX2__)
137#define PROMEKI_HAS_AVX2 1
138#endif
139#if defined(__AVX512F__)
140#define PROMEKI_HAS_AVX512F 1
141#endif
142
143// aarch64 always has NEON (mandatory in the base ABI); on arm32 it's gated
144// by the compiler's -mfpu=neon flag, which sets __ARM_NEON.
145#if defined(PROMEKI_ARCH_AARCH64) || defined(__ARM_NEON)
146#define PROMEKI_HAS_NEON 1
147#endif
148
149// Convenience: any 128-bit float vector ISA we know how to write intrinsics
150// for from a single PROMEKI_HAS_SIMD128 gate. Code that just wants "do I
151// have a 128-bit float vector unit" can key off this.
152#if defined(PROMEKI_HAS_SSE2) || defined(PROMEKI_HAS_NEON)
153#define PROMEKI_HAS_SIMD128 1
154#endif
155
156// ============================================================================
157// Compiler detection
158// ============================================================================
159
160// Note: Clang check must come before GCC check since Clang also defines __GNUC__
161#if defined(__clang__)
162#define PROMEKI_COMPILER_CLANG 1
163#elif defined(__GNUC__)
164#define PROMEKI_COMPILER_GCC 1
165#elif defined(_MSC_VER)
166#define PROMEKI_COMPILER_MSVC 1
167#endif
168
169// Convenience macro for GCC-compatible compilers (GCC or Clang)
170#if defined(PROMEKI_COMPILER_GCC) || defined(PROMEKI_COMPILER_CLANG)
171#define PROMEKI_COMPILER_GCC_COMPAT 1
172#endif
173
174// NVIDIA's nvcc is a driver around a host compiler (typically GCC or Clang),
175// so this is set in addition to one of the host-compiler macros above when
176// the current TU is being processed by nvcc. Use it to gate CUDA-only
177// constructs (`#pragma unroll`, `__device__`, etc.).
178#if defined(__CUDACC__)
179#define PROMEKI_COMPILER_NVCC 1
180#endif
181
182// ============================================================================
183// Compiler feature macros
184// ============================================================================
185
186// PROMEKI_UNROLL — request loop unrolling on the immediately-following loop.
187// Clang and nvcc honour `#pragma unroll`; GCC ignores it (and warns under
188// -Wunknown-pragmas, which we treat as an error in precommit). Falls back
189// to a no-op everywhere else — at -O3, GCC will already unroll loops with
190// constant trip counts on its own, so dropping the hint costs nothing in
191// practice.
192#if defined(PROMEKI_COMPILER_CLANG) || defined(PROMEKI_COMPILER_NVCC)
193#define PROMEKI_UNROLL _Pragma("unroll")
194#else
195#define PROMEKI_UNROLL
196#endif
197
198// ============================================================================
199// C library detection
200// ============================================================================
201
202#if defined(__GLIBC__)
203#define PROMEKI_LIBC_GLIBC 1
204#define PROMEKI_LIBC_GLIBC_VERSION_MAJOR __GLIBC__
205#define PROMEKI_LIBC_GLIBC_VERSION_MINOR __GLIBC_MINOR__
206#endif
207
208#endif // PROMEKI_ENABLE_CORE