new date 20231021
[pcc.git] / cc / ccom / gcc_compat.c
blobc1061db33d89789a2e9c25c5314430f0c2426bd9
1 /* $Id: gcc_compat.c,v 1.124 2023/07/23 08:55:09 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 #define NODE P1ND
40 #define nfree p1nfree
41 #define tfree p1tfree
42 #undef n_type
43 #define n_type ptype
44 #undef n_qual
45 #define n_qual pqual
46 #undef n_df
47 #define n_df pdf
50 static struct kw {
51 char *name, *ptr;
52 int rv;
53 } kw[] = {
55 * Do NOT change the order of these entries unless you know
56 * what you're doing!
58 /* 0 */ { "__asm", NULL, C_ASM },
59 /* 1 */ { "__signed", NULL, 0 },
60 /* 2 */ { "__inline", NULL, 0 },
61 /* 3 */ { "__const", NULL, 0 },
62 /* 4 */ { "__asm__", NULL, C_ASM },
63 /* 5 */ { "__inline__", NULL, 0 },
64 /* 6 */ { "__thread", NULL, 0 },
65 /* 7 */ { "__FUNCTION__", NULL, 0 },
66 /* 8 */ { "__volatile", NULL, 0 },
67 /* 9 */ { "__volatile__", NULL, 0 },
68 /* 10 */{ "__restrict", NULL, -1 },
69 /* 11 */{ "__typeof__", NULL, C_TYPEOF },
70 /* 12 */{ "typeof", NULL, C_TYPEOF },
71 /* 13 */{ "__extension__", NULL, -1 },
72 /* 14 */{ "__signed__", NULL, 0 },
73 /* 15 */{ "__attribute__", NULL, 0 },
74 /* 16 */{ "__attribute", NULL, 0 },
75 /* 17 */{ "__real__", NULL, 0 },
76 /* 18 */{ "__imag__", NULL, 0 },
77 /* 19 */{ "__builtin_offsetof", NULL, PCC_OFFSETOF },
78 /* 20 */{ "__PRETTY_FUNCTION__", NULL, 0 },
79 /* 21 */{ "__alignof__", NULL, C_ALIGNOF },
80 /* 22 */{ "__typeof", NULL, C_TYPEOF },
81 /* 23 */{ "__alignof", NULL, C_ALIGNOF },
82 /* 24 */{ "__restrict__", NULL, -1 },
83 { NULL, NULL, 0 },
86 /* g77 stuff */
87 #if SZFLOAT == SZLONG
88 #define G77_INTEGER LONG
89 #define G77_UINTEGER ULONG
90 #elif SZFLOAT == SZINT
91 #define G77_INTEGER INT
92 #define G77_UINTEGER UNSIGNED
93 #else
94 #error fix g77 stuff
95 #endif
96 #if SZFLOAT*2 == SZLONG
97 #define G77_LONGINT LONG
98 #define G77_ULONGINT ULONG
99 #elif SZFLOAT*2 == SZLONGLONG
100 #define G77_LONGINT LONGLONG
101 #define G77_ULONGINT ULONGLONG
102 #else
103 #error fix g77 long stuff
104 #endif
106 static TWORD g77t[] = { G77_INTEGER, G77_UINTEGER, G77_LONGINT, G77_ULONGINT };
107 static char *g77n[] = { "__g77_integer", "__g77_uinteger",
108 "__g77_longint", "__g77_ulongint" };
110 #ifdef TARGET_TIMODE
111 static char *loti, *hiti, *TISTR;
112 static char *lotf, *hitf, *TFSTR;
113 static char *loctf, *hictf, *loitf, *hiitf, *TCSTR;
114 static struct symtab *tisp, *tfsp, *tcsp, *ucmpti2sp, *cmpti2sp, *subvti3sp,
115 *addvti3sp, *mulvti3sp, *divti3sp, *udivti3sp, *modti3sp, *umodti3sp,
116 *ashlti3sp, *ashrti3sp, *lshrti3sp, *floatuntixfsp;
118 #define TYPE_TI 800
119 #define TYPE_TF 864
120 #define TYPE_TC 928
122 struct tifuns {
123 struct symtab **sp;
124 char *fun;
125 TWORD type;
126 int apt;
127 } tifuns[] = {
128 { &cmpti2sp, "__cmpti2", INT, 0 },
129 { &ucmpti2sp, "__ucmpti2", INT, 0 },
131 { &addvti3sp, "__addvti3", STRTY, 1 },
132 { &subvti3sp, "__subvti3", STRTY, 1 },
133 { &mulvti3sp, "__mulvti3", STRTY, 1 },
134 { &divti3sp, "__divti3", STRTY, 1 },
135 { &modti3sp, "__modti3", STRTY, 1 },
137 { &udivti3sp, "__udivti3", STRTY, 2 },
138 { &umodti3sp, "__umodti3", STRTY, 2 },
139 { &ashlti3sp, "__ashlti3", STRTY, 2 },
140 { &ashrti3sp, "__ashrti3", STRTY, 2 },
141 { &lshrti3sp, "__lshrti3", STRTY, 2 },
143 { &floatuntixfsp, "__floatuntixf", LDOUBLE, 0 },
147 static struct symtab *
148 addftn(char *n, TWORD t)
150 NODE *p = block(TYPE, 0, 0, 0, 0, 0);
151 struct symtab *sp;
153 sp = lookup(addname(n), 0);
154 p->n_type = INCREF(t) + (FTN-PTR);
155 p->n_sp = sp;
156 p->n_df = memset(permalloc(sizeof(union dimfun)), 0,
157 sizeof(union dimfun));
158 defid(p, EXTERN);
159 nfree(p);
160 return sp;
163 static struct symtab *
164 addstr(char *n, char *typ)
166 NODE *p = block(NAME, NIL, NIL, FLOAT, 0, 0);
167 struct symtab *sp;
168 NODE *q;
169 struct attr *ap;
170 struct rstack *rp;
171 extern struct rstack *rpole;
173 p->n_type = ctype(ULONGLONG);
174 rpole = rp = bstruct(NULL, STNAME, NULL);
175 if (typ[1] == 'I') {
176 soumemb(p, loti, 0);
177 soumemb(p, hiti, 0);
178 } else if (typ[1] == 'F') {
179 soumemb(p, lotf, 0);
180 soumemb(p, hitf, 0);
181 } else {
182 soumemb(p, loctf, 0);
183 soumemb(p, hictf, 0);
184 soumemb(p, loitf, 0);
185 soumemb(p, hiitf, 0);
187 q = dclstruct(rp);
188 sp = q->n_sp = lookup(addname(n), 0);
189 defid(q, TYPEDEF);
190 ap = attr_new(GCC_ATYP_MODE, 3);
191 ap->sarg(0) = addname(typ);
192 ap->iarg(1) = 0;
193 sp->sap = attr_add(sp->sap, ap);
194 nfree(q);
195 nfree(p);
197 return sp;
199 #endif
201 void
202 gcc_init(void)
204 struct kw *kwp;
205 NODE *p;
206 TWORD t;
207 int i, d_debug;
209 d_debug = ddebug;
210 ddebug = 0;
211 for (kwp = kw; kwp->name; kwp++)
212 kwp->ptr = addname(kwp->name);
214 for (i = 0; i < 4; i++) {
215 struct symtab *sp;
216 t = ctype(g77t[i]);
217 p = block(NAME, NIL, NIL, t, NULL, 0);
218 sp = lookup(addname(g77n[i]), 0);
219 p->n_sp = sp;
220 defid(p, TYPEDEF);
221 nfree(p);
223 ddebug = d_debug;
224 #ifdef TARGET_TIMODE
226 struct attr *ap2;
228 loti = addname("__loti");
229 hiti = addname("__hiti");
230 TISTR = addname("TI");
231 tisp = addstr("0ti", "TI");
233 lotf = addname("__lotf");
234 hitf = addname("__hitf");
235 TFSTR = addname("TF");
236 tfsp = addstr("0tf", "TF");
238 loctf = addname("__loctf");
239 hictf = addname("__hictf");
240 loitf = addname("__loitf");
241 hiitf = addname("__hiitf");
242 TCSTR = addname("TC");
243 tcsp = addstr("0tc", "TC");
245 ap2 = attr_new(GCC_ATYP_MODE, 3);
246 ap2->sarg(0) = TISTR;
247 ap2->iarg(1) = 1;
248 ap2 = attr_add(tisp->sap, ap2);
250 for (i = 0; i < (int)(sizeof(tifuns)/sizeof(tifuns[0])); i++) {
251 *tifuns[i].sp = addftn(tifuns[i].fun, tifuns[i].type);
252 switch (tifuns[i].apt) {
253 case 0: /* nothing */
254 break;
255 case 1: /* just tisp */
256 (*tifuns[i].sp)->sap = tisp->sap;
257 break;
258 case 2: /* mode string */
259 (*tifuns[i].sp)->sap = ap2;
265 #endif
268 #define TS "\n#pragma tls\n# %d\n"
269 #define TLLEN sizeof(TS)+10
271 * See if a string matches a gcc keyword.
274 gcc_keyword(char *str)
276 extern int inattr, parlvl, parbal;
277 char tlbuf[TLLEN], *tw;
278 struct kw *kwp;
279 int i;
281 /* XXX hack, should pass everything in expressions */
282 if (str == kw[21].ptr)
283 return kw[21].rv;
285 if (inattr)
286 return 0;
288 for (i = 0, kwp = kw; kwp->name; kwp++, i++)
289 if (str == kwp->ptr)
290 break;
291 if (kwp->name == NULL)
292 return 0;
293 if (kwp->rv)
294 return kwp->rv;
295 switch (i) {
296 case 1: /* __signed */
297 case 14: /* __signed__ */
298 yylval.type = SIGNED;
299 return C_TYPE;
300 case 2: /* __inline */
301 case 5: /* __inline__ */
302 yylval.type = INLINE;
303 return C_FUNSPEC;
304 case 3: /* __const */
305 yylval.type = CON;
306 return C_QUALIFIER;
307 case 6: /* __thread */
308 snprintf(tlbuf, TLLEN, TS, lineno);
309 tw = &tlbuf[strlen(tlbuf)];
310 while (tw > tlbuf)
311 cunput(*--tw);
312 return -1;
313 case 7: /* __FUNCTION__ */
314 case 20: /* __PRETTY_FUNCTION__ */
315 if (cftnsp == NULL) {
316 uerror("%s outside function", kwp->name);
317 yylval.strp = "";
318 } else
319 yylval.strp = cftnsp->sname; /* XXX - not C99 */
320 return C_STRING;
321 case 8: /* __volatile */
322 case 9: /* __volatile__ */
323 yylval.type = VOL;
324 return C_QUALIFIER;
325 case 15: /* __attribute__ */
326 case 16: /* __attribute */
327 inattr = 1;
328 parlvl = parbal;
329 return C_ATTRIBUTE;
330 case 17: /* __real__ */
331 yylval.intval = XREAL;
332 return C_UNOP;
333 case 18: /* __imag__ */
334 yylval.intval = XIMAG;
335 return C_UNOP;
337 cerror("gcc_keyword");
338 return 0;
341 #ifndef TARGET_ATTR
342 #define TARGET_ATTR(p, sue) 0
343 #endif
344 #ifndef ALMAX
345 #define ALMAX (ALLDOUBLE > ALLONGLONG ? ALLDOUBLE : ALLONGLONG)
346 #endif
348 /* allowed number of args */
349 #define A_0ARG 0x01
350 #define A_1ARG 0x02
351 #define A_2ARG 0x04
352 #define A_3ARG 0x08
353 /* arg # is a name */
354 #define A1_NAME 0x10
355 #define A2_NAME 0x20
356 #define A3_NAME 0x40
357 #define A_MANY 0x80
358 /* arg # is "string" */
359 #define A1_STR 0x100
360 #define A2_STR 0x200
361 #define A3_STR 0x400
363 #ifdef __MSC__
364 #define CS(x)
365 #else
366 #define CS(x) [x] =
367 #endif
369 struct atax {
370 int typ;
371 char *name;
372 } atax[GCC_ATYP_MAX] = {
373 CS(ATTR_NONE) { 0, NULL },
374 CS(ATTR_COMPLEX) { 0, NULL },
375 CS(xxxATTR_BASETYP) { 0, NULL },
376 CS(ATTR_QUALTYP) { 0, NULL },
377 CS(xxxATTR_STRUCT) { 0, NULL },
378 CS(xxxATTR_ALIGNED) { A_0ARG|A_1ARG, "aligned" },
379 CS(ATTR_NORETURN) { A_0ARG, "noreturn" },
380 CS(ATTR_P1LABELS) { A_0ARG, "p1labels" },
381 CS(ATTR_SONAME) { A_1ARG|A1_STR, "soname" },
382 CS(GCC_ATYP_PACKED) { A_0ARG|A_1ARG, "packed" },
383 CS(GCC_ATYP_SECTION) { A_1ARG|A1_STR, "section" },
384 CS(GCC_ATYP_TRANSP_UNION) { A_0ARG, "transparent_union" },
385 CS(GCC_ATYP_UNUSED) { A_0ARG, "unused" },
386 CS(GCC_ATYP_DEPRECATED) { A_0ARG, "deprecated" },
387 CS(GCC_ATYP_MAYALIAS) { A_0ARG, "may_alias" },
388 CS(GCC_ATYP_MODE) { A_1ARG|A1_NAME, "mode" },
389 CS(GCC_ATYP_FORMAT) { A_3ARG|A1_NAME, "format" },
390 CS(GCC_ATYP_NONNULL) { A_MANY, "nonnull" },
391 CS(GCC_ATYP_SENTINEL) { A_0ARG|A_1ARG, "sentinel" },
392 CS(GCC_ATYP_WEAK) { A_0ARG, "weak" },
393 CS(GCC_ATYP_FORMATARG) { A_1ARG, "format_arg" },
394 CS(GCC_ATYP_GNU_INLINE) { A_0ARG, "gnu_inline" },
395 CS(GCC_ATYP_MALLOC) { A_0ARG, "malloc" },
396 CS(GCC_ATYP_NOTHROW) { A_0ARG, "nothrow" },
397 CS(GCC_ATYP_CONST) { A_0ARG, "const" },
398 CS(GCC_ATYP_PURE) { A_0ARG, "pure" },
399 CS(GCC_ATYP_CONSTRUCTOR) { A_0ARG, "constructor" },
400 CS(GCC_ATYP_DESTRUCTOR) { A_0ARG, "destructor" },
401 CS(GCC_ATYP_VISIBILITY) { A_1ARG|A1_STR, "visibility" },
402 CS(GCC_ATYP_STDCALL) { A_0ARG, "stdcall" },
403 CS(GCC_ATYP_CDECL) { A_0ARG, "cdecl" },
404 CS(GCC_ATYP_WARN_UNUSED_RESULT) { A_0ARG, "warn_unused_result" },
405 CS(GCC_ATYP_USED) { A_0ARG, "used" },
406 CS(GCC_ATYP_NO_INSTR_FUN) { A_0ARG, "no_instrument_function" },
407 CS(GCC_ATYP_NOINLINE) { A_0ARG, "noinline" },
408 CS(GCC_ATYP_ALIAS) { A_1ARG|A1_STR, "alias" },
409 CS(GCC_ATYP_WEAKREF) { A_0ARG|A_1ARG|A1_STR, "weakref" },
410 CS(GCC_ATYP_ALLOCSZ) { A_1ARG|A_2ARG, "alloc_size" },
411 CS(GCC_ATYP_ALW_INL) { A_0ARG, "always_inline" },
412 CS(GCC_ATYP_TLSMODEL) { A_1ARG|A1_STR, "tls_model" },
413 CS(GCC_ATYP_ALIASWEAK) { A_1ARG|A1_STR, "aliasweak" },
414 CS(GCC_ATYP_RETURNS_TWICE) { A_0ARG, "returns_twice" },
415 CS(GCC_ATYP_WARNING) { A_1ARG|A1_STR, "warning" },
416 CS(GCC_ATYP_NOCLONE) { A_0ARG, "noclone" },
417 CS(GCC_ATYP_REGPARM) { A_1ARG, "regparm" },
418 CS(GCC_ATYP_FASTCALL) { A_0ARG, "fastcall" },
420 CS(GCC_ATYP_BOUNDED) { A_3ARG|A_MANY|A1_NAME, "bounded" },
422 CS(GCC_ATYP_WEAKIMPORT) { A_0ARG, "weak_import" },
425 #if SZPOINT(CHAR) == SZLONGLONG
426 #define GPT LONGLONG
427 #else
428 #define GPT INT
429 #endif
431 struct atax mods[] = {
432 { 0, NULL },
433 { INT, "SI" },
434 { INT, "word" },
435 { GPT, "pointer" },
436 { CHAR, "byte" },
437 { CHAR, "QI" },
438 { SHORT, "HI" },
439 { LONGLONG, "DI" },
440 { FLOAT, "SF" },
441 { DOUBLE, "DF" },
442 { LDOUBLE, "XF" },
443 { FCOMPLEX, "SC" },
444 { COMPLEX, "DC" },
445 { LCOMPLEX, "XC" },
446 { INT, "libgcc_cmp_return" },
447 { INT, "libgcc_shift_count" },
448 { LONG, "unwind_word" },
449 #ifdef TARGET_TIMODE
450 { 800, "TI" },
451 { 864, "TF" },
452 { 928, "TC" },
453 #endif
454 #ifdef TARGET_MODS
455 TARGET_MODS
456 #endif
458 #define ATSZ (sizeof(mods)/sizeof(mods[0]))
460 static int
461 amatch(char *s, struct atax *at, int mx)
463 int i;
464 size_t len;
466 if (s[0] == '_' && s[1] == '_')
467 s += 2;
468 len = strlen(s);
469 if (len > 2 && s[len-1] == '_' && s[len-2] == '_')
470 len -= 2;
471 for (i = 0; i < mx; i++) {
472 char *t = at[i].name;
473 if (t != NULL && strncmp(s, t, len) == 0 && t[len] == 0)
474 return i;
476 return 0;
479 static void
480 setaarg(int str, union aarg *aa, NODE *p)
482 if (str) {
483 if (((str & (A1_STR|A2_STR|A3_STR)) && p->n_op != STRING) ||
484 ((str & (A1_NAME|A2_NAME|A3_NAME)) && p->n_op != NAME))
485 uerror("bad arg to attribute");
486 if (p->n_op == STRING) {
487 aa->sarg = p->n_name; /* saved in cgram.y */
488 } else
489 aa->sarg = (char *)p->n_sp;
490 nfree(p);
491 } else
492 aa->iarg = (int)icons(eve(p));
496 * Parse attributes from an argument list.
498 static struct attr *
499 gcc_attribs(NODE *p)
501 NODE *q, *r;
502 struct attr *ap;
503 char *name = NULL, *c;
504 int cw, attr, narg;
506 if (p->n_op == NAME) {
507 name = (char *)p->n_sp;
508 } else if (p->n_op == CALL || p->n_op == UCALL) {
509 name = (char *)p->n_left->n_sp;
510 } else if (p->n_op == ICON && p->n_type == STRTY) {
511 return NULL;
512 } else
513 cerror("bad variable attribute");
515 if ((attr = amatch(name, atax, GCC_ATYP_MAX)) == 0) {
516 warner(Wattributes, name);
517 ap = NULL;
518 goto out;
520 narg = 0;
521 if (p->n_op == CALL)
522 for (narg = 1, q = p->n_right; q->n_op == CM; q = q->n_left)
523 narg++;
525 cw = atax[attr].typ;
526 if (!(cw & A_MANY) && ((narg > 3) || ((cw & (1 << narg)) == 0))) {
527 uerror("wrong attribute arg count");
528 return NULL;
530 ap = attr_new(attr, 3); /* XXX should be narg */
531 q = p->n_right;
533 switch (narg) {
534 default:
535 /* XXX */
536 while (narg-- > 3) {
537 r = q;
538 q = q->n_left;
539 tfree(r->n_right);
540 nfree(r);
542 /* FALLTHROUGH */
543 case 3:
544 setaarg(cw & (A3_NAME|A3_STR), &ap->aa[2], q->n_right);
545 r = q;
546 q = q->n_left;
547 nfree(r);
548 /* FALLTHROUGH */
549 case 2:
550 setaarg(cw & (A2_NAME|A2_STR), &ap->aa[1], q->n_right);
551 r = q;
552 q = q->n_left;
553 nfree(r);
554 /* FALLTHROUGH */
555 case 1:
556 setaarg(cw & (A1_NAME|A1_STR), &ap->aa[0], q);
557 p->n_op = UCALL;
558 /* FALLTHROUGH */
559 case 0:
560 break;
563 /* some attributes must be massaged special */
564 switch (attr) {
565 case xxxATTR_ALIGNED:
566 if (narg == 0)
567 ap->aa[0].iarg = ALMAX;
568 else
569 ap->aa[0].iarg *= SZCHAR;
570 break;
571 case GCC_ATYP_PACKED:
572 if (narg == 0)
573 ap->aa[0].iarg = 1; /* bitwise align */
574 else
575 ap->aa[0].iarg *= SZCHAR;
576 break;
578 case GCC_ATYP_VISIBILITY:
579 c = ap->aa[0].sarg;
580 if (strcmp(c, "default") && strcmp(c, "hidden") &&
581 strcmp(c, "internal") && strcmp(c, "protected"))
582 werror("unknown visibility %s", c);
583 break;
585 case GCC_ATYP_TLSMODEL:
586 c = ap->aa[0].sarg;
587 if (strcmp(c, "global-dynamic") && strcmp(c, "local-dynamic") &&
588 strcmp(c, "initial-exec") && strcmp(c, "local-exec"))
589 werror("unknown tls model %s", c);
590 break;
592 default:
593 break;
595 out:
596 return ap;
600 * Extract attributes from a node tree and return attribute entries
601 * based on its contents.
603 struct attr *
604 gcc_attr_parse(NODE *p)
606 struct attr *b, *c;
608 if (p == NIL)
609 return NULL;
611 if (p->n_op != CM) {
612 b = gcc_attribs(p);
613 tfree(p);
614 } else {
615 b = gcc_attr_parse(p->n_left);
616 c = gcc_attr_parse(p->n_right);
617 nfree(p);
618 b = b ? attr_add(b, c) : c;
620 return b;
624 * Fixup struct/unions depending on attributes.
626 void
627 gcc_tcattrfix(NODE *p)
629 struct ssdesc *ss;
630 struct symtab *sp;
631 struct attr *ap;
632 int sz, coff, csz, al, oal, mxal;
634 if (!ISSOU(p->n_type)) /* only for structs or unions */
635 return;
636 if ((ap = attr_find(p->n_ap, GCC_ATYP_PACKED)) == NULL)
637 return; /* nothing to fix */
639 al = ap->iarg(0);
640 mxal = 0;
642 /* Must repack struct */
643 coff = csz = 0;
644 for (sp = strmemb(p->n_td->ss); sp; sp = sp->snext) {
645 oal = talign(sp->stype, sp->sss);
646 if (oal > al)
647 oal = al;
648 if (mxal < oal)
649 mxal = oal;
650 if (sp->sclass & FIELD)
651 sz = sp->sclass&FLDSIZ;
652 else
653 sz = (int)tsize(sp->stype, sp->sdf, sp->sss);
654 sp->soffset = upoff(sz, oal, &coff);
655 if (coff > csz)
656 csz = coff;
657 if (p->n_type == UNIONTY)
658 coff = 0;
660 if (mxal < ALCHAR)
661 mxal = ALCHAR; /* for bitfields */
662 SETOFF(csz, mxal); /* Roundup to whatever */
664 ss = p->n_td->ss;
665 ss->sz = csz;
666 ss->al = mxal;
670 * gcc-specific pragmas.
673 pragmas_gcc(char *t)
675 char u;
676 extern char *pragstore;
678 if (strcmp((t = pragtok(NULL)), "diagnostic") == 0) {
679 int warn, err;
681 if (strcmp((t = pragtok(NULL)), "ignored") == 0)
682 warn = 0, err = 0;
683 else if (strcmp(t, "warning") == 0)
684 warn = 1, err = 0;
685 else if (strcmp(t, "error") == 0)
686 warn = 1, err = 1;
687 else
688 return 1;
690 if (eat('\"') || eat('-'))
691 return 1;
693 for (t = pragstore; *t && *t != '\"'; t++)
696 u = *t;
697 *t = 0;
698 Wset(pragstore + 1, warn, err);
699 *t = u;
700 } else if (strcmp(t, "poison") == 0) {
701 /* currently ignore */;
702 } else if (strcmp(t, "visibility") == 0) {
703 /* currently ignore */;
704 } else if (strcmp(t, "system_header") == 0) {
705 /* currently ignore */;
706 } else
707 werror("gcc pragma unsupported");
708 return 0;
712 * Fixup types when modes given in defid().
714 void
715 gcc_modefix(NODE *p)
717 struct ssdesc *ss;
718 struct attr *ap;
719 #ifdef TARGET_TIMODE
720 struct attr *a2;
721 #endif
722 struct symtab *sp;
723 char *s;
724 int i, u;
726 if ((ap = attr_find(p->n_ap, GCC_ATYP_MODE)) == NULL)
727 return;
729 u = ISUNSIGNED(BTYPE(p->n_type));
730 if ((i = amatch(ap->aa[0].sarg, mods, ATSZ)) == 0) {
731 werror("unknown mode arg %s", ap->aa[0].sarg);
732 return;
734 i = mods[i].typ;
735 if (i >= 1 && i <= MAXTYPES) {
736 MODTYPE(p->n_type, ctype(i));
737 if (u)
738 p->n_type = ENUNSIGN(p->n_type);
739 } else switch (i) {
740 #ifdef TARGET_TIMODE
741 case 864:
742 case 928:
743 case 800:
744 if (BTYPE(p->n_type) == STRTY)
745 break;
746 MODTYPE(p->n_type, tisp->stype);
747 p->n_df = tisp->sdf;
748 p->n_ap = tisp->sap;
749 if (ap->iarg(1) == u)
750 break;
751 /* must add a new mode struct to avoid overwriting */
752 a2 = attr_new(GCC_ATYP_MODE, 3);
753 a2->sarg(0) = ap->sarg(0);
754 a2->iarg(1) = u;
755 p->n_ap = attr_add(p->n_ap, a2);
756 break;
757 #endif
758 case FCOMPLEX:
759 case COMPLEX:
760 case LCOMPLEX:
761 /* Destination should have been converted to a struct already */
762 if (BTYPE(p->n_type) != STRTY)
763 uerror("gcc_modefix: complex not STRTY");
764 i -= (FCOMPLEX-FLOAT);
765 ss = strattr(p->n_td);
766 sp = ss->sp;
767 if (sp->stype == (unsigned)i)
768 return; /* Already correct type */
769 /* we must change to another struct */
770 s = i == FLOAT ? "0f" :
771 i == DOUBLE ? "0d" :
772 i == LDOUBLE ? "0l" : 0;
773 sp = lookup(addname(s), 0);
774 for (ap = sp->sap; ap != NULL; ap = ap->next)
775 p->n_ap = attr_add(p->n_ap, attr_dup(ap));
776 break;
778 default:
779 cerror("gcc_modefix");
783 #ifdef TARGET_TIMODE
786 * Return ap if this node is a TI node, else NULL.
788 struct attr *
789 isti(NODE *p)
791 struct attr *ap;
793 if (p->n_type != STRTY)
794 return NULL;
795 if ((ap = attr_find(p->n_ap, GCC_ATYP_MODE)) == NULL)
796 return NULL;
797 if (strcmp(ap->sarg(0), TISTR) && strcmp(ap->sarg(0), TFSTR) &&
798 strcmp(ap->sarg(0), TCSTR))
799 return NULL;
800 return ap;
803 static char *
804 tistack(void)
806 struct symtab *sp, *sp2;
807 char buf[12];
808 NODE *q;
809 char *n;
811 /* allocate space on stack */
812 snprintf(buf, 12, "%d", getlab());
813 n = addname(buf);
814 sp = lookup(n, 0);
815 sp2 = tisp;
816 q = block(TYPE, NIL, NIL, sp2->stype, sp2->sdf, sp2->sss);
817 q->n_sp = sp;
818 nidcl2(q, AUTO, 0);
819 nfree(q);
820 return n;
823 #define biop(x,y,z) block(x, y, z, INT, 0, 0)
825 * Create a ti node from something not a ti node.
826 * This usually means: allocate space on stack, store val, give stack address.
828 static NODE *
829 ticast(NODE *p, int u)
831 CONSZ val;
832 NODE *q;
833 char *n;
834 int u2;
836 n = tistack();
838 /* store val */
839 switch (p->n_op) {
840 case ICON:
841 val = 0;
842 if (u == 0 && glval(p) < 0)
843 val = -1;
844 q = eve(biop(DOT, bdty(NAME, n), bdty(NAME, loti)));
845 q = buildtree(ASSIGN, q, p);
846 p = biop(DOT, bdty(NAME, n), bdty(NAME, hiti));
847 p = eve(biop(ASSIGN, p, bcon(val)));
848 q = buildtree(COMOP, q, p);
849 p = buildtree(COMOP, q, eve(bdty(NAME, n)));
850 break;
852 default:
853 u2 = ISUNSIGNED(p->n_type);
854 q = eve(biop(DOT, bdty(NAME, n), bdty(NAME, loti)));
855 q = buildtree(ASSIGN, q, p);
856 p = biop(DOT, bdty(NAME, n), bdty(NAME, hiti));
857 if (u2) {
858 p = eve(biop(ASSIGN, p, bcon(0)));
859 } else {
860 q = buildtree(ASSIGN, eve(p1tcopy(p)), q);
861 p = buildtree(RSEQ, eve(p), bcon(SZLONG-1));
863 q = buildtree(COMOP, q, p);
864 p = buildtree(COMOP, q, eve(bdty(NAME, n)));
865 break;
867 return p;
871 * Check if we may have to do a cast to/from TI.
873 NODE *
874 gcc_eval_ticast(int op, NODE *p1, NODE *p2)
876 struct attr *a1, *a2;
877 int t;
879 a2 = NULL; /* XXX flow analysis */
880 if ((a1 = isti(p1)) == NULL && (a2 = isti(p2)) == NULL)
881 return NIL;
883 if (op == RETURN)
884 p1 = p1tcopy(p1);
885 if (a1 == NULL) {
886 if (a2 == NULL)
887 cerror("gcc_eval_ticast error");
888 switch (p1->n_type) {
889 case LDOUBLE:
890 p2 = doacall(floatuntixfsp,
891 nametree(floatuntixfsp), p2);
892 tfree(p1);
893 break;
894 case ULONG:
895 case LONG:
896 p2 = cast(structref(p2, DOT, loti), p1->n_type, 0);
897 tfree(p1);
898 break;
899 case VOID:
900 return NIL;
901 default:
902 uerror("gcc_eval_ticast: %d", p1->n_type);
904 return p2;
906 /* p2 can be anything, but we must cast it to p1 */
907 t = a1->iarg(1);
909 if (p2->n_type == STRTY &&
910 (a2 = attr_find(p2->n_ap, GCC_ATYP_MODE)) &&
911 strcmp(a2->sarg(0), TISTR) == 0) {
912 /* Already TI, just add extra mode bits */
913 a2 = attr_new(GCC_ATYP_MODE, 3);
914 a2->sarg(0) = TISTR;
915 a2->iarg(1) = t;
916 p2->n_ap = attr_add(p2->n_ap, a2);
917 } else {
918 p2 = ticast(p2, t);
920 tfree(p1);
921 return p2;
925 * Apply a unary op on a TI value.
927 NODE *
928 gcc_eval_tiuni(int op, NODE *p1)
930 struct attr *a1;
931 NODE *p;
933 if ((a1 = isti(p1)) == NULL)
934 return NULL;
936 switch (op) {
937 case UMINUS:
938 p = ticast(bcon(0), 0);
939 p = buildtree(CM, p, p1);
940 p = doacall(subvti3sp, nametree(subvti3sp), p);
941 break;
943 case UMUL:
944 p = NULL;
945 default:
946 uerror("unsupported unary TI mode op %d", op);
947 p = NULL;
949 return p;
953 * Evaluate AND/OR/ER. p1 and p2 are pointers to ti struct.
955 static NODE *
956 gcc_andorer(int op, NODE *p1, NODE *p2)
958 char *n = tistack();
959 NODE *p, *t1, *t2, *p3;
961 t1 = tempnode(0, p1->n_type, p1->n_df, p1->pss);
962 t2 = tempnode(0, p2->n_type, p2->n_df, p2->pss);
964 p1 = buildtree(ASSIGN, p1tcopy(t1), p1);
965 p2 = buildtree(ASSIGN, p1tcopy(t2), p2);
966 p = buildtree(COMOP, p1, p2);
968 p3 = buildtree(ADDROF, eve(bdty(NAME, n)), NIL);
969 p1 = buildtree(ASSIGN, structref(p1tcopy(p3), STREF, hiti),
970 buildtree(op, structref(p1tcopy(t1), STREF, hiti),
971 structref(p1tcopy(t2), STREF, hiti)));
972 p = buildtree(COMOP, p, p1);
973 p1 = buildtree(ASSIGN, structref(p1tcopy(p3), STREF, loti),
974 buildtree(op, structref(t1, STREF, loti),
975 structref(t2, STREF, loti)));
976 p = buildtree(COMOP, p, p1);
977 p = buildtree(COMOP, p, buildtree(UMUL, p3, NIL));
978 return p;
982 * Ensure that a 128-bit assign succeeds.
983 * If left is not TI, make right not TI,
984 * else if left _is_ TI, make right TI,
985 * else do nothing.
987 static NODE *
988 timodeassign(NODE *p1, NODE *p2)
990 struct attr *a1, *a2;
992 a1 = isti(p1);
993 a2 = isti(p2);
994 if (a1 && a2 == NULL) {
995 p2 = ticast(p2, a1->iarg(1));
996 } else if (a1 == NULL && a2) {
997 if (ISFTY(p1->n_type))
998 cerror("cannot TI float convert");
999 p2 = structref(p2, DOT, loti);
1001 return buildtree(ASSIGN, p1, p2);
1005 * Evaluate 128-bit operands.
1007 NODE *
1008 gcc_eval_timode(int op, NODE *p1, NODE *p2)
1010 struct attr *a1, *a2;
1011 struct symtab *sp;
1012 NODE *p;
1013 int isu = 0, gotti, isaop;
1015 if (op == CM)
1016 return buildtree(op, p1, p2);
1018 a1 = isti(p1);
1019 a2 = isti(p2);
1021 if (a1 == NULL && a2 == NULL)
1022 return NULL;
1024 if (op == ASSIGN)
1025 return timodeassign(p1, p2);
1027 gotti = (a1 != NULL);
1028 gotti += (a2 != NULL);
1030 if (gotti == 0)
1031 return NULL;
1033 if (a1 != NULL)
1034 isu = a1->iarg(1);
1035 if (a2 != NULL && !isu)
1036 isu = a2->iarg(1);
1038 if (a1 == NULL) {
1039 p1 = ticast(p1, isu);
1040 a1 = attr_find(p1->n_ap, GCC_ATYP_MODE);
1042 if (a2 == NULL && (cdope(op) & SHFFLG) == 0) {
1043 p2 = ticast(p2, isu);
1044 a2 = attr_find(p2->n_ap, GCC_ATYP_MODE);
1047 switch (op) {
1048 case GT:
1049 case GE:
1050 case LT:
1051 case LE:
1052 case EQ:
1053 case NE:
1054 /* change to call */
1055 sp = isu ? ucmpti2sp : cmpti2sp;
1056 p = doacall(sp, nametree(sp), buildtree(CM, p1, p2));
1057 p = buildtree(op, p, bcon(1));
1058 break;
1060 case AND:
1061 case ER:
1062 case OR:
1063 if (!ISPTR(p1->n_type))
1064 p1 = buildtree(ADDROF, p1, NIL);
1065 if (!ISPTR(p2->n_type))
1066 p2 = buildtree(ADDROF, p2, NIL);
1067 p = gcc_andorer(op, p1, p2);
1068 break;
1070 case LSEQ:
1071 case RSEQ:
1072 case LS:
1073 case RS:
1074 sp = op == LS || op == LSEQ ? ashlti3sp :
1075 isu ? lshrti3sp : ashrti3sp;
1076 p2 = cast(p2, INT, 0);
1077 /* XXX p1 p1tcopy may have side effects */
1078 p = doacall(sp, nametree(sp), buildtree(CM, p1tcopy(p1), p2));
1079 if (op == LSEQ || op == RSEQ) {
1080 p = buildtree(ASSIGN, p1, p);
1081 } else
1082 tfree(p1);
1083 break;
1085 case PLUSEQ:
1086 case MINUSEQ:
1087 case MULEQ:
1088 case DIVEQ:
1089 case MODEQ:
1090 case PLUS:
1091 case MINUS:
1092 case MUL:
1093 case DIV:
1094 case MOD:
1095 isaop = (cdope(op)&ASGOPFLG);
1096 if (isaop)
1097 op = UNASG op;
1098 sp = op == PLUS ? addvti3sp :
1099 op == MINUS ? subvti3sp :
1100 op == MUL ? mulvti3sp :
1101 op == DIV ? (isu ? udivti3sp : divti3sp) :
1102 op == MOD ? (isu ? umodti3sp : modti3sp) : 0;
1103 /* XXX p1 p1tcopy may have side effects */
1104 p = doacall(sp, nametree(sp), buildtree(CM, p1tcopy(p1), p2));
1105 if (isaop)
1106 p = buildtree(ASSIGN, p1, p);
1107 else
1108 tfree(p1);
1109 break;
1111 default:
1112 uerror("unsupported TImode op %d", op);
1113 p = bcon(0);
1115 return p;
1117 #endif
1119 #ifdef PCC_DEBUG
1120 void
1121 dump_attr(struct attr *ap)
1123 printf("attributes; ");
1124 for (; ap; ap = ap->next) {
1125 if (ap->atype >= GCC_ATYP_MAX) {
1126 printf("bad type %d, ", ap->atype);
1127 } else if (atax[ap->atype].name == 0) {
1128 char *c = ap->atype == ATTR_COMPLEX ? "complex" :
1129 "badtype";
1130 printf("%s, ", c);
1131 } else {
1132 printf("%s: ", atax[ap->atype].name);
1133 if (atax[ap->atype].typ & A1_STR)
1134 printf("%s ", ap->sarg(0));
1135 else
1136 printf("%d %d %d, ", ap->iarg(0),
1137 ap->iarg(1), ap->iarg(2));
1140 printf("\n");
1142 #endif
1143 #endif