regmove.c (optimize_reg_copy_1): Undo Aug 18 change.
[gcc.git] / gcc / c-pragma.c
1 /* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
2 Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
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.
10
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.
15
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. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "tree.h"
25 #include "except.h"
26 #include "function.h"
27 #include "defaults.h"
28 #include "c-pragma.h"
29 #include "flags.h"
30 #include "toplev.h"
31
32 #ifdef HANDLE_GENERIC_PRAGMAS
33
34 #ifdef HANDLE_PRAGMA_PACK
35 /* When structure field packing is in effect, this variable is the
36 number of bits to use as the maximum alignment. When packing is not
37 in effect, this is zero. */
38
39 extern int maximum_field_alignment;
40 #endif
41
42
43 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
44 typedef struct align_stack
45 {
46 int alignment;
47 unsigned int num_pushes;
48 struct align_stack * prev;
49 } align_stack;
50
51 static struct align_stack * alignment_stack = NULL;
52
53 static int push_alignment PROTO((int));
54 static int pop_alignment PROTO((void));
55
56 /* Push an alignment value onto the stack. */
57 static int
58 push_alignment (alignment)
59 int alignment;
60 {
61 switch (alignment)
62 {
63 case 0:
64 case 1:
65 case 2:
66 case 4:
67 case 8:
68 case 16:
69 break;
70 default:
71 warning ("\
72 Alignment must be a small power of two, not %d, in #pragma pack",
73 alignment);
74 return 0;
75 }
76
77 if (alignment_stack == NULL
78 || alignment_stack->alignment != alignment)
79 {
80 align_stack * entry;
81
82 entry = (align_stack *) xmalloc (sizeof (* entry));
83
84 if (entry == NULL)
85 {
86 warning ("Out of memory pushing #pragma pack");
87 return 0;
88 }
89
90 entry->alignment = alignment;
91 entry->num_pushes = 1;
92 entry->prev = alignment_stack;
93
94 alignment_stack = entry;
95
96 if (alignment < 8)
97 maximum_field_alignment = alignment * 8;
98 else
99 /* MSVC ignores alignments > 4. */
100 maximum_field_alignment = 0;
101 }
102 else
103 alignment_stack->num_pushes ++;
104
105 return 1;
106 }
107
108 /* Undo a push of an alignment onto the stack. */
109 static int
110 pop_alignment ()
111 {
112 if (alignment_stack == NULL)
113 {
114 warning ("\
115 #pragma pack(pop) encountered without corresponding #pragma pack(push,<n>)");
116 return 0;
117 }
118
119 if (-- alignment_stack->num_pushes == 0)
120 {
121 align_stack * entry;
122
123 entry = alignment_stack->prev;
124
125 if (entry == NULL || entry->alignment > 4)
126 maximum_field_alignment = 0;
127 else
128 maximum_field_alignment = entry->alignment * 8;
129
130 free (alignment_stack);
131
132 alignment_stack = entry;
133 }
134
135 return 1;
136 }
137
138 /* Generate 'packed' and 'aligned' attributes for decls whilst a
139 #pragma pack(push... is in effect. */
140 void
141 insert_pack_attributes (node, attributes, prefix)
142 tree node;
143 tree * attributes;
144 tree * prefix;
145 {
146 tree a;
147
148 /* If we are not packing, then there is nothing to do. */
149 if (maximum_field_alignment == 0
150 || alignment_stack == NULL)
151 return;
152
153 /* We are only interested in fields. */
154 if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
155 || TREE_CODE (node) != FIELD_DECL)
156 return;
157
158 /* Add a 'packed' attribute. */
159 * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
160
161 /* If the alignment is > 8 then add an alignment attribute as well. */
162 if (maximum_field_alignment > 8)
163 {
164 /* If the aligned attribute is already present then do not override it. */
165 for (a = * attributes; a; a = TREE_CHAIN (a))
166 {
167 tree name = TREE_PURPOSE (a);
168 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
169 break;
170 }
171
172 if (a == NULL)
173 for (a = * prefix; a; a = TREE_CHAIN (a))
174 {
175 tree name = TREE_PURPOSE (a);
176 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
177 break;
178 }
179
180 if (a == NULL)
181 {
182 * attributes = tree_cons
183 (get_identifier ("aligned"),
184 tree_cons (NULL,
185 build_int_2 (maximum_field_alignment / 8, 0),
186 NULL),
187 * attributes);
188 }
189 }
190
191 return;
192 }
193 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
194 \f
195 #ifdef HANDLE_PRAGMA_WEAK
196 static int add_weak PROTO((char *, char *));
197
198 static int
199 add_weak (name, value)
200 char * name;
201 char * value;
202 {
203 struct weak_syms * weak;
204
205 weak = (struct weak_syms *) permalloc (sizeof (struct weak_syms));
206
207 if (weak == NULL)
208 return 0;
209
210 weak->next = weak_decls;
211 weak->name = name;
212 weak->value = value;
213 weak_decls = weak;
214
215 return 1;
216 }
217 #endif /* HANDLE_PRAGMA_WEAK */
218 \f
219 /* Handle one token of a pragma directive. TOKEN is the current token, and
220 STRING is its printable form. Some front ends do not support generating
221 tokens, and will only pass in a STRING. Also some front ends will reuse
222 the buffer containing STRING, so it must be copied to a local buffer if
223 it needs to be preserved.
224
225 If STRING is non-NULL, then the return value will be ignored, and there
226 will be futher calls to handle_pragma_token() in order to handle the rest of
227 the line containing the #pragma directive. If STRING is NULL, the entire
228 line has now been presented to handle_pragma_token() and the return value
229 should be zero if the pragma flawed in some way, or if the pragma was not
230 recognised, and non-zero if it was successfully handled. */
231
232 int
233 handle_pragma_token (string, token)
234 char * string;
235 tree token;
236 {
237 static enum pragma_state state = ps_start;
238 static enum pragma_state type;
239 static char * name;
240 static char * value;
241 static int align;
242
243 /* If we have reached the end of the #pragma directive then
244 determine what value we should return. */
245
246 if (string == NULL)
247 {
248 int ret_val = 0;
249
250 switch (type)
251 {
252 default:
253 abort ();
254 break;
255
256 case ps_done:
257 /* The pragma was not recognised. */
258 break;
259
260 #ifdef HANDLE_PRAGMA_PACK
261 case ps_pack:
262 if (state == ps_right)
263 {
264 maximum_field_alignment = align * 8;
265 ret_val = 1;
266 }
267 else
268 warning ("malformed `#pragma pack'");
269 break;
270 #endif /* HANDLE_PRAGMA_PACK */
271
272 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
273 case ps_push:
274 if (state == ps_right)
275 ret_val = push_alignment (align);
276 else
277 warning ("incomplete '#pragma pack(push,<n>)'");
278 break;
279
280 case ps_pop:
281 if (state == ps_right)
282 ret_val = pop_alignment ();
283 else
284 warning ("missing closing parenthesis in '#pragma pack(pop)'");
285 break;
286 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
287
288 #ifdef HANDLE_PRAGMA_WEAK
289 case ps_weak:
290 if (HANDLE_PRAGMA_WEAK)
291 {
292 if (state == ps_name)
293 ret_val = add_weak (name, NULL);
294 else if (state == ps_value)
295 ret_val = add_weak (name, value);
296 else
297 warning ("malformed `#pragma weak'");
298 }
299 else
300 ret_val = 1; /* Ignore the pragma. */
301 break;
302 #endif /* HANDLE_PRAGMA_WEAK */
303 }
304
305 type = state = ps_start;
306
307 return ret_val;
308 }
309
310 /* If we have been given a token, but it is not an identifier,
311 or a small constant, then something has gone wrong. */
312 if (token)
313 {
314 switch (TREE_CODE (token))
315 {
316 case IDENTIFIER_NODE:
317 break;
318
319 case INTEGER_CST:
320 if (TREE_INT_CST_HIGH (token) != 0)
321 return 0;
322 break;
323
324 default:
325 return 0;
326 }
327 }
328
329 switch (state)
330 {
331 case ps_start:
332 type = state = ps_done;
333 #ifdef HANDLE_PRAGMA_PACK
334 if (strcmp (string, "pack") == 0)
335 type = state = ps_pack;
336 #endif
337 #ifdef HANDLE_PRAGMA_WEAK
338 if (strcmp (string, "weak") == 0)
339 type = state = ps_weak;
340 #endif
341 break;
342
343 #ifdef HANDLE_PRAGMA_WEAK
344 case ps_weak:
345 name = permalloc (strlen (string) + 1);
346 if (name == NULL)
347 {
348 warning ("Out of memory parsing #pragma weak");
349 state = ps_bad;
350 }
351 else
352 {
353 strcpy (name, string);
354 state = ps_name;
355 }
356 break;
357
358 case ps_name:
359 state = (strcmp (string, "=") ? ps_bad : ps_equals);
360 break;
361
362 case ps_equals:
363 value = permalloc (strlen (string) + 1);
364 if (value == NULL)
365 {
366 warning ("Out of memory parsing #pragma weak");
367 state = ps_bad;
368 }
369 else
370 {
371 strcpy (value, string);
372 state = ps_value;
373 }
374 break;
375
376 case ps_value:
377 state = ps_bad;
378 break;
379 #endif /* HANDLE_PRAGMA_WEAK */
380
381 #ifdef HANDLE_PRAGMA_PACK
382 case ps_pack:
383 state = (strcmp (string, "(") ? ps_bad : ps_left);
384 break;
385
386 case ps_left:
387
388 if (token && TREE_CODE(token) == INTEGER_CST)
389 align = TREE_INT_CST_LOW(token);
390 else
391 align = atoi (string);
392 switch (align)
393 {
394 case 1:
395 case 2:
396 case 4:
397 state = ps_align;
398 break;
399
400 case 0:
401 state = (strcmp (string, ")") ? ps_bad : ps_right);
402 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
403 if (state == ps_bad)
404 {
405 if (strcmp (string, "push") == 0)
406 type = state = ps_push;
407 else if (strcmp (string, "pop") == 0)
408 type = state = ps_pop;
409 }
410 #endif
411 break;
412
413 default:
414 state = ps_bad;
415 break;
416 }
417 break;
418
419 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
420 case ps_pop:
421 #endif
422 case ps_align:
423 state = (strcmp (string, ")") ? ps_bad : ps_right);
424 break;
425
426 case ps_right:
427 state = ps_bad;
428 break;
429 #endif /* HANDLE_PRAGMA_PACK */
430
431 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
432 case ps_push:
433 state = (strcmp (string, ",") ? ps_bad : ps_comma);
434 break;
435
436 case ps_comma:
437 align = atoi (string);
438 state = ps_align;
439 break;
440 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
441
442 case ps_bad:
443 case ps_done:
444 break;
445
446 default:
447 abort ();
448 }
449
450 return 1;
451 }
452 #endif /* HANDLE_GENERIC_PRAGMAS */