1 /* Id: pftn.c,v 1.420 2016/01/07 20:05:56 ragge Exp */ 2 /* $NetBSD: pftn.c,v 1.10 2016/02/09 20:37:32 plunky Exp $ */ 3 /* 4 * Copyright (c) 2003 Anders Magnusson (ragge (at) 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 /* 28 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 29 * 30 * Redistribution and use in source and binary forms, with or without 31 * modification, are permitted provided that the following conditions 32 * are met: 33 * 34 * Redistributions of source code and documentation must retain the above 35 * copyright notice, this list of conditions and the following disclaimer. 36 * Redistributions in binary form must reproduce the above copyright 37 * notice, this list of conditionsand the following disclaimer in the 38 * documentation and/or other materials provided with the distribution. 39 * All advertising materials mentioning features or use of this software 40 * must display the following acknowledgement: 41 * This product includes software developed or owned by Caldera 42 * International, Inc. 43 * Neither the name of Caldera International, Inc. nor the names of other 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 48 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 50 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 51 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE 52 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, 56 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 57 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 58 * POSSIBILITY OF SUCH DAMAGE. 59 */ 60 61 /* 62 * Many changes from the 32V sources, among them: 63 * - New symbol table manager (moved to another file). 64 * - Prototype saving/checks. 65 */ 66 67 # include "pass1.h" 68 #include "unicode.h" 69 70 #include <stddef.h> 71 #include <stdlib.h> 72 73 #include "cgram.h" 74 75 #define NODE P1ND 76 #define tfree p1tfree 77 #define nfree p1nfree 78 #define ccopy p1tcopy 79 #define flist p1flist 80 #define fwalk p1fwalk 81 82 struct symtab *cftnsp; 83 int arglistcnt, dimfuncnt; /* statistics */ 84 int symtabcnt, suedefcnt; /* statistics */ 85 int lcommsz, blkalloccnt; 86 int autooff, /* the next unused automatic offset */ 87 maxautooff, /* highest used automatic offset in function */ 88 argoff; /* the next unused argument offset */ 89 int retlab = NOLAB; /* return label for subroutine */ 90 int brklab; 91 int contlab; 92 int flostat; 93 int blevel; 94 int reached, prolab; 95 96 struct params; 97 98 #define MKTY(p, t, d, s) r = p1alloc(); *r = *p; \ 99 r = argcast(r, t, d, s); *p = *r; nfree(r); 100 101 /* 102 * Linked list stack while reading in structs. 103 */ 104 struct rstack { 105 struct rstack *rnext; 106 int rsou; 107 int rstr; 108 struct symtab *rsym; 109 struct symtab *rb; 110 struct attr *ap; 111 int flags; 112 #define LASTELM 1 113 } *rpole; 114 115 /* 116 * Linked list for parameter (and struct elements) declaration. 117 */ 118 static struct params { 119 struct params *prev; 120 struct symtab *sym; 121 } *lparam; 122 static int nparams; 123 124 /* defines used for getting things off of the initialization stack */ 125 126 NODE *arrstk[10]; 127 int arrstkp; 128 static int intcompare; 129 NODE *parlink; 130 131 void fixtype(NODE *p, int class); 132 int fixclass(int class, TWORD type); 133 static void dynalloc(struct symtab *p, int *poff); 134 static void evalidx(struct symtab *p); 135 int isdyn(struct symtab *p); 136 void inforce(OFFSZ n); 137 void vfdalign(int n); 138 static void ssave(struct symtab *); 139 #ifdef PCC_DEBUG 140 static void alprint(union arglist *al, int in); 141 #endif 142 static void lcommadd(struct symtab *sp); 143 static NODE *mkcmplx(NODE *p, TWORD dt); 144 static void cxargfixup(NODE *arg, TWORD dt, struct attr *ap); 145 extern int fun_inline; 146 147 void 148 defid(NODE *q, int class) 149 { 150 defid2(q, class, 0); 151 } 152 153 static void 154 addsoname(struct symtab *sp, char *so) 155 { 156 struct attr *ap = attr_new(ATTR_SONAME, 1); 157 ap->sarg(0) = so; 158 sp->sap = attr_add(sp->sap, ap); 159 } 160 161 /* 162 * Declaration of an identifier. Handles redeclarations, hiding, 163 * incomplete types and forward declarations. 164 * 165 * q is a TYPE node setup after parsing with n_type, n_df and n_ap. 166 * n_sp is a pointer to the not-yet initalized symbol table entry 167 * unless it's a redeclaration or supposed to hide a variable. 168 */ 169 170 void 171 defid2(NODE *q, int class, char *astr) 172 { 173 struct attr *ap; 174 struct symtab *p; 175 TWORD type, qual; 176 TWORD stp, stq; 177 int scl; 178 union dimfun *dsym, *ddef; 179 int slev, temp, changed; 180 181 if (q == NIL) 182 return; /* an error was detected */ 183 184 #ifdef GCC_COMPAT 185 gcc_modefix(q); 186 #endif 187 p = q->n_sp; 188 189 if (p->sname == NULL) 190 cerror("defining null identifier"); 191 192 #ifdef PCC_DEBUG 193 if (ddebug) { 194 printf("defid(%s '%s'(%p), ", p->sname, "soname" , p); 195 tprint(q->n_type, q->n_qual); 196 printf(", %s, (%p)), level %d\n\t", scnames(class), 197 q->n_df, blevel); 198 #ifdef GCC_COMPAT 199 dump_attr(q->n_ap); 200 #endif 201 } 202 #endif 203 204 fixtype(q, class); 205 206 type = q->n_type; 207 qual = q->n_qual; 208 class = fixclass(class, type); 209 210 stp = p->stype; 211 stq = p->squal; 212 slev = p->slevel; 213 214 #ifdef PCC_DEBUG 215 if (ddebug) { 216 printf(" modified to "); 217 tprint(type, qual); 218 printf(", %s\n", scnames(class)); 219 printf(" previous def'n: "); 220 tprint(stp, stq); 221 printf(", %s, (%p,%p)), level %d\n", 222 scnames(p->sclass), p->sdf, p->sap, slev); 223 } 224 #endif 225 226 if (blevel == 1) { 227 switch (class) { 228 default: 229 if (!(class&FIELD) && !ISFTN(type)) 230 uerror("declared argument %s missing", 231 p->sname ); 232 break; 233 case MOS: 234 case MOU: 235 cerror("field5"); 236 case TYPEDEF: 237 case PARAM: 238 break; 239 } 240 } 241 242 if (stp == UNDEF) 243 goto enter; /* New symbol */ 244 245 if (type != stp) 246 goto mismatch; 247 248 if (blevel > slev && (class == AUTO || class == REGISTER)) 249 /* new scope */ 250 goto mismatch; 251 252 /* 253 * test (and possibly adjust) dimensions. 254 * also check that prototypes are correct. 255 */ 256 dsym = p->sdf; 257 ddef = q->n_df; 258 changed = 0; 259 for (temp = type; temp & TMASK; temp = DECREF(temp)) { 260 if (ISARY(temp)) { 261 if (dsym->ddim == NOOFFSET) { 262 dsym->ddim = ddef->ddim; 263 changed = 1; 264 } else if (ddef->ddim != NOOFFSET && 265 dsym->ddim!=ddef->ddim) { 266 goto mismatch; 267 } 268 ++dsym; 269 ++ddef; 270 } else if (ISFTN(temp)) { 271 /* add a late-defined prototype here */ 272 if (!oldstyle && dsym->dfun == NULL) 273 dsym->dfun = ddef->dfun; 274 if (!oldstyle && ddef->dfun != NULL && 275 chkftn(dsym->dfun, ddef->dfun)) 276 uerror("declaration doesn't match prototype"); 277 dsym++, ddef++; 278 } 279 } 280 #ifdef STABS 281 if (changed && gflag) 282 stabs_chgsym(p); /* symbol changed */ 283 #endif 284 285 /* check that redeclarations are to the same structure */ 286 if (temp == STRTY || temp == UNIONTY) { 287 if (strmemb(p->sap) != strmemb(q->n_ap)) 288 goto mismatch; 289 } 290 291 scl = p->sclass; 292 293 #ifdef PCC_DEBUG 294 if (ddebug) 295 printf(" previous class: %s\n", scnames(scl)); 296 #endif 297 298 /* 299 * Its allowed to add attributes to existing declarations. 300 * Be careful though not to trash existing attributes. 301 * XXX - code below is probably not correct. 302 */ 303 if (p->sap && p->sap->atype <= ATTR_MAX) { 304 /* nothing special, just overwrite */ 305 p->sap = q->n_ap; 306 } else { 307 if (p->slevel == blevel) { 308 for (ap = q->n_ap; ap; ap = ap->next) { 309 if (ap->atype > ATTR_MAX) 310 p->sap = attr_add(p->sap, attr_dup(ap)); 311 } 312 } else 313 p->sap = q->n_ap; 314 } 315 316 if (class & FIELD) 317 cerror("field1"); 318 switch(class) { 319 320 case EXTERN: 321 if (astr) 322 addsoname(p, astr); 323 switch( scl ){ 324 case STATIC: 325 case USTATIC: 326 if( slev==0 ) 327 goto done; 328 break; 329 case EXTDEF: 330 case EXTERN: 331 goto done; 332 case SNULL: 333 if (p->sflags & SINLINE) { 334 p->sclass = EXTDEF; 335 inline_ref(p); 336 goto done; 337 } 338 break; 339 } 340 break; 341 342 case STATIC: 343 if (astr) 344 addsoname(p, astr); 345 if (scl==USTATIC || (scl==EXTERN && blevel==0)) { 346 p->sclass = STATIC; 347 goto done; 348 } 349 if (changed || (scl == STATIC && blevel == slev)) 350 goto done; /* identical redeclaration */ 351 break; 352 353 case USTATIC: 354 if (scl==STATIC || scl==USTATIC) 355 goto done; 356 break; 357 358 case TYPEDEF: 359 if (scl == class) 360 goto done; 361 break; 362 363 case MOU: 364 case MOS: 365 cerror("field6"); 366 367 case EXTDEF: 368 switch (scl) { 369 case EXTERN: 370 p->sclass = EXTDEF; 371 goto done; 372 case USTATIC: 373 p->sclass = STATIC; 374 goto done; 375 case SNULL: 376 #ifdef GCC_COMPAT 377 /* 378 * Handle redeclarations of inlined functions. 379 * This is allowed if the previous declaration is of 380 * type gnu_inline. 381 */ 382 if (attr_find(p->sap, GCC_ATYP_GNU_INLINE)) 383 goto done; 384 #endif 385 break; 386 } 387 break; 388 389 case AUTO: 390 case REGISTER: 391 break; /* mismatch.. */ 392 case SNULL: 393 if (fun_inline && ISFTN(type)) { 394 if (scl == EXTERN) { 395 p->sclass = EXTDEF; 396 inline_ref(p); 397 } 398 goto done; 399 } 400 break; 401 } 402 403 mismatch: 404 405 /* 406 * Only allowed for automatic variables. 407 */ 408 if ((blevel == 2 && slev == 1) || blevel <= slev || class == EXTERN) { 409 uerror("redeclaration of %s", p->sname); 410 return; 411 } 412 if ((ISFTN(p->stype) && ISFTN(type)) || 413 (!ISFTN(p->stype) && !ISFTN(type))) 414 warner(Wshadow, p->sname, p->slevel ? "local" : "global"); 415 q->n_sp = p = hide(p); 416 417 enter: /* make a new entry */ 418 419 if (type == VOID && class != TYPEDEF) 420 uerror("void not allowed for variables"); 421 422 #ifdef PCC_DEBUG 423 if(ddebug) 424 printf(" new entry made\n"); 425 #endif 426 p->stype = type; 427 p->squal = qual; 428 p->sclass = (char)class; 429 p->slevel = (char)blevel; 430 p->soffset = NOOFFSET; 431 if (q->n_ap) 432 p->sap = attr_add(q->n_ap, p->sap); 433 434 /* copy dimensions */ 435 p->sdf = q->n_df; 436 /* Do not save param info for old-style functions */ 437 if (ISFTN(type) && oldstyle) 438 p->sdf->dfun = NULL; 439 440 if (arrstkp) 441 evalidx(p); 442 443 /* allocate offsets */ 444 if (class&FIELD) { 445 cerror("field2"); /* new entry */ 446 } else switch (class) { 447 448 case REGISTER: 449 if (astr != NULL) 450 werror("no register assignment (yet)"); 451 p->sclass = class = AUTO; 452 /* FALLTHROUGH */ 453 case AUTO: 454 if (isdyn(p)) { 455 p->sflags |= SDYNARRAY; 456 dynalloc(p, &autooff); 457 } else 458 oalloc(p, &autooff); 459 break; 460 461 case PARAM: 462 if (q->n_type != FARG) 463 oalloc(p, &argoff); 464 break; 465 466 case STATIC: 467 case EXTDEF: 468 case EXTERN: 469 p->soffset = getlab(); 470 /* FALLTHROUGH */ 471 case USTATIC: 472 if (astr) 473 addsoname(p, astr); 474 break; 475 476 case MOU: 477 case MOS: 478 cerror("field7"); 479 case SNULL: 480 #ifdef notdef 481 if (fun_inline) { 482 p->slevel = 1; 483 p->soffset = getlab(); 484 } 485 #endif 486 break; 487 } 488 489 #ifdef STABS 490 if (gflag && p->stype != FARG) 491 stabs_newsym(p); 492 #endif 493 494 done: 495 fixdef(p); /* Leave last word to target */ 496 #ifndef HAVE_WEAKREF 497 { 498 struct attr *at; 499 500 /* Refer renamed function */ 501 if ((at = attr_find(p->sap, GCC_ATYP_WEAKREF))) 502 addsoname(p, at->sarg(0)); 503 } 504 #endif 505 #ifdef PCC_DEBUG 506 if (ddebug) { 507 printf( " sdf, offset: %p, %d\n\t", 508 p->sdf, p->soffset); 509 #ifdef GCC_COMPAT 510 dump_attr(p->sap); 511 #endif 512 } 513 #endif 514 } 515 516 void 517 ssave(struct symtab *sym) 518 { 519 struct params *p; 520 521 p = tmpalloc(sizeof(struct params)); 522 p->prev = lparam; 523 p->sym = sym; 524 lparam = p; 525 } 526 527 /* 528 * end of function 529 */ 530 void 531 ftnend(void) 532 { 533 #ifdef GCC_COMPAT 534 struct attr *gc, *gd; 535 #endif 536 extern int *mkclabs(void); 537 extern NODE *cftnod; 538 extern struct savbc *savbc; 539 extern struct swdef *swpole; 540 extern int tvaloff; 541 char *c; 542 543 if (retlab != NOLAB && nerrors == 0) { /* inside a real function */ 544 plabel(retlab); 545 if (cftnod) 546 ecomp(buildtree(FORCE, p1tcopy(cftnod), NIL)); 547 efcode(); /* struct return handled here */ 548 c = getexname(cftnsp); 549 SETOFF(maxautooff, ALCHAR); 550 send_passt(IP_EPILOG, maxautooff/SZCHAR, c, 551 cftnsp->stype, cftnsp->sclass == EXTDEF, 552 retlab, tvaloff, mkclabs()); 553 } 554 555 cftnod = NIL; 556 tcheck(); 557 brklab = contlab = retlab = NOLAB; 558 flostat = 0; 559 if (nerrors == 0) { 560 if (savbc != NULL) 561 cerror("bcsave error"); 562 if (lparam != NULL) 563 cerror("parameter reset error"); 564 if (swpole != NULL) 565 cerror("switch error"); 566 } 567 #ifdef GCC_COMPAT 568 if (cftnsp) { 569 gc = attr_find(cftnsp->sap, GCC_ATYP_CONSTRUCTOR); 570 gd = attr_find(cftnsp->sap, GCC_ATYP_DESTRUCTOR); 571 if (gc || gd) { 572 struct symtab sts = *cftnsp; 573 NODE *p; 574 sts.stype = INCREF(sts.stype); 575 p = nametree(&sts); 576 p->n_op = ICON; 577 if (gc) { 578 locctr(CTORS, NULL); 579 inval(0, SZPOINT(0), p); 580 } 581 if (gd) { 582 locctr(DTORS, NULL); 583 inval(0, SZPOINT(0), p); 584 } 585 tfree(p); 586 } 587 } 588 #endif 589 savbc = NULL; 590 lparam = NULL; 591 cftnsp = NULL; 592 maxautooff = autooff = AUTOINIT; 593 reached = 1; 594 595 if (isinlining) 596 inline_end(); 597 inline_prtout(); 598 599 tmpfree(); /* Release memory resources */ 600 } 601 602 static struct symtab nulsym = { 603 NULL, 0, 0, 0, 0, "null", INT, 0, NULL, NULL 604 }; 605 606 void 607 dclargs(void) 608 { 609 union dimfun *df; 610 union arglist *al; 611 struct params *a; 612 struct symtab *p, **parr = NULL; /* XXX gcc */ 613 int i; 614 615 /* 616 * Deal with fun(void) properly. 617 */ 618 if (nparams == 1 && lparam->sym && lparam->sym->stype == VOID) 619 goto done; 620 621 /* 622 * Generate a list for bfcode(). 623 * Parameters were pushed in reverse order. 624 */ 625 if (nparams != 0) 626 parr = FUNALLO(sizeof(struct symtab *) * nparams); 627 628 if (nparams) 629 for (a = lparam, i = 0; a != NULL; a = a->prev) { 630 p = a->sym; 631 parr[i++] = p; 632 if (p == NULL) { 633 uerror("parameter %d name missing", i); 634 p = &nulsym; /* empty symtab */ 635 } 636 if (p->stype == FARG) 637 p->stype = INT; 638 if (ISARY(p->stype)) { 639 p->stype += (PTR-ARY); 640 p->sdf++; 641 } else if (ISFTN(p->stype)) { 642 werror("function declared as argument"); 643 p->stype = INCREF(p->stype); 644 } 645 #ifdef STABS 646 if (gflag) 647 stabs_newsym(p); 648 #endif 649 } 650 if (oldstyle && (df = cftnsp->sdf) && (al = df->dfun)) { 651 /* 652 * Check against prototype of oldstyle function. 653 */ 654 union arglist *al2, *alb; 655 656 alb = al2 = FUNALLO(sizeof(union arglist) * nparams * 3 + 1); 657 for (i = 0; i < nparams; i++) { 658 TWORD type = parr[i]->stype; 659 (al2++)->type = type; 660 if (ISSOU(BTYPE(type))) 661 (al2++)->sap = parr[i]->sap; 662 while (!ISFTN(type) && !ISARY(type) && type > BTMASK) 663 type = DECREF(type); 664 if (type > BTMASK) 665 (al2++)->df = parr[i]->sdf; 666 } 667 al2->type = TNULL; 668 intcompare = 1; 669 if (chkftn(al, alb)) 670 uerror("function doesn't match prototype"); 671 FUNFREE(alb); 672 intcompare = 0; 673 674 } 675 676 if (oldstyle && nparams) { 677 /* Must recalculate offset for oldstyle args here */ 678 argoff = ARGINIT; 679 for (i = 0; i < nparams; i++) { 680 parr[i]->soffset = NOOFFSET; 681 oalloc(parr[i], &argoff); 682 } 683 } 684 685 done: autooff = AUTOINIT; 686 687 plabel(prolab); /* after prolog, used in optimization */ 688 retlab = getlab(); 689 bfcode(parr, nparams); 690 if (fun_inline && (xinline 691 #ifdef GCC_COMPAT 692 || attr_find(cftnsp->sap, GCC_ATYP_ALW_INL) 693 #endif 694 )) 695 inline_args(parr, nparams); 696 FUNFREE(parr); 697 plabel(getlab()); /* used when spilling */ 698 if (parlink) 699 ecomp(parlink); 700 parlink = NIL; 701 lparam = NULL; 702 nparams = 0; 703 symclear(1); /* In case of function pointer args */ 704 } 705 706 /* 707 * basic attributes for structs and enums 708 */ 709 static struct attr * 710 seattr(void) 711 { 712 return attr_add(attr_new(ATTR_ALIGNED, 4), attr_new(ATTR_STRUCT, 2)); 713 } 714 715 /* 716 * Struct/union/enum symtab construction. 717 */ 718 static void 719 defstr(struct symtab *sp, int class) 720 { 721 sp->sclass = (char)class; 722 if (class == STNAME) 723 sp->stype = STRTY; 724 else if (class == UNAME) 725 sp->stype = UNIONTY; 726 else if (class == ENAME) 727 sp->stype = ENUMTY; 728 } 729 730 /* 731 * Declare a struct/union/enum tag. 732 * If not found, create a new tag with UNDEF type. 733 */ 734 static struct symtab * 735 deftag(char *name, int class) 736 { 737 struct symtab *sp; 738 739 if ((sp = lookup(name, STAGNAME))->sap == NULL) { 740 /* New tag */ 741 defstr(sp, class); 742 } else if (sp->sclass != class) 743 uerror("tag %s redeclared", name); 744 return sp; 745 } 746 747 /* 748 * reference to a structure or union, with no definition 749 */ 750 NODE * 751 rstruct(char *tag, int soru) 752 { 753 struct symtab *sp; 754 755 sp = deftag(tag, soru); 756 if (sp->sap == NULL) 757 sp->sap = seattr(); 758 return mkty(sp->stype, 0, sp->sap); 759 } 760 761 static int enumlow, enumhigh; 762 int enummer; 763 764 /* 765 * Declare a member of enum. 766 */ 767 void 768 moedef(char *name) 769 { 770 struct symtab *sp; 771 772 sp = lookup(name, SNORMAL); 773 if (sp->stype == UNDEF || (sp->slevel < blevel)) { 774 if (sp->stype != UNDEF) 775 sp = hide(sp); 776 sp->stype = INT; /* always */ 777 sp->sclass = MOE; 778 sp->soffset = enummer; 779 } else 780 uerror("%s redeclared", name); 781 if (enummer < enumlow) 782 enumlow = enummer; 783 if (enummer > enumhigh) 784 enumhigh = enummer; 785 enummer++; 786 } 787 788 /* 789 * Declare an enum tag. Complain if already defined. 790 */ 791 struct symtab * 792 enumhd(char *name) 793 { 794 struct attr *ap; 795 struct symtab *sp; 796 797 enummer = enumlow = enumhigh = 0; 798 if (name == NULL) 799 return NULL; 800 801 sp = deftag(name, ENAME); 802 if (sp->stype != ENUMTY) { 803 if (sp->slevel == blevel) 804 uerror("%s redeclared", name); 805 sp = hide(sp); 806 defstr(sp, ENAME); 807 } 808 if (sp->sap == NULL) 809 ap = sp->sap = attr_new(ATTR_STRUCT, 4); 810 else 811 ap = attr_find(sp->sap, ATTR_STRUCT); 812 ap->amlist = sp; 813 return sp; 814 } 815 816 /* 817 * finish declaration of an enum 818 */ 819 NODE * 820 enumdcl(struct symtab *sp) 821 { 822 NODE *p; 823 TWORD t; 824 825 #ifdef ENUMSIZE 826 t = ENUMSIZE(enumhigh, enumlow); 827 #else 828 t = ctype(enumlow < 0 ? INT : UNSIGNED); 829 #ifdef notdef 830 if (enumhigh <= MAX_CHAR && enumlow >= MIN_CHAR) 831 t = ctype(CHAR); 832 else if (enumhigh <= MAX_SHORT && enumlow >= MIN_SHORT) 833 t = ctype(SHORT); 834 else 835 t = ctype(INT); 836 #endif 837 #endif 838 839 if (sp) 840 sp->stype = t; 841 p = mkty(t, 0, 0); 842 p->n_sp = sp; 843 return p; 844 } 845 846 /* 847 * Handle reference to an enum 848 */ 849 NODE * 850 enumref(char *name) 851 { 852 struct symtab *sp; 853 NODE *p; 854 855 sp = lookup(name, STAGNAME); 856 857 #ifdef notdef 858 /* 859 * 6.7.2.3 Clause 2: 860 * "A type specifier of the form 'enum identifier' without an 861 * enumerator list shall only appear after the type it specifies 862 * is complete." 863 */ 864 if (sp->sclass != ENAME) 865 uerror("enum %s undeclared", name); 866 #endif 867 if (sp->sclass == SNULL) { 868 /* declare existence of enum */ 869 sp = enumhd(name); 870 sp->stype = ENUMTY; 871 } 872 873 p = mkty(sp->stype, 0, sp->sap); 874 p->n_sp = sp; 875 return p; 876 } 877 878 /* 879 * begining of structure or union declaration 880 * It's an error if this routine is called twice with the same struct. 881 */ 882 struct rstack * 883 bstruct(char *name, int soru, NODE *gp) 884 { 885 struct rstack *r; 886 struct symtab *sp; 887 struct attr *ap, *gap; 888 889 #ifdef GCC_COMPAT 890 gap = gp ? gcc_attr_parse(gp) : NULL; 891 #else 892 gap = NULL; 893 #endif 894 895 if (name != NULL) { 896 sp = deftag(name, soru); 897 if (sp->sap == NULL) 898 sp->sap = seattr(); 899 ap = attr_find(sp->sap, ATTR_ALIGNED); 900 if (ap->iarg(0) != 0) { 901 if (sp->slevel < blevel) { 902 sp = hide(sp); 903 defstr(sp, soru); 904 sp->sap = seattr(); 905 } else 906 uerror("%s redeclared", name); 907 } 908 gap = sp->sap = attr_add(sp->sap, gap); 909 } else { 910 gap = attr_add(seattr(), gap); 911 sp = NULL; 912 } 913 914 r = tmpcalloc(sizeof(struct rstack)); 915 r->rsou = soru; 916 r->rsym = sp; 917 r->rb = NULL; 918 r->ap = gap; 919 r->rnext = rpole; 920 rpole = r; 921 922 return r; 923 } 924 925 /* 926 * Called after a struct is declared to restore the environment. 927 * - If ALSTRUCT is defined, this will be the struct alignment and the 928 * struct size will be a multiple of ALSTRUCT, otherwise it will use 929 * the alignment of the largest struct member. 930 */ 931 NODE * 932 dclstruct(struct rstack *r) 933 { 934 NODE *n; 935 struct attr *aps, *apb; 936 struct symtab *sp; 937 int al, sa, sz; 938 939 apb = attr_find(r->ap, ATTR_ALIGNED); 940 aps = attr_find(r->ap, ATTR_STRUCT); 941 aps->amlist = r->rb; 942 943 #ifdef ALSTRUCT 944 al = ALSTRUCT; 945 #else 946 al = ALCHAR; 947 #endif 948 949 /* 950 * extract size and alignment, calculate offsets 951 */ 952 for (sp = r->rb; sp; sp = sp->snext) { 953 sa = talign(sp->stype, sp->sap); 954 if (sp->sclass & FIELD) 955 sz = sp->sclass&FLDSIZ; 956 else 957 sz = (int)tsize(sp->stype, sp->sdf, sp->sap); 958 if (sz > rpole->rstr) 959 rpole->rstr = sz; /* for use with unions */ 960 /* 961 * set al, the alignment, to the lcm of the alignments 962 * of the members. 963 */ 964 SETOFF(al, sa); 965 } 966 967 SETOFF(rpole->rstr, al); 968 969 aps->amsize = rpole->rstr; 970 apb->iarg(0) = al; 971 972 #ifdef PCC_DEBUG 973 if (ddebug) { 974 printf("dclstruct(%s): size=%d, align=%d\n", 975 r->rsym ? r->rsym->sname : "??", 976 aps->amsize, apb->iarg(0)); 977 } 978 if (ddebug>1) { 979 printf("\tsize %d align %d link %p\n", 980 aps->amsize, apb->iarg(0), aps->amlist); 981 for (sp = aps->amlist; sp != NULL; sp = sp->snext) { 982 printf("\tmember %s(%p)\n", sp->sname, sp); 983 } 984 } 985 #endif 986 987 #ifdef STABS 988 if (gflag) 989 stabs_struct(r->rsym, r->ap); 990 #endif 991 992 rpole = r->rnext; 993 n = mkty(r->rsou == STNAME ? STRTY : UNIONTY, 0, r->ap); 994 n->n_sp = r->rsym; 995 996 n->n_qual |= 1; /* definition place XXX used by attributes */ 997 return n; 998 } 999 1000 /* 1001 * Add a new member to the current struct or union being declared. 1002 */ 1003 void 1004 soumemb(NODE *n, char *name, int class) 1005 { 1006 struct symtab *sp, *lsp; 1007 int incomp, tsz, al; 1008 TWORD t; 1009 1010 if (rpole == NULL) 1011 cerror("soumemb"); 1012 1013 /* check if tag name exists */ 1014 lsp = NULL; 1015 for (sp = rpole->rb; sp != NULL; lsp = sp, sp = sp->snext) 1016 if (*name != '*' && sp->sname == name) 1017 uerror("redeclaration of %s", name); 1018 1019 sp = getsymtab(name, SMOSNAME); 1020 if (rpole->rb == NULL) 1021 rpole->rb = sp; 1022 else 1023 lsp->snext = sp; 1024 1025 n->n_sp = sp; 1026 sp->stype = n->n_type; 1027 sp->squal = n->n_qual; 1028 sp->slevel = blevel; 1029 sp->sap = n->n_ap; 1030 sp->sdf = n->n_df; 1031 1032 if (class & FIELD) { 1033 sp->sclass = (char)class; 1034 if (rpole->rsou == UNAME) 1035 rpole->rstr = 0; 1036 falloc(sp, class&FLDSIZ, NIL); 1037 } else if (rpole->rsou == STNAME || rpole->rsou == UNAME) { 1038 sp->sclass = rpole->rsou == STNAME ? MOS : MOU; 1039 if (sp->sclass == MOU) 1040 rpole->rstr = 0; 1041 al = talign(sp->stype, sp->sap); 1042 tsz = (int)tsize(sp->stype, sp->sdf, sp->sap); 1043 sp->soffset = upoff(tsz, al, &rpole->rstr); 1044 } 1045 1046 /* 1047 * 6.7.2.1 clause 16: 1048 * "...the last member of a structure with more than one 1049 * named member may have incomplete array type;" 1050 */ 1051 if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET) 1052 incomp = 1; 1053 else 1054 incomp = 0; 1055 if ((rpole->flags & LASTELM) || (rpole->rb == sp && incomp == 1)) 1056 uerror("incomplete array in struct"); 1057 if (incomp == 1) 1058 rpole->flags |= LASTELM; 1059 1060 /* 1061 * 6.7.2.1 clause 2: 1062 * "...such a structure shall not be a member of a structure 1063 * or an element of an array." 1064 */ 1065 t = sp->stype; 1066 if (rpole->rsou != STNAME || BTYPE(t) != STRTY) 1067 return; /* not for unions */ 1068 while (ISARY(t)) 1069 t = DECREF(t); 1070 if (ISPTR(t)) 1071 return; 1072 1073 if ((lsp = strmemb(sp->sap)) != NULL) { 1074 for (; lsp->snext; lsp = lsp->snext) 1075 ; 1076 if (ISARY(lsp->stype) && lsp->snext && 1077 lsp->sdf->ddim == NOOFFSET) 1078 uerror("incomplete struct in struct"); 1079 } 1080 } 1081 1082 /* 1083 * error printing routine in parser 1084 */ 1085 void 1086 yyerror(char *s) 1087 { 1088 uerror(s); 1089 } 1090 1091 void yyaccpt(void); 1092 void 1093 yyaccpt(void) 1094 { 1095 ftnend(); 1096 } 1097 1098 /* 1099 * p is top of type list given to tymerge later. 1100 * Find correct CALL node and declare parameters from there. 1101 */ 1102 void 1103 ftnarg(NODE *p) 1104 { 1105 NODE *q; 1106 1107 #ifdef PCC_DEBUG 1108 if (ddebug > 2) 1109 printf("ftnarg(%p)\n", p); 1110 #endif 1111 /* 1112 * Push argument symtab entries onto param stack in reverse order, 1113 * due to the nature of the stack it will be reclaimed correct. 1114 */ 1115 for (; p->n_op != NAME; p = p->n_left) { 1116 if (p->n_op == UCALL && p->n_left->n_op == NAME) 1117 return; /* Nothing to enter */ 1118 if (p->n_op == CALL && p->n_left->n_op == NAME) 1119 break; 1120 } 1121 1122 p = p->n_right; 1123 while (p->n_op == CM) { 1124 q = p->n_right; 1125 if (q->n_op != ELLIPSIS) { 1126 ssave(q->n_sp); 1127 nparams++; 1128 #ifdef PCC_DEBUG 1129 if (ddebug > 2) 1130 printf(" saving sym %s (%p) from (%p)\n", 1131 q->n_sp->sname, q->n_sp, q); 1132 #endif 1133 } 1134 p = p->n_left; 1135 } 1136 ssave(p->n_sp); 1137 if (p->n_type != VOID) 1138 nparams++; 1139 1140 #ifdef PCC_DEBUG 1141 if (ddebug > 2) 1142 printf(" saving sym %s (%p) from (%p)\n", 1143 nparams ? p->n_sp->sname : "<noname>", p->n_sp, p); 1144 #endif 1145 } 1146 1147 /* 1148 * compute the alignment of an object with type ty, sizeoff index s 1149 */ 1150 int 1151 talign(unsigned int ty, struct attr *apl) 1152 { 1153 struct attr *al; 1154 int a; 1155 1156 for (; ty > BTMASK; ty = DECREF(ty)) { 1157 switch (ty & TMASK) { 1158 case PTR: 1159 return(ALPOINT); 1160 case ARY: 1161 continue; 1162 case FTN: 1163 cerror("compiler takes alignment of function"); 1164 } 1165 } 1166 1167 /* check for alignment attribute */ 1168 if ((al = attr_find(apl, ATTR_ALIGNED))) { 1169 if ((a = al->iarg(0)) == 0) { 1170 uerror("no alignment"); 1171 a = ALINT; 1172 } 1173 return a; 1174 } 1175 1176 #ifndef NO_COMPLEX 1177 if (ISITY(ty)) 1178 ty -= (FIMAG-FLOAT); 1179 #endif 1180 ty = BTYPE(ty); 1181 if (ty >= CHAR && ty <= ULONGLONG && ISUNSIGNED(ty)) 1182 ty = DEUNSIGN(ty); 1183 1184 switch (ty) { 1185 #ifdef GCC_COMPAT 1186 case VOID: a = ALCHAR; break; /* GCC */ 1187 #endif 1188 case BOOL: a = ALBOOL; break; 1189 case CHAR: a = ALCHAR; break; 1190 case SHORT: a = ALSHORT; break; 1191 case INT: a = ALINT; break; 1192 case LONG: a = ALLONG; break; 1193 case LONGLONG: a = ALLONGLONG; break; 1194 case FLOAT: a = ALFLOAT; break; 1195 case DOUBLE: a = ALDOUBLE; break; 1196 case LDOUBLE: a = ALLDOUBLE; break; 1197 default: 1198 uerror("no alignment"); 1199 a = ALINT; 1200 } 1201 return a; 1202 } 1203 1204 short sztable[] = { 0, SZBOOL, SZCHAR, SZCHAR, SZSHORT, SZSHORT, SZINT, SZINT, 1205 SZLONG, SZLONG, SZLONGLONG, SZLONGLONG, SZFLOAT, SZDOUBLE, SZLDOUBLE }; 1206 1207 /* compute the size associated with type ty, 1208 * dimoff d, and sizoff s */ 1209 /* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */ 1210 OFFSZ 1211 tsize(TWORD ty, union dimfun *d, struct attr *apl) 1212 { 1213 struct attr *ap, *ap2; 1214 OFFSZ mult, sz; 1215 1216 mult = 1; 1217 1218 for (; ty > BTMASK; ty = DECREF(ty)) { 1219 switch (ty & TMASK) { 1220 1221 case FTN: 1222 uerror( "cannot take size of function"); 1223 case PTR: 1224 return( SZPOINT(ty) * mult ); 1225 case ARY: 1226 if (d->ddim == NOOFFSET) 1227 return 0; 1228 if (d->ddim < 0) 1229 cerror("tsize: dynarray"); 1230 mult *= d->ddim; 1231 d++; 1232 } 1233 } 1234 1235 #ifndef NO_COMPLEX 1236 if (ISITY(ty)) 1237 ty -= (FIMAG-FLOAT); 1238 #endif 1239 1240 if (ty == VOID) 1241 ty = CHAR; 1242 if (ty <= LDOUBLE) 1243 sz = sztable[ty]; 1244 else if (ISSOU(ty)) { 1245 if ((ap = strattr(apl)) == NULL || 1246 (ap2 = attr_find(apl, ATTR_ALIGNED)) == NULL || 1247 (ap2->iarg(0) == 0)) { 1248 uerror("unknown structure/union/enum"); 1249 sz = SZINT; 1250 } else 1251 sz = ap->amsize; 1252 } else { 1253 uerror("unknown type"); 1254 sz = SZINT; 1255 } 1256 1257 return((unsigned int)sz * mult); 1258 } 1259 1260 #ifndef MYINSTRING 1261 /* 1262 * Print out a string of characters. 1263 * Assume that the assembler understands C-style escape 1264 * sequences. 1265 */ 1266 void 1267 instring(struct symtab *sp) 1268 { 1269 unsigned short sh[2]; 1270 char *s, *str; 1271 TWORD t; 1272 NODE *p; 1273 1274 locctr(STRNG, sp); 1275 defloc(sp); 1276 1277 t = BTYPE(sp->stype); 1278 str = s = sp->sname; 1279 if (t == ctype(USHORT)) { 1280 /* convert to UTF-16 */ 1281 p = xbcon(0, NULL, t); 1282 while (*s) { 1283 cp2u16(u82cp(&s), sh); 1284 if ((glval(p) = sh[0])) 1285 inval(0, SZSHORT, p); 1286 if ((glval(p) = sh[1])) 1287 inval(0, SZSHORT, p); 1288 } 1289 slval(p, 0); 1290 inval(0, SZSHORT, p); 1291 nfree(p); 1292 } else if (t == ctype(SZINT < 32 ? ULONG : UNSIGNED) || 1293 t == ctype(SZINT < 32 ? LONG : INT)) { 1294 /* convert to UTF-32 */ 1295 p = xbcon(0, NULL, t); 1296 while (*s) { 1297 slval(p, u82cp(&s)); 1298 inval(0, SZINT < 32 ? SZLONG : SZINT, p); 1299 } 1300 slval(p, 0); 1301 inval(0, SZINT < 32 ? SZLONG : SZINT, p); 1302 nfree(p); 1303 } else if (t == CHAR || t == UCHAR) { 1304 printf(PRTPREF "\t.ascii \""); 1305 while (*s) { 1306 if (*s == '\\') 1307 (void)esccon(&s); 1308 else 1309 s++; 1310 1311 if (s - str > 60) { 1312 fwrite(str, 1, s - str, stdout); 1313 printf("\"\n" PRTPREF "\t.ascii \""); 1314 str = s; 1315 } 1316 } 1317 1318 fwrite(str, 1, s - str, stdout); 1319 printf("\\0\"\n"); 1320 } else 1321 cerror("instring %ld", t); 1322 } 1323 #endif 1324 1325 /* 1326 * update the offset pointed to by poff; return the 1327 * offset of a value of size `size', alignment `alignment', 1328 * given that off is increasing 1329 */ 1330 int 1331 upoff(int size, int alignment, int *poff) 1332 { 1333 int off; 1334 1335 off = *poff; 1336 SETOFF(off, alignment); 1337 if (off < 0) 1338 cerror("structure or stack overgrown"); /* wrapped */ 1339 *poff = off+size; 1340 return (off); 1341 } 1342 1343 /* 1344 * allocate p with offset *poff, and update *poff 1345 */ 1346 int 1347 oalloc(struct symtab *p, int *poff ) 1348 { 1349 int al, off, tsz; 1350 int noff; 1351 1352 /* 1353 * Only generate tempnodes if we are optimizing, 1354 * and only for integers, floats or pointers, 1355 * and not if the type on this level is volatile. 1356 */ 1357 if (xtemps && ((p->sclass == AUTO) || (p->sclass == REGISTER)) && 1358 (p->stype < STRTY || ISPTR(p->stype)) && 1359 !(cqual(p->stype, p->squal) & VOL) && cisreg(p->stype)) { 1360 NODE *tn = tempnode(0, p->stype, p->sdf, p->sap); 1361 p->soffset = regno(tn); 1362 p->sflags |= STNODE; 1363 nfree(tn); 1364 return 0; 1365 } 1366 1367 al = talign(p->stype, p->sap); 1368 noff = off = *poff; 1369 tsz = (int)tsize(p->stype, p->sdf, p->sap); 1370 #ifdef BACKAUTO 1371 if (p->sclass == AUTO) { 1372 noff = off + tsz; 1373 if (noff < 0) 1374 cerror("stack overflow"); 1375 SETOFF(noff, al); 1376 off = -noff; 1377 } else 1378 #endif 1379 if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR || 1380 p->stype == SHORT || p->stype == USHORT || p->stype == BOOL)) { 1381 off = upoff(SZINT, ALINT, &noff); 1382 #if TARGET_ENDIAN == TARGET_BE 1383 off = noff - tsz; 1384 #endif 1385 } else { 1386 off = upoff(tsz, al, &noff); 1387 } 1388 1389 if (p->sclass != REGISTER) { 1390 /* in case we are allocating stack space for register arguments */ 1391 if (p->soffset == NOOFFSET) 1392 p->soffset = off; 1393 else if(off != p->soffset) 1394 return(1); 1395 } 1396 1397 *poff = noff; 1398 return(0); 1399 } 1400 1401 /* 1402 * Delay emission of code generated in argument headers. 1403 */ 1404 static void 1405 edelay(NODE *p) 1406 { 1407 if (blevel == 1) { 1408 /* Delay until after declarations */ 1409 if (parlink == NULL) 1410 parlink = p; 1411 else 1412 parlink = block(COMOP, parlink, p, 0, 0, 0); 1413 } else 1414 ecomp(p); 1415 } 1416 1417 /* 1418 * Traverse through the array args, evaluate them and put the 1419 * resulting temp numbers in the dim fields. 1420 */ 1421 static void 1422 evalidx(struct symtab *sp) 1423 { 1424 union dimfun *df; 1425 NODE *p; 1426 TWORD t; 1427 int astkp = 0; 1428 1429 if (arrstk[0] == NIL) 1430 astkp++; /* for parameter arrays */ 1431 1432 if (isdyn(sp)) 1433 sp->sflags |= SDYNARRAY; 1434 1435 df = sp->sdf; 1436 for (t = sp->stype; t > BTMASK; t = DECREF(t)) { 1437 if (!ISARY(t)) 1438 continue; 1439 if (df->ddim == -1) { 1440 p = tempnode(0, INT, 0, 0); 1441 df->ddim = -regno(p); 1442 edelay(buildtree(ASSIGN, p, arrstk[astkp++])); 1443 } 1444 df++; 1445 } 1446 arrstkp = 0; 1447 } 1448 1449 /* 1450 * Return 1 if dynamic array, 0 otherwise. 1451 */ 1452 int 1453 isdyn(struct symtab *sp) 1454 { 1455 union dimfun *df = sp->sdf; 1456 TWORD t; 1457 1458 for (t = sp->stype; t > BTMASK; t = DECREF(t)) { 1459 if (!ISARY(t)) 1460 return 0; 1461 if (df->ddim < 0 && df->ddim != NOOFFSET) 1462 return 1; 1463 df++; 1464 } 1465 return 0; 1466 } 1467 1468 /* 1469 * Allocate space on the stack for dynamic arrays (or at least keep track 1470 * of the index). 1471 * Strategy is as follows: 1472 * - first entry is a pointer to the dynamic datatype. 1473 * - if it's a one-dimensional array this will be the only entry used. 1474 * - if it's a multi-dimensional array the following (numdim-1) integers 1475 * will contain the sizes to multiply the indexes with. 1476 * - code to write the dimension sizes this will be generated here. 1477 * - code to allocate space on the stack will be generated here. 1478 */ 1479 static void 1480 dynalloc(struct symtab *p, int *poff) 1481 { 1482 union dimfun *df; 1483 NODE *n, *tn, *pol; 1484 TWORD t; 1485 1486 /* 1487 * The pointer to the array is not necessarily stored in a 1488 * TEMP node, but if it is, its number is in the soffset field; 1489 */ 1490 t = p->stype; 1491 p->sflags |= STNODE; 1492 p->stype = INCREF(p->stype); /* Make this an indirect pointer */ 1493 tn = tempnode(0, p->stype, p->sdf, p->sap); 1494 p->soffset = regno(tn); 1495 1496 df = p->sdf; 1497 1498 pol = bcon(1); 1499 for (; t > BTMASK; t = DECREF(t)) { 1500 if (!ISARY(t)) 1501 break; 1502 if (df->ddim < 0) 1503 n = tempnode(-df->ddim, INT, 0, 0); 1504 else 1505 n = bcon(df->ddim); 1506 1507 pol = buildtree(MUL, pol, n); 1508 df++; 1509 } 1510 /* Create stack gap */ 1511 spalloc(tn, pol, tsize(t, 0, p->sap)); 1512 } 1513 1514 /* 1515 * allocate a field of width w 1516 * new is 0 if new entry, 1 if redefinition, -1 if alignment 1517 */ 1518 int 1519 falloc(struct symtab *p, int w, NODE *pty) 1520 { 1521 TWORD otype, type; 1522 int al,sz; 1523 1524 otype = type = p ? p->stype : pty->n_type; 1525 1526 if (type == BOOL) 1527 type = BOOL_TYPE; 1528 if (!ISINTEGER(type)) { 1529 uerror("illegal field type"); 1530 type = INT; 1531 } 1532 1533 al = talign(type, NULL); 1534 sz = tsize(type, NULL, NULL); 1535 1536 if (w > sz) { 1537 uerror("field too big"); 1538 w = sz; 1539 } 1540 1541 if (w == 0) { /* align only */ 1542 SETOFF(rpole->rstr, al); 1543 if (p != NULL) 1544 uerror("zero size field"); 1545 return(0); 1546 } 1547 1548 if (rpole->rstr%al + w > sz) 1549 SETOFF(rpole->rstr, al); 1550 if (p == NULL) { 1551 rpole->rstr += w; /* we know it will fit */ 1552 return(0); 1553 } 1554 1555 /* establish the field */ 1556 1557 p->soffset = rpole->rstr; 1558 rpole->rstr += w; 1559 p->stype = otype; 1560 fldty(p); 1561 return(0); 1562 } 1563 1564 /* 1565 * Check if this symbol should be a common or must be handled in data seg. 1566 */ 1567 static void 1568 commchk(struct symtab *sp) 1569 { 1570 if ((sp->sflags & STLS) 1571 #ifdef GCC_COMPAT 1572 || attr_find(sp->sap, GCC_ATYP_SECTION) 1573 #endif 1574 ) { 1575 /* TLS handled in data segment */ 1576 if (sp->sclass == EXTERN) 1577 sp->sclass = EXTDEF; 1578 beginit(sp); 1579 endinit(1); 1580 } else { 1581 symdirec(sp); 1582 defzero(sp); 1583 } 1584 } 1585 1586 void 1587 nidcl(NODE *p, int class) 1588 { 1589 nidcl2(p, class, 0); 1590 } 1591 1592 /* 1593 * handle unitialized declarations assumed to be not functions: 1594 * int a; 1595 * extern int a; 1596 * static int a; 1597 */ 1598 void 1599 nidcl2(NODE *p, int class, char *astr) 1600 { 1601 struct symtab *sp; 1602 int commflag = 0; 1603 1604 /* compute class */ 1605 if (class == SNULL) { 1606 if (blevel > 1) 1607 class = AUTO; 1608 else if (blevel != 0 || rpole) 1609 cerror( "nidcl error" ); 1610 else /* blevel = 0 */ 1611 commflag = 1, class = EXTERN; 1612 } 1613 1614 defid2(p, class, astr); 1615 1616 sp = p->n_sp; 1617 /* check if forward decl */ 1618 if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET) 1619 return; 1620 1621 if (sp->sflags & SASG) 1622 return; /* already initialized */ 1623 1624 switch (class) { 1625 case EXTDEF: 1626 /* simulate initialization by 0 */ 1627 simpleinit(p->n_sp, bcon(0)); 1628 break; 1629 case EXTERN: 1630 if (commflag) 1631 lcommadd(p->n_sp); 1632 else 1633 extdec(p->n_sp); 1634 break; 1635 case STATIC: 1636 if (blevel == 0) 1637 lcommadd(p->n_sp); 1638 else 1639 commchk(p->n_sp); 1640 break; 1641 } 1642 } 1643 1644 struct lcd { 1645 SLIST_ENTRY(lcd) next; 1646 struct symtab *sp; 1647 }; 1648 1649 static SLIST_HEAD(, lcd) lhead = { NULL, &lhead.q_forw}; 1650 1651 /* 1652 * Add a local common statement to the printout list. 1653 */ 1654 void 1655 lcommadd(struct symtab *sp) 1656 { 1657 struct lcd *lc, *lcp; 1658 1659 lcp = NULL; 1660 SLIST_FOREACH(lc, &lhead, next) { 1661 if (lc->sp == sp) 1662 return; /* already exists */ 1663 if (lc->sp == NULL && lcp == NULL) 1664 lcp = lc; 1665 } 1666 if (lcp == NULL) { 1667 lc = permalloc(sizeof(struct lcd)); 1668 lcommsz += sizeof(struct lcd); 1669 lc->sp = sp; 1670 SLIST_INSERT_LAST(&lhead, lc, next); 1671 } else 1672 lcp->sp = sp; 1673 } 1674 1675 /* 1676 * Delete a local common statement. 1677 */ 1678 void 1679 lcommdel(struct symtab *sp) 1680 { 1681 struct lcd *lc; 1682 1683 SLIST_FOREACH(lc, &lhead, next) { 1684 if (lc->sp == sp) { 1685 lc->sp = NULL; 1686 return; 1687 } 1688 } 1689 } 1690 1691 /* 1692 * Print out the remaining common statements. 1693 */ 1694 void 1695 lcommprint(void) 1696 { 1697 struct lcd *lc; 1698 1699 SLIST_FOREACH(lc, &lhead, next) { 1700 if (lc->sp != NULL) 1701 commchk(lc->sp); 1702 } 1703 } 1704 1705 /* 1706 * Merge given types to a single node. 1707 * Any type can end up here. 1708 * p is the old node, q is the old (if any). 1709 * CLASS is AUTO, EXTERN, REGISTER, STATIC or TYPEDEF. 1710 * QUALIFIER is VOL or CON 1711 * TYPE is CHAR, SHORT, INT, LONG, SIGNED, UNSIGNED, VOID, BOOL, FLOAT, 1712 * DOUBLE, STRTY, UNIONTY. 1713 */ 1714 struct typctx { 1715 int class, qual, sig, uns, cmplx, imag, err, align; 1716 TWORD type; 1717 NODE *saved; 1718 struct attr *pre, *post; 1719 }; 1720 1721 static void 1722 typwalk(NODE *p, void *arg) 1723 { 1724 struct typctx *tc = arg; 1725 1726 #define cmop(x,y) block(CM, x, y, INT, 0, 0) 1727 switch (p->n_op) { 1728 case ALIGN: 1729 if (tc->align < glval(p)) 1730 tc->align = glval(p); 1731 break; 1732 case ATTRIB: 1733 #ifdef GCC_COMPAT 1734 if (tc->saved && (tc->saved->n_qual & 1)) { 1735 tc->post = attr_add(tc->post,gcc_attr_parse(p->n_left)); 1736 } else { 1737 tc->pre = attr_add(tc->pre, gcc_attr_parse(p->n_left)); 1738 } 1739 p->n_left = bcon(0); /* For tfree() */ 1740 #else 1741 uerror("gcc type attribute used"); 1742 #endif 1743 break; 1744 case CLASS: 1745 if (p->n_type == 0) 1746 break; /* inline hack */ 1747 if (tc->class) 1748 tc->err = 1; /* max 1 class */ 1749 tc->class = p->n_type; 1750 break; 1751 1752 case FUNSPEC: 1753 if (p->n_type == INLINE) { 1754 fun_inline = 1; 1755 } else if (p->n_type == NORETURN) { 1756 tc->pre = attr_add(tc->pre, attr_new(ATTR_NORETURN, 3)); 1757 } else 1758 tc->err = 1; 1759 break; 1760 1761 case QUALIFIER: 1762 if (p->n_qual == 0 && 1763 ((tc->saved && !ISPTR(tc->saved->n_type)) || 1764 (tc->saved == 0))) 1765 uerror("invalid use of 'restrict'"); 1766 tc->qual |= p->n_qual >> TSHIFT; 1767 break; 1768 1769 case TYPE: 1770 if (p->n_sp != NULL || ISSOU(p->n_type)) { 1771 /* typedef, enum or struct/union */ 1772 if (tc->saved || tc->type) 1773 tc->err = 1; 1774 #ifdef GCC_COMPAT 1775 if (ISSOU(p->n_type) && p->n_left) { 1776 if (tc->post) 1777 cerror("typwalk"); 1778 tc->post = gcc_attr_parse(p->n_left); 1779 } 1780 #endif 1781 tc->saved = ccopy(p); 1782 break; 1783 } 1784 1785 switch (p->n_type) { 1786 case BOOL: 1787 case CHAR: 1788 case FLOAT: 1789 case VOID: 1790 if (tc->type) 1791 tc->err = 1; 1792 tc->type = p->n_type; 1793 break; 1794 case DOUBLE: 1795 if (tc->type == 0) 1796 tc->type = DOUBLE; 1797 else if (tc->type == LONG) 1798 tc->type = LDOUBLE; 1799 else 1800 tc->err = 1; 1801 break; 1802 case SHORT: 1803 if (tc->type == 0 || tc->type == INT) 1804 tc->type = SHORT; 1805 else 1806 tc->err = 1; 1807 break; 1808 case INT: 1809 if (tc->type == SHORT || tc->type == LONG || 1810 tc->type == LONGLONG) 1811 break; 1812 else if (tc->type == 0) 1813 tc->type = INT; 1814 else 1815 tc->err = 1; 1816 break; 1817 case LONG: 1818 if (tc->type == 0) 1819 tc->type = LONG; 1820 else if (tc->type == INT) 1821 break; 1822 else if (tc->type == LONG) 1823 tc->type = LONGLONG; 1824 else if (tc->type == DOUBLE) 1825 tc->type = LDOUBLE; 1826 else 1827 tc->err = 1; 1828 break; 1829 case SIGNED: 1830 if (tc->sig || tc->uns) 1831 tc->err = 1; 1832 tc->sig = 1; 1833 break; 1834 case UNSIGNED: 1835 if (tc->sig || tc->uns) 1836 tc->err = 1; 1837 tc->uns = 1; 1838 break; 1839 case COMPLEX: 1840 tc->cmplx = 1; 1841 break; 1842 case IMAG: 1843 tc->imag = 1; 1844 break; 1845 default: 1846 cerror("typwalk"); 1847 } 1848 } 1849 1850 } 1851 1852 NODE * 1853 typenode(NODE *p) 1854 { 1855 struct attr *ap; 1856 struct symtab *sp; 1857 struct typctx tc; 1858 NODE *q; 1859 char *c; 1860 1861 memset(&tc, 0, sizeof(struct typctx)); 1862 1863 flist(p, typwalk, &tc); 1864 tfree(p); 1865 1866 if (tc.err) 1867 goto bad; 1868 1869 if (tc.cmplx || tc.imag) { 1870 if (tc.type == 0) 1871 tc.type = DOUBLE; 1872 if ((tc.cmplx && tc.imag) || tc.sig || tc.uns || 1873 !ISFTY(tc.type)) 1874 goto bad; 1875 if (tc.cmplx) { 1876 c = tc.type == DOUBLE ? "0d" : 1877 tc.type == FLOAT ? "0f" : "0l"; 1878 sp = lookup(addname(c), 0); 1879 tc.type = STRTY; 1880 tc.saved = mkty(tc.type, sp->sdf, sp->sap); 1881 tc.saved->n_sp = sp; 1882 tc.type = 0; 1883 } else 1884 tc.type += (FIMAG-FLOAT); 1885 } 1886 1887 if (tc.saved && tc.type) 1888 goto bad; 1889 if (tc.sig || tc.uns) { 1890 if (tc.type == 0) 1891 tc.type = tc.sig ? INT : UNSIGNED; 1892 if (tc.type > ULONGLONG) 1893 goto bad; 1894 if (tc.uns) 1895 tc.type = ENUNSIGN(tc.type); 1896 } 1897 1898 if (xuchar && tc.type == CHAR && tc.sig == 0) 1899 tc.type = UCHAR; 1900 1901 #ifdef GCC_COMPAT 1902 if (pragma_packed) { 1903 q = bdty(CALL, bdty(NAME, "packed"), bcon(pragma_packed)); 1904 tc.post = attr_add(tc.post, gcc_attr_parse(q)); 1905 } 1906 if (pragma_aligned) { 1907 /* Deal with relevant pragmas */ 1908 if (tc.align < pragma_aligned) 1909 tc.align = pragma_aligned; 1910 } 1911 pragma_aligned = pragma_packed = 0; 1912 #endif 1913 if ((q = tc.saved) == NULL) { 1914 TWORD t; 1915 if ((t = BTYPE(tc.type)) > LDOUBLE && t != VOID && 1916 t != BOOL && !(t >= FIMAG && t <= LIMAG)) 1917 cerror("typenode2 t %x", tc.type); 1918 if (t == UNDEF) { 1919 t = INT; 1920 MODTYPE(tc.type, INT); 1921 } 1922 q = mkty(tc.type, 0, 0); 1923 } 1924 q->n_ap = attr_add(q->n_ap, tc.post); 1925 q->n_qual = tc.qual; 1926 slval(q, tc.class); 1927 #ifdef GCC_COMPAT 1928 if (tc.post) { 1929 /* Can only occur for TYPEDEF, STRUCT or UNION */ 1930 if (tc.saved == NULL) 1931 cerror("typenode"); 1932 if (tc.saved->n_sp) /* trailer attributes for structs */ 1933 tc.saved->n_sp->sap = q->n_ap; 1934 } 1935 if (tc.pre) 1936 q->n_ap = attr_add(q->n_ap, tc.pre); 1937 gcc_tcattrfix(q); 1938 #endif 1939 1940 if (tc.align && (ap = attr_find(q->n_ap, ATTR_ALIGNED)) && 1941 ap->iarg(0) && tc.align > talign(q->n_type, q->n_ap)/SZCHAR) { 1942 q->n_ap = attr_add(q->n_ap, attr_new(ATTR_ALIGNED, 1)); 1943 q->n_ap->aa[0].iarg = SZCHAR * tc.align; 1944 } 1945 1946 return q; 1947 1948 bad: uerror("illegal type combination"); 1949 return mkty(INT, 0, 0); 1950 } 1951 1952 struct tylnk { 1953 struct tylnk *next; 1954 union dimfun df; 1955 }; 1956 1957 /* 1958 * Retrieve all CM-separated argument types, sizes and dimensions and 1959 * put them in an array. 1960 * XXX - can only check first type level, side effects? 1961 */ 1962 static union arglist * 1963 arglist(NODE *n) 1964 { 1965 union arglist *al; 1966 NODE *w = n, **ap; 1967 int num, cnt, i, j, k; 1968 TWORD ty; 1969 1970 #ifdef PCC_DEBUG 1971 if (pdebug) { 1972 printf("arglist %p\n", n); 1973 fwalk(n, eprint, 0); 1974 } 1975 #endif 1976 /* First: how much to allocate */ 1977 for (num = cnt = 0, w = n; w->n_op == CM; w = w->n_left) { 1978 cnt++; /* Number of levels */ 1979 num++; /* At least one per step */ 1980 if (w->n_right->n_op == ELLIPSIS) 1981 continue; 1982 ty = w->n_right->n_type; 1983 if (ty == ENUMTY) { 1984 uerror("arg %d enum undeclared", cnt); 1985 ty = w->n_right->n_type = INT; 1986 } 1987 if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY) 1988 num++; 1989 while (!ISFTN(ty) && !ISARY(ty) && ty > BTMASK) 1990 ty = DECREF(ty); 1991 if (ty > BTMASK) 1992 num++; 1993 } 1994 cnt++; 1995 ty = w->n_type; 1996 if (ty == ENUMTY) { 1997 uerror("arg %d enum undeclared", cnt); 1998 ty = w->n_type = INT; 1999 } 2000 if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY) 2001 num++; 2002 while (!ISFTN(ty) && !ISARY(ty) && ty > BTMASK) 2003 ty = DECREF(ty); 2004 if (ty > BTMASK) 2005 num++; 2006 num += 2; /* TEND + last arg type */ 2007 2008 /* Second: Create list to work on */ 2009 ap = FUNALLO(sizeof(NODE *) * cnt); 2010 al = permalloc(sizeof(union arglist) * num); 2011 arglistcnt += num; 2012 2013 for (w = n, i = 0; w->n_op == CM; w = w->n_left) 2014 ap[i++] = w->n_right; 2015 ap[i] = w; 2016 2017 /* Third: Create actual arg list */ 2018 for (k = 0, j = i; j >= 0; j--) { 2019 if (ap[j]->n_op == ELLIPSIS) { 2020 al[k++].type = TELLIPSIS; 2021 ap[j]->n_op = ICON; /* for tfree() */ 2022 continue; 2023 } 2024 /* Convert arrays to pointers */ 2025 if (ISARY(ap[j]->n_type)) { 2026 ap[j]->n_type += (PTR-ARY); 2027 ap[j]->n_df++; 2028 } 2029 /* Convert (silently) functions to pointers */ 2030 if (ISFTN(ap[j]->n_type)) 2031 ap[j]->n_type = INCREF(ap[j]->n_type); 2032 ty = ap[j]->n_type; 2033 #ifdef GCC_COMPAT 2034 if (ty == UNIONTY && 2035 attr_find(ap[j]->n_ap, GCC_ATYP_TRANSP_UNION)){ 2036 /* transparent unions must have compatible types 2037 * shortcut here: if pointers, set void *, 2038 * otherwise btype. 2039 */ 2040 struct symtab *sp = strmemb(ap[j]->n_ap); 2041 ty = ISPTR(sp->stype) ? PTR|VOID : sp->stype; 2042 } 2043 #endif 2044 al[k++].type = ty; 2045 if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY) 2046 al[k++].sap = ap[j]->n_ap; 2047 while (!ISFTN(ty) && !ISARY(ty) && ty > BTMASK) 2048 ty = DECREF(ty); 2049 if (ty > BTMASK) 2050 al[k++].df = ap[j]->n_df; 2051 } 2052 al[k++].type = TNULL; 2053 if (k > num) 2054 cerror("arglist: k%d > num%d", k, num); 2055 tfree(n); 2056 FUNFREE(ap); 2057 #ifdef PCC_DEBUG 2058 if (pdebug) 2059 alprint(al, 0); 2060 #endif 2061 return al; 2062 } 2063 2064 static void 2065 tylkadd(union dimfun dim, struct tylnk **tylkp, int *ntdim) 2066 { 2067 (*tylkp)->next = tmpalloc(sizeof(struct tylnk)); 2068 *tylkp = (*tylkp)->next; 2069 (*tylkp)->next = NULL; 2070 (*tylkp)->df = dim; 2071 (*ntdim)++; 2072 } 2073 2074 /* 2075 * build a type, and stash away dimensions, 2076 * from a parse tree of the declaration 2077 * the type is build top down, the dimensions bottom up 2078 */ 2079 static void 2080 tyreduce(NODE *p, struct tylnk **tylkp, int *ntdim) 2081 { 2082 union dimfun dim; 2083 NODE *r = NULL; 2084 int o; 2085 TWORD t, q; 2086 2087 o = p->n_op; 2088 if (o == NAME) { 2089 p->n_qual = DECQAL(p->n_qual); 2090 return; 2091 } 2092 2093 t = INCREF(p->n_type); 2094 q = p->n_qual; 2095 switch (o) { 2096 case CALL: 2097 t += (FTN-PTR); 2098 dim.dfun = arglist(p->n_right); 2099 break; 2100 case UCALL: 2101 t += (FTN-PTR); 2102 dim.dfun = NULL; 2103 break; 2104 case LB: 2105 t += (ARY-PTR); 2106 if (p->n_right->n_op != ICON) { 2107 r = p->n_right; 2108 o = RB; 2109 } else { 2110 dim.ddim = (int)glval(p->n_right); 2111 nfree(p->n_right); 2112 #ifdef notdef 2113 /* XXX - check dimensions at usage time */ 2114 if (dim.ddim == NOOFFSET && p->n_left->n_op == LB) 2115 uerror("null dimension"); 2116 #endif 2117 } 2118 break; 2119 } 2120 2121 p->n_left->n_type = t; 2122 p->n_left->n_qual = INCQAL(q) | p->n_left->n_qual; 2123 tyreduce(p->n_left, tylkp, ntdim); 2124 2125 if (o == LB || o == UCALL || o == CALL) 2126 tylkadd(dim, tylkp, ntdim); 2127 if (o == RB) { 2128 dim.ddim = -1; 2129 tylkadd(dim, tylkp, ntdim); 2130 arrstk[arrstkp++] = r; 2131 } 2132 2133 p->n_sp = p->n_left->n_sp; 2134 p->n_type = p->n_left->n_type; 2135 p->n_qual = p->n_left->n_qual; 2136 } 2137 2138 /* 2139 * merge type typ with identifier idp. 2140 * idp is returned as a NAME node with correct types, 2141 * typ is untouched since multiple declarations uses it. 2142 * typ has type attributes, idp can never carry such attributes 2143 * so on return just a pointer to the typ attributes is returned. 2144 */ 2145 NODE * 2146 tymerge(NODE *typ, NODE *idp) 2147 { 2148 TWORD t; 2149 NODE *p; 2150 union dimfun *j; 2151 struct tylnk *base, tylnk, *tylkp; 2152 struct attr *bap; 2153 int ntdim, i; 2154 2155 #ifdef PCC_DEBUG 2156 if (ddebug > 2) { 2157 printf("tymerge(%p,%p)\n", typ, idp); 2158 fwalk(typ, eprint, 0); 2159 fwalk(idp, eprint, 0); 2160 } 2161 #endif 2162 2163 if (typ->n_op != TYPE) 2164 cerror("tymerge: arg 1"); 2165 2166 bap = typ->n_ap; 2167 2168 idp->n_type = typ->n_type; 2169 idp->n_qual |= typ->n_qual; 2170 2171 tylkp = &tylnk; 2172 tylkp->next = NULL; 2173 ntdim = 0; 2174 2175 tyreduce(idp, &tylkp, &ntdim); 2176 2177 for (t = typ->n_type, j = typ->n_df; t&TMASK; t = DECREF(t)) 2178 if (ISARY(t) || ISFTN(t)) 2179 tylkadd(*j++, &tylkp, &ntdim); 2180 2181 if (ntdim) { 2182 union dimfun *a = permalloc(sizeof(union dimfun) * ntdim); 2183 dimfuncnt += ntdim; 2184 for (i = 0, base = tylnk.next; base; base = base->next, i++) 2185 a[i] = base->df; 2186 idp->n_df = a; 2187 } else 2188 idp->n_df = NULL; 2189 2190 /* now idp is a single node: fix up type */ 2191 if ((t = ctype(idp->n_type)) != idp->n_type) 2192 idp->n_type = t; 2193 2194 if (idp->n_op != NAME) { 2195 for (p = idp->n_left; p->n_op != NAME; p = nfree(p)) 2196 ; 2197 nfree(p); 2198 idp->n_op = NAME; 2199 } 2200 /* carefully not destroy any type attributes */ 2201 if (idp->n_ap != NULL) { 2202 struct attr *ap = idp->n_ap; 2203 while (ap->next) 2204 ap = ap->next; 2205 ap->next = bap; 2206 } else 2207 idp->n_ap = bap; 2208 2209 return(idp); 2210 } 2211 2212 static NODE * 2213 argcast(NODE *p, TWORD t, union dimfun *d, struct attr *ap) 2214 { 2215 NODE *u, *r = p1alloc(); 2216 2217 r->n_op = NAME; 2218 r->n_type = t; 2219 r->n_qual = 0; /* XXX */ 2220 r->n_df = d; 2221 r->n_ap = ap; 2222 2223 u = buildtree(CAST, r, p); 2224 nfree(u->n_left); 2225 r = u->n_right; 2226 nfree(u); 2227 return r; 2228 } 2229 2230 #ifdef PCC_DEBUG 2231 /* 2232 * Print a prototype. 2233 */ 2234 static void 2235 alprint(union arglist *al, int in) 2236 { 2237 TWORD t; 2238 int i = 0, j; 2239 2240 for (; al->type != TNULL; al++) { 2241 for (j = in; j > 0; j--) 2242 printf(" "); 2243 printf("arg %d: ", i++); 2244 t = al->type; 2245 tprint(t, 0); 2246 while (t > BTMASK) { 2247 if (ISARY(t)) { 2248 al++; 2249 printf(" dim %d ", al->df->ddim); 2250 } else if (ISFTN(t)) { 2251 al++; 2252 if (al->df->dfun) { 2253 printf("\n"); 2254 alprint(al->df->dfun, in+1); 2255 } 2256 } 2257 t = DECREF(t); 2258 } 2259 if (ISSOU(t)) { 2260 al++; 2261 printf(" (size %d align %d)", (int)tsize(t, 0, al->sap), 2262 (int)talign(t, al->sap)); 2263 } 2264 printf("\n"); 2265 } 2266 if (in == 0) 2267 printf("end arglist\n"); 2268 } 2269 #endif 2270 2271 int 2272 suemeq(struct attr *s1, struct attr *s2) 2273 { 2274 2275 return (strmemb(s1) == strmemb(s2)); 2276 } 2277 2278 /* 2279 * Sanity-check old-style args. 2280 */ 2281 static NODE * 2282 oldarg(NODE *p) 2283 { 2284 if (p->n_op == TYPE) 2285 uerror("type is not an argument"); 2286 if (p->n_type == FLOAT) 2287 return cast(p, DOUBLE, p->n_qual); 2288 return p; 2289 } 2290 2291 /* 2292 * Do prototype checking and add conversions before calling a function. 2293 * Argument f is function and a is a CM-separated list of arguments. 2294 * Returns a merged node (via buildtree() of function and arguments. 2295 */ 2296 NODE * 2297 doacall(struct symtab *sp, NODE *f, NODE *a) 2298 { 2299 NODE *w, *r; 2300 union arglist *al; 2301 struct ap { 2302 struct ap *next; 2303 NODE *node; 2304 } *at, *apole = NULL, *apary = NULL; 2305 int i, argidx/* , hasarray = 0*/; 2306 TWORD type, arrt; 2307 2308 #ifdef PCC_DEBUG 2309 if (ddebug) { 2310 printf("doacall.\n"); 2311 fwalk(f, eprint, 0); 2312 if (a) 2313 fwalk(a, eprint, 0); 2314 } 2315 #endif 2316 2317 /* First let MD code do something */ 2318 calldec(f, a); 2319 /* XXX XXX hack */ 2320 if ((f->n_op == CALL) && 2321 f->n_left->n_op == ADDROF && 2322 f->n_left->n_left->n_op == NAME && 2323 (f->n_left->n_left->n_type & 0x7e0) == 0x4c0) 2324 goto build; 2325 /* XXX XXX hack */ 2326 2327 /* Check for undefined or late defined enums */ 2328 if (BTYPE(f->n_type) == ENUMTY) { 2329 /* not-yet check if declared enum */ 2330 struct symtab *sq = strmemb(f->n_ap); 2331 if (sq->stype != ENUMTY) 2332 MODTYPE(f->n_type, sq->stype); 2333 if (BTYPE(f->n_type) == ENUMTY) 2334 uerror("enum %s not declared", sq->sname); 2335 } 2336 2337 /* 2338 * Do some basic checks. 2339 */ 2340 if (f->n_df == NULL || (al = f->n_df[0].dfun) == NULL) { 2341 /* 2342 * Handle non-prototype declarations. 2343 */ 2344 if (f->n_op == NAME && f->n_sp != NULL) { 2345 if (strncmp(f->n_sp->sname, "__builtin", 9) != 0 && 2346 (f->n_sp->sflags & SINSYS) == 0) 2347 warner(Wmissing_prototypes, f->n_sp->sname); 2348 } else 2349 warner(Wmissing_prototypes, "<pointer>"); 2350 2351 /* floats must be cast to double */ 2352 if (a == NULL) 2353 goto build; 2354 if (a->n_op != CM) { 2355 a = oldarg(a); 2356 } else { 2357 for (w = a; w->n_left->n_op == CM; w = w->n_left) 2358 w->n_right = oldarg(w->n_right); 2359 w->n_left = oldarg(w->n_left); 2360 w->n_right = oldarg(w->n_right); 2361 } 2362 goto build; 2363 } 2364 if (al->type == VOID) { 2365 if (a != NULL) 2366 uerror("function takes no arguments"); 2367 goto build; /* void function */ 2368 } else { 2369 if (a == NULL) { 2370 uerror("function needs arguments"); 2371 goto build; 2372 } 2373 } 2374 #ifdef PCC_DEBUG 2375 if (pdebug) { 2376 printf("arglist for %s\n", 2377 f->n_sp != NULL ? f->n_sp->sname : "function pointer"); 2378 alprint(al, 0); 2379 } 2380 #endif 2381 2382 /* 2383 * Create a list of pointers to the nodes given as arg. 2384 */ 2385 for (w = a, i = 1; w->n_op == CM; w = w->n_left) 2386 i++; 2387 apary = FUNALLO(sizeof(struct ap) * i); 2388 2389 for (w = a, i = 0; w->n_op == CM; w = w->n_left) { 2390 at = &apary[i++]; 2391 at->node = w->n_right; 2392 at->next = apole; 2393 apole = at; 2394 } 2395 at = &apary[i]; 2396 at->node = w; 2397 at->next = apole; 2398 apole = at; 2399 2400 /* 2401 * Do the typechecking by walking up the list. 2402 */ 2403 argidx = 1; 2404 while (al->type != TNULL) { 2405 if (al->type == TELLIPSIS) { 2406 /* convert the rest of float to double */ 2407 for (; apole; apole = apole->next) { 2408 if (apole->node->n_type != FLOAT) 2409 continue; 2410 MKTY(apole->node, DOUBLE, 0, 0); 2411 } 2412 goto build; 2413 } 2414 if (apole == NULL) { 2415 uerror("too few arguments to function"); 2416 goto build; 2417 } 2418 /* al = prototyp, apole = argument till ftn */ 2419 /* type = argumentets typ, arrt = prototypens typ */ 2420 type = apole->node->n_type; 2421 arrt = al->type; 2422 #if 0 2423 if ((hasarray = ISARY(arrt))) 2424 arrt += (PTR-ARY); 2425 #endif 2426 /* Taking addresses of arrays are meaningless in expressions */ 2427 /* but people tend to do that and also use in prototypes */ 2428 /* this is mostly a problem with typedefs */ 2429 if (ISARY(type)) { 2430 if (ISPTR(arrt) && ISARY(DECREF(arrt))) 2431 type = INCREF(type); 2432 else 2433 type += (PTR-ARY); 2434 } else if (ISPTR(type) && !ISARY(DECREF(type)) && 2435 ISPTR(arrt) && ISARY(DECREF(arrt))) { 2436 type += (ARY-PTR); 2437 type = INCREF(type); 2438 } 2439 2440 /* Check structs */ 2441 if (type <= BTMASK && arrt <= BTMASK) { 2442 #ifndef NO_COMPLEX 2443 if ((type != arrt) && (ANYCX(apole->node) || 2444 (arrt == STRTY && 2445 attr_find(al[1].sap, ATTR_COMPLEX)))) { 2446 cxargfixup(apole->node, arrt, al[1].sap); 2447 } else 2448 #endif 2449 if (type != arrt) { 2450 if (ISSOU(BTYPE(type)) || ISSOU(BTYPE(arrt))) { 2451 incomp: uerror("incompatible types for arg %d", 2452 argidx); 2453 } else { 2454 MKTY(apole->node, arrt, 0, 0) 2455 } 2456 #ifndef NO_COMPLEX 2457 } else if (type == STRTY && 2458 attr_find(apole->node->n_ap, ATTR_COMPLEX) && 2459 attr_find(al[1].sap, ATTR_COMPLEX)) { 2460 /* Both are complex */ 2461 if (strmemb(apole->node->n_ap)->stype != 2462 strmemb(al[1].sap)->stype) { 2463 /* must convert to correct type */ 2464 w = p1alloc(); 2465 *w = *apole->node; 2466 w = mkcmplx(w, 2467 strmemb(al[1].sap)->stype); 2468 *apole->node = *w; 2469 nfree(w); 2470 } 2471 goto out; 2472 #endif 2473 } else if (ISSOU(BTYPE(type))) { 2474 if (!suemeq(apole->node->n_ap, al[1].sap)) 2475 goto incomp; 2476 } 2477 goto out; 2478 } 2479 2480 /* XXX should (recusively) check return type and arg list of 2481 func ptr arg XXX */ 2482 if (ISFTN(DECREF(arrt)) && ISFTN(type)) 2483 type = INCREF(type); 2484 2485 /* Hereafter its only pointers (or arrays) left */ 2486 /* Check for struct/union intermixing with other types */ 2487 if (((type <= BTMASK) && ISSOU(BTYPE(type))) || 2488 ((arrt <= BTMASK) && ISSOU(BTYPE(arrt)))) 2489 goto incomp; 2490 2491 /* Check for struct/union compatibility */ 2492 if (type == arrt) { 2493 if (ISSOU(BTYPE(type))) { 2494 if (suemeq(apole->node->n_ap, al[1].sap)) 2495 goto out; 2496 } else 2497 goto out; 2498 } 2499 if (BTYPE(arrt) == VOID && type > BTMASK) 2500 goto skip; /* void *f = some pointer */ 2501 if (arrt > BTMASK && BTYPE(type) == VOID) 2502 goto skip; /* some *f = void pointer */ 2503 if (apole->node->n_op == ICON && glval(apole->node) == 0) 2504 goto skip; /* Anything assigned a zero */ 2505 2506 if ((type & ~BTMASK) == (arrt & ~BTMASK)) { 2507 /* do not complain for pointers with signedness */ 2508 if ((DEUNSIGN(BTYPE(type)) == DEUNSIGN(BTYPE(arrt))) && 2509 (BTYPE(type) != BTYPE(arrt))) { 2510 warner(Wpointer_sign); 2511 goto skip; 2512 } 2513 } 2514 2515 werror("implicit conversion of argument %d due to prototype", 2516 argidx); 2517 2518 skip: if (ISSOU(BTYPE(arrt))) { 2519 MKTY(apole->node, arrt, 0, al[1].sap) 2520 } else { 2521 MKTY(apole->node, arrt, 0, 0) 2522 } 2523 2524 out: al++; 2525 if (ISSOU(BTYPE(arrt))) 2526 al++; 2527 #if 0 2528 while (arrt > BTMASK && !ISFTN(arrt)) 2529 arrt = DECREF(arrt); 2530 if (ISFTN(arrt) || hasarray) 2531 al++; 2532 #else 2533 while (arrt > BTMASK) { 2534 if (ISARY(arrt) || ISFTN(arrt)) { 2535 al++; 2536 break; 2537 } 2538 arrt = DECREF(arrt); 2539 } 2540 #endif 2541 apole = apole->next; 2542 argidx++; 2543 } 2544 if (apole != NULL) 2545 uerror("too many arguments to function"); 2546 2547 build: if (apary) 2548 FUNFREE(apary); 2549 if (sp != NULL && (sp->sflags & SINLINE) && (w = inlinetree(sp, f, a))) 2550 return w; 2551 return buildtree(a == NIL ? UCALL : CALL, f, a); 2552 } 2553 2554 static int 2555 chk2(TWORD type, union dimfun *dsym, union dimfun *ddef) 2556 { 2557 while (type > BTMASK) { 2558 switch (type & TMASK) { 2559 case ARY: 2560 /* may be declared without dimension */ 2561 if (dsym->ddim == NOOFFSET) 2562 dsym->ddim = ddef->ddim; 2563 if (dsym->ddim < 0 && ddef->ddim < 0) 2564 ; /* dynamic arrays as arguments */ 2565 else if (ddef->ddim > 0 && dsym->ddim != ddef->ddim) 2566 return 1; 2567 dsym++, ddef++; 2568 break; 2569 case FTN: 2570 /* old-style function headers with function pointers 2571 * will most likely not have a prototype. 2572 * This is not considered an error. */ 2573 if (ddef->dfun == NULL) { 2574 #ifdef notyet 2575 werror("declaration not a prototype"); 2576 #endif 2577 } else if (chkftn(dsym->dfun, ddef->dfun)) 2578 return 1; 2579 dsym++, ddef++; 2580 break; 2581 } 2582 type = DECREF(type); 2583 } 2584 return 0; 2585 } 2586 2587 /* 2588 * Compare two function argument lists to see if they match. 2589 */ 2590 int 2591 chkftn(union arglist *usym, union arglist *udef) 2592 { 2593 TWORD t2; 2594 int ty, tyn; 2595 2596 if (usym == NULL) 2597 return 0; 2598 if (cftnsp != NULL && udef == NULL && usym->type == VOID) 2599 return 0; /* foo() { function with foo(void); prototype */ 2600 if (udef == NULL && usym->type != TNULL) 2601 return 1; 2602 while (usym->type != TNULL) { 2603 if (usym->type == udef->type) 2604 goto done; 2605 /* 2606 * If an old-style declaration, then all types smaller than 2607 * int are given as int parameters. 2608 */ 2609 if (intcompare) { 2610 ty = BTYPE(usym->type); 2611 tyn = BTYPE(udef->type); 2612 if (ty == tyn || ty != INT) 2613 return 1; 2614 if (tyn == CHAR || tyn == UCHAR || 2615 tyn == SHORT || tyn == USHORT) 2616 goto done; 2617 return 1; 2618 } else 2619 return 1; 2620 2621 done: ty = BTYPE(usym->type); 2622 t2 = usym->type; 2623 if (ISSOU(ty)) { 2624 usym++, udef++; 2625 if (suemeq(usym->sap, udef->sap) == 0) 2626 return 1; 2627 } 2628 2629 while (!ISFTN(t2) && !ISARY(t2) && t2 > BTMASK) 2630 t2 = DECREF(t2); 2631 if (t2 > BTMASK) { 2632 usym++, udef++; 2633 if (chk2(t2, usym->df, udef->df)) 2634 return 1; 2635 } 2636 usym++, udef++; 2637 } 2638 if (usym->type != udef->type) 2639 return 1; 2640 return 0; 2641 } 2642 2643 void 2644 fixtype(NODE *p, int class) 2645 { 2646 unsigned int t, type; 2647 int mod1, mod2; 2648 /* fix up the types, and check for legality */ 2649 2650 /* forward declared enums */ 2651 if (BTYPE(p->n_sp->stype) == ENUMTY) { 2652 MODTYPE(p->n_sp->stype, strmemb(p->n_sp->sap)->stype); 2653 } 2654 2655 if( (type = p->n_type) == UNDEF ) return; 2656 if ((mod2 = (type&TMASK))) { 2657 t = DECREF(type); 2658 while( mod1=mod2, mod2 = (t&TMASK) ){ 2659 if( mod1 == ARY && mod2 == FTN ){ 2660 uerror( "array of functions is illegal" ); 2661 type = 0; 2662 } 2663 else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){ 2664 uerror( "function returns illegal type" ); 2665 type = 0; 2666 } 2667 t = DECREF(t); 2668 } 2669 } 2670 2671 /* detect function arguments, watching out for structure declarations */ 2672 if (rpole && ISFTN(type)) { 2673 uerror("function illegal in structure or union"); 2674 type = INCREF(type); 2675 } 2676 p->n_type = type; 2677 } 2678 2679 /* 2680 * give undefined version of class 2681 */ 2682 int 2683 uclass(int class) 2684 { 2685 if (class == SNULL) 2686 return(EXTERN); 2687 else if (class == STATIC) 2688 return(USTATIC); 2689 else 2690 return(class); 2691 } 2692 2693 int 2694 fixclass(int class, TWORD type) 2695 { 2696 extern int fun_inline; 2697 2698 /* first, fix null class */ 2699 if (class == SNULL) { 2700 if (fun_inline && ISFTN(type)) 2701 return SNULL; 2702 if (rpole) 2703 cerror("field8"); 2704 else if (blevel == 0) 2705 class = EXTDEF; 2706 else 2707 class = AUTO; 2708 } 2709 2710 /* now, do general checking */ 2711 2712 if( ISFTN( type ) ){ 2713 switch( class ) { 2714 default: 2715 uerror( "function has illegal storage class" ); 2716 case AUTO: 2717 class = EXTERN; 2718 case EXTERN: 2719 case EXTDEF: 2720 case TYPEDEF: 2721 case STATIC: 2722 case USTATIC: 2723 ; 2724 } 2725 } 2726 2727 if (class & FIELD) { 2728 cerror("field3"); 2729 } 2730 2731 switch (class) { 2732 2733 case MOS: 2734 case MOU: 2735 cerror("field4"); 2736 2737 case REGISTER: 2738 if (blevel == 0) 2739 uerror("illegal register declaration"); 2740 if (blevel == 1) 2741 return(PARAM); 2742 else 2743 return(REGISTER); 2744 2745 case AUTO: 2746 if( blevel < 2 ) uerror( "illegal ULABEL class" ); 2747 return( class ); 2748 2749 case EXTERN: 2750 case STATIC: 2751 case EXTDEF: 2752 case TYPEDEF: 2753 case USTATIC: 2754 case PARAM: 2755 return( class ); 2756 2757 default: 2758 cerror( "illegal class: %d", class ); 2759 /* NOTREACHED */ 2760 2761 } 2762 return 0; /* XXX */ 2763 } 2764 2765 /* 2766 * Generates a goto statement; sets up label number etc. 2767 */ 2768 void 2769 gotolabel(char *name) 2770 { 2771 struct symtab *s = lookup(name, SLBLNAME|STEMP); 2772 2773 if (s->soffset == 0) { 2774 s->soffset = -getlab(); 2775 s->sclass = STATIC; 2776 } 2777 branch(s->soffset < 0 ? -s->soffset : s->soffset); 2778 } 2779 2780 /* 2781 * Sets a label for gotos. 2782 */ 2783 void 2784 deflabel(char *name, NODE *p) 2785 { 2786 struct symtab *s = lookup(name, SLBLNAME|STEMP); 2787 2788 #ifdef GCC_COMPAT 2789 s->sap = gcc_attr_parse(p); 2790 #endif 2791 if (s->soffset > 0) 2792 uerror("label '%s' redefined", name); 2793 if (s->soffset == 0) { 2794 s->soffset = getlab(); 2795 s->sclass = STATIC; 2796 } 2797 if (s->soffset < 0) 2798 s->soffset = -s->soffset; 2799 plabel( s->soffset); 2800 } 2801 2802 struct symtab * 2803 getsymtab(char *name, int flags) 2804 { 2805 struct symtab *s; 2806 2807 if (flags & SSTMT) { 2808 s = stmtalloc(sizeof(struct symtab)); 2809 } else if (flags & SBLK) { 2810 s = blkalloc(sizeof(struct symtab)); 2811 } else if (flags & STEMP) { 2812 s = tmpalloc(sizeof(struct symtab)); 2813 } else { 2814 s = permalloc(sizeof(struct symtab)); 2815 symtabcnt++; 2816 } 2817 s->sname = name; 2818 s->snext = NULL; 2819 s->stype = UNDEF; 2820 s->squal = 0; 2821 s->sclass = SNULL; 2822 s->sflags = (short)(flags & SMASK); 2823 s->soffset = 0; 2824 s->slevel = (char)blevel; 2825 s->sdf = NULL; 2826 s->sap = NULL; 2827 return s; 2828 } 2829 2830 int 2831 fldchk(int sz) 2832 { 2833 if (rpole->rsou != STNAME && rpole->rsou != UNAME) 2834 uerror("field outside of structure"); 2835 if (sz < 0 || sz >= FIELD) { 2836 uerror("illegal field size"); 2837 return 1; 2838 } 2839 return 0; 2840 } 2841 2842 #ifdef PCC_DEBUG 2843 static char * 2844 ccnames[] = { /* names of storage classes */ 2845 "SNULL", 2846 "AUTO", 2847 "EXTERN", 2848 "STATIC", 2849 "REGISTER", 2850 "EXTDEF", 2851 "LABEL", 2852 "ULABEL", 2853 "MOS", 2854 "PARAM", 2855 "STNAME", 2856 "MOU", 2857 "UNAME", 2858 "TYPEDEF", 2859 "FORTRAN", 2860 "ENAME", 2861 "MOE", 2862 "UFORTRAN", 2863 "USTATIC", 2864 }; 2865 2866 char * 2867 scnames(int c) 2868 { 2869 /* return the name for storage class c */ 2870 static char buf[12]; 2871 if( c&FIELD ){ 2872 snprintf( buf, sizeof(buf), "FIELD[%d]", c&FLDSIZ ); 2873 return( buf ); 2874 } 2875 return( ccnames[c] ); 2876 } 2877 #endif 2878 2879 #if 0 2880 static char *stack_chk_fail = "__stack_smash_handler"; 2881 static char *stack_chk_guard = "__guard"; 2882 #else 2883 static char *stack_chk_fail = "__stack_chk_fail"; 2884 static char *stack_chk_guard = "__stack_chk_guard"; 2885 #endif 2886 static char *stack_chk_canary = "__stack_chk_canary"; 2887 2888 void 2889 sspinit(void) 2890 { 2891 NODE *p; 2892 2893 p = block(NAME, NIL, NIL, FTN+VOID, 0, 0); 2894 p->n_sp = lookup(stack_chk_fail, SNORMAL); 2895 defid(p, EXTERN); 2896 nfree(p); 2897 2898 p = block(NAME, NIL, NIL, INT, 0, 0); 2899 p->n_sp = lookup(stack_chk_guard, SNORMAL); 2900 defid(p, EXTERN); 2901 nfree(p); 2902 } 2903 2904 void 2905 sspstart(void) 2906 { 2907 NODE *p, *q; 2908 2909 q = block(NAME, NIL, NIL, INT, 0, 0); 2910 q->n_sp = lookup(stack_chk_guard, SNORMAL); 2911 q = clocal(q); 2912 2913 p = block(REG, NIL, NIL, INCREF(INT), 0, 0); 2914 slval(p, 0); 2915 p->n_rval = FPREG; 2916 p = cast(p, INT, 0); 2917 q = buildtree(ER, p, q); 2918 2919 p = block(NAME, NIL, NIL, INT, 0, 0); 2920 p->n_qual = VOL >> TSHIFT; 2921 p->n_sp = lookup(stack_chk_canary, SNORMAL); 2922 defid(p, AUTO); 2923 p = clocal(p); 2924 ecomp(buildtree(ASSIGN, p, q)); 2925 } 2926 2927 void 2928 sspend(void) 2929 { 2930 NODE *p, *q; 2931 TWORD t; 2932 int lab; 2933 2934 if (retlab != NOLAB) { 2935 plabel(retlab); 2936 retlab = getlab(); 2937 } 2938 2939 t = DECREF(cftnsp->stype); 2940 if (t == BOOL) 2941 t = BOOL_TYPE; 2942 2943 p = block(NAME, NIL, NIL, INT, 0, 0); 2944 p->n_sp = lookup(stack_chk_canary, SNORMAL); 2945 p = clocal(p); 2946 2947 q = block(REG, NIL, NIL, INCREF(INT), 0, 0); 2948 slval(q, 0); 2949 q->n_rval = FPREG; 2950 q = cast(q, INT, 0); 2951 q = buildtree(ER, p, q); 2952 2953 p = block(NAME, NIL, NIL, INT, 0, 0); 2954 p->n_sp = lookup(stack_chk_guard, SNORMAL); 2955 p = clocal(p); 2956 2957 lab = getlab(); 2958 cbranch(buildtree(EQ, p, q), bcon(lab)); 2959 2960 p = block(NAME, NIL, NIL, FTN+VOID, 0, 0); 2961 p->n_sp = lookup(stack_chk_fail, SNORMAL); 2962 p = clocal(p); 2963 2964 q = eve(bdty(STRING, cftnsp->sname, PTR|CHAR)); 2965 ecomp(buildtree(CALL, p, q)); 2966 2967 plabel(lab); 2968 } 2969 2970 /* 2971 * Fetch pointer to first member in a struct list. 2972 */ 2973 struct symtab * 2974 strmemb(struct attr *ap) 2975 { 2976 2977 if ((ap = attr_find(ap, ATTR_STRUCT)) == NULL) 2978 cerror("strmemb"); 2979 return ap->amlist; 2980 } 2981 2982 #ifndef NO_COMPLEX 2983 2984 static char *real, *imag; 2985 static struct symtab *cxsp[3], *cxmul[3], *cxdiv[3]; 2986 static char *cxnmul[] = { "__mulsc3", "__muldc3", "__mulxc3" }; 2987 static char *cxndiv[] = { "__divsc3", "__divdc3", "__divxc3" }; 2988 /* 2989 * As complex numbers internally are handled as structs, create 2990 * these by hand-crafting them. 2991 */ 2992 void 2993 complinit(void) 2994 { 2995 struct attr *ap; 2996 struct rstack *rp; 2997 NODE *p, *q; 2998 char *n[] = { "0f", "0d", "0l" }; 2999 int i, d_debug; 3000 3001 d_debug = ddebug; 3002 ddebug = 0; 3003 real = addname("__real"); 3004 imag = addname("__imag"); 3005 p = block(NAME, NIL, NIL, FLOAT, 0, 0); 3006 for (i = 0; i < 3; i++) { 3007 p->n_type = FLOAT+i; 3008 rpole = rp = bstruct(NULL, STNAME, NULL); 3009 soumemb(p, real, 0); 3010 soumemb(p, imag, 0); 3011 q = dclstruct(rp); 3012 cxsp[i] = q->n_sp = lookup(addname(n[i]), 0); 3013 defid(q, TYPEDEF); 3014 ap = attr_new(ATTR_COMPLEX, 0); 3015 q->n_sp->sap = attr_add(q->n_sp->sap, ap); 3016 nfree(q); 3017 } 3018 /* create function declarations for external ops */ 3019 for (i = 0; i < 3; i++) { 3020 cxnmul[i] = addname(cxnmul[i]); 3021 p->n_sp = cxmul[i] = lookup(cxnmul[i], 0); 3022 p->n_type = FTN|STRTY; 3023 p->n_ap = cxsp[i]->sap; 3024 p->n_df = cxsp[i]->sdf; 3025 defid2(p, EXTERN, 0); 3026 cxmul[i]->sdf = permalloc(sizeof(union dimfun)); 3027 dimfuncnt++; 3028 cxmul[i]->sdf->dfun = NULL; 3029 cxndiv[i] = addname(cxndiv[i]); 3030 p->n_sp = cxdiv[i] = lookup(cxndiv[i], 0); 3031 p->n_type = FTN|STRTY; 3032 p->n_ap = cxsp[i]->sap; 3033 p->n_df = cxsp[i]->sdf; 3034 defid2(p, EXTERN, 0); 3035 cxdiv[i]->sdf = permalloc(sizeof(union dimfun)); 3036 dimfuncnt++; 3037 cxdiv[i]->sdf->dfun = NULL; 3038 } 3039 nfree(p); 3040 ddebug = d_debug; 3041 } 3042 3043 static TWORD 3044 maxtt(NODE *p) 3045 { 3046 TWORD t; 3047 3048 t = ANYCX(p) ? strmemb(p->n_ap)->stype : p->n_type; 3049 t = BTYPE(t); 3050 if (t == VOID) 3051 t = CHAR; /* pointers */ 3052 if (ISITY(t)) 3053 t -= (FIMAG - FLOAT); 3054 return t; 3055 } 3056 3057 /* 3058 * Return the highest real floating point type. 3059 * Known that at least one type is complex or imaginary. 3060 */ 3061 static TWORD 3062 maxtyp(NODE *l, NODE *r) 3063 { 3064 TWORD tl, tr, t; 3065 3066 tl = maxtt(l); 3067 tr = maxtt(r); 3068 t = tl > tr ? tl : tr; 3069 if (!ISFTY(t)) 3070 cerror("maxtyp"); 3071 return t; 3072 } 3073 3074 /* 3075 * Fetch space on stack for complex struct. 3076 */ 3077 static NODE * 3078 cxstore(TWORD t) 3079 { 3080 struct symtab s; 3081 3082 s = *cxsp[t - FLOAT]; 3083 s.sclass = AUTO; 3084 s.soffset = NOOFFSET; 3085 oalloc(&s, &autooff); 3086 return nametree(&s); 3087 } 3088 3089 #define comop(x,y) buildtree(COMOP, x, y) 3090 3091 /* 3092 * Convert node p to complex type dt. 3093 */ 3094 static NODE * 3095 mkcmplx(NODE *p, TWORD dt) 3096 { 3097 NODE *q, *r, *i, *t; 3098 3099 if (!ANYCX(p)) { 3100 /* Not complex, convert to complex on stack */ 3101 q = cxstore(dt); 3102 if (ISITY(p->n_type)) { 3103 p->n_type = p->n_type - FIMAG + FLOAT; 3104 r = bcon(0); 3105 i = p; 3106 } else { 3107 if (ISPTR(p->n_type)) 3108 p = cast(p, INTPTR, 0); 3109 r = p; 3110 i = bcon(0); 3111 } 3112 p = buildtree(ASSIGN, structref(ccopy(q), DOT, real), r); 3113 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), i)); 3114 p = comop(p, q); 3115 } else { 3116 if (strmemb(p->n_ap)->stype != dt) { 3117 q = cxstore(dt); 3118 p = buildtree(ADDROF, p, NIL); 3119 t = tempnode(0, p->n_type, p->n_df, p->n_ap); 3120 p = buildtree(ASSIGN, ccopy(t), p); 3121 p = comop(p, buildtree(ASSIGN, 3122 structref(ccopy(q), DOT, real), 3123 structref(ccopy(t), STREF, real))); 3124 p = comop(p, buildtree(ASSIGN, 3125 structref(ccopy(q), DOT, imag), 3126 structref(t, STREF, imag))); 3127 p = comop(p, q); 3128 } 3129 } 3130 return p; 3131 } 3132 3133 static NODE * 3134 cxasg(NODE *l, NODE *r) 3135 { 3136 TWORD tl, tr; 3137 3138 tl = strattr(l->n_ap) ? strmemb(l->n_ap)->stype : 0; 3139 tr = strattr(r->n_ap) ? strmemb(r->n_ap)->stype : 0; 3140 3141 if (ANYCX(l) && ANYCX(r) && tl != tr) { 3142 /* different types in structs */ 3143 r = mkcmplx(r, tl); 3144 } else if (!ANYCX(l)) 3145 r = structref(r, DOT, ISITY(l->n_type) ? imag : real); 3146 else if (!ANYCX(r)) 3147 r = mkcmplx(r, tl); 3148 return buildtree(ASSIGN, l, r); 3149 } 3150 3151 /* 3152 * Fixup complex operations. 3153 * At least one operand is complex. 3154 */ 3155 NODE * 3156 cxop(int op, NODE *l, NODE *r) 3157 { 3158 TWORD mxtyp; 3159 NODE *p, *q; 3160 NODE *ltemp, *rtemp; 3161 NODE *real_l, *imag_l; 3162 NODE *real_r, *imag_r; 3163 real_r = imag_r = NULL; /* bad uninit var warning */ 3164 3165 if (op == ASSIGN) 3166 return cxasg(l, r); 3167 3168 mxtyp = maxtyp(l, r); 3169 l = mkcmplx(l, mxtyp); 3170 if (op != UMINUS) 3171 r = mkcmplx(r, mxtyp); 3172 3173 if (op == COLON) 3174 return buildtree(COLON, l, r); 3175 3176 /* put a pointer to left and right elements in a TEMP */ 3177 l = buildtree(ADDROF, l, NIL); 3178 ltemp = tempnode(0, l->n_type, l->n_df, l->n_ap); 3179 l = buildtree(ASSIGN, ccopy(ltemp), l); 3180 3181 if (op != UMINUS) { 3182 r = buildtree(ADDROF, r, NIL); 3183 rtemp = tempnode(0, r->n_type, r->n_df, r->n_ap); 3184 r = buildtree(ASSIGN, ccopy(rtemp), r); 3185 3186 p = comop(l, r); 3187 } else 3188 p = l; 3189 3190 /* create the four trees needed for calculation */ 3191 real_l = structref(ccopy(ltemp), STREF, real); 3192 imag_l = structref(ltemp, STREF, imag); 3193 if (op != UMINUS) { 3194 real_r = structref(ccopy(rtemp), STREF, real); 3195 imag_r = structref(rtemp, STREF, imag); 3196 } 3197 3198 /* get storage on stack for the result */ 3199 q = cxstore(mxtyp); 3200 3201 switch (op) { 3202 case NE: 3203 case EQ: 3204 tfree(q); 3205 p = buildtree(op, comop(p, real_l), real_r); 3206 q = buildtree(op, imag_l, imag_r); 3207 p = buildtree(op == EQ ? ANDAND : OROR, p, q); 3208 return p; 3209 3210 case ANDAND: 3211 case OROR: /* go via EQ to get INT of it */ 3212 tfree(q); 3213 p = buildtree(NE, comop(p, real_l), bcon(0)); /* gets INT */ 3214 q = buildtree(NE, imag_l, bcon(0)); 3215 p = buildtree(OR, p, q); 3216 3217 q = buildtree(NE, real_r, bcon(0)); 3218 q = buildtree(OR, q, buildtree(NE, imag_r, bcon(0))); 3219 3220 p = buildtree(op, p, q); 3221 return p; 3222 3223 case UMINUS: 3224 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real), 3225 buildtree(op, real_l, NIL))); 3226 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), 3227 buildtree(op, imag_l, NIL))); 3228 break; 3229 3230 case PLUS: 3231 case MINUS: 3232 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real), 3233 buildtree(op, real_l, real_r))); 3234 p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), 3235 buildtree(op, imag_l, imag_r))); 3236 break; 3237 3238 case MUL: 3239 case DIV: 3240 /* Complex mul is "complex" */ 3241 /* (u+iv)*(x+iy)=((u*x)-(v*y))+i(v*x+y*u) */ 3242 /* Complex div is even more "complex" */ 3243 /* (u+iv)/(x+iy)=(u*x+v*y)/(x*x+y*y)+i((v*x-u*y)/(x*x+y*y)) */ 3244 /* but we need to do it via a subroutine */ 3245 tfree(q); 3246 p = buildtree(CM, comop(p, real_l), imag_l); 3247 p = buildtree(CM, p, real_r); 3248 p = buildtree(CM, p, imag_r); 3249 q = nametree(op == DIV ? 3250 cxdiv[mxtyp-FLOAT] : cxmul[mxtyp-FLOAT]); 3251 return buildtree(CALL, q, p); 3252 break; 3253 default: 3254 uerror("illegal operator %s", copst(op)); 3255 } 3256 return comop(p, q); 3257 } 3258 3259 /* 3260 * Fixup imaginary operations. 3261 * At least one operand is imaginary, none is complex. 3262 */ 3263 NODE * 3264 imop(int op, NODE *l, NODE *r) 3265 { 3266 NODE *p, *q; 3267 TWORD mxtyp; 3268 int li, ri; 3269 3270 li = ri = 0; 3271 if (ISITY(l->n_type)) 3272 li = 1, l->n_type = l->n_type - (FIMAG-FLOAT); 3273 if (ISITY(r->n_type)) 3274 ri = 1, r->n_type = r->n_type - (FIMAG-FLOAT); 3275 3276 mxtyp = maxtyp(l, r); 3277 switch (op) { 3278 case ASSIGN: 3279 /* if both are imag, store value, otherwise store 0.0 */ 3280 if (!(li && ri)) { 3281 tfree(r); 3282 r = bcon(0); 3283 } 3284 p = buildtree(ASSIGN, l, r); 3285 p->n_type += (FIMAG-FLOAT); 3286 break; 3287 3288 case PLUS: 3289 if (li && ri) { 3290 p = buildtree(PLUS, l, r); 3291 p->n_type += (FIMAG-FLOAT); 3292 } else { 3293 /* If one is imaginary and one is real, make complex */ 3294 if (li) 3295 q = l, l = r, r = q; /* switch */ 3296 q = cxstore(mxtyp); 3297 p = buildtree(ASSIGN, 3298 structref(ccopy(q), DOT, real), l); 3299 p = comop(p, buildtree(ASSIGN, 3300 structref(ccopy(q), DOT, imag), r)); 3301 p = comop(p, q); 3302 } 3303 break; 3304 3305 case MINUS: 3306 if (li && ri) { 3307 p = buildtree(MINUS, l, r); 3308 p->n_type += (FIMAG-FLOAT); 3309 } else if (li) { 3310 q = cxstore(mxtyp); 3311 p = buildtree(ASSIGN, structref(ccopy(q), DOT, real), 3312 buildtree(UMINUS, r, NIL)); 3313 p = comop(p, buildtree(ASSIGN, 3314 structref(ccopy(q), DOT, imag), l)); 3315 p = comop(p, q); 3316 } else /* if (ri) */ { 3317 q = cxstore(mxtyp); 3318 p = buildtree(ASSIGN, 3319 structref(ccopy(q), DOT, real), l); 3320 p = comop(p, buildtree(ASSIGN, 3321 structref(ccopy(q), DOT, imag), 3322 buildtree(UMINUS, r, NIL))); 3323 p = comop(p, q); 3324 } 3325 break; 3326 3327 case MUL: 3328 p = buildtree(MUL, l, r); 3329 if (li && ri) 3330 p = buildtree(UMINUS, p, NIL); 3331 if (li ^ ri) 3332 p->n_type += (FIMAG-FLOAT); 3333 break; 3334 3335 case DIV: 3336 p = buildtree(DIV, l, r); 3337 if (ri && !li) 3338 p = buildtree(UMINUS, p, NIL); 3339 if (li ^ ri) 3340 p->n_type += (FIMAG-FLOAT); 3341 break; 3342 3343 case EQ: 3344 case NE: 3345 case LT: 3346 case LE: 3347 case GT: 3348 case GE: 3349 if (li ^ ri) { /* always 0 */ 3350 tfree(l); 3351 tfree(r); 3352 p = bcon(0); 3353 } else 3354 p = buildtree(op, l, r); 3355 break; 3356 3357 default: 3358 cerror("imop"); 3359 p = NULL; 3360 } 3361 return p; 3362 } 3363 3364 NODE * 3365 cxelem(int op, NODE *p) 3366 { 3367 3368 if (ANYCX(p)) { 3369 p = structref(p, DOT, op == XREAL ? real : imag); 3370 } else if (op == XIMAG) { 3371 /* XXX sanitycheck? */ 3372 tfree(p); 3373 p = bcon(0); 3374 } 3375 return p; 3376 } 3377 3378 NODE * 3379 cxconj(NODE *p) 3380 { 3381 NODE *q, *r; 3382 3383 /* XXX side effects? */ 3384 q = cxstore(strmemb(p->n_ap)->stype); 3385 r = buildtree(ASSIGN, structref(ccopy(q), DOT, real), 3386 structref(ccopy(p), DOT, real)); 3387 r = comop(r, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), 3388 buildtree(UMINUS, structref(p, DOT, imag), NIL))); 3389 return comop(r, q); 3390 } 3391 3392 /* 3393 * Prepare for return. 3394 * There may be implicit casts to other types. 3395 */ 3396 NODE * 3397 imret(NODE *p, NODE *q) 3398 { 3399 if (ISITY(q->n_type) && ISITY(p->n_type)) { 3400 if (p->n_type != q->n_type) { 3401 p->n_type -= (FIMAG-FLOAT); 3402 p = cast(p, q->n_type - (FIMAG-FLOAT), 0); 3403 p->n_type += (FIMAG-FLOAT); 3404 } 3405 } else { 3406 p1tfree(p); 3407 if (ISITY(q->n_type)) { 3408 p = block(FCON, 0, 0, q->n_type, 0, 0); 3409 p->n_dcon = FLOAT_ZERO; 3410 } else 3411 p = bcon(0); 3412 } 3413 3414 return p; 3415 } 3416 3417 /* 3418 * Prepare for return. 3419 * There may be implicit casts to other types. 3420 */ 3421 NODE * 3422 cxret(NODE *p, NODE *q) 3423 { 3424 if (ANYCX(q)) { /* Return complex type */ 3425 p = mkcmplx(p, strmemb(q->n_ap)->stype); 3426 } else if (q->n_type < STRTY || ISITY(q->n_type)) { /* real or imag */ 3427 p = structref(p, DOT, ISITY(q->n_type) ? imag : real); 3428 if (p->n_type != q->n_type) 3429 p = cast(p, q->n_type, 0); 3430 } else 3431 cerror("cxred failing type"); 3432 return p; 3433 } 3434 3435 /* 3436 * either p1 or p2 is complex, so fixup the remaining type accordingly. 3437 */ 3438 NODE * 3439 cxcast(NODE *p1, NODE *p2) 3440 { 3441 if (ANYCX(p1) && ANYCX(p2)) { 3442 if (p1->n_type != p2->n_type) 3443 p2 = mkcmplx(p2, p1->n_type); 3444 } else if (ANYCX(p1)) { 3445 p2 = mkcmplx(p2, strmemb(p1->n_ap)->stype); 3446 } else /* if (ANYCX(p2)) */ { 3447 p2 = cast(structref(p2, DOT, real), p1->n_type, 0); 3448 } 3449 nfree(p1); 3450 return p2; 3451 } 3452 3453 static void 3454 cxargfixup(NODE *a, TWORD dt, struct attr *ap) 3455 { 3456 NODE *p; 3457 TWORD t; 3458 3459 p = p1alloc(); 3460 *p = *a; 3461 if (dt == STRTY) { 3462 /* dest complex */ 3463 t = strmemb(ap)->stype; 3464 p = mkcmplx(p, t); 3465 } else { 3466 /* src complex, not dest */ 3467 p = structref(p, DOT, ISFTY(dt) ? real : imag); 3468 } 3469 *a = *p; 3470 nfree(p); 3471 } 3472 #endif 3473 3474 /* 3475 * Allocations: 3476 * permalloc() Never freed. in pass2. 3477 * tmpalloc() during a function lifetime, then freed. in pass2. 3478 * blkalloc() during a block lifetime. Variables etc. In pass1. 3479 * stmtalloc() during a statement lifetime. Expression trees. In pass1. 3480 */ 3481 3482 /* 3483 * Short-time allocations during statements. 3484 */ 3485 #define MEMCHUNKSZ 8192 /* 8k per allocation */ 3486 struct balloc { 3487 char a1; 3488 union { 3489 long long l; 3490 long double d; 3491 } a2; 3492 }; 3493 #define ALIGNMENT offsetof(struct balloc, a2) 3494 #define ROUNDUP(x) (((x) + ((ALIGNMENT)-1)) & ~((ALIGNMENT)-1)) 3495 3496 #define MAXSZ MEMCHUNKSZ-sizeof(struct xalloc *) 3497 struct xalloc { 3498 struct xalloc *next; 3499 union { 3500 long long b; /* for initial alignment */ 3501 long double d; 3502 char elm[MAXSZ]; 3503 }; 3504 } *sapole, *bkpole; 3505 int cstp, cbkp; 3506 3507 void * 3508 stmtalloc(size_t size) 3509 { 3510 struct xalloc *xp; 3511 void *rv; 3512 3513 size = ROUNDUP(size); 3514 if (size > MAXSZ) 3515 cerror("stmtalloc"); 3516 if (sapole == 0 || (size + cstp) > MAXSZ) { 3517 xp = xmalloc(sizeof(struct xalloc)); 3518 xp->next = sapole; 3519 sapole = xp; 3520 cstp = 0; 3521 } 3522 rv = &sapole->elm[cstp]; 3523 cstp += size; 3524 return rv; 3525 } 3526 3527 void 3528 stmtfree(void) 3529 { 3530 extern P1ND *frelink; 3531 extern int usdnodes; 3532 struct xalloc *x1; 3533 3534 if (usdnodes != 0) 3535 cerror("stmtfree: usdnodes %d", usdnodes); 3536 frelink = NULL; 3537 3538 while (sapole) { 3539 x1 = sapole->next; 3540 free(sapole); 3541 sapole = x1; 3542 } 3543 cstp = 0; 3544 } 3545 3546 void * 3547 blkalloc(size_t size) 3548 { 3549 struct xalloc *xp; 3550 void *rv; 3551 3552 if (blevel < 2) 3553 return permalloc(size); 3554 3555 size = ROUNDUP(size); 3556 if (size > MAXSZ) 3557 cerror("blkalloc"); 3558 if (bkpole == 0 || (size + cbkp) > MAXSZ) { 3559 xp = xmalloc(sizeof(struct xalloc)); 3560 xp->next = bkpole; 3561 bkpole = xp; 3562 cbkp = 0; 3563 } 3564 rv = &bkpole->elm[cbkp]; 3565 cbkp += size; 3566 return rv; 3567 } 3568 3569 void 3570 blkfree(void) 3571 { 3572 struct xalloc *x1; 3573 3574 while (bkpole) { 3575 x1 = bkpole->next; 3576 free(bkpole); 3577 bkpole = x1; 3578 } 3579 cbkp = 0; 3580 } 3581 3582