]> git.sesse.net Git - stockfish/blob - src/incbin/incbin.h
Increase reduction based on the number of best move changes.
[stockfish] / src / incbin / incbin.h
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 # define INCBIN_ALIGNMENT_INDEX 4
31 #elif ULONG_MAX != 0xffffffffu
32 # define INCBIN_ALIGNMENT_INDEX 3
33 # else
34 # define INCBIN_ALIGNMENT_INDEX 2
35 #endif
36
37 /* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
38 #define INCBIN_ALIGN_SHIFT_0 1
39 #define INCBIN_ALIGN_SHIFT_1 2
40 #define INCBIN_ALIGN_SHIFT_2 4
41 #define INCBIN_ALIGN_SHIFT_3 8
42 #define INCBIN_ALIGN_SHIFT_4 16
43 #define INCBIN_ALIGN_SHIFT_5 32
44 #define INCBIN_ALIGN_SHIFT_6 64
45
46 /* Actual alignment value */
47 #define INCBIN_ALIGNMENT \
48     INCBIN_CONCATENATE( \
49         INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
50         INCBIN_ALIGNMENT_INDEX)
51
52 /* Stringize */
53 #define INCBIN_STR(X) \
54     #X
55 #define INCBIN_STRINGIZE(X) \
56     INCBIN_STR(X)
57 /* Concatenate */
58 #define INCBIN_CAT(X, Y) \
59     X ## Y
60 #define INCBIN_CONCATENATE(X, Y) \
61     INCBIN_CAT(X, Y)
62 /* Deferred macro expansion */
63 #define INCBIN_EVAL(X) \
64     X
65 #define INCBIN_INVOKE(N, ...) \
66     INCBIN_EVAL(N(__VA_ARGS__))
67
68 /* Green Hills uses a different directive for including binary data */
69 #if defined(__ghs__)
70 #  if (__ghs_asm == 2)
71 #    define INCBIN_MACRO ".file"
72 /* Or consider the ".myrawdata" entry in the ld file */
73 #  else
74 #    define INCBIN_MACRO "\tINCBIN"
75 #  endif
76 #else
77 #  define INCBIN_MACRO ".incbin"
78 #endif
79
80 #ifndef _MSC_VER
81 #  define INCBIN_ALIGN \
82     __attribute__((aligned(INCBIN_ALIGNMENT)))
83 #else
84 #  define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
85 #endif
86
87 #if defined(__arm__) || /* GNU C and RealView */ \
88     defined(__arm) || /* Diab */ \
89     defined(_ARM) /* ImageCraft */
90 #  define INCBIN_ARM
91 #endif
92
93 #ifdef __GNUC__
94 /* Utilize .balign where supported */
95 #  define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
96 #  define INCBIN_ALIGN_BYTE ".balign 1\n"
97 #elif defined(INCBIN_ARM)
98 /*
99  * On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
100  * the shift count. This is the value passed to `.align'
101  */
102 #  define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
103 #  define INCBIN_ALIGN_BYTE ".align 0\n"
104 #else
105 /* We assume other inline assembler's treat `.align' as `.balign' */
106 #  define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
107 #  define INCBIN_ALIGN_BYTE ".align 1\n"
108 #endif
109
110 /* INCBIN_CONST is used by incbin.c generated files */
111 #if defined(__cplusplus)
112 #  define INCBIN_EXTERNAL extern "C"
113 #  define INCBIN_CONST    extern const
114 #else
115 #  define INCBIN_EXTERNAL extern
116 #  define INCBIN_CONST    const
117 #endif
118
119 /**
120  * @brief Optionally override the linker section into which data is emitted.
121  *
122  * @warning If you use this facility, you'll have to deal with platform-specific linker output
123  * section naming on your own
124  *
125  * Overriding the default linker output section, e.g for esp8266/Arduino:
126  * @code
127  * #define INCBIN_OUTPUT_SECTION ".irom.text"
128  * #include "incbin.h"
129  * INCBIN(Foo, "foo.txt");
130  * // Data is emitted into program memory that never gets copied to RAM
131  * @endcode
132  */
133 #if !defined(INCBIN_OUTPUT_SECTION)
134 #  if defined(__APPLE__)
135 #    define INCBIN_OUTPUT_SECTION         ".const_data"
136 #  else
137 #    define INCBIN_OUTPUT_SECTION         ".rodata"
138 #  endif
139 #endif
140
141 #if defined(__APPLE__)
142 /* The directives are different for Apple branded compilers */
143 #  define INCBIN_SECTION         INCBIN_OUTPUT_SECTION "\n"
144 #  define INCBIN_GLOBAL(NAME)    ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
145 #  define INCBIN_INT             ".long "
146 #  define INCBIN_MANGLE          "_"
147 #  define INCBIN_BYTE            ".byte "
148 #  define INCBIN_TYPE(...)
149 #else
150 #  define INCBIN_SECTION         ".section " INCBIN_OUTPUT_SECTION "\n"
151 #  define INCBIN_GLOBAL(NAME)    ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
152 #  if defined(__ghs__)
153 #    define INCBIN_INT           ".word "
154 #  else
155 #    define INCBIN_INT           ".int "
156 #  endif
157 #  if defined(__USER_LABEL_PREFIX__)
158 #    define INCBIN_MANGLE        INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
159 #  else
160 #    define INCBIN_MANGLE        ""
161 #  endif
162 #  if defined(INCBIN_ARM)
163 /* On arm assemblers, `@' is used as a line comment token */
164 #    define INCBIN_TYPE(NAME)    ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
165 #  elif defined(__MINGW32__) || defined(__MINGW64__)
166 /* Mingw doesn't support this directive either */
167 #    define INCBIN_TYPE(NAME)
168 #  else
169 /* It's safe to use `@' on other architectures */
170 #    define INCBIN_TYPE(NAME)    ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
171 #  endif
172 #  define INCBIN_BYTE            ".byte "
173 #endif
174
175 /* List of style types used for symbol names */
176 #define INCBIN_STYLE_CAMEL 0
177 #define INCBIN_STYLE_SNAKE 1
178
179 /**
180  * @brief Specify the prefix to use for symbol names.
181  *
182  * By default this is `g', producing symbols of the form:
183  * @code
184  * #include "incbin.h"
185  * INCBIN(Foo, "foo.txt");
186  *
187  * // Now you have the following symbols:
188  * // const unsigned char gFooData[];
189  * // const unsigned char *const gFooEnd;
190  * // const unsigned int gFooSize;
191  * @endcode
192  *
193  * If however you specify a prefix before including: e.g:
194  * @code
195  * #define INCBIN_PREFIX incbin
196  * #include "incbin.h"
197  * INCBIN(Foo, "foo.txt");
198  *
199  * // Now you have the following symbols instead:
200  * // const unsigned char incbinFooData[];
201  * // const unsigned char *const incbinFooEnd;
202  * // const unsigned int incbinFooSize;
203  * @endcode
204  */
205 #if !defined(INCBIN_PREFIX)
206 #  define INCBIN_PREFIX g
207 #endif
208
209 /**
210  * @brief Specify the style used for symbol names.
211  *
212  * Possible options are
213  * - INCBIN_STYLE_CAMEL "CamelCase"
214  * - INCBIN_STYLE_SNAKE "snake_case"
215  *
216  * Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
217  * @code
218  * #include "incbin.h"
219  * INCBIN(Foo, "foo.txt");
220  *
221  * // Now you have the following symbols:
222  * // const unsigned char <prefix>FooData[];
223  * // const unsigned char *const <prefix>FooEnd;
224  * // const unsigned int <prefix>FooSize;
225  * @endcode
226  *
227  * If however you specify a style before including: e.g:
228  * @code
229  * #define INCBIN_STYLE INCBIN_STYLE_SNAKE
230  * #include "incbin.h"
231  * INCBIN(foo, "foo.txt");
232  *
233  * // Now you have the following symbols:
234  * // const unsigned char <prefix>foo_data[];
235  * // const unsigned char *const <prefix>foo_end;
236  * // const unsigned int <prefix>foo_size;
237  * @endcode
238  */
239 #if !defined(INCBIN_STYLE)
240 #  define INCBIN_STYLE INCBIN_STYLE_CAMEL
241 #endif
242
243 /* Style lookup tables */
244 #define INCBIN_STYLE_0_DATA Data
245 #define INCBIN_STYLE_0_END End
246 #define INCBIN_STYLE_0_SIZE Size
247 #define INCBIN_STYLE_1_DATA _data
248 #define INCBIN_STYLE_1_END _end
249 #define INCBIN_STYLE_1_SIZE _size
250
251 /* Style lookup: returning identifier */
252 #define INCBIN_STYLE_IDENT(TYPE) \
253     INCBIN_CONCATENATE( \
254         INCBIN_STYLE_, \
255         INCBIN_CONCATENATE( \
256             INCBIN_EVAL(INCBIN_STYLE), \
257             INCBIN_CONCATENATE(_, TYPE)))
258
259 /* Style lookup: returning string literal */
260 #define INCBIN_STYLE_STRING(TYPE) \
261     INCBIN_STRINGIZE( \
262         INCBIN_STYLE_IDENT(TYPE)) \
263
264 /* Generate the global labels by indirectly invoking the macro with our style
265  * type and concatenating the name against them. */
266 #define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
267     INCBIN_INVOKE( \
268         INCBIN_GLOBAL, \
269         INCBIN_CONCATENATE( \
270             NAME, \
271             INCBIN_INVOKE( \
272                 INCBIN_STYLE_IDENT, \
273                 TYPE))) \
274     INCBIN_INVOKE( \
275         INCBIN_TYPE, \
276         INCBIN_CONCATENATE( \
277             NAME, \
278             INCBIN_INVOKE( \
279                 INCBIN_STYLE_IDENT, \
280                 TYPE)))
281
282 /**
283  * @brief Externally reference binary data included in another translation unit.
284  *
285  * Produces three external symbols that reference the binary data included in
286  * another translation unit.
287  *
288  * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
289  * "Data", as well as "End" and "Size" after. An example is provided below.
290  *
291  * @param NAME The name given for the binary data
292  *
293  * @code
294  * INCBIN_EXTERN(Foo);
295  *
296  * // Now you have the following symbols:
297  * // extern const unsigned char <prefix>FooData[];
298  * // extern const unsigned char *const <prefix>FooEnd;
299  * // extern const unsigned int <prefix>FooSize;
300  * @endcode
301  */
302 #define INCBIN_EXTERN(NAME) \
303     INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \
304         INCBIN_CONCATENATE( \
305             INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
306             INCBIN_STYLE_IDENT(DATA))[]; \
307     INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \
308     INCBIN_CONCATENATE( \
309         INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
310         INCBIN_STYLE_IDENT(END)); \
311     INCBIN_EXTERNAL const unsigned int \
312         INCBIN_CONCATENATE( \
313             INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
314             INCBIN_STYLE_IDENT(SIZE))
315
316 /**
317  * @brief Include a binary file into the current translation unit.
318  *
319  * Includes a binary file into the current translation unit, producing three symbols
320  * for objects that encode the data and size respectively.
321  *
322  * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
323  * "Data", as well as "End" and "Size" after. An example is provided below.
324  *
325  * @param NAME The name to associate with this binary data (as an identifier.)
326  * @param FILENAME The file to include (as a string literal.)
327  *
328  * @code
329  * INCBIN(Icon, "icon.png");
330  *
331  * // Now you have the following symbols:
332  * // const unsigned char <prefix>IconData[];
333  * // const unsigned char *const <prefix>IconEnd;
334  * // const unsigned int <prefix>IconSize;
335  * @endcode
336  *
337  * @warning This must be used in global scope
338  * @warning The identifiers may be different if INCBIN_STYLE is not default
339  *
340  * To externally reference the data included by this in another translation unit
341  * please @see INCBIN_EXTERN.
342  */
343 #ifdef _MSC_VER
344 #define INCBIN(NAME, FILENAME) \
345     INCBIN_EXTERN(NAME)
346 #else
347 #define INCBIN(NAME, FILENAME) \
348     __asm__(INCBIN_SECTION \
349             INCBIN_GLOBAL_LABELS(NAME, DATA) \
350             INCBIN_ALIGN_HOST \
351             INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
352             INCBIN_MACRO " \"" FILENAME "\"\n" \
353             INCBIN_GLOBAL_LABELS(NAME, END) \
354             INCBIN_ALIGN_BYTE \
355             INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
356                 INCBIN_BYTE "1\n" \
357             INCBIN_GLOBAL_LABELS(NAME, SIZE) \
358             INCBIN_ALIGN_HOST \
359             INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
360                 INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
361                            INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
362             INCBIN_ALIGN_HOST \
363             ".text\n" \
364     ); \
365     INCBIN_EXTERN(NAME)
366
367 #endif
368 #endif