fennec
Loading...
Searching...
No Matches
intrinsics.h
Go to the documentation of this file.
1// =====================================================================================================================
2// fennec, a free and open source game engine
3// Copyright © 2025 Medusa Slockbower
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17// =====================================================================================================================
18
26
27#ifndef FENNEC_LANG_INTRINSICS_H
28#define FENNEC_LANG_INTRINSICS_H
29
100
101
102// Most major compilers support __has_builtin, notably GCC, MINGW, and CLANG
103#if defined(__has_builtin)
104
105
106// UTILITIES ===========================================================================================================
107
108// addressof is very difficult to implement without intrinsics.
109#if __has_builtin(__builtin_addressof)
110# define FENNEC_HAS_BUILTIN_ADDRESSOF 1
111# define FENNEC_BUILTIN_ADDRESSOF(arg) __builtin_addressof(arg)
112#else
113# define FENNEC_HAS_BUILTIN_ADDRESSOF 0
114#endif
115
116// bitcast is slightly more efficient for build times than using memcpy
117#if __has_builtin(__builtin_bit_cast)
118# define FENNEC_HAS_BUILTIN_BIT_CAST 1
119# define FENNEC_BUILTIN_BIT_CAST(type, arg) __builtin_bit_cast(type, arg)
120#else
121# define FENNEC_HAS_BUILTIN_BIT_CAST 0
122#endif
123
124#if __has_builtin(__builtin_LINE)
125# define FENNEC_HAS_BUILTIN_LINE 1
126# define FENNEC_BUILTIN_LINE() __builtin_LINE()
127#else
128# define FENNEC_HAS_BUILTIN_LINE 0
129#endif
130
131#if __has_builtin(__builtin_COLUMN)
132# define FENNEC_HAS_BUILTIN_COLUMN 1
133# define FENNEC_BUILTIN_COLUMN() __builtin_COLUMN()
134#else
135# define FENNEC_HAS_BUILTIN_COLUMN 0
136#endif
137
138#if __has_builtin(__builtin_FILE)
139# define FENNEC_HAS_BUILTIN_FILE 1
140# define FENNEC_BUILTIN_FILE() __builtin_FILE()
141#else
142# define FENNEC_HAS_BUILTIN_FILE 0
143#endif
144
145#if __has_builtin(__builtin_FUNCTION)
146# define FENNEC_HAS_BUILTIN_FUNCTION 1
147# define FENNEC_BUILTIN_FUNCTION() __builtin_FUNCTION()
148#else
149# define FENNEC_HAS_BUILTIN_FUNCTION 0
150#endif
151
152
153// PROPERTIES ==========================================================================================================
154
155// Inconsistent without intrinsics
156#if __has_builtin(__is_abstract)
157# define FENNEC_HAS_BUILTIN_IS_ABSTRACT 1
158# define FENNEC_BUILTIN_IS_ABSTRACT(arg) __is_abstract(arg)
159#else
160# define FENNEC_HAS_BUILTIN_IS_ABSTRACT 0
161#endif
162
163// Inconsistent without intrinsics
164#if __has_builtin(__is_array)
165# define FENNEC_HAS_BUILTIN_IS_ARRAY 1
166# define FENNEC_BUILTIN_IS_ARRAY(arg) __is_array(arg)
167#else
168# define FENNEC_HAS_BUILTIN_IS_ARRAY
169#endif
170
171// Inconsistent without intrinsics
172#if __has_builtin(__is_class)
173# define FENNEC_HAS_BUILTIN_IS_CLASS 1
174# define FENNEC_BUILTIN_IS_CLASS(arg) __is_class(arg)
175#else
176# define FENNEC_HAS_BUILTIN_IS_CLASS
177#endif
178
179#if __has_builtin(__is_member_pointer)
180# define FENNEC_HAS_BUILTIN_IS_MEMBER_POINTER 1
181# define FENNEC_BUILTIN_IS_MEMBER_POINTER(arg) __is_member_pointer(arg)
182#else
183# define FENNEC_HAS_BUILTIN_IS_MEMBER_POINTER 0
184#endif
185
186#if __has_builtin(__is_member_function_pointer)
187# define FENNEC_HAS_BUILTIN_IS_MEMBER_FUNCTION_POINTER 1
188# define FENNEC_BUILTIN_IS_MEMBER_FUNCTION_POINTER(arg) __is_member_function_pointer(arg)
189#else
190# define FENNEC_HAS_BUILTIN_IS_MEMBER_FUNCTION_POINTER 0
191#endif
192
193#if __has_builtin(__is_member_object_pointer)
194# define FENNEC_HAS_BUILTIN_IS_MEMBER_OBJECT_POINTER 1
195# define FENNEC_BUILTIN_IS_MEMBER_OBJECT_POINTER(arg) __is_member_object_pointer(arg)
196#else
197# define FENNEC_HAS_BUILTIN_IS_MEMBER_OBJECT_POINTER 0
198#endif
199
200
201// CONSTRUCTORS ========================================================================================================
202
203// Difficult and Inconsistent without intrinsics
204#if __has_builtin(__is_constructible)
205# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
206# define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(type, ...) __is_constructible(type __VA_OPT__(,) __VA_ARGS__)
207#else
208# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0
209#endif
210
211// Difficult and Inconsistent without intrinsics
212#if __has_builtin(__is_trivially_constructible)
213# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 1
214# define FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(type) __is_trivially_constructible(type)
215#else
216# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 0
217#endif
218
219// Difficult and Inconsistent without intrinsics
220#if __has_builtin(__has_trivial_destructor)
221# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 1
222# define FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(type) __has_trivial_destructor(type)
223#else
224# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 0
225#endif
226
227
228// ASSIGNMENTS =========================================================================================================
229
230// Difficult and Inconsistent without intrinsics
231#if __has_builtin(__is_assignable)
232# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 1
233# define FENNEC_BUILTIN_IS_ASSIGNABLE(a, b) __is_assignable(a, b)
234#else
235# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 0
236#endif
237
238// Inconsistent without intrinsics
239#if __has_builtin(__is_trivial)
240# define FENNEC_HAS_BUILTIN_IS_TRIVIAL 1
241# define FENNEC_BUILTIN_IS_TRIVIAL(a) __is_trivial(a)
242#else
243# define FENNEC_HAS_BUILTIN_IS_TRIVIAL 0
244#endif
245
246// Difficult and Inconsistent without intrinsics
247#if __has_builtin(__is_trivially_copyable)
248# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_COPYABLE 1
249# define FENNEC_BUILTIN_IS_TRIVIALLY_COPYABLE(a) __is_trivially_copyable(a)
250#else
251# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_COPYABLE 0
252#endif
253
254// Impossible without instrinsics
255#if __has_builtin(__is_standard_layout)
256# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 1
257# define FENNEC_BUILTIN_IS_STANDARD_LAYOUT(arg) __is_standard_layout(arg)
258#else
259# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 0
260#endif
261
262// Impossible without instrinsics
263#if __has_builtin(__has_unique_object_representations)
264# define FENNEC_HAS_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 1
265# define FENNEC_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS(arg) __has_unique_object_representations(arg)
266#else
267# define FENNEC_HAS_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 0
268#endif
269
270
271// Type Traits
272// can_convert is also very difficult to implement without intrinsics
273#if __has_builtin(__is_convertible)
274# define FENNEC_HAS_BUILTIN_IS_CONVERTIBLE 1
275# define FENNEC_BUILTIN_IS_CONVERTIBLE(arg0, arg1) __is_convertible(arg0, arg1)
276#else
277# define FENNEC_HAS_BUILTIN_IS_CONVERTIBLE 0
278#endif
279
280// Inconsistent without intrinsics.
281#if __has_builtin(__is_empty)
282# define FENNEC_HAS_BUILTIN_IS_EMPTY 1
283# define FENNEC_BUILTIN_IS_EMPTY(arg) __is_empty(arg)
284#else
285# define FENNEC_HAS_BUILTIN_IS_EMPTY 0
286
287// Inconsistent without intrinsics
288#if __has_builtin(__is_final)
289# define FENNEC_HAS_BUILTIN_IS_FINAL 1
290# define FENNEC_BUILTIN_IS_FINAL(arg) __is_final(arg)
291#else
292# define FENNEC_HAS_BUILTIN_IS_FINAL 0
293#endif
294#endif
295
296// Inconsistent without intrinsics.
297#if __has_builtin(__is_enum)
298# define FENNEC_HAS_BUILTIN_IS_ENUM 1
299# define FENNEC_BUILTIN_IS_ENUM(arg) __is_enum(arg)
300#else
301# define FENNEC_HAS_BUILTIN_IS_ENUM 0
302#endif
303
304// Inconsistent without intrinsics.
305#if __has_builtin(__is_union)
306# define FENNEC_HAS_BUILTIN_IS_UNION 1
307# define FENNEC_BUILTIN_IS_UNION(arg) __is_union(arg)
308#else
309# define FENNEC_HAS_BUILTIN_IS_UNION 0
310#endif
311
312// Inconsistent without intrinsics
313#if __has_builtin(__is_final)
314# define FENNEC_HAS_BUILTIN_IS_FINAL 1
315# define FENNEC_BUILTIN_IS_FINAL(arg) __is_final(arg)
316#else
317# define FENNEC_HAS_BUILTIN_IS_FINAL 0
318#endif
319
320// Inconsistent without intrinsics
321#if __has_builtin(__is_aggregate)
322# define FENNEC_HAS_BUILTIN_IS_AGGREGATE 1
323# define FENNEC_BUILTIN_IS_AGGREGATE(arg) __is_aggregate(arg)
324#else
325# define FENNEC_HAS_BUILTIN_IS_AGGREGATE 0
326#endif
327
328// Inconsistent without intrinsics
329#if __has_builtin(__builtin_is_implicit_lifetime)
330# define FENNEC_HAS_BUILTIN_IS_IMPLICIT_LIFETIME 1
331# define FENNEC_BUILTIN_IS_IMPLICIT_LIFETIME(arg) __builtin_is_implicit_lifetime(arg)
332#else
333# define FENNEC_HAS_BUILTIN_IS_IMPLICIT_LIFETIME 0
334#endif
335
336// Inconsistent without intrinsics
337#if __has_builtin(__is_function)
338# define FENNEC_HAS_BUILTIN_IS_FUNCTION 1
339# define FENNEC_BUILTIN_IS_FUNCTION(arg) __is_function(arg)
340#else
341# define FENNEC_HAS_BUILTIN_IS_FUNCTION 0
342#endif
343
344// Inconsistent without intrinsics
345#if __has_builtin(__is_object)
346# define FENNEC_HAS_BUILTIN_IS_OBJECT 1
347# define FENNEC_BUILTIN_IS_OBJECT(arg) __is_object(arg)
348#else
349# define FENNEC_HAS_BUILTIN_IS_FUNCTION 0
350#endif
351
352// Inconsistent without intrinsics
353#if __has_builtin(__is_polymorphic)
354# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 1
355# define FENNEC_BUILTIN_IS_POLYMORPHIC(arg) __is_polymorphic(arg)
356#else
357# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 0
358#endif
359
360
361// For compilers without or differently named builtins
362#else
363
364// TODO: More compiler support
365
366#if FENNEC_COMPILER_MSVC
367
368# define FENNEC_HAS_BUILTIN_ADDRESS_OF 1
369# define FENNEC_BUILTIN_ADDRESS_OF(arg) __builtin_addressof(arg)
370
371# define FENNEC_HAS_BUILTIN_BIT_CAST 1
372# define FENNEC_BUILTIN_BIT_CAST(type, arg) __builtin_bit_cast(type, arg)
373
374# define FENNEC_HAS_BUILTIN_IS_CONVERTIBLE 1
375# define FENNEC_BUILTIN_IS_CONVERTIBLE(arg0, arg1) __is_convertible_to(arg0, arg1)
376
377# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
378# define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
379
380# define FENNEC_HAS_BUILTIN_IS_EMPTY 1
381# define FENNEC_BUILTIN_IS_EMPTY(arg) __is_empty(arg)
382
383# define FENNEC_HAS_BUILTIN_IS_FINAL 1
384# define FENNEC_BUILTIN_IS_FINAL(arg) __is_final(arg)
385
386# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 1
387# define FENNEC_BUILTIN_IS_POLYMORPHIC(arg) __is_polymorphic(arg)
388
389# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 1
390# define FENNEC_BUILTIN_IS_STANDARD_LAYOUT(arg) __is_standard_layout(arg)
391
392#endif
393
394#endif
395
396#endif // FENNEC_LANG_INTRINSICS_H