gcc is rather over-aggressive about optimising out static data structures
[people/asdlkf/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_fn) 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 __frobnicator __table ( frobnicators, 01 )
119  *
120  * @endcode
121  *
122  * Any module providing frobnicating services would look something
123  * like
124  *
125  * @code
126  *
127  *   #include "frob.h"
128  *
129  *   static void my_frob ( void ) {
130  *      // Do my frobnicating
131  *      ...
132  *   }
133  *
134  *   struct frob my_frobnicator __frobnicator = {
135  *      .name = "my_frob",
136  *      .frob = my_frob,
137  *   };
138  *
139  * @endcode
140  *
141  * The central frobnicator code (frob.c) would use the frobnicating
142  * modules as follows
143  *
144  * @code
145  *
146  *   #include "frob.h"
147  *
148  *   static struct frob frob_start[0] __table_start ( frobnicators );
149  *   static struct frob frob_end[0] __table_end ( frobnicators );
150  *
151  *   // Call all linked-in frobnicators
152  *   void frob_all ( void ) {
153  *      struct frob *frob;
154  *
155  *      for ( frob = frob_start ; frob < frob_end ; frob++ ) {
156  *         printf ( "Calling frobnicator \"%s\"\n", frob->name );
157  *         frob->frob ();
158  *      }
159  *   }
160  *
161  * @endcode
162  *
163  * See init.h and init.c for a real-life example.
164  *
165  */
166
167 #ifdef DOXYGEN
168 #define __attribute__(x)
169 #endif
170
171 #define __table_str(x) #x
172 #define __table_section(table,idx) \
173         __section__ ( ".tbl." __table_str(table) "." __table_str(idx) )
174
175 #define __table_section_start(table) __table_section(table,00)
176 #define __table_section_end(table) __table_section(table,99)
177
178
179 /**
180  * Linker table entry.
181  *
182  * Declares a data structure to be part of a linker table.  Use as
183  * e.g.
184  *
185  * @code
186  *
187  *   struct my_foo __table ( foo, 01 ) = {
188  *      ...
189  *   };
190  *
191  * @endcode
192  *
193  */
194 #define __table(table,idx) \
195         __attribute__ (( unused, __table_section(table,idx) ))
196
197 /**
198  * Linker table start marker.
199  *
200  * Declares a data structure (usually an empty data structure) to be
201  * the start of a linker table.  Use as e.g.
202  *
203  * @code
204  *
205  *   static struct foo_start[0] __table_start ( foo );
206  *
207  * @endcode
208  *
209  */
210 #define __table_start(table) \
211         __attribute__ (( unused, __table_section_start(table) ))
212
213 /**
214  * Linker table end marker.
215  *
216  * Declares a data structure (usually an empty data structure) to be
217  * the end of a linker table.  Use as e.g.
218  *
219  * @code
220  *
221  *   static struct foo_end[0] __table_end ( foo );
222  *
223  * @endcode
224  *
225  */
226 #define __table_end(table) \
227         __attribute__ (( unused, __table_section_end(table) ))
228
229 #endif /* _GPXE_TABLES_H */