* rtl.h (global_rtx_index): New enum.
[official-gcc.git] / gcc / c-pragma.c
blobc002587b4f1f95a7140754b8ae11f0c1b3032e22
1 /* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
2 Copyright (C) 1992, 1997, 1998, 1999 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "tree.h"
25 #include "function.h"
26 #include "defaults.h"
27 #include "c-pragma.h"
28 #include "flags.h"
29 #include "toplev.h"
31 #ifdef HANDLE_GENERIC_PRAGMAS
33 #ifdef HANDLE_PRAGMA_PACK
34 /* When structure field packing is in effect, this variable is the
35 number of bits to use as the maximum alignment. When packing is not
36 in effect, this is zero. */
38 extern int maximum_field_alignment;
39 #endif
42 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
43 typedef struct align_stack
45 int alignment;
46 unsigned int num_pushes;
47 tree id;
48 struct align_stack * prev;
49 } align_stack;
51 static struct align_stack * alignment_stack = NULL;
53 static int push_alignment PROTO((int, tree));
54 static int pop_alignment PROTO((tree));
56 /* Push an alignment value onto the stack. */
57 static int
58 push_alignment (alignment, id)
59 int alignment;
60 tree id;
62 switch (alignment)
64 case 0:
65 case 1:
66 case 2:
67 case 4:
68 case 8:
69 case 16:
70 break;
71 default:
72 warning ("\
73 Alignment must be a small power of two, not %d, in #pragma pack",
74 alignment);
75 return 0;
78 if (alignment_stack == NULL
79 || alignment_stack->alignment != alignment
80 || id != NULL_TREE)
82 align_stack * entry;
84 entry = (align_stack *) xmalloc (sizeof (* entry));
86 if (entry == NULL)
88 warning ("Out of memory pushing #pragma pack");
89 return 0;
92 entry->alignment = alignment;
93 entry->num_pushes = 1;
94 entry->id = id;
95 entry->prev = alignment_stack;
97 alignment_stack = entry;
99 maximum_field_alignment = alignment * 8;
101 else
102 alignment_stack->num_pushes ++;
104 return 1;
107 /* Undo a push of an alignment onto the stack. */
108 static int
109 pop_alignment (id)
110 tree id;
112 align_stack * entry;
114 if (alignment_stack == NULL)
116 warning ("\
117 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
119 return 0;
122 /* If we got an identifier, strip away everything above the target
123 entry so that the next step will restore the state just below it. */
124 if (id)
126 for (entry = alignment_stack; entry; entry = entry->prev)
127 if (entry->id == id)
129 entry->num_pushes = 1;
130 alignment_stack = entry;
131 break;
133 if (entry == NULL)
134 warning ("\
135 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
136 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
139 if (-- alignment_stack->num_pushes == 0)
141 entry = alignment_stack->prev;
143 if (entry == NULL)
144 maximum_field_alignment = 0;
145 else
146 maximum_field_alignment = entry->alignment * 8;
148 free (alignment_stack);
150 alignment_stack = entry;
153 return 1;
156 /* Generate 'packed' and 'aligned' attributes for decls whilst a
157 #pragma pack(push... is in effect. */
158 void
159 insert_pack_attributes (node, attributes, prefix)
160 tree node;
161 tree * attributes;
162 tree * prefix;
164 tree a;
165 int field_alignment;
167 /* If we are not packing, then there is nothing to do. */
168 if (maximum_field_alignment == 0
169 || alignment_stack == NULL)
170 return;
172 /* We are only interested in fields. */
173 if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
174 || TREE_CODE (node) != FIELD_DECL)
175 return;
177 field_alignment = TYPE_ALIGN (TREE_TYPE (node));
178 if (field_alignment <= 0 || field_alignment > maximum_field_alignment)
179 field_alignment = maximum_field_alignment;
181 /* Add a 'packed' attribute. */
182 * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
184 /* If the alignment is > 8 then add an alignment attribute as well. */
185 if (field_alignment > 8)
187 /* If the aligned attribute is already present then do not override it. */
188 for (a = * attributes; a; a = TREE_CHAIN (a))
190 tree name = TREE_PURPOSE (a);
191 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
192 break;
195 if (a == NULL)
196 for (a = * prefix; a; a = TREE_CHAIN (a))
198 tree name = TREE_PURPOSE (a);
199 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
200 break;
203 if (a == NULL)
205 * attributes = tree_cons
206 (get_identifier ("aligned"),
207 tree_cons (NULL,
208 build_int_2 (field_alignment / 8, 0),
209 NULL),
210 * attributes);
214 return;
216 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
218 /* Handle one token of a pragma directive. TOKEN is the current token, and
219 STRING is its printable form. Some front ends do not support generating
220 tokens, and will only pass in a STRING. Also some front ends will reuse
221 the buffer containing STRING, so it must be copied to a local buffer if
222 it needs to be preserved.
224 If STRING is non-NULL, then the return value will be ignored, and there
225 will be futher calls to handle_pragma_token() in order to handle the rest of
226 the line containing the #pragma directive. If STRING is NULL, the entire
227 line has now been presented to handle_pragma_token() and the return value
228 should be zero if the pragma flawed in some way, or if the pragma was not
229 recognised, and non-zero if it was successfully handled. */
232 handle_pragma_token (string, token)
233 const char * string;
234 tree token;
236 static enum pragma_state state = ps_start;
237 static enum pragma_state type;
238 #ifdef HANDLE_PRAGMA_WEAK
239 static char * name;
240 static char * value;
241 #endif
242 #if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
243 static int align;
244 #endif
245 static tree id;
247 /* If we have reached the end of the #pragma directive then
248 determine what value we should return. */
250 if (string == NULL)
252 int ret_val = 0;
254 switch (type)
256 default:
257 abort ();
258 break;
260 case ps_done:
261 /* The pragma was not recognised. */
262 break;
264 #ifdef HANDLE_PRAGMA_PACK
265 case ps_pack:
266 if (state == ps_right)
268 maximum_field_alignment = align * 8;
269 ret_val = 1;
271 else
272 warning ("malformed `#pragma pack'");
273 break;
274 #endif /* HANDLE_PRAGMA_PACK */
276 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
277 case ps_push:
278 if (state == ps_right)
279 ret_val = push_alignment (align, id);
280 else
281 warning ("malformed '#pragma pack(push[,id],<n>)'");
282 break;
284 case ps_pop:
285 if (state == ps_right)
286 ret_val = pop_alignment (id);
287 else
288 warning ("malformed '#pragma pack(pop[,id])'");
289 break;
290 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
292 #ifdef HANDLE_PRAGMA_WEAK
293 case ps_weak:
294 if (HANDLE_PRAGMA_WEAK)
296 if (state == ps_name)
297 ret_val = add_weak (name, NULL);
298 else if (state == ps_value)
299 ret_val = add_weak (name, value);
300 else
301 warning ("malformed `#pragma weak'");
303 else
304 ret_val = 1; /* Ignore the pragma. */
305 break;
306 #endif /* HANDLE_PRAGMA_WEAK */
308 case ps_poison:
309 ret_val = 1;
310 break;
313 type = state = ps_start;
314 id = NULL_TREE;
316 return ret_val;
319 /* If we have been given a token, but it is not an identifier,
320 or a small constant, then something has gone wrong. */
321 if (token)
323 switch (TREE_CODE (token))
325 case IDENTIFIER_NODE:
326 break;
328 case INTEGER_CST:
329 if (TREE_INT_CST_HIGH (token) != 0)
330 return 0;
331 break;
333 default:
334 return 0;
338 switch (state)
340 case ps_start:
341 type = state = ps_done;
342 #ifdef HANDLE_PRAGMA_PACK
343 if (strcmp (string, "pack") == 0)
344 type = state = ps_pack;
345 #endif
346 #ifdef HANDLE_PRAGMA_WEAK
347 if (strcmp (string, "weak") == 0)
348 type = state = ps_weak;
349 #endif
350 if (strcmp (string, "poison") == 0)
351 type = state = ps_poison;
352 break;
354 #ifdef HANDLE_PRAGMA_WEAK
355 case ps_weak:
356 name = permalloc (strlen (string) + 1);
357 if (name == NULL)
359 warning ("Out of memory parsing #pragma weak");
360 state = ps_bad;
362 else
364 strcpy (name, string);
365 state = ps_name;
367 break;
369 case ps_name:
370 state = (strcmp (string, "=") ? ps_bad : ps_equals);
371 break;
373 case ps_equals:
374 value = permalloc (strlen (string) + 1);
375 if (value == NULL)
377 warning ("Out of memory parsing #pragma weak");
378 state = ps_bad;
380 else
382 strcpy (value, string);
383 state = ps_value;
385 break;
387 case ps_value:
388 state = ps_bad;
389 break;
390 #endif /* HANDLE_PRAGMA_WEAK */
392 #ifdef HANDLE_PRAGMA_PACK
393 case ps_pack:
394 state = (strcmp (string, "(") ? ps_bad : ps_left);
395 break;
397 case ps_left:
399 if (token == NULL_TREE)
401 /* #pragma pack () resets packing rules to their
402 defaults. */
403 if (strcmp (string, ")") == 0)
405 align = 0;
406 state = ps_right;
408 else
409 state = ps_bad;
411 else if (TREE_CODE (token) == INTEGER_CST)
412 goto handle_align;
414 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
415 else if (TREE_CODE (token) == IDENTIFIER_NODE)
417 if (strcmp (string, "push") == 0)
418 type = state = ps_push;
419 else if (strcmp (string, "pop") == 0)
420 type = state = ps_pop;
421 else
422 state = ps_bad;
424 #endif
425 else
426 state = ps_bad;
427 break;
429 handle_align:
430 align = TREE_INT_CST_LOW (token);
431 switch (align)
433 case 1:
434 case 2:
435 case 4:
436 case 8:
437 case 16:
438 state = ps_align;
439 break;
441 default:
442 state = ps_bad;
443 break;
445 break;
447 case ps_align:
448 state = (strcmp (string, ")") ? ps_bad : ps_right);
449 break;
451 case ps_right:
452 state = ps_bad;
453 break;
454 #endif /* HANDLE_PRAGMA_PACK */
456 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
457 case ps_push:
458 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
459 break;
461 case ps_pushid:
462 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
463 break;
465 case ps_pushcomma:
466 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
468 id = token;
469 state = ps_pushid;
470 break;
473 /* else fall through */
474 case ps_pushcomma2:
475 if (token && TREE_CODE (token) == INTEGER_CST)
476 goto handle_align;
477 else
478 state = ps_bad;
479 break;
481 case ps_pop:
482 if (strcmp (string, ",") == 0)
483 state = ps_popcomma;
484 else
485 state = (strcmp (string, ")") ? ps_bad : ps_right);
486 break;
488 case ps_popcomma:
489 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
491 id = token;
492 state = ps_align;
494 else
495 state = ps_bad;
496 break;
497 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
499 case ps_poison:
500 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
501 state = ps_bad;
502 break;
504 case ps_bad:
505 case ps_done:
506 break;
508 default:
509 abort ();
512 return 1;
514 #endif /* HANDLE_GENERIC_PRAGMAS */