1/* Id: gcc_compat.c,v 1.119 2015/11/13 17:11:40 ragge Exp */ 2/* $NetBSD: gcc_compat.c,v 1.6 2016/02/09 20:37:32 plunky Exp $ */ 3/* 4 * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30/* 31 * Routines to support some of the gcc extensions to C. 32 */ 33#ifdef GCC_COMPAT 34 35#include "pass1.h" 36#include "cgram.h" 37 38#include <string.h> 39 40#define NODE P1ND 41#define nfree p1nfree 42#define tfree p1tfree 43 44static struct kw { 45 char *name, *ptr; 46 int rv; 47} kw[] = { 48/* 49 * Do NOT change the order of these entries unless you know 50 * what you're doing! 51 */ 52/* 0 */ { "__asm", NULL, C_ASM }, 53/* 1 */ { "__signed", NULL, 0 }, 54/* 2 */ { "__inline", NULL, 0 }, 55/* 3 */ { "__const", NULL, 0 }, 56/* 4 */ { "__asm__", NULL, C_ASM }, 57/* 5 */ { "__inline__", NULL, 0 }, 58/* 6 */ { "__thread", NULL, 0 }, 59/* 7 */ { "__FUNCTION__", NULL, 0 }, 60/* 8 */ { "__volatile", NULL, 0 }, 61/* 9 */ { "__volatile__", NULL, 0 }, 62/* 10 */{ "__restrict", NULL, -1 }, 63/* 11 */{ "__typeof__", NULL, C_TYPEOF }, 64/* 12 */{ "typeof", NULL, C_TYPEOF }, 65/* 13 */{ "__extension__", NULL, -1 }, 66/* 14 */{ "__signed__", NULL, 0 }, 67/* 15 */{ "__attribute__", NULL, 0 }, 68/* 16 */{ "__attribute", NULL, 0 }, 69/* 17 */{ "__real__", NULL, 0 }, 70/* 18 */{ "__imag__", NULL, 0 }, 71/* 19 */{ "__builtin_offsetof", NULL, PCC_OFFSETOF }, 72/* 20 */{ "__PRETTY_FUNCTION__", NULL, 0 }, 73/* 21 */{ "__alignof__", NULL, C_ALIGNOF }, 74/* 22 */{ "__typeof", NULL, C_TYPEOF }, 75/* 23 */{ "__alignof", NULL, C_ALIGNOF }, 76/* 24 */{ "__restrict__", NULL, -1 }, 77 { NULL, NULL, 0 }, 78}; 79 80/* g77 stuff */ 81#if SZFLOAT == SZLONG 82#define G77_INTEGER LONG 83#define G77_UINTEGER ULONG 84#elif SZFLOAT == SZINT 85#define G77_INTEGER INT 86#define G77_UINTEGER UNSIGNED 87#else 88#error fix g77 stuff 89#endif 90#if SZFLOAT*2 == SZLONG 91#define G77_LONGINT LONG 92#define G77_ULONGINT ULONG 93#elif SZFLOAT*2 == SZLONGLONG 94#define G77_LONGINT LONGLONG 95#define G77_ULONGINT ULONGLONG 96#else 97#error fix g77 long stuff 98#endif 99 100static TWORD g77t[] = { G77_INTEGER, G77_UINTEGER, G77_LONGINT, G77_ULONGINT }; 101static char *g77n[] = { "__g77_integer", "__g77_uinteger", 102 "__g77_longint", "__g77_ulongint" }; 103 104#ifdef TARGET_TIMODE 105static char *loti, *hiti, *TISTR; 106static struct symtab *tisp, *ucmpti2sp, *cmpti2sp, *subvti3sp, 107 *addvti3sp, *mulvti3sp, *divti3sp, *udivti3sp, *modti3sp, *umodti3sp, 108 *ashldi3sp, *ashrdi3sp, *lshrdi3sp, *floatuntixfsp; 109 110static struct symtab * 111addftn(char *n, TWORD t) 112{ 113 NODE *p = block(TYPE, 0, 0, 0, 0, 0); 114 struct symtab *sp; 115 116 sp = lookup(addname(n), 0); 117 p->n_type = INCREF(t) + (FTN-PTR); 118 p->n_sp = sp; 119 p->n_df = memset(permalloc(sizeof(union dimfun)), 0, 120 sizeof(union dimfun)); 121 defid(p, EXTERN); 122 nfree(p); 123 return sp; 124} 125 126static struct symtab * 127addstr(char *n) 128{ 129 NODE *p = block(NAME, NIL, NIL, FLOAT, 0, 0); 130 struct symtab *sp; 131 NODE *q; 132 struct attr *ap; 133 struct rstack *rp; 134 extern struct rstack *rpole; 135 136 p->n_type = ctype(ULONGLONG); 137 rpole = rp = bstruct(NULL, STNAME, NULL); 138 soumemb(p, loti, 0); 139 soumemb(p, hiti, 0); 140 q = dclstruct(rp); 141 sp = q->n_sp = lookup(addname(n), 0); 142 defid(q, TYPEDEF); 143 ap = attr_new(GCC_ATYP_MODE, 3); 144 ap->sarg(0) = addname("TI"); 145 ap->iarg(1) = 0; 146 sp->sap = attr_add(sp->sap, ap); 147 nfree(q); 148 nfree(p); 149 150 return sp; 151} 152#endif 153 154void 155gcc_init(void) 156{ 157 struct kw *kwp; 158 NODE *p; 159 TWORD t; 160 int i, d_debug; 161 162 d_debug = ddebug; 163 ddebug = 0; 164 for (kwp = kw; kwp->name; kwp++) 165 kwp->ptr = addname(kwp->name); 166 167 for (i = 0; i < 4; i++) { 168 struct symtab *sp; 169 t = ctype(g77t[i]); 170 p = block(NAME, NIL, NIL, t, NULL, 0); 171 sp = lookup(addname(g77n[i]), 0); 172 p->n_sp = sp; 173 defid(p, TYPEDEF); 174 nfree(p); 175 } 176 ddebug = d_debug; 177#ifdef TARGET_TIMODE 178 { 179 struct attr *ap; 180 181 loti = addname("__loti"); 182 hiti = addname("__hiti"); 183 TISTR = addname("TI"); 184 185 tisp = addstr("0ti"); 186 187 cmpti2sp = addftn("__cmpti2", INT); 188 ucmpti2sp = addftn("__ucmpti2", INT); 189 190 addvti3sp = addftn("__addvti3", STRTY); 191 addvti3sp->sap = tisp->sap; 192 subvti3sp = addftn("__subvti3", STRTY); 193 subvti3sp->sap = tisp->sap; 194 mulvti3sp = addftn("__mulvti3", STRTY); 195 mulvti3sp->sap = tisp->sap; 196 divti3sp = addftn("__divti3", STRTY); 197 divti3sp->sap = tisp->sap; 198 modti3sp = addftn("__modti3", STRTY); 199 modti3sp->sap = tisp->sap; 200 201 ap = attr_new(GCC_ATYP_MODE, 3); 202 ap->sarg(0) = TISTR; 203 ap->iarg(1) = 1; 204 ap = attr_add(tisp->sap, ap); 205 udivti3sp = addftn("__udivti3", STRTY); 206 udivti3sp->sap = ap; 207 umodti3sp = addftn("__umodti3", STRTY); 208 umodti3sp->sap = ap; 209 ashldi3sp = addftn("__ashldi3", ctype(LONGLONG)); 210 ashldi3sp->sap = ap; 211 ashrdi3sp = addftn("__ashrdi3", ctype(LONGLONG)); 212 ashrdi3sp->sap = ap; 213 lshrdi3sp = addftn("__lshrdi3", ctype(LONGLONG)); 214 lshrdi3sp->sap = ap; 215 216 floatuntixfsp = addftn("__floatuntixf", LDOUBLE); 217 } 218#endif 219} 220 221#define TS "\n#pragma tls\n# %d\n" 222#define TLLEN sizeof(TS)+10 223/* 224 * See if a string matches a gcc keyword. 225 */ 226int 227gcc_keyword(char *str) 228{ 229 extern int inattr, parlvl, parbal; 230 char tlbuf[TLLEN], *tw; 231 struct kw *kwp; 232 int i; 233 234 /* XXX hack, should pass everything in expressions */ 235 if (str == kw[21].ptr) 236 return kw[21].rv; 237 238 if (inattr) 239 return 0; 240 241 for (i = 0, kwp = kw; kwp->name; kwp++, i++) 242 if (str == kwp->ptr) 243 break; 244 if (kwp->name == NULL) 245 return 0; 246 if (kwp->rv) 247 return kwp->rv; 248 switch (i) { 249 case 1: /* __signed */ 250 case 14: /* __signed__ */ 251 yylval.type = SIGNED; 252 return C_TYPE; 253 case 2: /* __inline */ 254 case 5: /* __inline__ */ 255 yylval.type = INLINE; 256 return C_FUNSPEC; 257 case 3: /* __const */ 258 yylval.type = CON; 259 return C_QUALIFIER; 260 case 6: /* __thread */ 261 snprintf(tlbuf, TLLEN, TS, lineno); 262 tw = &tlbuf[strlen(tlbuf)]; 263 while (tw > tlbuf) 264 cunput(*--tw); 265 return -1; 266 case 7: /* __FUNCTION__ */ 267 case 20: /* __PRETTY_FUNCTION__ */ 268 if (cftnsp == NULL) { 269 uerror("%s outside function", kwp->name); 270 yylval.strp = ""; 271 } else 272 yylval.strp = cftnsp->sname; /* XXX - not C99 */ 273 return C_STRING; 274 case 8: /* __volatile */ 275 case 9: /* __volatile__ */ 276 yylval.type = VOL; 277 return C_QUALIFIER; 278 case 15: /* __attribute__ */ 279 case 16: /* __attribute */ 280 inattr = 1; 281 parlvl = parbal; 282 return C_ATTRIBUTE; 283 case 17: /* __real__ */ 284 yylval.intval = XREAL; 285 return C_UNOP; 286 case 18: /* __imag__ */ 287 yylval.intval = XIMAG; 288 return C_UNOP; 289 } 290 cerror("gcc_keyword"); 291 return 0; 292} 293 294#ifndef TARGET_ATTR 295#define TARGET_ATTR(p, sue) 0 296#endif 297#ifndef ALMAX 298#define ALMAX (ALLDOUBLE > ALLONGLONG ? ALLDOUBLE : ALLONGLONG) 299#endif 300 301/* allowed number of args */ 302#define A_0ARG 0x01 303#define A_1ARG 0x02 304#define A_2ARG 0x04 305#define A_3ARG 0x08 306/* arg # is a name */ 307#define A1_NAME 0x10 308#define A2_NAME 0x20 309#define A3_NAME 0x40 310#define A_MANY 0x80 311/* arg # is "string" */ 312#define A1_STR 0x100 313#define A2_STR 0x200 314#define A3_STR 0x400 315 316#ifdef __MSC__ 317#define CS(x) 318#else 319#define CS(x) [x] = 320#endif 321 322struct atax { 323 int typ; 324 char *name; 325} atax[GCC_ATYP_MAX] = { 326 CS(ATTR_NONE) { 0, NULL }, 327 CS(ATTR_COMPLEX) { 0, NULL }, 328 CS(xxxATTR_BASETYP) { 0, NULL }, 329 CS(ATTR_QUALTYP) { 0, NULL }, 330 CS(ATTR_STRUCT) { 0, NULL }, 331 CS(ATTR_ALIGNED) { A_0ARG|A_1ARG, "aligned" }, 332 CS(ATTR_NORETURN) { A_0ARG, "noreturn" }, 333 CS(ATTR_P1LABELS) { A_0ARG, "p1labels" }, 334 CS(ATTR_SONAME) { A_1ARG|A1_STR, "soname" }, 335 CS(GCC_ATYP_PACKED) { A_0ARG|A_1ARG, "packed" }, 336 CS(GCC_ATYP_SECTION) { A_1ARG|A1_STR, "section" }, 337 CS(GCC_ATYP_TRANSP_UNION) { A_0ARG, "transparent_union" }, 338 CS(GCC_ATYP_UNUSED) { A_0ARG, "unused" }, 339 CS(GCC_ATYP_DEPRECATED) { A_0ARG, "deprecated" }, 340 CS(GCC_ATYP_MAYALIAS) { A_0ARG, "may_alias" }, 341 CS(GCC_ATYP_MODE) { A_1ARG|A1_NAME, "mode" }, 342 CS(GCC_ATYP_FORMAT) { A_3ARG|A1_NAME, "format" }, 343 CS(GCC_ATYP_NONNULL) { A_MANY, "nonnull" }, 344 CS(GCC_ATYP_SENTINEL) { A_0ARG|A_1ARG, "sentinel" }, 345 CS(GCC_ATYP_WEAK) { A_0ARG, "weak" }, 346 CS(GCC_ATYP_FORMATARG) { A_1ARG, "format_arg" }, 347 CS(GCC_ATYP_GNU_INLINE) { A_0ARG, "gnu_inline" }, 348 CS(GCC_ATYP_MALLOC) { A_0ARG, "malloc" }, 349 CS(GCC_ATYP_NOTHROW) { A_0ARG, "nothrow" }, 350 CS(GCC_ATYP_CONST) { A_0ARG, "const" }, 351 CS(GCC_ATYP_PURE) { A_0ARG, "pure" }, 352 CS(GCC_ATYP_CONSTRUCTOR) { A_0ARG, "constructor" }, 353 CS(GCC_ATYP_DESTRUCTOR) { A_0ARG, "destructor" }, 354 CS(GCC_ATYP_VISIBILITY) { A_1ARG|A1_STR, "visibility" }, 355 CS(GCC_ATYP_STDCALL) { A_0ARG, "stdcall" }, 356 CS(GCC_ATYP_CDECL) { A_0ARG, "cdecl" }, 357 CS(GCC_ATYP_WARN_UNUSED_RESULT) { A_0ARG, "warn_unused_result" }, 358 CS(GCC_ATYP_USED) { A_0ARG, "used" }, 359 CS(GCC_ATYP_NO_INSTR_FUN) { A_0ARG, "no_instrument_function" }, 360 CS(GCC_ATYP_NOINLINE) { A_0ARG, "noinline" }, 361 CS(GCC_ATYP_ALIAS) { A_1ARG|A1_STR, "alias" }, 362 CS(GCC_ATYP_WEAKREF) { A_0ARG|A_1ARG|A1_STR, "weakref" }, 363 CS(GCC_ATYP_ALLOCSZ) { A_1ARG|A_2ARG, "alloc_size" }, 364 CS(GCC_ATYP_ALW_INL) { A_0ARG, "always_inline" }, 365 CS(GCC_ATYP_TLSMODEL) { A_1ARG|A1_STR, "tls_model" }, 366 CS(GCC_ATYP_ALIASWEAK) { A_1ARG|A1_STR, "aliasweak" }, 367 CS(GCC_ATYP_RETURNS_TWICE) { A_0ARG, "returns_twice" }, 368 CS(GCC_ATYP_WARNING) { A_1ARG|A1_STR, "warning" }, 369 CS(GCC_ATYP_NOCLONE) { A_0ARG, "noclone" }, 370 CS(GCC_ATYP_REGPARM) { A_1ARG, "regparm" }, 371 CS(GCC_ATYP_FASTCALL) { A_0ARG, "fastcall" }, 372 373 CS(GCC_ATYP_BOUNDED) { A_3ARG|A_MANY|A1_NAME, "bounded" }, 374 375 CS(GCC_ATYP_WEAKIMPORT) { A_0ARG, "weak_import" }, 376}; 377 378#if SZPOINT(CHAR) == SZLONGLONG 379#define GPT LONGLONG 380#else 381#define GPT INT 382#endif 383 384struct atax mods[] = { 385 { 0, NULL }, 386 { INT, "SI" }, 387 { INT, "word" }, 388 { GPT, "pointer" }, 389 { CHAR, "byte" }, 390 { CHAR, "QI" }, 391 { SHORT, "HI" }, 392 { LONGLONG, "DI" }, 393 { FLOAT, "SF" }, 394 { DOUBLE, "DF" }, 395 { LDOUBLE, "XF" }, 396 { FCOMPLEX, "SC" }, 397 { COMPLEX, "DC" }, 398 { LCOMPLEX, "XC" }, 399 { INT, "libgcc_cmp_return" }, 400 { INT, "libgcc_shift_count" }, 401 { LONG, "unwind_word" }, 402#ifdef TARGET_TIMODE 403 { 800, "TI" }, 404#endif 405#ifdef TARGET_MODS 406 TARGET_MODS 407#endif 408}; 409#define ATSZ (sizeof(mods)/sizeof(mods[0])) 410 411static int 412amatch(char *s, struct atax *at, int mx) 413{ 414 int i, len; 415 416 if (s[0] == '_' && s[1] == '_') 417 s += 2; 418 len = strlen(s); 419 if (len > 2 && s[len-1] == '_' && s[len-2] == '_') 420 len -= 2; 421 for (i = 0; i < mx; i++) { 422 char *t = at[i].name; 423 if (t != NULL && strncmp(s, t, len) == 0 && t[len] == 0) 424 return i; 425 } 426 return 0; 427} 428 429static void 430setaarg(int str, union aarg *aa, NODE *p) 431{ 432 if (str) { 433 if (((str & (A1_STR|A2_STR|A3_STR)) && p->n_op != STRING) || 434 ((str & (A1_NAME|A2_NAME|A3_NAME)) && p->n_op != NAME)) 435 uerror("bad arg to attribute"); 436 if (p->n_op == STRING) { 437 aa->sarg = p->n_name; /* saved in cgram.y */ 438 } else 439 aa->sarg = (char *)p->n_sp; 440 nfree(p); 441 } else 442 aa->iarg = (int)icons(eve(p)); 443} 444 445/* 446 * Parse attributes from an argument list. 447 */ 448static struct attr * 449gcc_attribs(NODE *p) 450{ 451 NODE *q, *r; 452 struct attr *ap; 453 char *name = NULL, *c; 454 int cw, attr, narg; 455 456 if (p->n_op == NAME) { 457 name = (char *)p->n_sp; 458 } else if (p->n_op == CALL || p->n_op == UCALL) { 459 name = (char *)p->n_left->n_sp; 460 } else if (p->n_op == ICON && p->n_type == STRTY) { 461 return NULL; 462 } else 463 cerror("bad variable attribute"); 464 465 if ((attr = amatch(name, atax, GCC_ATYP_MAX)) == 0) { 466 warner(Wattributes, name); 467 ap = NULL; 468 goto out; 469 } 470 narg = 0; 471 if (p->n_op == CALL) 472 for (narg = 1, q = p->n_right; q->n_op == CM; q = q->n_left) 473 narg++; 474 475 cw = atax[attr].typ; 476 if (!(cw & A_MANY) && ((narg > 3) || ((cw & (1 << narg)) == 0))) { 477 uerror("wrong attribute arg count"); 478 return NULL; 479 } 480 ap = attr_new(attr, 3); /* XXX should be narg */ 481 q = p->n_right; 482 483 switch (narg) { 484 default: 485 /* XXX */ 486 while (narg-- > 3) { 487 r = q; 488 q = q->n_left; 489 tfree(r->n_right); 490 nfree(r); 491 } 492 /* FALLTHROUGH */ 493 case 3: 494 setaarg(cw & (A3_NAME|A3_STR), &ap->aa[2], q->n_right); 495 r = q; 496 q = q->n_left; 497 nfree(r); 498 /* FALLTHROUGH */ 499 case 2: 500 setaarg(cw & (A2_NAME|A2_STR), &ap->aa[1], q->n_right); 501 r = q; 502 q = q->n_left; 503 nfree(r); 504 /* FALLTHROUGH */ 505 case 1: 506 setaarg(cw & (A1_NAME|A1_STR), &ap->aa[0], q); 507 p->n_op = UCALL; 508 /* FALLTHROUGH */ 509 case 0: 510 break; 511 } 512 513 /* some attributes must be massaged special */ 514 switch (attr) { 515 case ATTR_ALIGNED: 516 if (narg == 0) 517 ap->aa[0].iarg = ALMAX; 518 else 519 ap->aa[0].iarg *= SZCHAR; 520 break; 521 case GCC_ATYP_PACKED: 522 if (narg == 0) 523 ap->aa[0].iarg = 1; /* bitwise align */ 524 else 525 ap->aa[0].iarg *= SZCHAR; 526 break; 527 528 case GCC_ATYP_VISIBILITY: 529 c = ap->aa[0].sarg; 530 if (strcmp(c, "default") && strcmp(c, "hidden") && 531 strcmp(c, "internal") && strcmp(c, "protected")) 532 werror("unknown visibility %s", c); 533 break; 534 535 case GCC_ATYP_TLSMODEL: 536 c = ap->aa[0].sarg; 537 if (strcmp(c, "global-dynamic") && strcmp(c, "local-dynamic") && 538 strcmp(c, "initial-exec") && strcmp(c, "local-exec")) 539 werror("unknown tls model %s", c); 540 break; 541 542 default: 543 break; 544 } 545out: 546 return ap; 547} 548 549/* 550 * Extract attributes from a node tree and return attribute entries 551 * based on its contents. 552 */ 553struct attr * 554gcc_attr_parse(NODE *p) 555{ 556 struct attr *b, *c; 557 558 if (p == NIL) 559 return NULL; 560 561 if (p->n_op != CM) { 562 b = gcc_attribs(p); 563 tfree(p); 564 } else { 565 b = gcc_attr_parse(p->n_left); 566 c = gcc_attr_parse(p->n_right); 567 nfree(p); 568 b = b ? attr_add(b, c) : c; 569 } 570 return b; 571} 572 573/* 574 * Fixup struct/unions depending on attributes. 575 */ 576void 577gcc_tcattrfix(NODE *p) 578{ 579 struct symtab *sp; 580 struct attr *ap; 581 int sz, coff, csz, al, oal, mxal; 582 583 if (!ISSOU(p->n_type)) /* only for structs or unions */ 584 return; 585 if ((ap = attr_find(p->n_ap, GCC_ATYP_PACKED)) == NULL) 586 return; /* nothing to fix */ 587 588 al = ap->iarg(0); 589 mxal = 0; 590 591 /* Must repack struct */ 592 coff = csz = 0; 593 for (sp = strmemb(ap); sp; sp = sp->snext) { 594 oal = talign(sp->stype, sp->sap); 595 if (oal > al) 596 oal = al; 597 if (mxal < oal) 598 mxal = oal; 599 if (sp->sclass & FIELD) 600 sz = sp->sclass&FLDSIZ; 601 else 602 sz = (int)tsize(sp->stype, sp->sdf, sp->sap); 603 sp->soffset = upoff(sz, oal, &coff); 604 if (coff > csz) 605 csz = coff; 606 if (p->n_type == UNIONTY) 607 coff = 0; 608 } 609 if (mxal < ALCHAR) 610 mxal = ALCHAR; /* for bitfields */ 611 SETOFF(csz, mxal); /* Roundup to whatever */ 612 613 ap = attr_find(p->n_ap, ATTR_STRUCT); 614 ap->amsize = csz; 615 ap = attr_find(p->n_ap, ATTR_ALIGNED); 616 ap->iarg(0) = mxal; 617 618} 619 620/* 621 * gcc-specific pragmas. 622 */ 623int 624pragmas_gcc(char *t) 625{ 626 char u; 627 extern char *pragstore; 628 629 if (strcmp((t = pragtok(NULL)), "diagnostic") == 0) { 630 int warn, err; 631 632 if (strcmp((t = pragtok(NULL)), "ignored") == 0) 633 warn = 0, err = 0; 634 else if (strcmp(t, "warning") == 0) 635 warn = 1, err = 0; 636 else if (strcmp(t, "error") == 0) 637 warn = 1, err = 1; 638 else 639 return 1; 640 641 if (eat('\"') || eat('-')) 642 return 1; 643 644 for (t = pragstore; *t && *t != '\"'; t++) 645 ; 646 647 u = *t; 648 *t = 0; 649 Wset(pragstore + 1, warn, err); 650 *t = u; 651 } else if (strcmp(t, "poison") == 0) { 652 /* currently ignore */; 653 } else if (strcmp(t, "visibility") == 0) { 654 /* currently ignore */; 655 } else if (strcmp(t, "system_header") == 0) { 656 /* currently ignore */; 657 } else 658 werror("gcc pragma unsupported"); 659 return 0; 660} 661 662/* 663 * Fixup types when modes given in defid(). 664 */ 665void 666gcc_modefix(NODE *p) 667{ 668 struct attr *ap; 669#ifdef TARGET_TIMODE 670 struct attr *a2; 671#endif 672 struct symtab *sp; 673 char *s; 674 int i, u; 675 676 if ((ap = attr_find(p->n_ap, GCC_ATYP_MODE)) == NULL) 677 return; 678 679 u = ISUNSIGNED(BTYPE(p->n_type)); 680 if ((i = amatch(ap->aa[0].sarg, mods, ATSZ)) == 0) { 681 werror("unknown mode arg %s", ap->aa[0].sarg); 682 return; 683 } 684 i = mods[i].typ; 685 if (i >= 1 && i <= MAXTYPES) { 686 MODTYPE(p->n_type, ctype(i)); 687 if (u) 688 p->n_type = ENUNSIGN(p->n_type); 689 } else switch (i) { 690#ifdef TARGET_TIMODE 691 case 800: 692 if (BTYPE(p->n_type) == STRTY) 693 break; 694 MODTYPE(p->n_type, tisp->stype); 695 p->n_df = tisp->sdf; 696 p->n_ap = tisp->sap; 697 if (ap->iarg(1) == u) 698 break; 699 /* must add a new mode struct to avoid overwriting */ 700 a2 = attr_new(GCC_ATYP_MODE, 3); 701 a2->sarg(0) = ap->sarg(0); 702 a2->iarg(1) = u; 703 p->n_ap = attr_add(p->n_ap, a2); 704 break; 705#endif 706 case FCOMPLEX: 707 case COMPLEX: 708 case LCOMPLEX: 709 /* Destination should have been converted to a struct already */ 710 if (BTYPE(p->n_type) != STRTY) 711 uerror("gcc_modefix: complex not STRTY"); 712 i -= (FCOMPLEX-FLOAT); 713 ap = strattr(p->n_ap); 714 sp = ap->amlist; 715 if (sp->stype == (unsigned)i) 716 return; /* Already correct type */ 717 /* we must change to another struct */ 718 s = i == FLOAT ? "0f" : 719 i == DOUBLE ? "0d" : 720 i == LDOUBLE ? "0l" : 0; 721 sp = lookup(addname(s), 0); 722 for (ap = sp->sap; ap != NULL; ap = ap->next) 723 p->n_ap = attr_add(p->n_ap, attr_dup(ap)); 724 break; 725 726 default: 727 cerror("gcc_modefix"); 728 } 729} 730 731#ifdef TARGET_TIMODE 732 733/* 734 * Return ap if this node is a TI node, else NULL. 735 */ 736struct attr * 737isti(NODE *p) 738{ 739 struct attr *ap; 740 741 if (p->n_type != STRTY) 742 return NULL; 743 if ((ap = attr_find(p->n_ap, GCC_ATYP_MODE)) == NULL) 744 return NULL; 745 if (strcmp(ap->sarg(0), TISTR)) 746 return NULL; 747 return ap; 748} 749 750static char * 751tistack(void) 752{ 753 struct symtab *sp, *sp2; 754 char buf[12]; 755 NODE *q; 756 char *n; 757 758 /* allocate space on stack */ 759 snprintf(buf, 12, "%d", getlab()); 760 n = addname(buf); 761 sp = lookup(n, 0); 762 sp2 = tisp; 763 q = block(TYPE, NIL, NIL, sp2->stype, sp2->sdf, sp2->sap); 764 q->n_sp = sp; 765 nidcl2(q, AUTO, 0); 766 nfree(q); 767 return n; 768} 769 770#define biop(x,y,z) block(x, y, z, INT, 0, 0) 771/* 772 * Create a ti node from something not a ti node. 773 * This usually means: allocate space on stack, store val, give stack address. 774 */ 775static NODE * 776ticast(NODE *p, int u) 777{ 778 CONSZ val; 779 NODE *q; 780 char *n; 781 int u2; 782 783 n = tistack(); 784 785 /* store val */ 786 switch (p->n_op) { 787 case ICON: 788 val = 0; 789 if (u == 0 && p->n_lval < 0) 790 val = -1; 791 q = eve(biop(DOT, bdty(NAME, n), bdty(NAME, loti))); 792 q = buildtree(ASSIGN, q, p); 793 p = biop(DOT, bdty(NAME, n), bdty(NAME, hiti)); 794 p = eve(biop(ASSIGN, p, bcon(val))); 795 q = buildtree(COMOP, q, p); 796 p = buildtree(COMOP, q, eve(bdty(NAME, n))); 797 break; 798 799 default: 800 u2 = ISUNSIGNED(p->n_type); 801 q = eve(biop(DOT, bdty(NAME, n), bdty(NAME, loti))); 802 q = buildtree(ASSIGN, q, p); 803 p = biop(DOT, bdty(NAME, n), bdty(NAME, hiti)); 804 if (u2) { 805 p = eve(biop(ASSIGN, p, bcon(0))); 806 } else { 807 q = buildtree(ASSIGN, eve(ccopy(p)), q); 808 p = buildtree(RSEQ, eve(p), bcon(SZLONG-1)); 809 } 810 q = buildtree(COMOP, q, p); 811 p = buildtree(COMOP, q, eve(bdty(NAME, n))); 812 break; 813 } 814 return p; 815} 816 817/* 818 * Check if we may have to do a cast to/from TI. 819 */ 820NODE * 821gcc_eval_ticast(int op, NODE *p1, NODE *p2) 822{ 823 struct attr *a1, *a2; 824 int t; 825 826 if ((a1 = isti(p1)) == NULL && (a2 = isti(p2)) == NULL) 827 return NIL; 828 829 if (op == RETURN) 830 p1 = ccopy(p1); 831 if (a1 == NULL) { 832 if (a2 == NULL) 833 cerror("gcc_eval_ticast error"); 834 switch (p1->n_type) { 835 case LDOUBLE: 836 p2 = doacall(floatuntixfsp, 837 nametree(floatuntixfsp), p2); 838 tfree(p1); 839 break; 840 case ULONG: 841 case LONG: 842 p2 = cast(structref(p2, DOT, loti), p1->n_type, 0); 843 tfree(p1); 844 break; 845 case VOID: 846 return NIL; 847 default: 848 uerror("gcc_eval_ticast: %d", p1->n_type); 849 } 850 return p2; 851 } 852 /* p2 can be anything, but we must cast it to p1 */ 853 t = a1->iarg(1); 854 855 if (p2->n_type == STRTY && 856 (a2 = attr_find(p2->n_ap, GCC_ATYP_MODE)) && 857 strcmp(a2->sarg(0), TISTR) == 0) { 858 /* Already TI, just add extra mode bits */ 859 a2 = attr_new(GCC_ATYP_MODE, 3); 860 a2->sarg(0) = TISTR; 861 a2->iarg(1) = t; 862 p2->n_ap = attr_add(p2->n_ap, a2); 863 } else { 864 p2 = ticast(p2, t); 865 } 866 tfree(p1); 867 return p2; 868} 869 870/* 871 * Apply a unary op on a TI value. 872 */ 873NODE * 874gcc_eval_tiuni(int op, NODE *p1) 875{ 876 struct attr *a1; 877 NODE *p; 878 879 if ((a1 = isti(p1)) == NULL) 880 return NULL; 881 882 switch (op) { 883 case UMINUS: 884 p = ticast(bcon(0), 0); 885 p = buildtree(CM, p, p1); 886 p = doacall(subvti3sp, nametree(subvti3sp), p); 887 break; 888 889 case UMUL: 890 p = NULL; 891 default: 892 uerror("unsupported unary TI mode op %d", op); 893 p = NULL; 894 } 895 return p; 896} 897 898/* 899 * Evaluate AND/OR/ER. p1 and p2 are pointers to ti struct. 900 */ 901static NODE * 902gcc_andorer(int op, NODE *p1, NODE *p2) 903{ 904 char *n = tistack(); 905 NODE *p, *t1, *t2, *p3; 906 907 t1 = tempnode(0, p1->n_type, p1->n_df, p1->n_ap); 908 t2 = tempnode(0, p2->n_type, p2->n_df, p2->n_ap); 909 910 p1 = buildtree(ASSIGN, ccopy(t1), p1); 911 p2 = buildtree(ASSIGN, ccopy(t2), p2); 912 p = buildtree(COMOP, p1, p2); 913 914 p3 = buildtree(ADDROF, eve(bdty(NAME, n)), NIL); 915 p1 = buildtree(ASSIGN, structref(ccopy(p3), STREF, hiti), 916 buildtree(op, structref(ccopy(t1), STREF, hiti), 917 structref(ccopy(t2), STREF, hiti))); 918 p = buildtree(COMOP, p, p1); 919 p1 = buildtree(ASSIGN, structref(ccopy(p3), STREF, loti), 920 buildtree(op, structref(t1, STREF, loti), 921 structref(t2, STREF, loti))); 922 p = buildtree(COMOP, p, p1); 923 p = buildtree(COMOP, p, buildtree(UMUL, p3, NIL)); 924 return p; 925} 926 927/* 928 * Ensure that a 128-bit assign succeeds. 929 * If left is not TI, make right not TI, 930 * else if left _is_ TI, make right TI, 931 * else do nothing. 932 */ 933static NODE * 934timodeassign(NODE *p1, NODE *p2) 935{ 936 struct attr *a1, *a2; 937 938 a1 = isti(p1); 939 a2 = isti(p2); 940 if (a1 && a2 == NULL) { 941 p2 = ticast(p2, a1->iarg(1)); 942 } else if (a1 == NULL && a2) { 943 if (ISFTY(p1->n_type)) 944 cerror("cannot TI float convert"); 945 p2 = structref(p2, DOT, loti); 946 } 947 return buildtree(ASSIGN, p1, p2); 948} 949 950/* 951 * Evaluate 128-bit operands. 952 */ 953NODE * 954gcc_eval_timode(int op, NODE *p1, NODE *p2) 955{ 956 struct attr *a1, *a2; 957 struct symtab *sp; 958 NODE *p; 959 int isu = 0, gotti, isaop; 960 961 if (op == CM) 962 return buildtree(op, p1, p2); 963 964 a1 = isti(p1); 965 a2 = isti(p2); 966 967 if (a1 == NULL && a2 == NULL) 968 return NULL; 969 970 if (op == ASSIGN) 971 return timodeassign(p1, p2); 972 973 gotti = (a1 != NULL); 974 gotti += (a2 != NULL); 975 976 if (gotti == 0) 977 return NULL; 978 979 if (a1 != NULL) 980 isu = a1->iarg(1); 981 if (a2 != NULL && !isu) 982 isu = a2->iarg(1); 983 984 if (a1 == NULL) { 985 p1 = ticast(p1, isu); 986 a1 = attr_find(p1->n_ap, GCC_ATYP_MODE); 987 } 988 if (a2 == NULL && (cdope(op) & SHFFLG) == 0) { 989 p2 = ticast(p2, isu); 990 a2 = attr_find(p2->n_ap, GCC_ATYP_MODE); 991 } 992 993 switch (op) { 994 case GT: 995 case GE: 996 case LT: 997 case LE: 998 case EQ: 999 case NE: 1000 /* change to call */ 1001 sp = isu ? ucmpti2sp : cmpti2sp; 1002 p = doacall(sp, nametree(sp), buildtree(CM, p1, p2)); 1003 p = buildtree(op, p, bcon(1)); 1004 break; 1005 1006 case AND: 1007 case ER: 1008 case OR: 1009 if (!ISPTR(p1->n_type)) 1010 p1 = buildtree(ADDROF, p1, NIL); 1011 if (!ISPTR(p2->n_type)) 1012 p2 = buildtree(ADDROF, p2, NIL); 1013 p = gcc_andorer(op, p1, p2); 1014 break; 1015 1016 case LSEQ: 1017 case RSEQ: 1018 case LS: 1019 case RS: 1020 sp = op == LS || op == LSEQ ? ashldi3sp : 1021 isu ? lshrdi3sp : ashrdi3sp; 1022 p2 = cast(p2, INT, 0); 1023 /* XXX p1 ccopy may have side effects */ 1024 p = doacall(sp, nametree(sp), buildtree(CM, ccopy(p1), p2)); 1025 if (op == LSEQ || op == RSEQ) { 1026 p = buildtree(ASSIGN, p1, p); 1027 } else 1028 tfree(p1); 1029 break; 1030 1031 case PLUSEQ: 1032 case MINUSEQ: 1033 case MULEQ: 1034 case DIVEQ: 1035 case MODEQ: 1036 case PLUS: 1037 case MINUS: 1038 case MUL: 1039 case DIV: 1040 case MOD: 1041 isaop = (cdope(op)&ASGOPFLG); 1042 if (isaop) 1043 op = UNASG op; 1044 sp = op == PLUS ? addvti3sp : 1045 op == MINUS ? subvti3sp : 1046 op == MUL ? mulvti3sp : 1047 op == DIV ? (isu ? udivti3sp : divti3sp) : 1048 op == MOD ? (isu ? umodti3sp : modti3sp) : 0; 1049 /* XXX p1 ccopy may have side effects */ 1050 p = doacall(sp, nametree(sp), buildtree(CM, ccopy(p1), p2)); 1051 if (isaop) 1052 p = buildtree(ASSIGN, p1, p); 1053 else 1054 tfree(p1); 1055 break; 1056 1057 default: 1058 uerror("unsupported TImode op %d", op); 1059 p = bcon(0); 1060 } 1061 return p; 1062} 1063#endif 1064 1065#ifdef PCC_DEBUG 1066void 1067dump_attr(struct attr *ap) 1068{ 1069 printf("attributes; "); 1070 for (; ap; ap = ap->next) { 1071 if (ap->atype >= GCC_ATYP_MAX) { 1072 printf("bad type %d, ", ap->atype); 1073 } else if (atax[ap->atype].name == 0) { 1074 char *c = ap->atype == ATTR_COMPLEX ? "complex" : 1075 ap->atype == ATTR_STRUCT ? "struct" : "badtype"; 1076 printf("%s, ", c); 1077 } else { 1078 printf("%s: ", atax[ap->atype].name); 1079 if (atax[ap->atype].typ & A1_STR) 1080 printf("%s ", ap->sarg(0)); 1081 else 1082 printf("%d %d %d, ", ap->iarg(0), 1083 ap->iarg(1), ap->iarg(2)); 1084 } 1085 } 1086 printf("\n"); 1087} 1088#endif 1089#endif 1090