1 /* $Id: gcc_compat.c,v 1.77 2011/02/01 14:20:02 ragge Exp $ */
3 * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Routines to support some of the gcc extensions to C.
44 * Do NOT change the order of these entries unless you know
47 /* 0 */ { "__asm", NULL
, C_ASM
},
48 /* 1 */ { "__signed", NULL
, 0 },
49 /* 2 */ { "__inline", NULL
, C_FUNSPEC
},
50 /* 3 */ { "__const", NULL
, 0 },
51 /* 4 */ { "__asm__", NULL
, C_ASM
},
52 /* 5 */ { "__inline__", NULL
, C_FUNSPEC
},
53 /* 6 */ { "__thread", NULL
, 0 },
54 /* 7 */ { "__FUNCTION__", NULL
, 0 },
55 /* 8 */ { "__volatile", NULL
, 0 },
56 /* 9 */ { "__volatile__", NULL
, 0 },
57 /* 10 */{ "__restrict", NULL
, -1 },
58 /* 11 */{ "__typeof__", NULL
, C_TYPEOF
},
59 /* 12 */{ "typeof", NULL
, C_TYPEOF
},
60 /* 13 */{ "__extension__", NULL
, -1 },
61 /* 14 */{ "__signed__", NULL
, 0 },
62 /* 15 */{ "__attribute__", NULL
, 0 },
63 /* 16 */{ "__attribute", NULL
, 0 },
64 /* 17 */{ "__real__", NULL
, 0 },
65 /* 18 */{ "__imag__", NULL
, 0 },
66 /* 19 */{ "__builtin_offsetof", NULL
, PCC_OFFSETOF
},
67 /* 20 */{ "__PRETTY_FUNCTION__", NULL
, 0 },
68 /* 21 */{ "__alignof__", NULL
, C_ALIGNOF
},
69 /* 22 */{ "__typeof", NULL
, C_TYPEOF
},
70 /* 23 */{ "__alignof", NULL
, C_ALIGNOF
},
71 /* 24 */{ "__restrict__", NULL
, -1 },
77 #define G77_INTEGER LONG
78 #define G77_UINTEGER ULONG
79 #elif SZFLOAT == SZINT
80 #define G77_INTEGER INT
81 #define G77_UINTEGER UNSIGNED
85 #if SZFLOAT*2 == SZLONG
86 #define G77_LONGINT LONG
87 #define G77_ULONGINT ULONG
88 #elif SZFLOAT*2 == SZLONGLONG
89 #define G77_LONGINT LONGLONG
90 #define G77_ULONGINT ULONGLONG
92 #error fix g77 long stuff
95 static TWORD g77t
[] = { G77_INTEGER
, G77_UINTEGER
, G77_LONGINT
, G77_ULONGINT
};
96 static char *g77n
[] = { "__g77_integer", "__g77_uinteger",
97 "__g77_longint", "__g77_ulongint" };
107 for (kwp
= kw
; kwp
->name
; kwp
++)
108 kwp
->ptr
= addname(kwp
->name
);
110 for (i
= 0; i
< 4; i
++) {
113 p
= block(NAME
, NIL
, NIL
, t
, NULL
, MKAP(t
));
114 sp
= lookup(addname(g77n
[i
]), 0);
122 #define TS "\n#pragma tls\n# %d\n"
123 #define TLLEN sizeof(TS)+10
125 * See if a string matches a gcc keyword.
128 gcc_keyword(char *str
, NODE
**n
)
130 extern int inattr
, parlvl
, parbal
;
131 YYSTYPE
*yyl
= (YYSTYPE
*)n
; /* XXX should pass yylval */
132 char tlbuf
[TLLEN
], *tw
;
136 /* XXX hack, should pass everything in expressions */
137 if (str
== kw
[21].ptr
)
143 for (i
= 0, kwp
= kw
; kwp
->name
; kwp
++, i
++)
146 if (kwp
->name
== NULL
)
151 case 1: /* __signed */
152 case 14: /* __signed__ */
153 *n
= mkty((TWORD
)SIGNED
, 0, MKAP(SIGNED
));
155 case 3: /* __const */
156 *n
= block(QUALIFIER
, NIL
, NIL
, CON
, 0, 0);
159 case 6: /* __thread */
160 snprintf(tlbuf
, TLLEN
, TS
, lineno
);
161 tw
= &tlbuf
[strlen(tlbuf
)];
165 case 7: /* __FUNCTION__ */
166 case 20: /* __PRETTY_FUNCTION__ */
167 if (cftnsp
== NULL
) {
168 uerror("%s outside function", kwp
->name
);
171 yylval
.strp
= cftnsp
->sname
; /* XXX - not C99 */
173 case 8: /* __volatile */
174 case 9: /* __volatile__ */
175 *n
= block(QUALIFIER
, NIL
, NIL
, VOL
, 0, 0);
178 case 15: /* __attribute__ */
179 case 16: /* __attribute */
183 case 17: /* __real__ */
186 case 18: /* __imag__ */
190 cerror("gcc_keyword");
195 #define TARGET_ATTR(p, sue) 0
198 #define ALMAX (ALLDOUBLE > ALLONGLONG ? ALLDOUBLE : ALLONGLONG)
201 /* allowed number of args */
206 /* arg # is a name */
211 /* arg # is "string" */
225 } atax
[GCC_ATYP_MAX
] = {
226 CS(ATTR_NONE
) { 0, NULL
},
227 CS(ATTR_COMPLEX
) { 0, NULL
},
228 CS(ATTR_BASETYP
) { 0, NULL
},
229 CS(ATTR_QUALTYP
) { 0, NULL
},
230 CS(ATTR_STRUCT
) { 0, NULL
},
231 CS(GCC_ATYP_ALIGNED
) { A_0ARG
|A_1ARG
, "aligned" },
232 CS(GCC_ATYP_PACKED
) { A_0ARG
|A_1ARG
, "packed" },
233 CS(GCC_ATYP_SECTION
) { A_1ARG
|A1_STR
, "section" },
234 CS(GCC_ATYP_TRANSP_UNION
) { A_0ARG
, "transparent_union" },
235 CS(GCC_ATYP_UNUSED
) { A_0ARG
, "unused" },
236 CS(GCC_ATYP_DEPRECATED
) { A_0ARG
, "deprecated" },
237 CS(GCC_ATYP_MAYALIAS
) { A_0ARG
, "may_alias" },
238 CS(GCC_ATYP_MODE
) { A_1ARG
|A1_NAME
, "mode" },
239 CS(GCC_ATYP_NORETURN
) { A_0ARG
, "noreturn" },
240 CS(GCC_ATYP_FORMAT
) { A_3ARG
|A1_NAME
, "format" },
241 CS(GCC_ATYP_NONNULL
) { A_MANY
, "nonnull" },
242 CS(GCC_ATYP_SENTINEL
) { A_0ARG
|A_1ARG
, "sentinel" },
243 CS(GCC_ATYP_WEAK
) { A_0ARG
, "weak" },
244 CS(GCC_ATYP_FORMATARG
) { A_1ARG
, "format_arg" },
245 CS(GCC_ATYP_GNU_INLINE
) { A_0ARG
, "gnu_inline" },
246 CS(GCC_ATYP_MALLOC
) { A_0ARG
, "malloc" },
247 CS(GCC_ATYP_NOTHROW
) { A_0ARG
, "nothrow" },
248 CS(GCC_ATYP_CONST
) { A_0ARG
, "const" },
249 CS(GCC_ATYP_PURE
) { A_0ARG
, "pure" },
250 CS(GCC_ATYP_CONSTRUCTOR
) { A_0ARG
, "constructor" },
251 CS(GCC_ATYP_DESTRUCTOR
) { A_0ARG
, "destructor" },
252 CS(GCC_ATYP_VISIBILITY
) { A_1ARG
|A1_STR
, "visibility" },
253 CS(GCC_ATYP_STDCALL
) { A_0ARG
, "stdcall" },
254 CS(GCC_ATYP_CDECL
) { A_0ARG
, "cdecl" },
255 CS(GCC_ATYP_WARN_UNUSED_RESULT
) { A_0ARG
, "warn_unused_result" },
256 CS(GCC_ATYP_USED
) { A_0ARG
, "used" },
257 CS(GCC_ATYP_NO_INSTR_FUN
) { A_0ARG
, "no_instrument_function" },
258 CS(GCC_ATYP_NOINLINE
) { A_0ARG
, "noinline" },
259 CS(GCC_ATYP_ALIAS
) { A_1ARG
|A1_STR
, "alias" },
260 CS(GCC_ATYP_WEAKREF
) { A_0ARG
|A_1ARG
|A1_STR
, "weakref" },
261 CS(GCC_ATYP_ALLOCSZ
) { A_1ARG
|A_2ARG
, "alloc_size" },
262 CS(GCC_ATYP_ALW_INL
) { A_0ARG
, "always_inline" },
263 CS(GCC_ATYP_TLSMODEL
) { A_1ARG
|A1_STR
, "tls_model" },
264 CS(GCC_ATYP_ALIASWEAK
) { A_1ARG
|A1_STR
, "aliasweak" },
266 CS(GCC_ATYP_BOUNDED
) { A_3ARG
|A_MANY
|A1_NAME
, "bounded" },
269 #if SZPOINT(CHAR) == SZLONGLONG
275 struct atax mods
[] = {
294 #define ATSZ (sizeof(mods)/sizeof(mods[0]))
297 amatch(char *s
, struct atax
*at
, int mx
)
301 if (s
[0] == '_' && s
[1] == '_')
304 if (len
> 2 && s
[len
-1] == '_' && s
[len
-2] == '_')
306 for (i
= 0; i
< mx
; i
++) {
307 char *t
= at
[i
].name
;
308 if (t
!= NULL
&& strncmp(s
, t
, len
) == 0 && t
[len
] == 0)
315 setaarg(int str
, union aarg
*aa
, NODE
*p
)
318 if (((str
& (A1_STR
|A2_STR
|A3_STR
)) && p
->n_op
!= STRING
) ||
319 ((str
& (A1_NAME
|A2_NAME
|A3_NAME
)) && p
->n_op
!= NAME
))
320 uerror("bad arg to attribute");
321 if (p
->n_op
== STRING
) {
322 aa
->sarg
= newstring(p
->n_name
, strlen(p
->n_name
)+1);
324 aa
->sarg
= (char *)p
->n_sp
;
327 aa
->iarg
= (int)icons(eve(p
));
331 * Parse attributes from an argument list.
338 char *name
= NULL
, *c
;
339 int cw
, attr
, narg
, i
;
341 if (p
->n_op
== NAME
) {
342 name
= (char *)p
->n_sp
;
343 } else if (p
->n_op
== CALL
|| p
->n_op
== UCALL
) {
344 name
= (char *)p
->n_left
->n_sp
;
345 } else if (p
->n_op
== ICON
&& p
->n_type
== STRTY
) {
348 cerror("bad variable attribute");
350 if ((attr
= amatch(name
, atax
, GCC_ATYP_MAX
)) == 0) {
351 werror("unsupported attribute '%s'", name
);
357 for (narg
= 1, q
= p
->n_right
; q
->n_op
== CM
; q
= q
->n_left
)
361 if (!(cw
& A_MANY
) && ((narg
> 3) || ((cw
& (1 << narg
)) == 0))) {
362 uerror("wrong attribute arg count");
365 ap
= attr_new(attr
, 3); /* XXX should be narg */
379 setaarg(cw
& (A3_NAME
|A3_STR
), &ap
->aa
[2], q
->n_right
);
385 setaarg(cw
& (A2_NAME
|A2_STR
), &ap
->aa
[1], q
->n_right
);
391 setaarg(cw
& (A1_NAME
|A1_STR
), &ap
->aa
[0], q
);
398 /* some attributes must be massaged special */
400 case GCC_ATYP_ALIGNED
:
402 ap
->aa
[0].iarg
= ALMAX
;
404 ap
->aa
[0].iarg
*= SZCHAR
;
406 case GCC_ATYP_PACKED
:
408 ap
->aa
[0].iarg
= 1; /* bitwise align */
410 ap
->aa
[0].iarg
*= SZCHAR
;
414 if ((i
= amatch(ap
->aa
[0].sarg
, mods
, ATSZ
)) == 0)
415 werror("unknown mode arg %s", ap
->aa
[0].sarg
);
416 ap
->aa
[0].iarg
= ctype(mods
[i
].typ
);
419 case GCC_ATYP_VISIBILITY
:
421 if (strcmp(c
, "default") && strcmp(c
, "hidden") &&
422 strcmp(c
, "internal") && strcmp(c
, "protected"))
423 werror("unknown visibility %s", c
);
426 case GCC_ATYP_TLSMODEL
:
428 if (strcmp(c
, "global-dynamic") && strcmp(c
, "local-dynamic") &&
429 strcmp(c
, "initial-exec") && strcmp(c
, "local-exec"))
430 werror("unknown tls model %s", c
);
441 * Extract attributes from a node tree and return attribute entries
442 * based on its contents.
445 gcc_attr_parse(NODE
*p
)
456 b
= gcc_attr_parse(p
->n_left
);
457 c
= gcc_attr_parse(p
->n_right
);
459 b
= b
? attr_add(b
, c
) : c
;
465 * Fixup struct/unions depending on attributes.
468 gcc_tcattrfix(NODE
*p
)
472 int sz
, coff
, csz
, al
;
474 if ((ap
= attr_find(p
->n_ap
, GCC_ATYP_PACKED
)) == NULL
)
475 return; /* nothing to fix */
479 /* Must repack struct */
481 for (sp
= strmemb(ap
); sp
; sp
= sp
->snext
) {
482 if (sp
->sclass
& FIELD
)
483 sz
= sp
->sclass
&FLDSIZ
;
485 sz
= (int)tsize(sp
->stype
, sp
->sdf
, sp
->sap
);
491 if (p
->n_type
== UNIONTY
)
494 SETOFF(csz
, al
); /* Roundup to whatever */
496 ap
= attr_find(p
->n_ap
, ATTR_BASETYP
);
502 * gcc-specific pragmas.
507 int ign
, warn
, err
, i
, u
;
508 extern bittype warnary
[], werrary
[];
509 extern char *flagstr
[], *pragstore
;
511 if (strcmp((t
= pragtok(NULL
)), "diagnostic") == 0) {
512 ign
= warn
= err
= 0;
513 if (strcmp((t
= pragtok(NULL
)), "ignored") == 0)
515 else if (strcmp(t
, "warning") == 0)
517 else if (strcmp(t
, "error") == 0)
521 if (eat('\"') || eat('-'))
523 for (t
= pragstore
; *t
&& *t
!= '\"'; t
++)
527 for (i
= 0; i
< NUMW
; i
++) {
528 if (strcmp(flagstr
[i
], pragstore
+1) != 0)
535 BITCLEAR(werrary
, i
);
537 BITCLEAR(warnary
, i
);
538 BITCLEAR(werrary
, i
);
543 } else if (strcmp(t
, "poison") == 0) {
544 /* currently ignore */;
545 } else if (strcmp(t
, "visibility") == 0) {
546 /* currently ignore */;
548 werror("gcc pragma unsupported");
554 dump_attr(struct attr
*ap
)
556 printf("attributes; ");
557 for (; ap
; ap
= ap
->next
) {
558 if (ap
->atype
>= GCC_ATYP_MAX
) {
559 printf("bad type %d, ", ap
->atype
);
560 } else if (atax
[ap
->atype
].name
== 0) {
561 char *c
= ap
->atype
== ATTR_COMPLEX
? "complex" :
562 ap
->atype
== ATTR_BASETYP
? "basetyp" :
563 ap
->atype
== ATTR_STRUCT
? "struct" : "badtype";
566 printf("%s: ", atax
[ap
->atype
].name
);
567 printf("%d %d %d, ", ap
->iarg(0),
568 ap
->iarg(1), ap
->iarg(2));