Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
official-stockfish
GitHub Repository: official-stockfish/Stockfish
Path: blob/master/src/incbin/incbin.h
376 views
1
/**
2
* @file incbin.h
3
* @author Dale Weiler
4
* @brief Utility for including binary files
5
*
6
* Facilities for including binary files into the current translation unit and
7
* making use from them externally in other translation units.
8
*/
9
#ifndef INCBIN_HDR
10
#define INCBIN_HDR
11
#include <limits.h>
12
#if defined(__AVX512BW__) || \
13
defined(__AVX512CD__) || \
14
defined(__AVX512DQ__) || \
15
defined(__AVX512ER__) || \
16
defined(__AVX512PF__) || \
17
defined(__AVX512VL__) || \
18
defined(__AVX512F__)
19
# define INCBIN_ALIGNMENT_INDEX 6
20
#elif defined(__AVX__) || \
21
defined(__AVX2__)
22
# define INCBIN_ALIGNMENT_INDEX 5
23
#elif defined(__SSE__) || \
24
defined(__SSE2__) || \
25
defined(__SSE3__) || \
26
defined(__SSSE3__) || \
27
defined(__SSE4_1__) || \
28
defined(__SSE4_2__) || \
29
defined(__neon__) || \
30
defined(__ARM_NEON) || \
31
defined(__ALTIVEC__)
32
# define INCBIN_ALIGNMENT_INDEX 4
33
#elif ULONG_MAX != 0xffffffffu
34
# define INCBIN_ALIGNMENT_INDEX 3
35
# else
36
# define INCBIN_ALIGNMENT_INDEX 2
37
#endif
38
39
/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
40
#define INCBIN_ALIGN_SHIFT_0 1
41
#define INCBIN_ALIGN_SHIFT_1 2
42
#define INCBIN_ALIGN_SHIFT_2 4
43
#define INCBIN_ALIGN_SHIFT_3 8
44
#define INCBIN_ALIGN_SHIFT_4 16
45
#define INCBIN_ALIGN_SHIFT_5 32
46
#define INCBIN_ALIGN_SHIFT_6 64
47
48
/* Actual alignment value */
49
#define INCBIN_ALIGNMENT \
50
INCBIN_CONCATENATE( \
51
INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
52
INCBIN_ALIGNMENT_INDEX)
53
54
/* Stringize */
55
#define INCBIN_STR(X) \
56
#X
57
#define INCBIN_STRINGIZE(X) \
58
INCBIN_STR(X)
59
/* Concatenate */
60
#define INCBIN_CAT(X, Y) \
61
X ## Y
62
#define INCBIN_CONCATENATE(X, Y) \
63
INCBIN_CAT(X, Y)
64
/* Deferred macro expansion */
65
#define INCBIN_EVAL(X) \
66
X
67
#define INCBIN_INVOKE(N, ...) \
68
INCBIN_EVAL(N(__VA_ARGS__))
69
/* Variable argument count for overloading by arity */
70
#define INCBIN_VA_ARG_COUNTER(_1, _2, _3, N, ...) N
71
#define INCBIN_VA_ARGC(...) INCBIN_VA_ARG_COUNTER(__VA_ARGS__, 3, 2, 1, 0)
72
73
/* Green Hills uses a different directive for including binary data */
74
#if defined(__ghs__)
75
# if (__ghs_asm == 2)
76
# define INCBIN_MACRO ".file"
77
/* Or consider the ".myrawdata" entry in the ld file */
78
# else
79
# define INCBIN_MACRO "\tINCBIN"
80
# endif
81
#else
82
# define INCBIN_MACRO ".incbin"
83
#endif
84
85
#ifndef _MSC_VER
86
# define INCBIN_ALIGN \
87
__attribute__((aligned(INCBIN_ALIGNMENT)))
88
#else
89
# define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
90
#endif
91
92
#if defined(__arm__) || /* GNU C and RealView */ \
93
defined(__arm) || /* Diab */ \
94
defined(_ARM) /* ImageCraft */
95
# define INCBIN_ARM
96
#endif
97
98
#ifdef __GNUC__
99
/* Utilize .balign where supported */
100
# define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
101
# define INCBIN_ALIGN_BYTE ".balign 1\n"
102
#elif defined(INCBIN_ARM)
103
/*
104
* On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
105
* the shift count. This is the value passed to `.align'
106
*/
107
# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
108
# define INCBIN_ALIGN_BYTE ".align 0\n"
109
#else
110
/* We assume other inline assembler's treat `.align' as `.balign' */
111
# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
112
# define INCBIN_ALIGN_BYTE ".align 1\n"
113
#endif
114
115
/* INCBIN_CONST is used by incbin.c generated files */
116
#if defined(__cplusplus)
117
# define INCBIN_EXTERNAL extern "C"
118
# define INCBIN_CONST extern const
119
#else
120
# define INCBIN_EXTERNAL extern
121
# define INCBIN_CONST const
122
#endif
123
124
/**
125
* @brief Optionally override the linker section into which size and data is
126
* emitted.
127
*
128
* @warning If you use this facility, you might have to deal with
129
* platform-specific linker output section naming on your own.
130
*/
131
#if !defined(INCBIN_OUTPUT_SECTION)
132
# if defined(__APPLE__)
133
# define INCBIN_OUTPUT_SECTION ".const_data"
134
# else
135
# define INCBIN_OUTPUT_SECTION ".rodata"
136
# endif
137
#endif
138
139
/**
140
* @brief Optionally override the linker section into which data is emitted.
141
*
142
* @warning If you use this facility, you might have to deal with
143
* platform-specific linker output section naming on your own.
144
*/
145
#if !defined(INCBIN_OUTPUT_DATA_SECTION)
146
# define INCBIN_OUTPUT_DATA_SECTION INCBIN_OUTPUT_SECTION
147
#endif
148
149
/**
150
* @brief Optionally override the linker section into which size is emitted.
151
*
152
* @warning If you use this facility, you might have to deal with
153
* platform-specific linker output section naming on your own.
154
*
155
* @note This is useful for Harvard architectures where program memory cannot
156
* be directly read from the program without special instructions. With this you
157
* can chose to put the size variable in RAM rather than ROM.
158
*/
159
#if !defined(INCBIN_OUTPUT_SIZE_SECTION)
160
# define INCBIN_OUTPUT_SIZE_SECTION INCBIN_OUTPUT_SECTION
161
#endif
162
163
#if defined(__APPLE__)
164
# include "TargetConditionals.h"
165
# if defined(TARGET_OS_IPHONE) && !defined(INCBIN_SILENCE_BITCODE_WARNING)
166
# warning "incbin is incompatible with bitcode. Using the library will break upload to App Store if you have bitcode enabled. Add `#define INCBIN_SILENCE_BITCODE_WARNING` before including this header to silence this warning."
167
# endif
168
/* The directives are different for Apple branded compilers */
169
# define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
170
# define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
171
# define INCBIN_INT ".long "
172
# define INCBIN_MANGLE "_"
173
# define INCBIN_BYTE ".byte "
174
# define INCBIN_TYPE(...)
175
#else
176
# define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"
177
# define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
178
# if defined(__ghs__)
179
# define INCBIN_INT ".word "
180
# else
181
# define INCBIN_INT ".int "
182
# endif
183
# if defined(__USER_LABEL_PREFIX__)
184
# define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
185
# else
186
# define INCBIN_MANGLE ""
187
# endif
188
# if defined(INCBIN_ARM)
189
/* On arm assemblers, `@' is used as a line comment token */
190
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
191
# elif defined(__MINGW32__) || defined(__MINGW64__)
192
/* Mingw doesn't support this directive either */
193
# define INCBIN_TYPE(NAME)
194
# else
195
/* It's safe to use `@' on other architectures */
196
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
197
# endif
198
# define INCBIN_BYTE ".byte "
199
#endif
200
201
/* List of style types used for symbol names */
202
#define INCBIN_STYLE_CAMEL 0
203
#define INCBIN_STYLE_SNAKE 1
204
205
/**
206
* @brief Specify the prefix to use for symbol names.
207
*
208
* @note By default this is "g".
209
*
210
* @code
211
* #define INCBIN_PREFIX incbin
212
* #include "incbin.h"
213
* INCBIN(Foo, "foo.txt");
214
*
215
* // Now you have the following symbols instead:
216
* // const unsigned char incbinFoo<data>[];
217
* // const unsigned char *const incbinFoo<end>;
218
* // const unsigned int incbinFoo<size>;
219
* @endcode
220
*/
221
#if !defined(INCBIN_PREFIX)
222
# define INCBIN_PREFIX g
223
#endif
224
225
/**
226
* @brief Specify the style used for symbol names.
227
*
228
* Possible options are
229
* - INCBIN_STYLE_CAMEL "CamelCase"
230
* - INCBIN_STYLE_SNAKE "snake_case"
231
*
232
* @note By default this is INCBIN_STYLE_CAMEL
233
*
234
* @code
235
* #define INCBIN_STYLE INCBIN_STYLE_SNAKE
236
* #include "incbin.h"
237
* INCBIN(foo, "foo.txt");
238
*
239
* // Now you have the following symbols:
240
* // const unsigned char <prefix>foo_data[];
241
* // const unsigned char *const <prefix>foo_end;
242
* // const unsigned int <prefix>foo_size;
243
* @endcode
244
*/
245
#if !defined(INCBIN_STYLE)
246
# define INCBIN_STYLE INCBIN_STYLE_CAMEL
247
#endif
248
249
/* Style lookup tables */
250
#define INCBIN_STYLE_0_DATA Data
251
#define INCBIN_STYLE_0_END End
252
#define INCBIN_STYLE_0_SIZE Size
253
#define INCBIN_STYLE_1_DATA _data
254
#define INCBIN_STYLE_1_END _end
255
#define INCBIN_STYLE_1_SIZE _size
256
257
/* Style lookup: returning identifier */
258
#define INCBIN_STYLE_IDENT(TYPE) \
259
INCBIN_CONCATENATE( \
260
INCBIN_STYLE_, \
261
INCBIN_CONCATENATE( \
262
INCBIN_EVAL(INCBIN_STYLE), \
263
INCBIN_CONCATENATE(_, TYPE)))
264
265
/* Style lookup: returning string literal */
266
#define INCBIN_STYLE_STRING(TYPE) \
267
INCBIN_STRINGIZE( \
268
INCBIN_STYLE_IDENT(TYPE)) \
269
270
/* Generate the global labels by indirectly invoking the macro with our style
271
* type and concatenating the name against them. */
272
#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
273
INCBIN_INVOKE( \
274
INCBIN_GLOBAL, \
275
INCBIN_CONCATENATE( \
276
NAME, \
277
INCBIN_INVOKE( \
278
INCBIN_STYLE_IDENT, \
279
TYPE))) \
280
INCBIN_INVOKE( \
281
INCBIN_TYPE, \
282
INCBIN_CONCATENATE( \
283
NAME, \
284
INCBIN_INVOKE( \
285
INCBIN_STYLE_IDENT, \
286
TYPE)))
287
288
/**
289
* @brief Externally reference binary data included in another translation unit.
290
*
291
* Produces three external symbols that reference the binary data included in
292
* another translation unit.
293
*
294
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
295
* "Data", as well as "End" and "Size" after. An example is provided below.
296
*
297
* @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.
298
* @param NAME The name given for the binary data
299
*
300
* @code
301
* INCBIN_EXTERN(Foo);
302
*
303
* // Now you have the following symbols:
304
* // extern const unsigned char <prefix>Foo<data>[];
305
* // extern const unsigned char *const <prefix>Foo<end>;
306
* // extern const unsigned int <prefix>Foo<size>;
307
* @endcode
308
*
309
* You may specify a custom optional data type as well as the first argument.
310
* @code
311
* INCBIN_EXTERN(custom_type, Foo);
312
*
313
* // Now you have the following symbols:
314
* // extern const custom_type <prefix>Foo<data>[];
315
* // extern const custom_type *const <prefix>Foo<end>;
316
* // extern const unsigned int <prefix>Foo<size>;
317
* @endcode
318
*/
319
#define INCBIN_EXTERN(...) \
320
INCBIN_CONCATENATE(INCBIN_EXTERN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)
321
#define INCBIN_EXTERN_1(NAME, ...) \
322
INCBIN_EXTERN_2(unsigned char, NAME)
323
#define INCBIN_EXTERN_2(TYPE, NAME) \
324
INCBIN_EXTERNAL const INCBIN_ALIGN TYPE \
325
INCBIN_CONCATENATE( \
326
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
327
INCBIN_STYLE_IDENT(DATA))[]; \
328
INCBIN_EXTERNAL const INCBIN_ALIGN TYPE *const \
329
INCBIN_CONCATENATE( \
330
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
331
INCBIN_STYLE_IDENT(END)); \
332
INCBIN_EXTERNAL const unsigned int \
333
INCBIN_CONCATENATE( \
334
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
335
INCBIN_STYLE_IDENT(SIZE))
336
337
/**
338
* @brief Externally reference textual data included in another translation unit.
339
*
340
* Produces three external symbols that reference the textual data included in
341
* another translation unit.
342
*
343
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
344
* "Data", as well as "End" and "Size" after. An example is provided below.
345
*
346
* @param NAME The name given for the textual data
347
*
348
* @code
349
* INCBIN_EXTERN(Foo);
350
*
351
* // Now you have the following symbols:
352
* // extern const char <prefix>Foo<data>[];
353
* // extern const char *const <prefix>Foo<end>;
354
* // extern const unsigned int <prefix>Foo<size>;
355
* @endcode
356
*/
357
#define INCTXT_EXTERN(NAME) \
358
INCBIN_EXTERN_2(char, NAME)
359
360
/**
361
* @brief Include a binary file into the current translation unit.
362
*
363
* Includes a binary file into the current translation unit, producing three symbols
364
* for objects that encode the data and size respectively.
365
*
366
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
367
* "Data", as well as "End" and "Size" after. An example is provided below.
368
*
369
* @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.
370
* @param NAME The name to associate with this binary data (as an identifier.)
371
* @param FILENAME The file to include (as a string literal.)
372
*
373
* @code
374
* INCBIN(Icon, "icon.png");
375
*
376
* // Now you have the following symbols:
377
* // const unsigned char <prefix>Icon<data>[];
378
* // const unsigned char *const <prefix>Icon<end>;
379
* // const unsigned int <prefix>Icon<size>;
380
* @endcode
381
*
382
* You may specify a custom optional data type as well as the first argument.
383
* These macros are specialized by arity.
384
* @code
385
* INCBIN(custom_type, Icon, "icon.png");
386
*
387
* // Now you have the following symbols:
388
* // const custom_type <prefix>Icon<data>[];
389
* // const custom_type *const <prefix>Icon<end>;
390
* // const unsigned int <prefix>Icon<size>;
391
* @endcode
392
*
393
* @warning This must be used in global scope
394
* @warning The identifiers may be different if INCBIN_STYLE is not default
395
*
396
* To externally reference the data included by this in another translation unit
397
* please @see INCBIN_EXTERN.
398
*/
399
#ifdef _MSC_VER
400
# define INCBIN(NAME, FILENAME) \
401
INCBIN_EXTERN(NAME)
402
#else
403
# define INCBIN(...) \
404
INCBIN_CONCATENATE(INCBIN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)
405
# if defined(__GNUC__)
406
# define INCBIN_1(...) _Pragma("GCC error \"Single argument INCBIN not allowed\"")
407
# elif defined(__clang__)
408
# define INCBIN_1(...) _Pragma("clang error \"Single argument INCBIN not allowed\"")
409
# else
410
# define INCBIN_1(...) /* Cannot do anything here */
411
# endif
412
# define INCBIN_2(NAME, FILENAME) \
413
INCBIN_3(unsigned char, NAME, FILENAME)
414
# define INCBIN_3(TYPE, NAME, FILENAME) INCBIN_COMMON(TYPE, NAME, FILENAME, /* No terminator for binary data */)
415
# define INCBIN_COMMON(TYPE, NAME, FILENAME, TERMINATOR) \
416
__asm__(INCBIN_SECTION \
417
INCBIN_GLOBAL_LABELS(NAME, DATA) \
418
INCBIN_ALIGN_HOST \
419
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
420
INCBIN_MACRO " \"" FILENAME "\"\n" \
421
TERMINATOR \
422
INCBIN_GLOBAL_LABELS(NAME, END) \
423
INCBIN_ALIGN_BYTE \
424
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
425
INCBIN_BYTE "1\n" \
426
INCBIN_GLOBAL_LABELS(NAME, SIZE) \
427
INCBIN_ALIGN_HOST \
428
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
429
INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
430
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
431
INCBIN_ALIGN_HOST \
432
".text\n" \
433
); \
434
INCBIN_EXTERN(TYPE, NAME)
435
#endif
436
437
/**
438
* @brief Include a textual file into the current translation unit.
439
*
440
* This behaves the same as INCBIN except it produces char compatible arrays
441
* and implicitly adds a null-terminator byte, thus the size of data included
442
* by this is one byte larger than that of INCBIN.
443
*
444
* Includes a textual file into the current translation unit, producing three
445
* symbols for objects that encode the data and size respectively.
446
*
447
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
448
* "Data", as well as "End" and "Size" after. An example is provided below.
449
*
450
* @param NAME The name to associate with this binary data (as an identifier.)
451
* @param FILENAME The file to include (as a string literal.)
452
*
453
* @code
454
* INCTXT(Readme, "readme.txt");
455
*
456
* // Now you have the following symbols:
457
* // const char <prefix>Readme<data>[];
458
* // const char *const <prefix>Readme<end>;
459
* // const unsigned int <prefix>Readme<size>;
460
* @endcode
461
*
462
* @warning This must be used in global scope
463
* @warning The identifiers may be different if INCBIN_STYLE is not default
464
*
465
* To externally reference the data included by this in another translation unit
466
* please @see INCBIN_EXTERN.
467
*/
468
#if defined(_MSC_VER)
469
# define INCTXT(NAME, FILENAME) \
470
INCBIN_EXTERN(NAME)
471
#else
472
# define INCTXT(NAME, FILENAME) \
473
INCBIN_COMMON(char, NAME, FILENAME, INCBIN_BYTE "0\n")
474
#endif
475
476
#endif
477