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