[build] Enable building with the Intel C compiler (icc)
[people/mcb30/gpxe.git] / src / include / gpxe / tables.h
1 #ifndef _GPXE_TABLES_H
2 #define _GPXE_TABLES_H
3
4 /** @page ifdef_harmful #ifdef considered harmful
5  *
6  * Overuse of @c #ifdef has long been a problem in Etherboot.
7  * Etherboot provides a rich array of features, but all these features
8  * take up valuable space in a ROM image.  The traditional solution to
9  * this problem has been for each feature to have its own @c #ifdef
10  * option, allowing the feature to be compiled in only if desired.
11  *
12  * The problem with this is that it becomes impossible to compile, let
13  * alone test, all possible versions of Etherboot.  Code that is not
14  * typically used tends to suffer from bit-rot over time.  It becomes
15  * extremely difficult to predict which combinations of compile-time
16  * options will result in code that can even compile and link
17  * correctly.
18  *
19  * To solve this problem, we have adopted a new approach from
20  * Etherboot 5.5 onwards.  @c #ifdef is now "considered harmful", and
21  * its use should be minimised.  Separate features should be
22  * implemented in separate @c .c files, and should \b always be
23  * compiled (i.e. they should \b not be guarded with a @c #ifdef @c
24  * MY_PET_FEATURE statement).  By making (almost) all code always
25  * compile, we avoid the problem of bit-rot in rarely-used code.
26  *
27  * The file config.h, in combination with the @c make command line,
28  * specifies the objects that will be included in any particular build
29  * of Etherboot.  For example, suppose that config.h includes the line
30  *
31  * @code
32  *
33  *   #define CONSOLE_SERIAL
34  *   #define DOWNLOAD_PROTO_TFTP
35  *
36  * @endcode
37  *
38  * When a particular Etherboot image (e.g. @c bin/rtl8139.zdsk) is
39  * built, the options specified in config.h are used to drag in the
40  * relevant objects at link-time.  For the above example, serial.o and
41  * tftp.o would be linked in.
42  *
43  * There remains one problem to solve: how do these objects get used?
44  * Traditionally, we had code such as
45  *
46  * @code
47  *
48  *    #ifdef CONSOLE_SERIAL
49  *      serial_init();
50  *    #endif
51  *
52  * @endcode
53  *
54  * in main.c, but this reintroduces @c #ifdef and so is a Bad Idea.
55  * We cannot simply remove the @c #ifdef and make it
56  *
57  * @code
58  *
59  *   serial_init();
60  *
61  * @endcode
62  *
63  * because then serial.o would end up always being linked in.
64  *
65  * The solution is to use @link tables.h linker tables @endlink.
66  *
67  */
68
69 /** @file
70  *
71  * Linker tables
72  *
73  * Read @ref ifdef_harmful first for some background on the motivation
74  * for using linker tables.
75  *
76  * This file provides macros for dealing with linker-generated tables
77  * of fixed-size symbols.  We make fairly extensive use of these in
78  * order to avoid @c #ifdef spaghetti and/or linker symbol pollution.
79  * For example, instead of having code such as
80  *
81  * @code
82  *
83  *    #ifdef CONSOLE_SERIAL
84  *      serial_init();
85  *    #endif
86  *
87  * @endcode
88  *
89  * we make serial.c generate an entry in the initialisation function
90  * table, and then have a function call_init_fns() that simply calls
91  * all functions present in this table.  If and only if serial.o gets
92  * linked in, then its initialisation function will be called.  We
93  * avoid linker symbol pollution (i.e. always dragging in serial.o
94  * just because of a call to serial_init()) and we also avoid @c
95  * #ifdef spaghetti (having to conditionalise every reference to
96  * functions in serial.c).
97  *
98  * The linker script takes care of assembling the tables for us.  All
99  * our table sections have names of the format @c .tbl.NAME.NN where
100  * @c NAME designates the data structure stored in the table (e.g. @c
101  * init_fns) and @c NN is a two-digit decimal number used to impose an
102  * ordering upon the tables if required.  @c NN=00 is reserved for the
103  * symbol indicating "table start", and @c NN=99 is reserved for the
104  * symbol indicating "table end".
105  *
106  * As an example, suppose that we want to create a "frobnicator"
107  * feature framework, and allow for several independent modules to
108  * provide frobnicating services.  Then we would create a frob.h
109  * header file containing e.g.
110  *
111  * @code
112  *
113  *   struct frobnicator {
114  *      const char *name;               // Name of the frobnicator
115  *      void ( *frob ) ( void );        // The frobnicating function itself
116  *   };
117  *
118  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
119  *
120  *   #define __frobnicator __table_entry ( FROBNICATORS, 01 )
121  *
122  * @endcode
123  *
124  * Any module providing frobnicating services would look something
125  * like
126  *
127  * @code
128  *
129  *   #include "frob.h"
130  *
131  *   static void my_frob ( void ) {
132  *      // Do my frobnicating
133  *      ...
134  *   }
135  *
136  *   struct frob my_frobnicator __frobnicator = {
137  *      .name = "my_frob",
138  *      .frob = my_frob,
139  *   };
140  *
141  * @endcode
142  *
143  * The central frobnicator code (frob.c) would use the frobnicating
144  * modules as follows
145  *
146  * @code
147  *
148  *   #include "frob.h"
149  *
150  *   // Call all linked-in frobnicators
151  *   void frob_all ( void ) {
152  *      struct frob *frob;
153  *
154  *      for_each_table ( frob, FROBNICATORS ) {
155  *         printf ( "Calling frobnicator \"%s\"\n", frob->name );
156  *         frob->frob ();
157  *      }
158  *   }
159  *
160  * @endcode
161  *
162  * See init.h and init.c for a real-life example.
163  *
164  */
165
166 #ifdef DOXYGEN
167 #define __attribute__( x )
168 #endif
169
170 /**
171  * Declare a linker table
172  *
173  * @v type              Data type
174  * @v name              Table name
175  * @ret table           Linker table
176  */
177 #define __table( type, name ) ( type, name )
178
179 /**
180  * Get linker table data type
181  *
182  * @v table             Linker table
183  * @ret type            Data type
184  */
185 #define __table_type( table ) __table_extract_type table
186 #define __table_extract_type( type, name ) type
187
188 /**
189  * Get linker table name
190  *
191  * @v table             Linker table
192  * @ret name            Table name
193  */
194 #define __table_name( table ) __table_extract_name table
195 #define __table_extract_name( type, name ) name
196
197 /**
198  * Get linker table section name
199  *
200  * @v table             Linker table
201  * @v idx               Sub-table index
202  * @ret section         Section name
203  */
204 #define __table_section( table, idx ) \
205         ".tbl." __table_name ( table ) "." __table_str ( idx )
206 #define __table_str( x ) #x
207
208 /**
209  * Get linker table alignment
210  *
211  * @v table             Linker table
212  * @ret align           Alignment
213  */
214 #define __table_alignment( table ) __alignof__ ( __table_type ( table ) )
215
216 /**
217  * Declare a linker table entry
218  *
219  * @v table             Linker table
220  * @v idx               Sub-table index
221  *
222  * Example usage:
223  *
224  * @code
225  *
226  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
227  *
228  *   #define __frobnicator __table_entry ( FROBNICATORS, 01 )
229  *
230  *   struct frobnicator my_frob __frobnicator = {
231  *      ...
232  *   };
233  *
234  * @endcode
235  */
236 #define __table_entry( table, idx )                                     \
237         __attribute__ (( __section__ ( __table_section ( table, idx ) ),\
238                          __aligned__ ( __table_alignment ( table ) ) ))
239
240 /**
241  * Get start of linker table entries
242  *
243  * @v table             Linker table
244  * @v idx               Sub-table index
245  * @ret entries         Start of entries
246  */
247 #define __table_entries( table, idx ) ( {                               \
248         static __table_type ( table ) __table_entries[0]                \
249                 __table_entry ( table, idx );                           \
250         __table_entries; } )
251
252 /**
253  * Get start of linker table
254  *
255  * @v table             Linker table
256  * @ret start           Start of linker table
257  *
258  * Example usage:
259  *
260  * @code
261  *
262  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
263  *
264  *   struct frobnicator *frobs = table_start ( FROBNICATORS );
265  *
266  * @endcode
267  */
268 #define table_start( table ) __table_entries ( table, 00 )
269
270 /**
271  * Get end of linker table
272  *
273  * @v table             Linker table
274  * @ret end             End of linker table
275  *
276  * Example usage:
277  *
278  * @code
279  *
280  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
281  *
282  *   struct frobnicator *frobs_end = table_end ( FROBNICATORS );
283  *
284  * @endcode
285  */
286 #define table_end( table ) __table_entries ( table, 99 )
287
288 /**
289  * Get number of entries in linker table
290  *
291  * @v table             Linker table
292  * @ret num_entries     Number of entries in linker table
293  *
294  * Example usage:
295  *
296  * @code
297  *
298  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
299  *
300  *   unsigned int num_frobs = table_num_entries ( FROBNICATORS );
301  *
302  * @endcode
303  *
304  */
305 #define table_num_entries( table )                                      \
306         ( ( unsigned int ) ( table_end ( table ) -                      \
307                              table_start ( table ) ) )
308
309 /**
310  * Iterate through all entries within a linker table
311  *
312  * @v pointer           Entry pointer
313  * @v table             Linker table
314  *
315  * Example usage:
316  *
317  * @code
318  *
319  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
320  *
321  *   struct frobnicator *frob;
322  *
323  *   for_each_table_entry ( frob, FROBNICATORS ) {
324  *     ...
325  *   }
326  *
327  * @endcode
328  *
329  */
330 #define for_each_table_entry( pointer, table )                          \
331         for ( pointer = table_start ( table ) ;                         \
332               pointer < table_end ( table ) ;                           \
333               pointer++ )
334
335 /**
336  * Iterate through all entries within a linker table in reverse order
337  *
338  * @v pointer           Entry pointer
339  * @v table             Linker table
340  *
341  * Example usage:
342  *
343  * @code
344  *
345  *   #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
346  *
347  *   struct frobnicator *frob;
348  *
349  *   for_each_table_entry_reverse ( frob, FROBNICATORS ) {
350  *     ...
351  *   }
352  *
353  * @endcode
354  *
355  */
356 #define for_each_table_entry_reverse( pointer, table )                  \
357         for ( pointer = ( table_end ( table ) - 1 ) ;                   \
358               pointer >= table_start ( table ) ;                        \
359               pointer-- )
360
361 /******************************************************************************
362  *
363  * Intel's C compiler chokes on several of the constructs used in this
364  * file.  The workarounds are ugly, so we use them only for an icc
365  * build.
366  *
367  */
368 #define ICC_ALIGN_HACK_FACTOR 128
369 #ifdef __ICC
370
371 /*
372  * icc miscompiles zero-length arrays by inserting padding to a length
373  * of two array elements.  We therefore have to generate the
374  * __table_entries() symbols by hand in asm.
375  *
376  */
377 #undef __table_entries
378 #define __table_entries( table, idx ) ( {                               \
379         extern __table_type ( table )                                   \
380                 __table_temp_sym ( idx, __LINE__ ) []                   \
381                 __table_entry ( table, idx )                            \
382                 asm ( __table_entries_sym ( table, idx ) );             \
383         __asm__ ( ".ifndef %c0\n\t"                                     \
384                   ".section " __table_section ( table, idx ) "\n\t"     \
385                   ".align %c1\n\t"                                      \
386                   "\n%c0:\n\t"                                          \
387                   ".previous\n\t"                                       \
388                   ".endif\n\t"                                          \
389                   : : "i" ( __table_temp_sym ( idx, __LINE__ ) ),       \
390                       "i" ( __table_alignment ( table ) ) );            \
391         __table_temp_sym ( idx, __LINE__ ); } )
392 #define __table_entries_sym( table, idx )                               \
393         "__tbl_" __table_name ( table ) "_" #idx
394 #define __table_temp_sym( a, b )                                        \
395         ___table_temp_sym( __table_, a, _, b )
396 #define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d
397
398 /*
399  * icc ignores __attribute__ (( aligned (x) )) when it is used to
400  * decrease the compiler's default choice of alignment (which may be
401  * higher than the alignment actually required by the structure).  We
402  * work around this by forcing the alignment to a large multiple of
403  * the required value (so that we are never attempting to decrease the
404  * default alignment) and then postprocessing the object file to
405  * reduce the alignment back down to the "real" value.
406  *
407  */
408 #undef __table_alignment
409 #define __table_alignment( table ) \
410         ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) )
411
412 /*
413  * Because of the alignment hack, we must ensure that the compiler
414  * never tries to place multiple objects within the same section,
415  * otherwise the assembler will insert padding to the (incorrect)
416  * alignment boundary.  Do this by appending the line number to table
417  * section names.
418  *
419  * Note that we don't need to worry about padding between array
420  * elements, since the alignment is declared on the variable (i.e. the
421  * whole array) rather than on the type (i.e. on all individual array
422  * elements).
423  */
424 #undef __table_section
425 #define __table_section( table, idx ) \
426         ".tbl." __table_name ( table ) "." __table_str ( idx ) \
427         "." __table_xstr ( __LINE__ )
428 #define __table_xstr( x ) __table_str ( x )
429
430 #endif /* __ICC */
431
432 #endif /* _GPXE_TABLES_H */