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)
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. */
32 #ifdef HANDLE_GENERIC_PRAGMAS
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. */
39 extern int maximum_field_alignment
;
43 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
44 typedef struct align_stack
47 unsigned int num_pushes
;
49 struct align_stack
* prev
;
52 static struct align_stack
* alignment_stack
= NULL
;
54 static int push_alignment
PROTO((int, tree
));
55 static int pop_alignment
PROTO((tree
));
57 /* Push an alignment value onto the stack. */
59 push_alignment (alignment
, id
)
74 Alignment must be a small power of two, not %d, in #pragma pack",
79 if (alignment_stack
== NULL
80 || alignment_stack
->alignment
!= alignment
85 entry
= (align_stack
*) xmalloc (sizeof (* entry
));
89 warning ("Out of memory pushing #pragma pack");
93 entry
->alignment
= alignment
;
94 entry
->num_pushes
= 1;
96 entry
->prev
= alignment_stack
;
98 alignment_stack
= entry
;
100 maximum_field_alignment
= alignment
* 8;
103 alignment_stack
->num_pushes
++;
108 /* Undo a push of an alignment onto the stack. */
115 if (alignment_stack
== NULL
)
118 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
123 /* If we got an identifier, strip away everything above the target
124 entry so that the next step will restore the state just below it. */
127 for (entry
= alignment_stack
; entry
; entry
= entry
->prev
)
130 entry
->num_pushes
= 1;
131 alignment_stack
= entry
;
136 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
137 , IDENTIFIER_POINTER (id
), IDENTIFIER_POINTER (id
));
140 if (-- alignment_stack
->num_pushes
== 0)
142 entry
= alignment_stack
->prev
;
145 maximum_field_alignment
= 0;
147 maximum_field_alignment
= entry
->alignment
* 8;
149 free (alignment_stack
);
151 alignment_stack
= entry
;
157 /* Generate 'packed' and 'aligned' attributes for decls whilst a
158 #pragma pack(push... is in effect. */
160 insert_pack_attributes (node
, attributes
, prefix
)
168 /* If we are not packing, then there is nothing to do. */
169 if (maximum_field_alignment
== 0
170 || alignment_stack
== NULL
)
173 /* We are only interested in fields. */
174 if (TREE_CODE_CLASS (TREE_CODE (node
)) != 'd'
175 || TREE_CODE (node
) != FIELD_DECL
)
178 field_alignment
= TYPE_ALIGN (TREE_TYPE (node
));
179 if (field_alignment
<= 0 || field_alignment
> maximum_field_alignment
)
180 field_alignment
= maximum_field_alignment
;
182 /* Add a 'packed' attribute. */
183 * attributes
= tree_cons (get_identifier ("packed"), NULL
, * attributes
);
185 /* If the alignment is > 8 then add an alignment attribute as well. */
186 if (field_alignment
> 8)
188 /* If the aligned attribute is already present then do not override it. */
189 for (a
= * attributes
; a
; a
= TREE_CHAIN (a
))
191 tree name
= TREE_PURPOSE (a
);
192 if (strcmp (IDENTIFIER_POINTER (name
), "aligned") == 0)
197 for (a
= * prefix
; a
; a
= TREE_CHAIN (a
))
199 tree name
= TREE_PURPOSE (a
);
200 if (strcmp (IDENTIFIER_POINTER (name
), "aligned") == 0)
206 * attributes
= tree_cons
207 (get_identifier ("aligned"),
209 build_int_2 (field_alignment
/ 8, 0),
217 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
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.
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. */
233 handle_pragma_token (string
, token
)
237 static enum pragma_state state
= ps_start
;
238 static enum pragma_state type
;
239 #ifdef HANDLE_PRAGMA_WEAK
243 #if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
248 /* If we have reached the end of the #pragma directive then
249 determine what value we should return. */
262 /* The pragma was not recognised. */
265 #ifdef HANDLE_PRAGMA_PACK
267 if (state
== ps_right
)
269 maximum_field_alignment
= align
* 8;
273 warning ("malformed `#pragma pack'");
275 #endif /* HANDLE_PRAGMA_PACK */
277 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
279 if (state
== ps_right
)
280 ret_val
= push_alignment (align
, id
);
282 warning ("malformed '#pragma pack(push[,id],<n>)'");
286 if (state
== ps_right
)
287 ret_val
= pop_alignment (id
);
289 warning ("malformed '#pragma pack(pop[,id])'");
291 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
293 #ifdef HANDLE_PRAGMA_WEAK
295 if (HANDLE_PRAGMA_WEAK
)
297 if (state
== ps_name
)
298 ret_val
= add_weak (name
, NULL
);
299 else if (state
== ps_value
)
300 ret_val
= add_weak (name
, value
);
302 warning ("malformed `#pragma weak'");
305 ret_val
= 1; /* Ignore the pragma. */
307 #endif /* HANDLE_PRAGMA_WEAK */
314 type
= state
= ps_start
;
320 /* If we have been given a token, but it is not an identifier,
321 or a small constant, then something has gone wrong. */
324 switch (TREE_CODE (token
))
326 case IDENTIFIER_NODE
:
330 if (TREE_INT_CST_HIGH (token
) != 0)
342 type
= state
= ps_done
;
343 #ifdef HANDLE_PRAGMA_PACK
344 if (strcmp (string
, "pack") == 0)
345 type
= state
= ps_pack
;
347 #ifdef HANDLE_PRAGMA_WEAK
348 if (strcmp (string
, "weak") == 0)
349 type
= state
= ps_weak
;
351 if (strcmp (string
, "poison") == 0)
352 type
= state
= ps_poison
;
355 #ifdef HANDLE_PRAGMA_WEAK
357 name
= permalloc (strlen (string
) + 1);
360 warning ("Out of memory parsing #pragma weak");
365 strcpy (name
, string
);
371 state
= (strcmp (string
, "=") ? ps_bad
: ps_equals
);
375 value
= permalloc (strlen (string
) + 1);
378 warning ("Out of memory parsing #pragma weak");
383 strcpy (value
, string
);
391 #endif /* HANDLE_PRAGMA_WEAK */
393 #ifdef HANDLE_PRAGMA_PACK
395 state
= (strcmp (string
, "(") ? ps_bad
: ps_left
);
400 if (token
== NULL_TREE
)
402 /* #pragma pack () resets packing rules to their
404 if (strcmp (string
, ")") == 0)
412 else if (TREE_CODE (token
) == INTEGER_CST
)
415 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
416 else if (TREE_CODE (token
) == IDENTIFIER_NODE
)
418 if (strcmp (string
, "push") == 0)
419 type
= state
= ps_push
;
420 else if (strcmp (string
, "pop") == 0)
421 type
= state
= ps_pop
;
431 align
= TREE_INT_CST_LOW (token
);
449 state
= (strcmp (string
, ")") ? ps_bad
: ps_right
);
455 #endif /* HANDLE_PRAGMA_PACK */
457 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
459 state
= (strcmp (string
, ",") ? ps_bad
: ps_pushcomma
);
463 state
= (strcmp (string
, ",") ? ps_bad
: ps_pushcomma2
);
467 if (token
&& TREE_CODE (token
) == IDENTIFIER_NODE
)
474 /* else fall through */
476 if (token
&& TREE_CODE (token
) == INTEGER_CST
)
483 if (strcmp (string
, ",") == 0)
486 state
= (strcmp (string
, ")") ? ps_bad
: ps_right
);
490 if (token
&& TREE_CODE (token
) == IDENTIFIER_NODE
)
498 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
501 if (token
&& TREE_CODE (token
) != IDENTIFIER_NODE
)
515 #endif /* HANDLE_GENERIC_PRAGMAS */
517 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
522 align_stack
*a
= *(align_stack
**) p
;
526 ggc_mark_tree (a
->id
);
535 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
536 ggc_add_root (&alignment_stack
, 1, sizeof(alignment_stack
),