* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / cc / ccom / gcc_compat.c
blob34f6a712653682f49ab28e3aa7c14abad94d2cdc
1 /* $Id: gcc_compat.c,v 1.77 2011/02/01 14:20:02 ragge Exp $ */
2 /*
3 * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
32 #ifdef GCC_COMPAT
34 #include "pass1.h"
35 #include "cgram.h"
37 #include <string.h>
39 static struct kw {
40 char *name, *ptr;
41 int rv;
42 } kw[] = {
44 * Do NOT change the order of these entries unless you know
45 * what you're doing!
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 },
72 { NULL, NULL, 0 },
75 /* g77 stuff */
76 #if SZFLOAT == SZLONG
77 #define G77_INTEGER LONG
78 #define G77_UINTEGER ULONG
79 #elif SZFLOAT == SZINT
80 #define G77_INTEGER INT
81 #define G77_UINTEGER UNSIGNED
82 #else
83 #error fix g77 stuff
84 #endif
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
91 #else
92 #error fix g77 long stuff
93 #endif
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" };
99 void
100 gcc_init()
102 struct kw *kwp;
103 NODE *p;
104 TWORD t;
105 int i;
107 for (kwp = kw; kwp->name; kwp++)
108 kwp->ptr = addname(kwp->name);
110 for (i = 0; i < 4; i++) {
111 struct symtab *sp;
112 t = ctype(g77t[i]);
113 p = block(NAME, NIL, NIL, t, NULL, MKAP(t));
114 sp = lookup(addname(g77n[i]), 0);
115 p->n_sp = sp;
116 defid(p, TYPEDEF);
117 nfree(p);
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;
133 struct kw *kwp;
134 int i;
136 /* XXX hack, should pass everything in expressions */
137 if (str == kw[21].ptr)
138 return kw[21].rv;
140 if (inattr)
141 return 0;
143 for (i = 0, kwp = kw; kwp->name; kwp++, i++)
144 if (str == kwp->ptr)
145 break;
146 if (kwp->name == NULL)
147 return 0;
148 if (kwp->rv)
149 return kwp->rv;
150 switch (i) {
151 case 1: /* __signed */
152 case 14: /* __signed__ */
153 *n = mkty((TWORD)SIGNED, 0, MKAP(SIGNED));
154 return C_TYPE;
155 case 3: /* __const */
156 *n = block(QUALIFIER, NIL, NIL, CON, 0, 0);
157 (*n)->n_qual = CON;
158 return C_QUALIFIER;
159 case 6: /* __thread */
160 snprintf(tlbuf, TLLEN, TS, lineno);
161 tw = &tlbuf[strlen(tlbuf)];
162 while (tw > tlbuf)
163 cunput(*--tw);
164 return -1;
165 case 7: /* __FUNCTION__ */
166 case 20: /* __PRETTY_FUNCTION__ */
167 if (cftnsp == NULL) {
168 uerror("%s outside function", kwp->name);
169 yylval.strp = "";
170 } else
171 yylval.strp = cftnsp->sname; /* XXX - not C99 */
172 return C_STRING;
173 case 8: /* __volatile */
174 case 9: /* __volatile__ */
175 *n = block(QUALIFIER, NIL, NIL, VOL, 0, 0);
176 (*n)->n_qual = VOL;
177 return C_QUALIFIER;
178 case 15: /* __attribute__ */
179 case 16: /* __attribute */
180 inattr = 1;
181 parlvl = parbal;
182 return C_ATTRIBUTE;
183 case 17: /* __real__ */
184 yyl->intval = XREAL;
185 return C_UNOP;
186 case 18: /* __imag__ */
187 yyl->intval = XIMAG;
188 return C_UNOP;
190 cerror("gcc_keyword");
191 return 0;
194 #ifndef TARGET_ATTR
195 #define TARGET_ATTR(p, sue) 0
196 #endif
197 #ifndef ALMAX
198 #define ALMAX (ALLDOUBLE > ALLONGLONG ? ALLDOUBLE : ALLONGLONG)
199 #endif
201 /* allowed number of args */
202 #define A_0ARG 0x01
203 #define A_1ARG 0x02
204 #define A_2ARG 0x04
205 #define A_3ARG 0x08
206 /* arg # is a name */
207 #define A1_NAME 0x10
208 #define A2_NAME 0x20
209 #define A3_NAME 0x40
210 #define A_MANY 0x80
211 /* arg # is "string" */
212 #define A1_STR 0x100
213 #define A2_STR 0x200
214 #define A3_STR 0x400
216 #ifdef __MSC__
217 #define CS(x)
218 #else
219 #define CS(x) [x] =
220 #endif
222 struct atax {
223 int typ;
224 char *name;
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
270 #define GPT LONGLONG
271 #else
272 #define GPT INT
273 #endif
275 struct atax mods[] = {
276 { 0, NULL },
277 { INT, "SI" },
278 { INT, "word" },
279 { GPT, "pointer" },
280 { CHAR, "byte" },
281 { CHAR, "QI" },
282 { SHORT, "HI" },
283 { LONGLONG, "DI" },
284 { FLOAT, "SF" },
285 { DOUBLE, "DF" },
286 { LDOUBLE, "XF" },
287 { FCOMPLEX, "SC" },
288 { COMPLEX, "DC" },
289 { LCOMPLEX, "XC" },
290 #ifdef TARGET_MODS
291 TARGET_MODS
292 #endif
294 #define ATSZ (sizeof(mods)/sizeof(mods[0]))
296 static int
297 amatch(char *s, struct atax *at, int mx)
299 int i, len;
301 if (s[0] == '_' && s[1] == '_')
302 s += 2;
303 len = strlen(s);
304 if (len > 2 && s[len-1] == '_' && s[len-2] == '_')
305 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)
309 return i;
311 return 0;
314 static void
315 setaarg(int str, union aarg *aa, NODE *p)
317 if (str) {
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);
323 } else
324 aa->sarg = (char *)p->n_sp;
325 nfree(p);
326 } else
327 aa->iarg = (int)icons(eve(p));
331 * Parse attributes from an argument list.
333 static struct attr *
334 gcc_attribs(NODE *p)
336 NODE *q, *r;
337 struct attr *ap;
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) {
346 return NULL;
347 } else
348 cerror("bad variable attribute");
350 if ((attr = amatch(name, atax, GCC_ATYP_MAX)) == 0) {
351 werror("unsupported attribute '%s'", name);
352 ap = NULL;
353 goto out;
355 narg = 0;
356 if (p->n_op == CALL)
357 for (narg = 1, q = p->n_right; q->n_op == CM; q = q->n_left)
358 narg++;
360 cw = atax[attr].typ;
361 if (!(cw & A_MANY) && ((narg > 3) || ((cw & (1 << narg)) == 0))) {
362 uerror("wrong attribute arg count");
363 return NULL;
365 ap = attr_new(attr, 3); /* XXX should be narg */
366 q = p->n_right;
368 switch (narg) {
369 default:
370 /* XXX */
371 while (narg-- > 3) {
372 r = q;
373 q = q->n_left;
374 tfree(r->n_right);
375 nfree(r);
377 /* FALLTHROUGH */
378 case 3:
379 setaarg(cw & (A3_NAME|A3_STR), &ap->aa[2], q->n_right);
380 r = q;
381 q = q->n_left;
382 nfree(r);
383 /* FALLTHROUGH */
384 case 2:
385 setaarg(cw & (A2_NAME|A2_STR), &ap->aa[1], q->n_right);
386 r = q;
387 q = q->n_left;
388 nfree(r);
389 /* FALLTHROUGH */
390 case 1:
391 setaarg(cw & (A1_NAME|A1_STR), &ap->aa[0], q);
392 p->n_op = UCALL;
393 /* FALLTHROUGH */
394 case 0:
395 break;
398 /* some attributes must be massaged special */
399 switch (attr) {
400 case GCC_ATYP_ALIGNED:
401 if (narg == 0)
402 ap->aa[0].iarg = ALMAX;
403 else
404 ap->aa[0].iarg *= SZCHAR;
405 break;
406 case GCC_ATYP_PACKED:
407 if (narg == 0)
408 ap->aa[0].iarg = 1; /* bitwise align */
409 else
410 ap->aa[0].iarg *= SZCHAR;
411 break;
413 case GCC_ATYP_MODE:
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);
417 break;
419 case GCC_ATYP_VISIBILITY:
420 c = ap->aa[0].sarg;
421 if (strcmp(c, "default") && strcmp(c, "hidden") &&
422 strcmp(c, "internal") && strcmp(c, "protected"))
423 werror("unknown visibility %s", c);
424 break;
426 case GCC_ATYP_TLSMODEL:
427 c = ap->aa[0].sarg;
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);
431 break;
433 default:
434 break;
436 out:
437 return ap;
441 * Extract attributes from a node tree and return attribute entries
442 * based on its contents.
444 struct attr *
445 gcc_attr_parse(NODE *p)
447 struct attr *b, *c;
449 if (p == NIL)
450 return NULL;
452 if (p->n_op != CM) {
453 b = gcc_attribs(p);
454 tfree(p);
455 } else {
456 b = gcc_attr_parse(p->n_left);
457 c = gcc_attr_parse(p->n_right);
458 nfree(p);
459 b = b ? attr_add(b, c) : c;
461 return b;
465 * Fixup struct/unions depending on attributes.
467 void
468 gcc_tcattrfix(NODE *p)
470 struct symtab *sp;
471 struct attr *ap;
472 int sz, coff, csz, al;
474 if ((ap = attr_find(p->n_ap, GCC_ATYP_PACKED)) == NULL)
475 return; /* nothing to fix */
477 al = ap->iarg(0);
479 /* Must repack struct */
480 coff = csz = 0;
481 for (sp = strmemb(ap); sp; sp = sp->snext) {
482 if (sp->sclass & FIELD)
483 sz = sp->sclass&FLDSIZ;
484 else
485 sz = (int)tsize(sp->stype, sp->sdf, sp->sap);
486 SETOFF(sz, al);
487 sp->soffset = coff;
488 coff += sz;
489 if (coff > csz)
490 csz = coff;
491 if (p->n_type == UNIONTY)
492 coff = 0;
494 SETOFF(csz, al); /* Roundup to whatever */
496 ap = attr_find(p->n_ap, ATTR_BASETYP);
497 ap->atypsz = csz;
498 ap->aalign = al;
502 * gcc-specific pragmas.
505 pragmas_gcc(char *t)
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)
514 ign = 1;
515 else if (strcmp(t, "warning") == 0)
516 warn = 1;
517 else if (strcmp(t, "error") == 0)
518 err = 1;
519 else
520 return 1;
521 if (eat('\"') || eat('-'))
522 return 1;
523 for (t = pragstore; *t && *t != '\"'; t++)
525 u = *t;
526 *t = 0;
527 for (i = 0; i < NUMW; i++) {
528 if (strcmp(flagstr[i], pragstore+1) != 0)
529 continue;
530 if (err) {
531 BITSET(warnary, i);
532 BITSET(werrary, i);
533 } else if (warn) {
534 BITSET(warnary, i);
535 BITCLEAR(werrary, i);
536 } else {
537 BITCLEAR(warnary, i);
538 BITCLEAR(werrary, i);
540 return 0;
542 *t = u;
543 } else if (strcmp(t, "poison") == 0) {
544 /* currently ignore */;
545 } else if (strcmp(t, "visibility") == 0) {
546 /* currently ignore */;
547 } else
548 werror("gcc pragma unsupported");
549 return 0;
552 #ifdef PCC_DEBUG
553 void
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";
564 printf("%s, ", c);
565 } else {
566 printf("%s: ", atax[ap->atype].name);
567 printf("%d %d %d, ", ap->iarg(0),
568 ap->iarg(1), ap->iarg(2));
571 printf("\n");
573 #endif
574 #endif