source: mainline/uspace/app/pcc/cc/ccom/gcc_compat.c@ fae4d30

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fae4d30 was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • Property mode set to 100644
File size: 13.8 KB
Line 
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.
5 *
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
16 *
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.
27 */
28
29/*
30 * Routines to support some of the gcc extensions to C.
31 */
32#ifdef GCC_COMPAT
33
34#include "pass1.h"
35#include "cgram.h"
36
37#include <string.h>
38
39static struct kw {
40 char *name, *ptr;
41 int rv;
42} kw[] = {
43/*
44 * Do NOT change the order of these entries unless you know
45 * what you're doing!
46 */
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 },
73};
74
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
94
95static TWORD g77t[] = { G77_INTEGER, G77_UINTEGER, G77_LONGINT, G77_ULONGINT };
96static char *g77n[] = { "__g77_integer", "__g77_uinteger",
97 "__g77_longint", "__g77_ulongint" };
98
99void
100gcc_init()
101{
102 struct kw *kwp;
103 NODE *p;
104 TWORD t;
105 int i;
106
107 for (kwp = kw; kwp->name; kwp++)
108 kwp->ptr = addname(kwp->name);
109
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);
118 }
119
120}
121
122#define TS "\n#pragma tls\n# %d\n"
123#define TLLEN sizeof(TS)+10
124/*
125 * See if a string matches a gcc keyword.
126 */
127int
128gcc_keyword(char *str, NODE **n)
129{
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;
135
136 /* XXX hack, should pass everything in expressions */
137 if (str == kw[21].ptr)
138 return kw[21].rv;
139
140 if (inattr)
141 return 0;
142
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;
189 }
190 cerror("gcc_keyword");
191 return 0;
192}
193
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
200
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
215
216#ifdef __MSC__
217#define CS(x)
218#else
219#define CS(x) [x] =
220#endif
221
222struct 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" },
265
266 CS(GCC_ATYP_BOUNDED) { A_3ARG|A_MANY|A1_NAME, "bounded" },
267};
268
269#if SZPOINT(CHAR) == SZLONGLONG
270#define GPT LONGLONG
271#else
272#define GPT INT
273#endif
274
275struct 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
293};
294#define ATSZ (sizeof(mods)/sizeof(mods[0]))
295
296static int
297amatch(char *s, struct atax *at, int mx)
298{
299 int i, len;
300
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;
310 }
311 return 0;
312}
313
314static void
315setaarg(int str, union aarg *aa, NODE *p)
316{
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));
328}
329
330/*
331 * Parse attributes from an argument list.
332 */
333static struct attr *
334gcc_attribs(NODE *p)
335{
336 NODE *q, *r;
337 struct attr *ap;
338 char *name = NULL, *c;
339 int cw, attr, narg, i;
340
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");
349
350 if ((attr = amatch(name, atax, GCC_ATYP_MAX)) == 0) {
351 werror("unsupported attribute '%s'", name);
352 ap = NULL;
353 goto out;
354 }
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++;
359
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;
364 }
365 ap = attr_new(attr, 3); /* XXX should be narg */
366 q = p->n_right;
367
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);
376 }
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;
396 }
397
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;
412
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;
418
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;
425
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;
432
433 default:
434 break;
435 }
436out:
437 return ap;
438}
439
440/*
441 * Extract attributes from a node tree and return attribute entries
442 * based on its contents.
443 */
444struct attr *
445gcc_attr_parse(NODE *p)
446{
447 struct attr *b, *c;
448
449 if (p == NIL)
450 return NULL;
451
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;
460 }
461 return b;
462}
463
464/*
465 * Fixup struct/unions depending on attributes.
466 */
467void
468gcc_tcattrfix(NODE *p)
469{
470 struct symtab *sp;
471 struct attr *ap;
472 int sz, coff, csz, al;
473
474 if ((ap = attr_find(p->n_ap, GCC_ATYP_PACKED)) == NULL)
475 return; /* nothing to fix */
476
477 al = ap->iarg(0);
478
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;
493 }
494 SETOFF(csz, al); /* Roundup to whatever */
495
496 ap = attr_find(p->n_ap, ATTR_BASETYP);
497 ap->atypsz = csz;
498 ap->aalign = al;
499}
500
501/*
502 * gcc-specific pragmas.
503 */
504int
505pragmas_gcc(char *t)
506{
507 int ign, warn, err, i, u;
508 extern bittype warnary[], werrary[];
509 extern char *flagstr[], *pragstore;
510
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++)
524 ;
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);
539 }
540 return 0;
541 }
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;
550}
551
552#ifdef PCC_DEBUG
553void
554dump_attr(struct attr *ap)
555{
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));
569 }
570 }
571 printf("\n");
572}
573#endif
574#endif
Note: See TracBrowser for help on using the repository browser.