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