|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char *sccsid[] = "@(#)expr.c 5.9 (Berkeley) 1/3/88"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * expr.c ! 13: * ! 14: * Routines for handling expressions, f77 compiler pass 1. ! 15: * ! 16: * University of Utah CS Dept modification history: ! 17: * ! 18: * $Log: expr.c,v $ ! 19: * Revision 5.13 86/05/07 18:54:23 donn ! 20: * Adjusted the warning for OPEQ with logical operands -- this is now printed ! 21: * in mkexpr since cktype can be called several times on the same operands ! 22: * (argh -- how slow can this compiler get?!). ! 23: * ! 24: * Revision 5.12 86/05/07 17:40:54 donn ! 25: * Make the lengths of expr nodes be copied by cpexpr and freed by frexpr. ! 26: * ! 27: * Revision 5.11 86/05/07 16:57:17 donn ! 28: * Logical data is supposed to be compared using .eqv. and .neqv., but we ! 29: * will support .eq. and .ne. with a warning. Other relational operators ! 30: * now provoke errors when used with logical operands. ! 31: * ! 32: * Revision 5.10 86/04/26 13:24:30 donn ! 33: * Someone forgot about comparisons of logical constants in consbinop() -- ! 34: * the results of such tests were garbage. ! 35: * ! 36: * Revision 5.9 86/02/20 23:38:31 donn ! 37: * Fix memory management problem with reordering of array dimension and ! 38: * substring code in mklhs(). ! 39: * ! 40: * Revision 5.8 85/12/20 21:37:58 donn ! 41: * Fix bug in mklhs() that caused the 'first character' substring parameter ! 42: * to be evaluated twice. ! 43: * ! 44: * Revision 5.7 85/12/20 19:42:05 donn ! 45: * Be more specfic -- name the offending subroutine when it's used as a ! 46: * function. ! 47: * ! 48: * Revision 5.6 85/12/19 20:08:12 donn ! 49: * Don't optimize first/last char values when they contain function calls ! 50: * or array references. ! 51: * ! 52: * Revision 5.5 85/12/19 00:35:22 donn ! 53: * Lots of changes for handling hardware errors which can crop up when ! 54: * evaluating constant expressions. ! 55: * ! 56: * Revision 5.4 85/11/25 00:23:53 donn ! 57: * 4.3 beta ! 58: * ! 59: * Revision 5.3 85/08/10 05:48:16 donn ! 60: * Fixed another of my goofs in the substring parameter conversion code. ! 61: * ! 62: * Revision 5.2 85/08/10 04:13:51 donn ! 63: * Jerry Berkman's change to call pow() directly rather than indirectly ! 64: * through pow_dd, in mkpower(). ! 65: * ! 66: * Revision 5.1 85/08/10 03:44:19 donn ! 67: * 4.3 alpha ! 68: * ! 69: * Revision 3.16 85/06/21 16:38:09 donn ! 70: * The fix to mkprim() didn't handle null substring parameters (sigh). ! 71: * ! 72: * Revision 3.15 85/06/04 04:37:03 donn ! 73: * Changed mkprim() to force substring parameters to be integral types. ! 74: * ! 75: * Revision 3.14 85/06/04 03:41:52 donn ! 76: * Change impldcl() to handle functions of type 'undefined'. ! 77: * ! 78: * Revision 3.13 85/05/06 23:14:55 donn ! 79: * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get ! 80: * a temporary when converting character strings to integers; previously we ! 81: * were having problems because mkconv() was called after tempalloc(). ! 82: * ! 83: * Revision 3.12 85/03/18 08:07:47 donn ! 84: * Fixes to help out with short integers -- if integers are by default short, ! 85: * then so are constants; and if addresses can't be stored in shorts, complain. ! 86: * ! 87: * Revision 3.11 85/03/16 22:31:27 donn ! 88: * Added hack to mkconv() to allow character values of length > 1 to be ! 89: * converted to numeric types, for Helge Skrivervik. Note that this does ! 90: * not affect use of the intrinsic ichar() conversion. ! 91: * ! 92: * Revision 3.10 85/01/15 21:06:47 donn ! 93: * Changed mkconv() to comment on implicit conversions; added intrconv() for ! 94: * use with explicit conversions by intrinsic functions. ! 95: * ! 96: * Revision 3.9 85/01/11 21:05:49 donn ! 97: * Added changes to implement SAVE statements. ! 98: * ! 99: * Revision 3.8 84/12/17 02:21:06 donn ! 100: * Added a test to prevent constant folding from being done on expressions ! 101: * whose type is not known at that point in mkexpr(). ! 102: * ! 103: * Revision 3.7 84/12/11 21:14:17 donn ! 104: * Removed obnoxious 'excess precision' warning. ! 105: * ! 106: * Revision 3.6 84/11/23 01:00:36 donn ! 107: * Added code to trim excess precision from single-precision constants, and ! 108: * to warn the user when this occurs. ! 109: * ! 110: * Revision 3.5 84/11/23 00:10:39 donn ! 111: * Changed stfcall() to remark on argument type clashes in 'calls' to ! 112: * statement functions. ! 113: * ! 114: * Revision 3.4 84/11/22 21:21:17 donn ! 115: * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics. ! 116: * ! 117: * Revision 3.3 84/11/12 18:26:14 donn ! 118: * Shuffled some code around so that the compiler remembers to free some vleng ! 119: * structures which used to just sit around. ! 120: * ! 121: * Revision 3.2 84/10/16 19:24:15 donn ! 122: * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent ! 123: * core dumps by replacing bad subscripts with good ones. ! 124: * ! 125: * Revision 3.1 84/10/13 01:31:32 donn ! 126: * Merged Jerry Berkman's version into mine. ! 127: * ! 128: * Revision 2.7 84/09/27 15:42:52 donn ! 129: * The last fix for multiplying undeclared variables by 0 isn't sufficient, ! 130: * since the type of the 0 may not be the (implicit) type of the variable. ! 131: * I added a hack to check the implicit type of implicitly declared ! 132: * variables... ! 133: * ! 134: * Revision 2.6 84/09/14 19:34:03 donn ! 135: * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert ! 136: * 0 to type UNKNOWN, which is illegal. Fix is to use native type instead. ! 137: * Not sure how correct (or important) this is... ! 138: * ! 139: * Revision 2.5 84/08/05 23:05:27 donn ! 140: * Added fixes to prevent fixexpr() from slicing and dicing complex conversions ! 141: * with two operands. ! 142: * ! 143: * Revision 2.4 84/08/05 17:34:48 donn ! 144: * Added an optimization to mklhs() to detect substrings of the form ch(i:i) ! 145: * and assign constant length 1 to them. ! 146: * ! 147: * Revision 2.3 84/07/19 19:38:33 donn ! 148: * Added a typecast to the last fix. Somehow I missed it the first time... ! 149: * ! 150: * Revision 2.2 84/07/19 17:19:57 donn ! 151: * Caused OPPAREN expressions to inherit the length of their operands, so ! 152: * that parenthesized character expressions work correctly. ! 153: * ! 154: * Revision 2.1 84/07/19 12:03:02 donn ! 155: * Changed comment headers for UofU. ! 156: * ! 157: * Revision 1.2 84/04/06 20:12:17 donn ! 158: * Fixed bug which caused programs with mixed-type multiplications involving ! 159: * the constant 0 to choke the compiler. ! 160: * ! 161: */ ! 162: ! 163: #include "defs.h" ! 164: ! 165: ! 166: /* little routines to create constant blocks */ ! 167: ! 168: Constp mkconst(t) ! 169: register int t; ! 170: { ! 171: register Constp p; ! 172: ! 173: p = ALLOC(Constblock); ! 174: p->tag = TCONST; ! 175: p->vtype = t; ! 176: return(p); ! 177: } ! 178: ! 179: ! 180: expptr mklogcon(l) ! 181: register int l; ! 182: { ! 183: register Constp p; ! 184: ! 185: p = mkconst(TYLOGICAL); ! 186: p->constant.ci = l; ! 187: return( (expptr) p ); ! 188: } ! 189: ! 190: ! 191: ! 192: expptr mkintcon(l) ! 193: ftnint l; ! 194: { ! 195: register Constp p; ! 196: int usetype; ! 197: ! 198: if(tyint == TYSHORT) ! 199: { ! 200: short s = l; ! 201: if(l != s) ! 202: usetype = TYLONG; ! 203: else ! 204: usetype = TYSHORT; ! 205: } ! 206: else ! 207: usetype = tyint; ! 208: p = mkconst(usetype); ! 209: p->constant.ci = l; ! 210: return( (expptr) p ); ! 211: } ! 212: ! 213: ! 214: ! 215: expptr mkaddcon(l) ! 216: register int l; ! 217: { ! 218: register Constp p; ! 219: ! 220: p = mkconst(TYADDR); ! 221: p->constant.ci = l; ! 222: return( (expptr) p ); ! 223: } ! 224: ! 225: ! 226: ! 227: expptr mkrealcon(t, d) ! 228: register int t; ! 229: double d; ! 230: { ! 231: register Constp p; ! 232: ! 233: if(t == TYREAL) ! 234: { ! 235: float f = d; ! 236: if(f != d) ! 237: { ! 238: #ifdef notdef ! 239: warn("excess precision in real constant lost"); ! 240: #endif notdef ! 241: d = f; ! 242: } ! 243: } ! 244: p = mkconst(t); ! 245: p->constant.cd[0] = d; ! 246: return( (expptr) p ); ! 247: } ! 248: ! 249: ! 250: expptr mkbitcon(shift, leng, s) ! 251: int shift; ! 252: register int leng; ! 253: register char *s; ! 254: { ! 255: Constp p; ! 256: register int i, j, k; ! 257: register char *bp; ! 258: int size; ! 259: ! 260: size = (shift*leng + BYTESIZE -1)/BYTESIZE; ! 261: bp = (char *) ckalloc(size); ! 262: ! 263: i = 0; ! 264: ! 265: #if (TARGET == PDP11 || TARGET == VAX) ! 266: j = 0; ! 267: #else ! 268: j = size; ! 269: #endif ! 270: ! 271: k = 0; ! 272: ! 273: while (leng > 0) ! 274: { ! 275: k |= (hextoi(s[--leng]) << i); ! 276: i += shift; ! 277: if (i >= BYTESIZE) ! 278: { ! 279: #if (TARGET == PDP11 || TARGET == VAX) ! 280: bp[j++] = k & MAXBYTE; ! 281: #else ! 282: bp[--j] = k & MAXBYTE; ! 283: #endif ! 284: k = k >> BYTESIZE; ! 285: i -= BYTESIZE; ! 286: } ! 287: } ! 288: ! 289: if (k != 0) ! 290: #if (TARGET == PDP11 || TARGET == VAX) ! 291: bp[j++] = k; ! 292: #else ! 293: bp[--j] = k; ! 294: #endif ! 295: ! 296: p = mkconst(TYBITSTR); ! 297: p->vleng = ICON(size); ! 298: p->constant.ccp = bp; ! 299: ! 300: return ((expptr) p); ! 301: } ! 302: ! 303: ! 304: ! 305: expptr mkstrcon(l,v) ! 306: int l; ! 307: register char *v; ! 308: { ! 309: register Constp p; ! 310: register char *s; ! 311: ! 312: p = mkconst(TYCHAR); ! 313: p->vleng = ICON(l); ! 314: p->constant.ccp = s = (char *) ckalloc(l); ! 315: while(--l >= 0) ! 316: *s++ = *v++; ! 317: return( (expptr) p ); ! 318: } ! 319: ! 320: ! 321: expptr mkcxcon(realp,imagp) ! 322: register expptr realp, imagp; ! 323: { ! 324: int rtype, itype; ! 325: register Constp p; ! 326: ! 327: rtype = realp->headblock.vtype; ! 328: itype = imagp->headblock.vtype; ! 329: ! 330: if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) ) ! 331: { ! 332: p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX); ! 333: if( ISINT(rtype) ) ! 334: p->constant.cd[0] = realp->constblock.constant.ci; ! 335: else p->constant.cd[0] = realp->constblock.constant.cd[0]; ! 336: if( ISINT(itype) ) ! 337: p->constant.cd[1] = imagp->constblock.constant.ci; ! 338: else p->constant.cd[1] = imagp->constblock.constant.cd[0]; ! 339: } ! 340: else ! 341: { ! 342: err("invalid complex constant"); ! 343: p = (Constp) errnode(); ! 344: } ! 345: ! 346: frexpr(realp); ! 347: frexpr(imagp); ! 348: return( (expptr) p ); ! 349: } ! 350: ! 351: ! 352: expptr errnode() ! 353: { ! 354: struct Errorblock *p; ! 355: p = ALLOC(Errorblock); ! 356: p->tag = TERROR; ! 357: p->vtype = TYERROR; ! 358: return( (expptr) p ); ! 359: } ! 360: ! 361: ! 362: ! 363: ! 364: ! 365: expptr mkconv(t, p) ! 366: register int t; ! 367: register expptr p; ! 368: { ! 369: register expptr q; ! 370: Addrp r, s; ! 371: register int pt; ! 372: expptr opconv(); ! 373: ! 374: if(t==TYUNKNOWN || t==TYERROR) ! 375: badtype("mkconv", t); ! 376: pt = p->headblock.vtype; ! 377: if(t == pt) ! 378: return(p); ! 379: ! 380: if( pt == TYCHAR && ISNUMERIC(t) ) ! 381: { ! 382: warn("implicit conversion of character to numeric type"); ! 383: ! 384: /* ! 385: * Ugly kluge to copy character values into numerics. ! 386: */ ! 387: s = mkaltemp(t, ENULL); ! 388: r = (Addrp) cpexpr(s); ! 389: r->vtype = TYCHAR; ! 390: r->varleng = typesize[t]; ! 391: r->vleng = mkintcon(r->varleng); ! 392: q = mkexpr(OPASSIGN, r, p); ! 393: q = mkexpr(OPCOMMA, q, s); ! 394: return(q); ! 395: } ! 396: ! 397: #if SZADDR > SZSHORT ! 398: if( pt == TYADDR && t == TYSHORT) ! 399: { ! 400: err("insufficient precision to hold address type"); ! 401: return( errnode() ); ! 402: } ! 403: #endif ! 404: if( pt == TYADDR && ISNUMERIC(t) ) ! 405: warn("implicit conversion of address to numeric type"); ! 406: ! 407: if( ISCONST(p) && pt!=TYADDR) ! 408: { ! 409: q = (expptr) mkconst(t); ! 410: consconv(t, &(q->constblock.constant), ! 411: p->constblock.vtype, &(p->constblock.constant) ); ! 412: frexpr(p); ! 413: } ! 414: #if TARGET == PDP11 ! 415: else if(ISINT(t) && pt==TYCHAR) ! 416: { ! 417: q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255)); ! 418: if(t == TYLONG) ! 419: q = opconv(q, TYLONG); ! 420: } ! 421: #endif ! 422: else ! 423: q = opconv(p, t); ! 424: ! 425: if(t == TYCHAR) ! 426: q->constblock.vleng = ICON(1); ! 427: return(q); ! 428: } ! 429: ! 430: ! 431: ! 432: /* intrinsic conversions */ ! 433: expptr intrconv(t, p) ! 434: register int t; ! 435: register expptr p; ! 436: { ! 437: register expptr q; ! 438: register int pt; ! 439: expptr opconv(); ! 440: ! 441: if(t==TYUNKNOWN || t==TYERROR) ! 442: badtype("intrconv", t); ! 443: pt = p->headblock.vtype; ! 444: if(t == pt) ! 445: return(p); ! 446: ! 447: else if( ISCONST(p) && pt!=TYADDR) ! 448: { ! 449: q = (expptr) mkconst(t); ! 450: consconv(t, &(q->constblock.constant), ! 451: p->constblock.vtype, &(p->constblock.constant) ); ! 452: frexpr(p); ! 453: } ! 454: #if TARGET == PDP11 ! 455: else if(ISINT(t) && pt==TYCHAR) ! 456: { ! 457: q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255)); ! 458: if(t == TYLONG) ! 459: q = opconv(q, TYLONG); ! 460: } ! 461: #endif ! 462: else ! 463: q = opconv(p, t); ! 464: ! 465: if(t == TYCHAR) ! 466: q->constblock.vleng = ICON(1); ! 467: return(q); ! 468: } ! 469: ! 470: ! 471: ! 472: expptr opconv(p, t) ! 473: expptr p; ! 474: int t; ! 475: { ! 476: register expptr q; ! 477: ! 478: q = mkexpr(OPCONV, p, PNULL); ! 479: q->headblock.vtype = t; ! 480: return(q); ! 481: } ! 482: ! 483: ! 484: ! 485: expptr addrof(p) ! 486: expptr p; ! 487: { ! 488: return( mkexpr(OPADDR, p, PNULL) ); ! 489: } ! 490: ! 491: ! 492: ! 493: tagptr cpexpr(p) ! 494: register tagptr p; ! 495: { ! 496: register tagptr e; ! 497: int tag; ! 498: register chainp ep, pp; ! 499: tagptr cpblock(); ! 500: ! 501: static int blksize[ ] = ! 502: { 0, ! 503: sizeof(struct Nameblock), ! 504: sizeof(struct Constblock), ! 505: sizeof(struct Exprblock), ! 506: sizeof(struct Addrblock), ! 507: sizeof(struct Tempblock), ! 508: sizeof(struct Primblock), ! 509: sizeof(struct Listblock), ! 510: sizeof(struct Errorblock) ! 511: }; ! 512: ! 513: if(p == NULL) ! 514: return(NULL); ! 515: ! 516: if( (tag = p->tag) == TNAME) ! 517: return(p); ! 518: ! 519: e = cpblock( blksize[p->tag] , p); ! 520: ! 521: switch(tag) ! 522: { ! 523: case TCONST: ! 524: if(e->constblock.vtype == TYCHAR) ! 525: { ! 526: e->constblock.constant.ccp = ! 527: copyn(1+strlen(e->constblock.constant.ccp), ! 528: e->constblock.constant.ccp); ! 529: e->constblock.vleng = ! 530: (expptr) cpexpr(e->constblock.vleng); ! 531: } ! 532: case TERROR: ! 533: break; ! 534: ! 535: case TEXPR: ! 536: e->exprblock.leftp = (expptr) cpexpr(p->exprblock.leftp); ! 537: e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp); ! 538: e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng); ! 539: break; ! 540: ! 541: case TLIST: ! 542: if(pp = p->listblock.listp) ! 543: { ! 544: ep = e->listblock.listp = ! 545: mkchain( cpexpr(pp->datap), CHNULL); ! 546: for(pp = pp->nextp ; pp ; pp = pp->nextp) ! 547: ep = ep->nextp = ! 548: mkchain( cpexpr(pp->datap), CHNULL); ! 549: } ! 550: break; ! 551: ! 552: case TADDR: ! 553: e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng); ! 554: e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset); ! 555: e->addrblock.istemp = NO; ! 556: break; ! 557: ! 558: case TTEMP: ! 559: e->tempblock.vleng = (expptr) cpexpr(e->tempblock.vleng); ! 560: e->tempblock.istemp = NO; ! 561: break; ! 562: ! 563: case TPRIM: ! 564: e->primblock.argsp = (struct Listblock *) ! 565: cpexpr(e->primblock.argsp); ! 566: e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp); ! 567: e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp); ! 568: break; ! 569: ! 570: default: ! 571: badtag("cpexpr", tag); ! 572: } ! 573: ! 574: return(e); ! 575: } ! 576: ! 577: frexpr(p) ! 578: register tagptr p; ! 579: { ! 580: register chainp q; ! 581: ! 582: if(p == NULL) ! 583: return; ! 584: ! 585: switch(p->tag) ! 586: { ! 587: case TCONST: ! 588: switch (p->constblock.vtype) ! 589: { ! 590: case TYBITSTR: ! 591: case TYCHAR: ! 592: case TYHOLLERITH: ! 593: free( (charptr) (p->constblock.constant.ccp) ); ! 594: frexpr(p->constblock.vleng); ! 595: } ! 596: break; ! 597: ! 598: case TADDR: ! 599: if (!optimflag && p->addrblock.istemp) ! 600: { ! 601: frtemp(p); ! 602: return; ! 603: } ! 604: frexpr(p->addrblock.vleng); ! 605: frexpr(p->addrblock.memoffset); ! 606: break; ! 607: ! 608: case TTEMP: ! 609: frexpr(p->tempblock.vleng); ! 610: break; ! 611: ! 612: case TERROR: ! 613: break; ! 614: ! 615: case TNAME: ! 616: return; ! 617: ! 618: case TPRIM: ! 619: frexpr(p->primblock.argsp); ! 620: frexpr(p->primblock.fcharp); ! 621: frexpr(p->primblock.lcharp); ! 622: break; ! 623: ! 624: case TEXPR: ! 625: frexpr(p->exprblock.leftp); ! 626: if(p->exprblock.rightp) ! 627: frexpr(p->exprblock.rightp); ! 628: if(p->exprblock.vleng) ! 629: frexpr(p->exprblock.vleng); ! 630: break; ! 631: ! 632: case TLIST: ! 633: for(q = p->listblock.listp ; q ; q = q->nextp) ! 634: frexpr(q->datap); ! 635: frchain( &(p->listblock.listp) ); ! 636: break; ! 637: ! 638: default: ! 639: badtag("frexpr", p->tag); ! 640: } ! 641: ! 642: free( (charptr) p ); ! 643: } ! 644: ! 645: /* fix up types in expression; replace subtrees and convert ! 646: names to address blocks */ ! 647: ! 648: expptr fixtype(p) ! 649: register tagptr p; ! 650: { ! 651: ! 652: if(p == 0) ! 653: return(0); ! 654: ! 655: switch(p->tag) ! 656: { ! 657: case TCONST: ! 658: return( (expptr) p ); ! 659: ! 660: case TADDR: ! 661: p->addrblock.memoffset = fixtype(p->addrblock.memoffset); ! 662: return( (expptr) p); ! 663: ! 664: case TTEMP: ! 665: return( (expptr) p); ! 666: ! 667: case TERROR: ! 668: return( (expptr) p); ! 669: ! 670: default: ! 671: badtag("fixtype", p->tag); ! 672: ! 673: case TEXPR: ! 674: return( fixexpr(p) ); ! 675: ! 676: case TLIST: ! 677: return( (expptr) p ); ! 678: ! 679: case TPRIM: ! 680: if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR) ! 681: { ! 682: if(p->primblock.namep->vtype == TYSUBR) ! 683: { ! 684: dclerr("function invocation of subroutine", ! 685: p->primblock.namep); ! 686: return( errnode() ); ! 687: } ! 688: else ! 689: return( mkfunct(p) ); ! 690: } ! 691: else return( mklhs(p) ); ! 692: } ! 693: } ! 694: ! 695: ! 696: ! 697: ! 698: ! 699: /* special case tree transformations and cleanups of expression trees */ ! 700: ! 701: expptr fixexpr(p) ! 702: register Exprp p; ! 703: { ! 704: expptr lp; ! 705: register expptr rp; ! 706: register expptr q; ! 707: int opcode, ltype, rtype, ptype, mtype; ! 708: expptr lconst, rconst; ! 709: expptr mkpower(); ! 710: ! 711: if( ISERROR(p) ) ! 712: return( (expptr) p ); ! 713: else if(p->tag != TEXPR) ! 714: badtag("fixexpr", p->tag); ! 715: opcode = p->opcode; ! 716: if (ISCONST(p->leftp)) ! 717: lconst = (expptr) cpexpr(p->leftp); ! 718: else ! 719: lconst = NULL; ! 720: if (p->rightp && ISCONST(p->rightp)) ! 721: rconst = (expptr) cpexpr(p->rightp); ! 722: else ! 723: rconst = NULL; ! 724: lp = p->leftp = fixtype(p->leftp); ! 725: ltype = lp->headblock.vtype; ! 726: if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP) ! 727: { ! 728: err("left side of assignment must be variable"); ! 729: frexpr(p); ! 730: return( errnode() ); ! 731: } ! 732: ! 733: if(p->rightp) ! 734: { ! 735: rp = p->rightp = fixtype(p->rightp); ! 736: rtype = rp->headblock.vtype; ! 737: } ! 738: else ! 739: { ! 740: rp = NULL; ! 741: rtype = 0; ! 742: } ! 743: ! 744: if(ltype==TYERROR || rtype==TYERROR) ! 745: { ! 746: frexpr(p); ! 747: frexpr(lconst); ! 748: frexpr(rconst); ! 749: return( errnode() ); ! 750: } ! 751: ! 752: /* force folding if possible */ ! 753: if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) ) ! 754: { ! 755: q = mkexpr(opcode, lp, rp); ! 756: if( ISCONST(q) ) ! 757: { ! 758: frexpr(lconst); ! 759: frexpr(rconst); ! 760: return(q); ! 761: } ! 762: free( (charptr) q ); /* constants did not fold */ ! 763: } ! 764: ! 765: if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR) ! 766: { ! 767: frexpr(p); ! 768: frexpr(lconst); ! 769: frexpr(rconst); ! 770: return( errnode() ); ! 771: } ! 772: ! 773: switch(opcode) ! 774: { ! 775: case OPCONCAT: ! 776: if(p->vleng == NULL) ! 777: p->vleng = mkexpr(OPPLUS, ! 778: cpexpr(lp->headblock.vleng), ! 779: cpexpr(rp->headblock.vleng) ); ! 780: break; ! 781: ! 782: case OPASSIGN: ! 783: case OPPLUSEQ: ! 784: case OPSTAREQ: ! 785: if(ltype == rtype) ! 786: break; ! 787: if( ! rconst && ISREAL(ltype) && ISREAL(rtype) ) ! 788: break; ! 789: if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) ) ! 790: break; ! 791: if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT) ! 792: #if FAMILY==PCC ! 793: && typesize[ltype]>=typesize[rtype] ) ! 794: #else ! 795: && typesize[ltype]==typesize[rtype] ) ! 796: #endif ! 797: break; ! 798: if (rconst) ! 799: { ! 800: p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) ); ! 801: frexpr(rp); ! 802: } ! 803: else ! 804: p->rightp = fixtype(mkconv(ptype, rp)); ! 805: break; ! 806: ! 807: case OPSLASH: ! 808: if( ISCOMPLEX(rtype) ) ! 809: { ! 810: p = (Exprp) call2(ptype, ! 811: ptype==TYCOMPLEX? "c_div" : "z_div", ! 812: mkconv(ptype, lp), mkconv(ptype, rp) ); ! 813: break; ! 814: } ! 815: case OPPLUS: ! 816: case OPMINUS: ! 817: case OPSTAR: ! 818: case OPMOD: ! 819: if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) || ! 820: (rtype==TYREAL && ! rconst ) )) ! 821: break; ! 822: if( ISCOMPLEX(ptype) ) ! 823: break; ! 824: if(ltype != ptype) ! 825: if (lconst) ! 826: { ! 827: p->leftp = fixtype(mkconv(ptype, ! 828: cpexpr(lconst))); ! 829: frexpr(lp); ! 830: } ! 831: else ! 832: p->leftp = fixtype(mkconv(ptype,lp)); ! 833: if(rtype != ptype) ! 834: if (rconst) ! 835: { ! 836: p->rightp = fixtype(mkconv(ptype, ! 837: cpexpr(rconst))); ! 838: frexpr(rp); ! 839: } ! 840: else ! 841: p->rightp = fixtype(mkconv(ptype,rp)); ! 842: break; ! 843: ! 844: case OPPOWER: ! 845: return( mkpower(p) ); ! 846: ! 847: case OPLT: ! 848: case OPLE: ! 849: case OPGT: ! 850: case OPGE: ! 851: case OPEQ: ! 852: case OPNE: ! 853: if(ltype == rtype) ! 854: break; ! 855: mtype = cktype(OPMINUS, ltype, rtype); ! 856: if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) || ! 857: (rtype==TYREAL && ! rconst) )) ! 858: break; ! 859: if( ISCOMPLEX(mtype) ) ! 860: break; ! 861: if(ltype != mtype) ! 862: if (lconst) ! 863: { ! 864: p->leftp = fixtype(mkconv(mtype, ! 865: cpexpr(lconst))); ! 866: frexpr(lp); ! 867: } ! 868: else ! 869: p->leftp = fixtype(mkconv(mtype,lp)); ! 870: if(rtype != mtype) ! 871: if (rconst) ! 872: { ! 873: p->rightp = fixtype(mkconv(mtype, ! 874: cpexpr(rconst))); ! 875: frexpr(rp); ! 876: } ! 877: else ! 878: p->rightp = fixtype(mkconv(mtype,rp)); ! 879: break; ! 880: ! 881: ! 882: case OPCONV: ! 883: if(ISCOMPLEX(p->vtype)) ! 884: { ! 885: ptype = cktype(OPCONV, p->vtype, ltype); ! 886: if(p->rightp) ! 887: ptype = cktype(OPCONV, ptype, rtype); ! 888: break; ! 889: } ! 890: ptype = cktype(OPCONV, p->vtype, ltype); ! 891: if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA) ! 892: { ! 893: lp->exprblock.rightp = ! 894: fixtype( mkconv(ptype, lp->exprblock.rightp) ); ! 895: free( (charptr) p ); ! 896: p = (Exprp) lp; ! 897: } ! 898: break; ! 899: ! 900: case OPADDR: ! 901: if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR) ! 902: fatal("addr of addr"); ! 903: break; ! 904: ! 905: case OPCOMMA: ! 906: case OPQUEST: ! 907: case OPCOLON: ! 908: break; ! 909: ! 910: case OPPAREN: ! 911: p->vleng = (expptr) cpexpr( lp->headblock.vleng ); ! 912: break; ! 913: ! 914: case OPMIN: ! 915: case OPMAX: ! 916: ptype = p->vtype; ! 917: break; ! 918: ! 919: default: ! 920: break; ! 921: } ! 922: ! 923: p->vtype = ptype; ! 924: frexpr(lconst); ! 925: frexpr(rconst); ! 926: return((expptr) p); ! 927: } ! 928: ! 929: #if SZINT < SZLONG ! 930: /* ! 931: for efficient subscripting, replace long ints by shorts ! 932: in easy places ! 933: */ ! 934: ! 935: expptr shorten(p) ! 936: register expptr p; ! 937: { ! 938: register expptr q; ! 939: ! 940: if(p->headblock.vtype != TYLONG) ! 941: return(p); ! 942: ! 943: switch(p->tag) ! 944: { ! 945: case TERROR: ! 946: case TLIST: ! 947: return(p); ! 948: ! 949: case TCONST: ! 950: case TADDR: ! 951: return( mkconv(TYINT,p) ); ! 952: ! 953: case TEXPR: ! 954: break; ! 955: ! 956: default: ! 957: badtag("shorten", p->tag); ! 958: } ! 959: ! 960: switch(p->exprblock.opcode) ! 961: { ! 962: case OPPLUS: ! 963: case OPMINUS: ! 964: case OPSTAR: ! 965: q = shorten( cpexpr(p->exprblock.rightp) ); ! 966: if(q->headblock.vtype == TYINT) ! 967: { ! 968: p->exprblock.leftp = shorten(p->exprblock.leftp); ! 969: if(p->exprblock.leftp->headblock.vtype == TYLONG) ! 970: frexpr(q); ! 971: else ! 972: { ! 973: frexpr(p->exprblock.rightp); ! 974: p->exprblock.rightp = q; ! 975: p->exprblock.vtype = TYINT; ! 976: } ! 977: } ! 978: break; ! 979: ! 980: case OPNEG: ! 981: case OPPAREN: ! 982: p->exprblock.leftp = shorten(p->exprblock.leftp); ! 983: if(p->exprblock.leftp->headblock.vtype == TYINT) ! 984: p->exprblock.vtype = TYINT; ! 985: break; ! 986: ! 987: case OPCALL: ! 988: case OPCCALL: ! 989: p = mkconv(TYINT,p); ! 990: break; ! 991: default: ! 992: break; ! 993: } ! 994: ! 995: return(p); ! 996: } ! 997: #endif ! 998: ! 999: /* fix an argument list, taking due care for special first level cases */ ! 1000: ! 1001: fixargs(doput, p0) ! 1002: int doput; /* doput is true if the function is not intrinsic; ! 1003: was used to decide whether to do a putconst, ! 1004: but this is no longer done here (Feb82)*/ ! 1005: struct Listblock *p0; ! 1006: { ! 1007: register chainp p; ! 1008: register tagptr q, t; ! 1009: register int qtag; ! 1010: int nargs; ! 1011: Addrp mkscalar(); ! 1012: ! 1013: nargs = 0; ! 1014: if(p0) ! 1015: for(p = p0->listp ; p ; p = p->nextp) ! 1016: { ! 1017: ++nargs; ! 1018: q = p->datap; ! 1019: qtag = q->tag; ! 1020: if(qtag == TCONST) ! 1021: { ! 1022: if(q->constblock.vtype == TYSHORT) ! 1023: q = (tagptr) mkconv(tyint, q); ! 1024: p->datap = q ; ! 1025: } ! 1026: else if(qtag==TPRIM && q->primblock.argsp==0 && ! 1027: q->primblock.namep->vclass==CLPROC) ! 1028: p->datap = (tagptr) mkaddr(q->primblock.namep); ! 1029: else if(qtag==TPRIM && q->primblock.argsp==0 && ! 1030: q->primblock.namep->vdim!=NULL) ! 1031: p->datap = (tagptr) mkscalar(q->primblock.namep); ! 1032: else if(qtag==TPRIM && q->primblock.argsp==0 && ! 1033: q->primblock.namep->vdovar && ! 1034: (t = (tagptr) memversion(q->primblock.namep)) ) ! 1035: p->datap = (tagptr) fixtype(t); ! 1036: else ! 1037: p->datap = (tagptr) fixtype(q); ! 1038: } ! 1039: return(nargs); ! 1040: } ! 1041: ! 1042: ! 1043: Addrp mkscalar(np) ! 1044: register Namep np; ! 1045: { ! 1046: register Addrp ap; ! 1047: ! 1048: vardcl(np); ! 1049: ap = mkaddr(np); ! 1050: ! 1051: #if TARGET == VAX ! 1052: /* on the VAX, prolog causes array arguments ! 1053: to point at the (0,...,0) element, except when ! 1054: subscript checking is on ! 1055: */ ! 1056: #ifdef SDB ! 1057: if( !checksubs && !sdbflag && np->vstg==STGARG) ! 1058: #else ! 1059: if( !checksubs && np->vstg==STGARG) ! 1060: #endif ! 1061: { ! 1062: register struct Dimblock *dp; ! 1063: dp = np->vdim; ! 1064: frexpr(ap->memoffset); ! 1065: ap->memoffset = mkexpr(OPSTAR, ! 1066: (np->vtype==TYCHAR ? ! 1067: cpexpr(np->vleng) : ! 1068: (tagptr)ICON(typesize[np->vtype]) ), ! 1069: cpexpr(dp->baseoffset) ); ! 1070: } ! 1071: #endif ! 1072: return(ap); ! 1073: } ! 1074: ! 1075: ! 1076: ! 1077: ! 1078: ! 1079: expptr mkfunct(p) ! 1080: register struct Primblock *p; ! 1081: { ! 1082: struct Entrypoint *ep; ! 1083: Addrp ap; ! 1084: struct Extsym *extp; ! 1085: register Namep np; ! 1086: register expptr q; ! 1087: expptr intrcall(), stfcall(); ! 1088: int k, nargs; ! 1089: int class; ! 1090: ! 1091: if(p->tag != TPRIM) ! 1092: return( errnode() ); ! 1093: ! 1094: np = p->namep; ! 1095: class = np->vclass; ! 1096: ! 1097: if(class == CLUNKNOWN) ! 1098: { ! 1099: np->vclass = class = CLPROC; ! 1100: if(np->vstg == STGUNKNOWN) ! 1101: { ! 1102: if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) ) ! 1103: { ! 1104: np->vstg = STGINTR; ! 1105: np->vardesc.varno = k; ! 1106: np->vprocclass = PINTRINSIC; ! 1107: } ! 1108: else ! 1109: { ! 1110: extp = mkext( varunder(VL,np->varname) ); ! 1111: extp->extstg = STGEXT; ! 1112: np->vstg = STGEXT; ! 1113: np->vardesc.varno = extp - extsymtab; ! 1114: np->vprocclass = PEXTERNAL; ! 1115: } ! 1116: } ! 1117: else if(np->vstg==STGARG) ! 1118: { ! 1119: if(np->vtype!=TYCHAR && !ftn66flag) ! 1120: warn("Dummy procedure not declared EXTERNAL. Code may be wrong."); ! 1121: np->vprocclass = PEXTERNAL; ! 1122: } ! 1123: } ! 1124: ! 1125: if(class != CLPROC) ! 1126: fatali("invalid class code %d for function", class); ! 1127: if(p->fcharp || p->lcharp) ! 1128: { ! 1129: err("no substring of function call"); ! 1130: goto error; ! 1131: } ! 1132: impldcl(np); ! 1133: nargs = fixargs( np->vprocclass!=PINTRINSIC, p->argsp); ! 1134: ! 1135: switch(np->vprocclass) ! 1136: { ! 1137: case PEXTERNAL: ! 1138: ap = mkaddr(np); ! 1139: call: ! 1140: q = mkexpr(OPCALL, ap, p->argsp); ! 1141: if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN) ! 1142: { ! 1143: err("attempt to use untyped function"); ! 1144: goto error; ! 1145: } ! 1146: if(np->vleng) ! 1147: q->exprblock.vleng = (expptr) cpexpr(np->vleng); ! 1148: break; ! 1149: ! 1150: case PINTRINSIC: ! 1151: q = intrcall(np, p->argsp, nargs); ! 1152: break; ! 1153: ! 1154: case PSTFUNCT: ! 1155: q = stfcall(np, p->argsp); ! 1156: break; ! 1157: ! 1158: case PTHISPROC: ! 1159: warn("recursive call"); ! 1160: for(ep = entries ; ep ; ep = ep->entnextp) ! 1161: if(ep->enamep == np) ! 1162: break; ! 1163: if(ep == NULL) ! 1164: fatal("mkfunct: impossible recursion"); ! 1165: ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) ); ! 1166: goto call; ! 1167: ! 1168: default: ! 1169: fatali("mkfunct: impossible vprocclass %d", ! 1170: (int) (np->vprocclass) ); ! 1171: } ! 1172: free( (charptr) p ); ! 1173: return(q); ! 1174: ! 1175: error: ! 1176: frexpr(p); ! 1177: return( errnode() ); ! 1178: } ! 1179: ! 1180: ! 1181: ! 1182: LOCAL expptr stfcall(np, actlist) ! 1183: Namep np; ! 1184: struct Listblock *actlist; ! 1185: { ! 1186: register chainp actuals; ! 1187: int nargs; ! 1188: chainp oactp, formals; ! 1189: int type; ! 1190: expptr q, rhs, ap; ! 1191: Namep tnp; ! 1192: register struct Rplblock *rp; ! 1193: struct Rplblock *tlist; ! 1194: ! 1195: if(actlist) ! 1196: { ! 1197: actuals = actlist->listp; ! 1198: free( (charptr) actlist); ! 1199: } ! 1200: else ! 1201: actuals = NULL; ! 1202: oactp = actuals; ! 1203: ! 1204: nargs = 0; ! 1205: tlist = NULL; ! 1206: if( (type = np->vtype) == TYUNKNOWN) ! 1207: { ! 1208: err("attempt to use untyped statement function"); ! 1209: q = errnode(); ! 1210: goto ret; ! 1211: } ! 1212: formals = (chainp) (np->varxptr.vstfdesc->datap); ! 1213: rhs = (expptr) (np->varxptr.vstfdesc->nextp); ! 1214: ! 1215: /* copy actual arguments into temporaries */ ! 1216: while(actuals!=NULL && formals!=NULL) ! 1217: { ! 1218: rp = ALLOC(Rplblock); ! 1219: rp->rplnp = tnp = (Namep) (formals->datap); ! 1220: ap = fixtype(actuals->datap); ! 1221: if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR ! 1222: && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) ) ! 1223: { ! 1224: rp->rplvp = (expptr) ap; ! 1225: rp->rplxp = NULL; ! 1226: rp->rpltag = ap->tag; ! 1227: } ! 1228: else { ! 1229: rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng); ! 1230: rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) ); ! 1231: if( (rp->rpltag = rp->rplxp->tag) == TERROR) ! 1232: err("disagreement of argument types in statement function call"); ! 1233: else if(tnp->vtype!=ap->headblock.vtype) ! 1234: warn("argument type mismatch in statement function"); ! 1235: } ! 1236: rp->rplnextp = tlist; ! 1237: tlist = rp; ! 1238: actuals = actuals->nextp; ! 1239: formals = formals->nextp; ! 1240: ++nargs; ! 1241: } ! 1242: ! 1243: if(actuals!=NULL || formals!=NULL) ! 1244: err("statement function definition and argument list differ"); ! 1245: ! 1246: /* ! 1247: now push down names involved in formal argument list, then ! 1248: evaluate rhs of statement function definition in this environment ! 1249: */ ! 1250: ! 1251: if(tlist) /* put tlist in front of the rpllist */ ! 1252: { ! 1253: for(rp = tlist; rp->rplnextp; rp = rp->rplnextp) ! 1254: ; ! 1255: rp->rplnextp = rpllist; ! 1256: rpllist = tlist; ! 1257: } ! 1258: ! 1259: q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) ); ! 1260: ! 1261: /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */ ! 1262: while(--nargs >= 0) ! 1263: { ! 1264: if(rpllist->rplxp) ! 1265: q = mkexpr(OPCOMMA, rpllist->rplxp, q); ! 1266: rp = rpllist->rplnextp; ! 1267: frexpr(rpllist->rplvp); ! 1268: free(rpllist); ! 1269: rpllist = rp; ! 1270: } ! 1271: ! 1272: ret: ! 1273: frchain( &oactp ); ! 1274: return(q); ! 1275: } ! 1276: ! 1277: ! 1278: ! 1279: ! 1280: Addrp mkplace(np) ! 1281: register Namep np; ! 1282: { ! 1283: register Addrp s; ! 1284: register struct Rplblock *rp; ! 1285: int regn; ! 1286: ! 1287: /* is name on the replace list? */ ! 1288: ! 1289: for(rp = rpllist ; rp ; rp = rp->rplnextp) ! 1290: { ! 1291: if(np == rp->rplnp) ! 1292: { ! 1293: if(rp->rpltag == TNAME) ! 1294: { ! 1295: np = (Namep) (rp->rplvp); ! 1296: break; ! 1297: } ! 1298: else return( (Addrp) cpexpr(rp->rplvp) ); ! 1299: } ! 1300: } ! 1301: ! 1302: /* is variable a DO index in a register ? */ ! 1303: ! 1304: if(np->vdovar && ( (regn = inregister(np)) >= 0) ) ! 1305: if(np->vtype == TYERROR) ! 1306: return( (Addrp) errnode() ); ! 1307: else ! 1308: { ! 1309: s = ALLOC(Addrblock); ! 1310: s->tag = TADDR; ! 1311: s->vstg = STGREG; ! 1312: s->vtype = TYIREG; ! 1313: s->issaved = np->vsave; ! 1314: s->memno = regn; ! 1315: s->memoffset = ICON(0); ! 1316: return(s); ! 1317: } ! 1318: ! 1319: vardcl(np); ! 1320: return(mkaddr(np)); ! 1321: } ! 1322: ! 1323: ! 1324: ! 1325: ! 1326: expptr mklhs(p) ! 1327: register struct Primblock *p; ! 1328: { ! 1329: expptr suboffset(); ! 1330: expptr ep = ENULL; ! 1331: register Addrp s; ! 1332: Namep np; ! 1333: ! 1334: if(p->tag != TPRIM) ! 1335: return( (expptr) p ); ! 1336: np = p->namep; ! 1337: ! 1338: s = mkplace(np); ! 1339: if(s->tag!=TADDR || s->vstg==STGREG) ! 1340: { ! 1341: free( (charptr) p ); ! 1342: return( (expptr) s ); ! 1343: } ! 1344: ! 1345: /* do the substring part */ ! 1346: ! 1347: if(p->fcharp || p->lcharp) ! 1348: { ! 1349: if(np->vtype != TYCHAR) ! 1350: errstr("substring of noncharacter %s", varstr(VL,np->varname)); ! 1351: else { ! 1352: if(p->lcharp == NULL) ! 1353: p->lcharp = (expptr) cpexpr(s->vleng); ! 1354: frexpr(s->vleng); ! 1355: if(p->fcharp) ! 1356: { ! 1357: if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM ! 1358: && p->fcharp->primblock.namep == p->lcharp->primblock.namep ! 1359: && p->fcharp->primblock.argsp == NULL ! 1360: && p->lcharp->primblock.argsp == NULL) ! 1361: /* A trivial optimization -- upper == lower */ ! 1362: s->vleng = ICON(1); ! 1363: else ! 1364: { ! 1365: if(p->fcharp->tag == TEXPR ! 1366: || (p->fcharp->tag == TPRIM ! 1367: && p->fcharp->primblock.argsp != NULL)) ! 1368: { ! 1369: ep = fixtype(cpexpr(p->fcharp)); ! 1370: p->fcharp = (expptr) mktemp(ep->headblock.vtype, ENULL); ! 1371: } ! 1372: s->vleng = mkexpr(OPMINUS, p->lcharp, ! 1373: mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) )); ! 1374: } ! 1375: } ! 1376: else ! 1377: s->vleng = p->lcharp; ! 1378: } ! 1379: } ! 1380: ! 1381: /* compute the address modified by subscripts */ ! 1382: ! 1383: s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) ); ! 1384: frexpr(p->argsp); ! 1385: p->argsp = NULL; ! 1386: ! 1387: s->vleng = fixtype( s->vleng ); ! 1388: s->memoffset = fixtype( s->memoffset ); ! 1389: if(ep) ! 1390: /* this code depends on memoffset being evaluated before vleng */ ! 1391: s->memoffset = mkexpr(OPCOMMA, mkexpr(OPASSIGN, cpexpr(p->fcharp), ep), s->memoffset); ! 1392: frexpr(p->fcharp); ! 1393: free( (charptr) p ); ! 1394: return( (expptr) s ); ! 1395: } ! 1396: ! 1397: ! 1398: ! 1399: ! 1400: ! 1401: deregister(np) ! 1402: Namep np; ! 1403: { ! 1404: if(nregvar>0 && regnamep[nregvar-1]==np) ! 1405: { ! 1406: --nregvar; ! 1407: #if FAMILY == DMR ! 1408: putnreg(); ! 1409: #endif ! 1410: } ! 1411: } ! 1412: ! 1413: ! 1414: ! 1415: ! 1416: Addrp memversion(np) ! 1417: register Namep np; ! 1418: { ! 1419: register Addrp s; ! 1420: ! 1421: if(np->vdovar==NO || (inregister(np)<0) ) ! 1422: return(NULL); ! 1423: np->vdovar = NO; ! 1424: s = mkplace(np); ! 1425: np->vdovar = YES; ! 1426: return(s); ! 1427: } ! 1428: ! 1429: ! 1430: ! 1431: inregister(np) ! 1432: register Namep np; ! 1433: { ! 1434: register int i; ! 1435: ! 1436: for(i = 0 ; i < nregvar ; ++i) ! 1437: if(regnamep[i] == np) ! 1438: return( regnum[i] ); ! 1439: return(-1); ! 1440: } ! 1441: ! 1442: ! 1443: ! 1444: ! 1445: enregister(np) ! 1446: Namep np; ! 1447: { ! 1448: if( inregister(np) >= 0) ! 1449: return(YES); ! 1450: if(nregvar >= maxregvar) ! 1451: return(NO); ! 1452: vardcl(np); ! 1453: if( ONEOF(np->vtype, MSKIREG) ) ! 1454: { ! 1455: regnamep[nregvar++] = np; ! 1456: if(nregvar > highregvar) ! 1457: highregvar = nregvar; ! 1458: #if FAMILY == DMR ! 1459: putnreg(); ! 1460: #endif ! 1461: return(YES); ! 1462: } ! 1463: else ! 1464: return(NO); ! 1465: } ! 1466: ! 1467: ! 1468: ! 1469: ! 1470: expptr suboffset(p) ! 1471: register struct Primblock *p; ! 1472: { ! 1473: int n; ! 1474: expptr size; ! 1475: expptr oftwo(); ! 1476: chainp cp; ! 1477: expptr offp, prod; ! 1478: expptr subcheck(); ! 1479: struct Dimblock *dimp; ! 1480: expptr sub[MAXDIM+1]; ! 1481: register Namep np; ! 1482: ! 1483: np = p->namep; ! 1484: offp = ICON(0); ! 1485: n = 0; ! 1486: if(p->argsp) ! 1487: for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp) ! 1488: { ! 1489: sub[n] = fixtype(cpexpr(cp->datap)); ! 1490: if ( ! ISINT(sub[n]->headblock.vtype)) { ! 1491: errstr("%s: non-integer subscript expression", ! 1492: varstr(VL, np->varname) ); ! 1493: /* Provide a substitute -- go on to find more errors */ ! 1494: frexpr(sub[n]); ! 1495: sub[n] = ICON(1); ! 1496: } ! 1497: if(n > maxdim) ! 1498: { ! 1499: char str[28+VL]; ! 1500: sprintf(str, "%s: more than %d subscripts", ! 1501: varstr(VL, np->varname), maxdim ); ! 1502: err( str ); ! 1503: break; ! 1504: } ! 1505: } ! 1506: ! 1507: dimp = np->vdim; ! 1508: if(n>0 && dimp==NULL) ! 1509: errstr("%s: subscripts on scalar variable", ! 1510: varstr(VL, np->varname), maxdim ); ! 1511: else if(dimp && dimp->ndim!=n) ! 1512: errstr("wrong number of subscripts on %s", ! 1513: varstr(VL, np->varname) ); ! 1514: else if(n > 0) ! 1515: { ! 1516: prod = sub[--n]; ! 1517: while( --n >= 0) ! 1518: prod = mkexpr(OPPLUS, sub[n], ! 1519: mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) ); ! 1520: #if TARGET == VAX ! 1521: #ifdef SDB ! 1522: if(checksubs || np->vstg!=STGARG || sdbflag) ! 1523: #else ! 1524: if(checksubs || np->vstg!=STGARG) ! 1525: #endif ! 1526: prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); ! 1527: #else ! 1528: prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); ! 1529: #endif ! 1530: if(checksubs) ! 1531: prod = subcheck(np, prod); ! 1532: size = np->vtype == TYCHAR ? ! 1533: (expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]); ! 1534: if (!oftwo(size)) ! 1535: prod = mkexpr(OPSTAR, prod, size); ! 1536: else ! 1537: prod = mkexpr(OPLSHIFT,prod,oftwo(size)); ! 1538: ! 1539: offp = mkexpr(OPPLUS, offp, prod); ! 1540: } ! 1541: ! 1542: if(p->fcharp && np->vtype==TYCHAR) ! 1543: offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) )); ! 1544: ! 1545: return(offp); ! 1546: } ! 1547: ! 1548: ! 1549: ! 1550: ! 1551: expptr subcheck(np, p) ! 1552: Namep np; ! 1553: register expptr p; ! 1554: { ! 1555: struct Dimblock *dimp; ! 1556: expptr t, checkvar, checkcond, badcall; ! 1557: ! 1558: dimp = np->vdim; ! 1559: if(dimp->nelt == NULL) ! 1560: return(p); /* don't check arrays with * bounds */ ! 1561: checkvar = NULL; ! 1562: checkcond = NULL; ! 1563: if( ISICON(p) ) ! 1564: { ! 1565: if(p->constblock.constant.ci < 0) ! 1566: goto badsub; ! 1567: if( ISICON(dimp->nelt) ) ! 1568: if(p->constblock.constant.ci < dimp->nelt->constblock.constant.ci) ! 1569: return(p); ! 1570: else ! 1571: goto badsub; ! 1572: } ! 1573: if(p->tag==TADDR && p->addrblock.vstg==STGREG) ! 1574: { ! 1575: checkvar = (expptr) cpexpr(p); ! 1576: t = p; ! 1577: } ! 1578: else { ! 1579: checkvar = (expptr) mktemp(p->headblock.vtype, ENULL); ! 1580: t = mkexpr(OPASSIGN, cpexpr(checkvar), p); ! 1581: } ! 1582: checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) ); ! 1583: if( ! ISICON(p) ) ! 1584: checkcond = mkexpr(OPAND, checkcond, ! 1585: mkexpr(OPLE, ICON(0), cpexpr(checkvar)) ); ! 1586: ! 1587: badcall = call4(p->headblock.vtype, "s_rnge", ! 1588: mkstrcon(VL, np->varname), ! 1589: mkconv(TYLONG, cpexpr(checkvar)), ! 1590: mkstrcon(XL, procname), ! 1591: ICON(lineno) ); ! 1592: badcall->exprblock.opcode = OPCCALL; ! 1593: p = mkexpr(OPQUEST, checkcond, ! 1594: mkexpr(OPCOLON, checkvar, badcall)); ! 1595: ! 1596: return(p); ! 1597: ! 1598: badsub: ! 1599: frexpr(p); ! 1600: errstr("subscript on variable %s out of range", varstr(VL,np->varname)); ! 1601: return ( ICON(0) ); ! 1602: } ! 1603: ! 1604: ! 1605: ! 1606: ! 1607: Addrp mkaddr(p) ! 1608: register Namep p; ! 1609: { ! 1610: struct Extsym *extp; ! 1611: register Addrp t; ! 1612: Addrp intraddr(); ! 1613: ! 1614: switch( p->vstg) ! 1615: { ! 1616: case STGUNKNOWN: ! 1617: if(p->vclass != CLPROC) ! 1618: break; ! 1619: extp = mkext( varunder(VL, p->varname) ); ! 1620: extp->extstg = STGEXT; ! 1621: p->vstg = STGEXT; ! 1622: p->vardesc.varno = extp - extsymtab; ! 1623: p->vprocclass = PEXTERNAL; ! 1624: ! 1625: case STGCOMMON: ! 1626: case STGEXT: ! 1627: case STGBSS: ! 1628: case STGINIT: ! 1629: case STGEQUIV: ! 1630: case STGARG: ! 1631: case STGLENG: ! 1632: case STGAUTO: ! 1633: t = ALLOC(Addrblock); ! 1634: t->tag = TADDR; ! 1635: if(p->vclass==CLPROC && p->vprocclass==PTHISPROC) ! 1636: t->vclass = CLVAR; ! 1637: else ! 1638: t->vclass = p->vclass; ! 1639: t->vtype = p->vtype; ! 1640: t->vstg = p->vstg; ! 1641: t->memno = p->vardesc.varno; ! 1642: t->issaved = p->vsave; ! 1643: if(p->vdim) t->isarray = YES; ! 1644: t->memoffset = ICON(p->voffset); ! 1645: if(p->vleng) ! 1646: { ! 1647: t->vleng = (expptr) cpexpr(p->vleng); ! 1648: if( ISICON(t->vleng) ) ! 1649: t->varleng = t->vleng->constblock.constant.ci; ! 1650: } ! 1651: if (p->vstg == STGBSS) ! 1652: t->varsize = p->varsize; ! 1653: else if (p->vstg == STGEQUIV) ! 1654: t->varsize = eqvclass[t->memno].eqvleng; ! 1655: return(t); ! 1656: ! 1657: case STGINTR: ! 1658: return( intraddr(p) ); ! 1659: ! 1660: } ! 1661: /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass); ! 1662: badstg("mkaddr", p->vstg); ! 1663: /* NOTREACHED */ ! 1664: } ! 1665: ! 1666: ! 1667: ! 1668: ! 1669: Addrp mkarg(type, argno) ! 1670: int type, argno; ! 1671: { ! 1672: register Addrp p; ! 1673: ! 1674: p = ALLOC(Addrblock); ! 1675: p->tag = TADDR; ! 1676: p->vtype = type; ! 1677: p->vclass = CLVAR; ! 1678: p->vstg = (type==TYLENG ? STGLENG : STGARG); ! 1679: p->memno = argno; ! 1680: return(p); ! 1681: } ! 1682: ! 1683: ! 1684: ! 1685: ! 1686: expptr mkprim(v, args, substr) ! 1687: register union ! 1688: { ! 1689: struct Paramblock paramblock; ! 1690: struct Nameblock nameblock; ! 1691: struct Headblock headblock; ! 1692: } *v; ! 1693: struct Listblock *args; ! 1694: chainp substr; ! 1695: { ! 1696: register struct Primblock *p; ! 1697: ! 1698: if(v->headblock.vclass == CLPARAM) ! 1699: { ! 1700: if(args || substr) ! 1701: { ! 1702: errstr("no qualifiers on parameter name %s", ! 1703: varstr(VL,v->paramblock.varname)); ! 1704: frexpr(args); ! 1705: if(substr) ! 1706: { ! 1707: frexpr(substr->datap); ! 1708: frexpr(substr->nextp->datap); ! 1709: frchain(&substr); ! 1710: } ! 1711: frexpr(v); ! 1712: return( errnode() ); ! 1713: } ! 1714: return( (expptr) cpexpr(v->paramblock.paramval) ); ! 1715: } ! 1716: ! 1717: p = ALLOC(Primblock); ! 1718: p->tag = TPRIM; ! 1719: p->vtype = v->nameblock.vtype; ! 1720: p->namep = (Namep) v; ! 1721: p->argsp = args; ! 1722: if(substr) ! 1723: { ! 1724: p->fcharp = (expptr) substr->datap; ! 1725: if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype)) ! 1726: p->fcharp = mkconv(TYINT, p->fcharp); ! 1727: p->lcharp = (expptr) substr->nextp->datap; ! 1728: if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype)) ! 1729: p->lcharp = mkconv(TYINT, p->lcharp); ! 1730: frchain(&substr); ! 1731: } ! 1732: return( (expptr) p); ! 1733: } ! 1734: ! 1735: ! 1736: ! 1737: vardcl(v) ! 1738: register Namep v; ! 1739: { ! 1740: int nelt; ! 1741: struct Dimblock *t; ! 1742: Addrp p; ! 1743: expptr neltp; ! 1744: int eltsize; ! 1745: int varsize; ! 1746: int tsize; ! 1747: int align; ! 1748: ! 1749: if(v->vdcldone) ! 1750: return; ! 1751: if(v->vclass == CLNAMELIST) ! 1752: return; ! 1753: ! 1754: if(v->vtype == TYUNKNOWN) ! 1755: impldcl(v); ! 1756: if(v->vclass == CLUNKNOWN) ! 1757: v->vclass = CLVAR; ! 1758: else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC) ! 1759: { ! 1760: dclerr("used both as variable and non-variable", v); ! 1761: return; ! 1762: } ! 1763: if(v->vstg==STGUNKNOWN) ! 1764: v->vstg = implstg[ letter(v->varname[0]) ]; ! 1765: ! 1766: switch(v->vstg) ! 1767: { ! 1768: case STGBSS: ! 1769: v->vardesc.varno = ++lastvarno; ! 1770: if (v->vclass != CLVAR) ! 1771: break; ! 1772: nelt = 1; ! 1773: t = v->vdim; ! 1774: if (t) ! 1775: { ! 1776: neltp = t->nelt; ! 1777: if (neltp && ISICON(neltp)) ! 1778: nelt = neltp->constblock.constant.ci; ! 1779: else ! 1780: dclerr("improperly dimensioned array", v); ! 1781: } ! 1782: ! 1783: if (v->vtype == TYCHAR) ! 1784: { ! 1785: v->vleng = fixtype(v->vleng); ! 1786: if (v->vleng == NULL) ! 1787: eltsize = typesize[TYCHAR]; ! 1788: else if (ISICON(v->vleng)) ! 1789: eltsize = typesize[TYCHAR] * ! 1790: v->vleng->constblock.constant.ci; ! 1791: else if (v->vleng->tag != TERROR) ! 1792: { ! 1793: errstr("nonconstant string length on %s", ! 1794: varstr(VL, v->varname)); ! 1795: eltsize = 0; ! 1796: } ! 1797: } ! 1798: else ! 1799: eltsize = typesize[v->vtype]; ! 1800: ! 1801: v->varsize = nelt * eltsize; ! 1802: break; ! 1803: case STGAUTO: ! 1804: if(v->vclass==CLPROC && v->vprocclass==PTHISPROC) ! 1805: break; ! 1806: nelt = 1; ! 1807: if(t = v->vdim) ! 1808: if( (neltp = t->nelt) && ISCONST(neltp) ) ! 1809: nelt = neltp->constblock.constant.ci; ! 1810: else ! 1811: dclerr("adjustable automatic array", v); ! 1812: p = autovar(nelt, v->vtype, v->vleng); ! 1813: v->vardesc.varno = p->memno; ! 1814: v->voffset = p->memoffset->constblock.constant.ci; ! 1815: frexpr(p); ! 1816: break; ! 1817: ! 1818: default: ! 1819: break; ! 1820: } ! 1821: v->vdcldone = YES; ! 1822: } ! 1823: ! 1824: ! 1825: ! 1826: ! 1827: impldcl(p) ! 1828: register Namep p; ! 1829: { ! 1830: register int k; ! 1831: int type, leng; ! 1832: ! 1833: if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) ) ! 1834: return; ! 1835: if(p->vtype == TYUNKNOWN) ! 1836: { ! 1837: k = letter(p->varname[0]); ! 1838: type = impltype[ k ]; ! 1839: leng = implleng[ k ]; ! 1840: if(type == TYUNKNOWN) ! 1841: { ! 1842: if(p->vclass == CLPROC) ! 1843: dclerr("attempt to use function of undefined type", p); ! 1844: else ! 1845: dclerr("attempt to use undefined variable", p); ! 1846: type = TYERROR; ! 1847: leng = 1; ! 1848: } ! 1849: settype(p, type, leng); ! 1850: } ! 1851: } ! 1852: ! 1853: ! 1854: ! 1855: ! 1856: LOCAL letter(c) ! 1857: register int c; ! 1858: { ! 1859: if( isupper(c) ) ! 1860: c = tolower(c); ! 1861: return(c - 'a'); ! 1862: } ! 1863: ! 1864: #define ICONEQ(z, c) (ISICON(z) && z->constblock.constant.ci==c) ! 1865: #define COMMUTE { e = lp; lp = rp; rp = e; } ! 1866: ! 1867: ! 1868: expptr mkexpr(opcode, lp, rp) ! 1869: int opcode; ! 1870: register expptr lp, rp; ! 1871: { ! 1872: register expptr e, e1; ! 1873: int etype; ! 1874: int ltype, rtype; ! 1875: int ltag, rtag; ! 1876: expptr q, q1; ! 1877: expptr fold(); ! 1878: int k; ! 1879: ! 1880: ltype = lp->headblock.vtype; ! 1881: ltag = lp->tag; ! 1882: if(rp && opcode!=OPCALL && opcode!=OPCCALL) ! 1883: { ! 1884: rtype = rp->headblock.vtype; ! 1885: rtag = rp->tag; ! 1886: } ! 1887: else { ! 1888: rtype = 0; ! 1889: rtag = 0; ! 1890: } ! 1891: ! 1892: /* ! 1893: * Yuck. Why can't we fold constants AFTER ! 1894: * variables are implicitly declared??? ! 1895: */ ! 1896: if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL) ! 1897: { ! 1898: k = letter(lp->primblock.namep->varname[0]); ! 1899: ltype = impltype[ k ]; ! 1900: } ! 1901: if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL) ! 1902: { ! 1903: k = letter(rp->primblock.namep->varname[0]); ! 1904: rtype = impltype[ k ]; ! 1905: } ! 1906: ! 1907: /* ! 1908: * Eliminate all but the topmost OPPAREN operator when folding constants. ! 1909: */ ! 1910: if(lp->tag == TEXPR && ! 1911: lp->exprblock.opcode == OPPAREN && ! 1912: lp->exprblock.leftp->tag == TCONST) ! 1913: { ! 1914: q = (expptr) cpexpr(lp->exprblock.leftp); ! 1915: frexpr(lp); ! 1916: lp = q; ! 1917: ltag = TCONST; ! 1918: ltype = lp->constblock.vtype; ! 1919: } ! 1920: if(rp && ! 1921: rp->tag == TEXPR && ! 1922: rp->exprblock.opcode == OPPAREN && ! 1923: rp->exprblock.leftp->tag == TCONST) ! 1924: { ! 1925: q = (expptr) cpexpr(rp->exprblock.leftp); ! 1926: frexpr(rp); ! 1927: rp = q; ! 1928: rtag = TCONST; ! 1929: rtype = rp->constblock.vtype; ! 1930: } ! 1931: ! 1932: etype = cktype(opcode, ltype, rtype); ! 1933: if(etype == TYERROR) ! 1934: goto error; ! 1935: ! 1936: if(ltag==TCONST && (rp==0 || rtag==TCONST) ) ! 1937: goto makenode; ! 1938: if(etype == TYUNKNOWN) ! 1939: goto makenode; ! 1940: ! 1941: switch(opcode) ! 1942: { ! 1943: /* check for multiplication by 0 and 1 and addition to 0 */ ! 1944: ! 1945: case OPSTAR: ! 1946: if( ISCONST(lp) ) ! 1947: COMMUTE ! 1948: ! 1949: if( ISICON(rp) ) ! 1950: { ! 1951: if(rp->constblock.constant.ci == 0) ! 1952: { ! 1953: if(etype == TYUNKNOWN) ! 1954: break; ! 1955: rp = mkconv(etype, rp); ! 1956: goto retright; ! 1957: } ! 1958: if ((lp->tag == TEXPR) && ! 1959: ((lp->exprblock.opcode == OPPLUS) || ! 1960: (lp->exprblock.opcode == OPMINUS)) && ! 1961: ISCONST(lp->exprblock.rightp) && ! 1962: ISINT(lp->exprblock.rightp->constblock.vtype)) ! 1963: { ! 1964: q1 = mkexpr(OPSTAR, lp->exprblock.rightp, ! 1965: cpexpr(rp)); ! 1966: q = mkexpr(OPSTAR, lp->exprblock.leftp, rp); ! 1967: q = mkexpr(lp->exprblock.opcode, q, q1); ! 1968: free ((char *) lp); ! 1969: return q; ! 1970: } ! 1971: else ! 1972: goto mulop; ! 1973: } ! 1974: break; ! 1975: ! 1976: case OPSLASH: ! 1977: case OPMOD: ! 1978: if( ICONEQ(rp, 0) ) ! 1979: { ! 1980: err("attempted division by zero"); ! 1981: rp = ICON(1); ! 1982: break; ! 1983: } ! 1984: if(opcode == OPMOD) ! 1985: break; ! 1986: ! 1987: ! 1988: mulop: ! 1989: if( ISICON(rp) ) ! 1990: { ! 1991: if(rp->constblock.constant.ci == 1) ! 1992: goto retleft; ! 1993: ! 1994: if(rp->constblock.constant.ci == -1) ! 1995: { ! 1996: frexpr(rp); ! 1997: return( mkexpr(OPNEG, lp, PNULL) ); ! 1998: } ! 1999: } ! 2000: ! 2001: if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) ) ! 2002: { ! 2003: if(opcode == OPSTAR) ! 2004: e = mkexpr(OPSTAR, lp->exprblock.rightp, rp); ! 2005: else if(ISICON(rp) && ! 2006: (lp->exprblock.rightp->constblock.constant.ci % ! 2007: rp->constblock.constant.ci) == 0) ! 2008: e = mkexpr(OPSLASH, lp->exprblock.rightp, rp); ! 2009: else break; ! 2010: ! 2011: e1 = lp->exprblock.leftp; ! 2012: free( (charptr) lp ); ! 2013: return( mkexpr(OPSTAR, e1, e) ); ! 2014: } ! 2015: break; ! 2016: ! 2017: ! 2018: case OPPLUS: ! 2019: if( ISCONST(lp) ) ! 2020: COMMUTE ! 2021: goto addop; ! 2022: ! 2023: case OPMINUS: ! 2024: if( ICONEQ(lp, 0) ) ! 2025: { ! 2026: frexpr(lp); ! 2027: return( mkexpr(OPNEG, rp, ENULL) ); ! 2028: } ! 2029: ! 2030: if( ISCONST(rp) ) ! 2031: { ! 2032: opcode = OPPLUS; ! 2033: consnegop(rp); ! 2034: } ! 2035: ! 2036: addop: ! 2037: if( ISICON(rp) ) ! 2038: { ! 2039: if(rp->constblock.constant.ci == 0) ! 2040: goto retleft; ! 2041: if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) ) ! 2042: { ! 2043: e = mkexpr(OPPLUS, lp->exprblock.rightp, rp); ! 2044: e1 = lp->exprblock.leftp; ! 2045: free( (charptr) lp ); ! 2046: return( mkexpr(OPPLUS, e1, e) ); ! 2047: } ! 2048: } ! 2049: break; ! 2050: ! 2051: ! 2052: case OPPOWER: ! 2053: break; ! 2054: ! 2055: case OPNEG: ! 2056: if(ltag==TEXPR && lp->exprblock.opcode==OPNEG) ! 2057: { ! 2058: e = lp->exprblock.leftp; ! 2059: free( (charptr) lp ); ! 2060: return(e); ! 2061: } ! 2062: break; ! 2063: ! 2064: case OPNOT: ! 2065: if(ltag==TEXPR && lp->exprblock.opcode==OPNOT) ! 2066: { ! 2067: e = lp->exprblock.leftp; ! 2068: free( (charptr) lp ); ! 2069: return(e); ! 2070: } ! 2071: break; ! 2072: ! 2073: case OPCALL: ! 2074: case OPCCALL: ! 2075: etype = ltype; ! 2076: if(rp!=NULL && rp->listblock.listp==NULL) ! 2077: { ! 2078: free( (charptr) rp ); ! 2079: rp = NULL; ! 2080: } ! 2081: break; ! 2082: ! 2083: case OPAND: ! 2084: case OPOR: ! 2085: if( ISCONST(lp) ) ! 2086: COMMUTE ! 2087: ! 2088: if( ISCONST(rp) ) ! 2089: { ! 2090: if(rp->constblock.constant.ci == 0) ! 2091: if(opcode == OPOR) ! 2092: goto retleft; ! 2093: else ! 2094: goto retright; ! 2095: else if(opcode == OPOR) ! 2096: goto retright; ! 2097: else ! 2098: goto retleft; ! 2099: } ! 2100: case OPLSHIFT: ! 2101: if (ISICON(rp)) ! 2102: { ! 2103: if (rp->constblock.constant.ci == 0) ! 2104: goto retleft; ! 2105: if ((lp->tag == TEXPR) && ! 2106: ((lp->exprblock.opcode == OPPLUS) || ! 2107: (lp->exprblock.opcode == OPMINUS)) && ! 2108: ISICON(lp->exprblock.rightp)) ! 2109: { ! 2110: q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp, ! 2111: cpexpr(rp)); ! 2112: q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp); ! 2113: q = mkexpr(lp->exprblock.opcode, q, q1); ! 2114: free((char *) lp); ! 2115: return q; ! 2116: } ! 2117: } ! 2118: ! 2119: case OPEQV: ! 2120: case OPNEQV: ! 2121: ! 2122: case OPBITAND: ! 2123: case OPBITOR: ! 2124: case OPBITXOR: ! 2125: case OPBITNOT: ! 2126: case OPRSHIFT: ! 2127: ! 2128: case OPLT: ! 2129: case OPGT: ! 2130: case OPLE: ! 2131: case OPGE: ! 2132: break; ! 2133: ! 2134: case OPEQ: ! 2135: case OPNE: ! 2136: /* ! 2137: * This warning is here instead of in cktype because ! 2138: * cktype repeats warnings (it can be run more ! 2139: * than once on an expression). ! 2140: */ ! 2141: if (ltype == TYLOGICAL) ! 2142: warn("logical operand of nonlogical operator"); ! 2143: break; ! 2144: ! 2145: case OPCONCAT: ! 2146: ! 2147: case OPMIN: ! 2148: case OPMAX: ! 2149: ! 2150: case OPASSIGN: ! 2151: case OPPLUSEQ: ! 2152: case OPSTAREQ: ! 2153: ! 2154: case OPCONV: ! 2155: case OPADDR: ! 2156: ! 2157: case OPCOMMA: ! 2158: case OPQUEST: ! 2159: case OPCOLON: ! 2160: ! 2161: case OPPAREN: ! 2162: break; ! 2163: ! 2164: default: ! 2165: badop("mkexpr", opcode); ! 2166: } ! 2167: ! 2168: makenode: ! 2169: ! 2170: e = (expptr) ALLOC(Exprblock); ! 2171: e->exprblock.tag = TEXPR; ! 2172: e->exprblock.opcode = opcode; ! 2173: e->exprblock.vtype = etype; ! 2174: e->exprblock.leftp = lp; ! 2175: e->exprblock.rightp = rp; ! 2176: if(ltag==TCONST && (rp==0 || rtag==TCONST) ) ! 2177: e = fold(e); ! 2178: return(e); ! 2179: ! 2180: retleft: ! 2181: frexpr(rp); ! 2182: return(lp); ! 2183: ! 2184: retright: ! 2185: frexpr(lp); ! 2186: return(rp); ! 2187: ! 2188: error: ! 2189: frexpr(lp); ! 2190: if(rp && opcode!=OPCALL && opcode!=OPCCALL) ! 2191: frexpr(rp); ! 2192: return( errnode() ); ! 2193: } ! 2194: ! 2195: #define ERR(s) { errs = s; goto error; } ! 2196: ! 2197: cktype(op, lt, rt) ! 2198: register int op, lt, rt; ! 2199: { ! 2200: char *errs; ! 2201: ! 2202: if(lt==TYERROR || rt==TYERROR) ! 2203: goto error1; ! 2204: ! 2205: if(lt==TYUNKNOWN) ! 2206: return(TYUNKNOWN); ! 2207: if(rt==TYUNKNOWN) ! 2208: if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && ! 2209: op!=OPCCALL && op!=OPADDR && op!=OPPAREN) ! 2210: return(TYUNKNOWN); ! 2211: ! 2212: switch(op) ! 2213: { ! 2214: case OPPLUS: ! 2215: case OPMINUS: ! 2216: case OPSTAR: ! 2217: case OPSLASH: ! 2218: case OPPOWER: ! 2219: case OPMOD: ! 2220: if( ISNUMERIC(lt) && ISNUMERIC(rt) ) ! 2221: return( maxtype(lt, rt) ); ! 2222: ERR("nonarithmetic operand of arithmetic operator") ! 2223: ! 2224: case OPNEG: ! 2225: if( ISNUMERIC(lt) ) ! 2226: return(lt); ! 2227: ERR("nonarithmetic operand of negation") ! 2228: ! 2229: case OPNOT: ! 2230: if(lt == TYLOGICAL) ! 2231: return(TYLOGICAL); ! 2232: ERR("NOT of nonlogical") ! 2233: ! 2234: case OPAND: ! 2235: case OPOR: ! 2236: case OPEQV: ! 2237: case OPNEQV: ! 2238: if(lt==TYLOGICAL && rt==TYLOGICAL) ! 2239: return(TYLOGICAL); ! 2240: ERR("nonlogical operand of logical operator") ! 2241: ! 2242: case OPLT: ! 2243: case OPGT: ! 2244: case OPLE: ! 2245: case OPGE: ! 2246: case OPEQ: ! 2247: case OPNE: ! 2248: if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) ! 2249: { ! 2250: if(lt != rt) ! 2251: ERR("illegal comparison") ! 2252: if(lt == TYLOGICAL) ! 2253: { ! 2254: if(op!=OPEQ && op!=OPNE) ! 2255: ERR("order comparison of complex data") ! 2256: } ! 2257: } ! 2258: ! 2259: else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) ) ! 2260: { ! 2261: if(op!=OPEQ && op!=OPNE) ! 2262: ERR("order comparison of complex data") ! 2263: } ! 2264: ! 2265: else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) ) ! 2266: ERR("comparison of nonarithmetic data") ! 2267: return(TYLOGICAL); ! 2268: ! 2269: case OPCONCAT: ! 2270: if(lt==TYCHAR && rt==TYCHAR) ! 2271: return(TYCHAR); ! 2272: ERR("concatenation of nonchar data") ! 2273: ! 2274: case OPCALL: ! 2275: case OPCCALL: ! 2276: return(lt); ! 2277: ! 2278: case OPADDR: ! 2279: return(TYADDR); ! 2280: ! 2281: case OPCONV: ! 2282: if(ISCOMPLEX(lt)) ! 2283: { ! 2284: if(ISNUMERIC(rt)) ! 2285: return(lt); ! 2286: ERR("impossible conversion") ! 2287: } ! 2288: if(rt == 0) ! 2289: return(0); ! 2290: if(lt==TYCHAR && ISINT(rt) ) ! 2291: return(TYCHAR); ! 2292: case OPASSIGN: ! 2293: case OPPLUSEQ: ! 2294: case OPSTAREQ: ! 2295: if( ISINT(lt) && rt==TYCHAR) ! 2296: return(lt); ! 2297: if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) ! 2298: if(op!=OPASSIGN || lt!=rt) ! 2299: { ! 2300: /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */ ! 2301: /* debug fatal("impossible conversion. possible compiler bug"); */ ! 2302: ERR("impossible conversion") ! 2303: } ! 2304: return(lt); ! 2305: ! 2306: case OPMIN: ! 2307: case OPMAX: ! 2308: case OPBITOR: ! 2309: case OPBITAND: ! 2310: case OPBITXOR: ! 2311: case OPBITNOT: ! 2312: case OPLSHIFT: ! 2313: case OPRSHIFT: ! 2314: case OPPAREN: ! 2315: return(lt); ! 2316: ! 2317: case OPCOMMA: ! 2318: case OPQUEST: ! 2319: case OPCOLON: ! 2320: return(rt); ! 2321: ! 2322: default: ! 2323: badop("cktype", op); ! 2324: } ! 2325: error: err(errs); ! 2326: error1: return(TYERROR); ! 2327: } ! 2328: ! 2329: #if HERE == VAX ! 2330: #include <signal.h> ! 2331: #include <setjmp.h> ! 2332: #define setfpe() ;asm("bispsw $0x60") ! 2333: jmp_buf jmp_fpe; ! 2334: ! 2335: LOCAL int fold_fpe_handler( sig, code ) ! 2336: int sig; ! 2337: int code; ! 2338: { ! 2339: char *message; ! 2340: ! 2341: switch ( code ) ! 2342: { ! 2343: case FPE_INTOVF_TRAP: ! 2344: message = "integer overflow"; break; ! 2345: case FPE_INTDIV_TRAP: ! 2346: message = "integer divide by zero"; break; ! 2347: case FPE_FLTOVF_TRAP: ! 2348: case FPE_FLTOVF_FAULT: ! 2349: message = "floating overflow"; break; ! 2350: case FPE_FLTDIV_TRAP: ! 2351: case FPE_FLTDIV_FAULT: ! 2352: message = "floating divide by zero"; break; ! 2353: case FPE_FLTUND_TRAP: ! 2354: case FPE_FLTUND_FAULT: ! 2355: message = "floating underflow"; break; ! 2356: default: ! 2357: message = "arithmetic exception"; ! 2358: } ! 2359: errstr("%s in constant expression", message); ! 2360: longjmp(jmp_fpe, 1); ! 2361: } ! 2362: #endif ! 2363: ! 2364: #ifndef setfpe ! 2365: #define setfpe() ! 2366: #endif ! 2367: ! 2368: LOCAL expptr fold(e) ! 2369: register expptr e; ! 2370: { ! 2371: Constp p; ! 2372: register expptr lp, rp; ! 2373: int etype, mtype, ltype, rtype, opcode; ! 2374: int i, ll, lr; ! 2375: char *q, *s; ! 2376: union Constant lcon, rcon; ! 2377: ! 2378: #if HERE == VAX ! 2379: int (*fpe_handler)(); ! 2380: ! 2381: if(setjmp(jmp_fpe)) ! 2382: { ! 2383: (void) signal(SIGFPE, fpe_handler); ! 2384: frexpr(e); ! 2385: return(errnode()); ! 2386: } ! 2387: fpe_handler = signal(SIGFPE, fold_fpe_handler); ! 2388: setfpe(); ! 2389: #endif ! 2390: ! 2391: opcode = e->exprblock.opcode; ! 2392: etype = e->exprblock.vtype; ! 2393: ! 2394: lp = e->exprblock.leftp; ! 2395: ltype = lp->headblock.vtype; ! 2396: rp = e->exprblock.rightp; ! 2397: ! 2398: if(rp == 0) ! 2399: switch(opcode) ! 2400: { ! 2401: case OPNOT: ! 2402: lp->constblock.constant.ci = ! lp->constblock.constant.ci; ! 2403: return(lp); ! 2404: ! 2405: case OPBITNOT: ! 2406: lp->constblock.constant.ci = ~ lp->constblock.constant.ci; ! 2407: return(lp); ! 2408: ! 2409: case OPNEG: ! 2410: consnegop(lp); ! 2411: return(lp); ! 2412: ! 2413: case OPCONV: ! 2414: case OPADDR: ! 2415: case OPPAREN: ! 2416: return(e); ! 2417: ! 2418: default: ! 2419: badop("fold", opcode); ! 2420: } ! 2421: ! 2422: rtype = rp->headblock.vtype; ! 2423: ! 2424: p = ALLOC(Constblock); ! 2425: p->tag = TCONST; ! 2426: p->vtype = etype; ! 2427: p->vleng = e->exprblock.vleng; ! 2428: ! 2429: switch(opcode) ! 2430: { ! 2431: case OPCOMMA: ! 2432: case OPQUEST: ! 2433: case OPCOLON: ! 2434: return(e); ! 2435: ! 2436: case OPAND: ! 2437: p->constant.ci = lp->constblock.constant.ci && ! 2438: rp->constblock.constant.ci; ! 2439: break; ! 2440: ! 2441: case OPOR: ! 2442: p->constant.ci = lp->constblock.constant.ci || ! 2443: rp->constblock.constant.ci; ! 2444: break; ! 2445: ! 2446: case OPEQV: ! 2447: p->constant.ci = lp->constblock.constant.ci == ! 2448: rp->constblock.constant.ci; ! 2449: break; ! 2450: ! 2451: case OPNEQV: ! 2452: p->constant.ci = lp->constblock.constant.ci != ! 2453: rp->constblock.constant.ci; ! 2454: break; ! 2455: ! 2456: case OPBITAND: ! 2457: p->constant.ci = lp->constblock.constant.ci & ! 2458: rp->constblock.constant.ci; ! 2459: break; ! 2460: ! 2461: case OPBITOR: ! 2462: p->constant.ci = lp->constblock.constant.ci | ! 2463: rp->constblock.constant.ci; ! 2464: break; ! 2465: ! 2466: case OPBITXOR: ! 2467: p->constant.ci = lp->constblock.constant.ci ^ ! 2468: rp->constblock.constant.ci; ! 2469: break; ! 2470: ! 2471: case OPLSHIFT: ! 2472: p->constant.ci = lp->constblock.constant.ci << ! 2473: rp->constblock.constant.ci; ! 2474: break; ! 2475: ! 2476: case OPRSHIFT: ! 2477: p->constant.ci = lp->constblock.constant.ci >> ! 2478: rp->constblock.constant.ci; ! 2479: break; ! 2480: ! 2481: case OPCONCAT: ! 2482: ll = lp->constblock.vleng->constblock.constant.ci; ! 2483: lr = rp->constblock.vleng->constblock.constant.ci; ! 2484: p->constant.ccp = q = (char *) ckalloc(ll+lr); ! 2485: p->vleng = ICON(ll+lr); ! 2486: s = lp->constblock.constant.ccp; ! 2487: for(i = 0 ; i < ll ; ++i) ! 2488: *q++ = *s++; ! 2489: s = rp->constblock.constant.ccp; ! 2490: for(i = 0; i < lr; ++i) ! 2491: *q++ = *s++; ! 2492: break; ! 2493: ! 2494: ! 2495: case OPPOWER: ! 2496: if( ! ISINT(rtype) ) ! 2497: return(e); ! 2498: conspower(&(p->constant), lp, rp->constblock.constant.ci); ! 2499: break; ! 2500: ! 2501: ! 2502: default: ! 2503: if(ltype == TYCHAR) ! 2504: { ! 2505: lcon.ci = cmpstr(lp->constblock.constant.ccp, ! 2506: rp->constblock.constant.ccp, ! 2507: lp->constblock.vleng->constblock.constant.ci, ! 2508: rp->constblock.vleng->constblock.constant.ci); ! 2509: rcon.ci = 0; ! 2510: mtype = tyint; ! 2511: } ! 2512: else { ! 2513: mtype = maxtype(ltype, rtype); ! 2514: consconv(mtype, &lcon, ltype, &(lp->constblock.constant) ); ! 2515: consconv(mtype, &rcon, rtype, &(rp->constblock.constant) ); ! 2516: } ! 2517: consbinop(opcode, mtype, &(p->constant), &lcon, &rcon); ! 2518: break; ! 2519: } ! 2520: ! 2521: frexpr(e); ! 2522: return( (expptr) p ); ! 2523: } ! 2524: ! 2525: ! 2526: ! 2527: /* assign constant l = r , doing coercion */ ! 2528: ! 2529: consconv(lt, lv, rt, rv) ! 2530: int lt, rt; ! 2531: register union Constant *lv, *rv; ! 2532: { ! 2533: switch(lt) ! 2534: { ! 2535: case TYCHAR: ! 2536: *(lv->ccp = (char *) ckalloc(1)) = rv->ci; ! 2537: break; ! 2538: ! 2539: case TYSHORT: ! 2540: case TYLONG: ! 2541: if(rt == TYCHAR) ! 2542: lv->ci = rv->ccp[0]; ! 2543: else if( ISINT(rt) ) ! 2544: lv->ci = rv->ci; ! 2545: else lv->ci = rv->cd[0]; ! 2546: break; ! 2547: ! 2548: case TYCOMPLEX: ! 2549: case TYDCOMPLEX: ! 2550: switch(rt) ! 2551: { ! 2552: case TYSHORT: ! 2553: case TYLONG: ! 2554: /* fall through and do real assignment of ! 2555: first element ! 2556: */ ! 2557: case TYREAL: ! 2558: case TYDREAL: ! 2559: lv->cd[1] = 0; break; ! 2560: case TYCOMPLEX: ! 2561: case TYDCOMPLEX: ! 2562: lv->cd[1] = rv->cd[1]; break; ! 2563: } ! 2564: ! 2565: case TYREAL: ! 2566: case TYDREAL: ! 2567: if( ISINT(rt) ) ! 2568: lv->cd[0] = rv->ci; ! 2569: else lv->cd[0] = rv->cd[0]; ! 2570: if( lt == TYREAL) ! 2571: { ! 2572: float f = lv->cd[0]; ! 2573: lv->cd[0] = f; ! 2574: } ! 2575: break; ! 2576: ! 2577: case TYLOGICAL: ! 2578: lv->ci = rv->ci; ! 2579: break; ! 2580: } ! 2581: } ! 2582: ! 2583: ! 2584: ! 2585: consnegop(p) ! 2586: register Constp p; ! 2587: { ! 2588: setfpe(); ! 2589: ! 2590: switch(p->vtype) ! 2591: { ! 2592: case TYSHORT: ! 2593: case TYLONG: ! 2594: p->constant.ci = - p->constant.ci; ! 2595: break; ! 2596: ! 2597: case TYCOMPLEX: ! 2598: case TYDCOMPLEX: ! 2599: p->constant.cd[1] = - p->constant.cd[1]; ! 2600: /* fall through and do the real parts */ ! 2601: case TYREAL: ! 2602: case TYDREAL: ! 2603: p->constant.cd[0] = - p->constant.cd[0]; ! 2604: break; ! 2605: default: ! 2606: badtype("consnegop", p->vtype); ! 2607: } ! 2608: } ! 2609: ! 2610: ! 2611: ! 2612: LOCAL conspower(powp, ap, n) ! 2613: register union Constant *powp; ! 2614: Constp ap; ! 2615: ftnint n; ! 2616: { ! 2617: register int type; ! 2618: union Constant x; ! 2619: ! 2620: switch(type = ap->vtype) /* pow = 1 */ ! 2621: { ! 2622: case TYSHORT: ! 2623: case TYLONG: ! 2624: powp->ci = 1; ! 2625: break; ! 2626: case TYCOMPLEX: ! 2627: case TYDCOMPLEX: ! 2628: powp->cd[1] = 0; ! 2629: case TYREAL: ! 2630: case TYDREAL: ! 2631: powp->cd[0] = 1; ! 2632: break; ! 2633: default: ! 2634: badtype("conspower", type); ! 2635: } ! 2636: ! 2637: if(n == 0) ! 2638: return; ! 2639: if(n < 0) ! 2640: { ! 2641: if( ISINT(type) ) ! 2642: { ! 2643: if (ap->constant.ci == 0) ! 2644: err("zero raised to a negative power"); ! 2645: else if (ap->constant.ci == 1) ! 2646: return; ! 2647: else if (ap->constant.ci == -1) ! 2648: { ! 2649: if (n < -2) ! 2650: n = n + 2; ! 2651: n = -n; ! 2652: if (n % 2 == 1) ! 2653: powp->ci = -1; ! 2654: } ! 2655: else ! 2656: powp->ci = 0; ! 2657: return; ! 2658: } ! 2659: n = - n; ! 2660: consbinop(OPSLASH, type, &x, powp, &(ap->constant)); ! 2661: } ! 2662: else ! 2663: consbinop(OPSTAR, type, &x, powp, &(ap->constant)); ! 2664: ! 2665: for( ; ; ) ! 2666: { ! 2667: if(n & 01) ! 2668: consbinop(OPSTAR, type, powp, powp, &x); ! 2669: if(n >>= 1) ! 2670: consbinop(OPSTAR, type, &x, &x, &x); ! 2671: else ! 2672: break; ! 2673: } ! 2674: } ! 2675: ! 2676: ! 2677: ! 2678: /* do constant operation cp = a op b */ ! 2679: ! 2680: ! 2681: LOCAL consbinop(opcode, type, cp, ap, bp) ! 2682: int opcode, type; ! 2683: register union Constant *ap, *bp, *cp; ! 2684: { ! 2685: int k; ! 2686: double temp; ! 2687: ! 2688: setfpe(); ! 2689: ! 2690: switch(opcode) ! 2691: { ! 2692: case OPPLUS: ! 2693: switch(type) ! 2694: { ! 2695: case TYSHORT: ! 2696: case TYLONG: ! 2697: cp->ci = ap->ci + bp->ci; ! 2698: break; ! 2699: case TYCOMPLEX: ! 2700: case TYDCOMPLEX: ! 2701: cp->cd[1] = ap->cd[1] + bp->cd[1]; ! 2702: case TYREAL: ! 2703: case TYDREAL: ! 2704: cp->cd[0] = ap->cd[0] + bp->cd[0]; ! 2705: break; ! 2706: } ! 2707: break; ! 2708: ! 2709: case OPMINUS: ! 2710: switch(type) ! 2711: { ! 2712: case TYSHORT: ! 2713: case TYLONG: ! 2714: cp->ci = ap->ci - bp->ci; ! 2715: break; ! 2716: case TYCOMPLEX: ! 2717: case TYDCOMPLEX: ! 2718: cp->cd[1] = ap->cd[1] - bp->cd[1]; ! 2719: case TYREAL: ! 2720: case TYDREAL: ! 2721: cp->cd[0] = ap->cd[0] - bp->cd[0]; ! 2722: break; ! 2723: } ! 2724: break; ! 2725: ! 2726: case OPSTAR: ! 2727: switch(type) ! 2728: { ! 2729: case TYSHORT: ! 2730: case TYLONG: ! 2731: cp->ci = ap->ci * bp->ci; ! 2732: break; ! 2733: case TYREAL: ! 2734: case TYDREAL: ! 2735: cp->cd[0] = ap->cd[0] * bp->cd[0]; ! 2736: break; ! 2737: case TYCOMPLEX: ! 2738: case TYDCOMPLEX: ! 2739: temp = ap->cd[0] * bp->cd[0] - ! 2740: ap->cd[1] * bp->cd[1] ; ! 2741: cp->cd[1] = ap->cd[0] * bp->cd[1] + ! 2742: ap->cd[1] * bp->cd[0] ; ! 2743: cp->cd[0] = temp; ! 2744: break; ! 2745: } ! 2746: break; ! 2747: case OPSLASH: ! 2748: switch(type) ! 2749: { ! 2750: case TYSHORT: ! 2751: case TYLONG: ! 2752: cp->ci = ap->ci / bp->ci; ! 2753: break; ! 2754: case TYREAL: ! 2755: case TYDREAL: ! 2756: cp->cd[0] = ap->cd[0] / bp->cd[0]; ! 2757: break; ! 2758: case TYCOMPLEX: ! 2759: case TYDCOMPLEX: ! 2760: zdiv(cp,ap,bp); ! 2761: break; ! 2762: } ! 2763: break; ! 2764: ! 2765: case OPMOD: ! 2766: if( ISINT(type) ) ! 2767: { ! 2768: cp->ci = ap->ci % bp->ci; ! 2769: break; ! 2770: } ! 2771: else ! 2772: fatal("inline mod of noninteger"); ! 2773: ! 2774: default: /* relational ops */ ! 2775: switch(type) ! 2776: { ! 2777: case TYSHORT: ! 2778: case TYLONG: ! 2779: if(ap->ci < bp->ci) ! 2780: k = -1; ! 2781: else if(ap->ci == bp->ci) ! 2782: k = 0; ! 2783: else k = 1; ! 2784: break; ! 2785: case TYREAL: ! 2786: case TYDREAL: ! 2787: if(ap->cd[0] < bp->cd[0]) ! 2788: k = -1; ! 2789: else if(ap->cd[0] == bp->cd[0]) ! 2790: k = 0; ! 2791: else k = 1; ! 2792: break; ! 2793: case TYCOMPLEX: ! 2794: case TYDCOMPLEX: ! 2795: if(ap->cd[0] == bp->cd[0] && ! 2796: ap->cd[1] == bp->cd[1] ) ! 2797: k = 0; ! 2798: else k = 1; ! 2799: break; ! 2800: case TYLOGICAL: ! 2801: if(ap->ci == bp->ci) ! 2802: k = 0; ! 2803: else k = 1; ! 2804: break; ! 2805: } ! 2806: ! 2807: switch(opcode) ! 2808: { ! 2809: case OPEQ: ! 2810: cp->ci = (k == 0); ! 2811: break; ! 2812: case OPNE: ! 2813: cp->ci = (k != 0); ! 2814: break; ! 2815: case OPGT: ! 2816: cp->ci = (k == 1); ! 2817: break; ! 2818: case OPLT: ! 2819: cp->ci = (k == -1); ! 2820: break; ! 2821: case OPGE: ! 2822: cp->ci = (k >= 0); ! 2823: break; ! 2824: case OPLE: ! 2825: cp->ci = (k <= 0); ! 2826: break; ! 2827: default: ! 2828: badop ("consbinop", opcode); ! 2829: } ! 2830: break; ! 2831: } ! 2832: } ! 2833: ! 2834: ! 2835: ! 2836: ! 2837: conssgn(p) ! 2838: register expptr p; ! 2839: { ! 2840: if( ! ISCONST(p) ) ! 2841: fatal( "sgn(nonconstant)" ); ! 2842: ! 2843: switch(p->headblock.vtype) ! 2844: { ! 2845: case TYSHORT: ! 2846: case TYLONG: ! 2847: if(p->constblock.constant.ci > 0) return(1); ! 2848: if(p->constblock.constant.ci < 0) return(-1); ! 2849: return(0); ! 2850: ! 2851: case TYREAL: ! 2852: case TYDREAL: ! 2853: if(p->constblock.constant.cd[0] > 0) return(1); ! 2854: if(p->constblock.constant.cd[0] < 0) return(-1); ! 2855: return(0); ! 2856: ! 2857: case TYCOMPLEX: ! 2858: case TYDCOMPLEX: ! 2859: return(p->constblock.constant.cd[0]!=0 || p->constblock.constant.cd[1]!=0); ! 2860: ! 2861: default: ! 2862: badtype( "conssgn", p->constblock.vtype); ! 2863: } ! 2864: /* NOTREACHED */ ! 2865: } ! 2866: ! 2867: char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" }; ! 2868: ! 2869: ! 2870: LOCAL expptr mkpower(p) ! 2871: register expptr p; ! 2872: { ! 2873: register expptr q, lp, rp; ! 2874: int ltype, rtype, mtype; ! 2875: struct Listblock *args, *mklist(); ! 2876: Addrp ap; ! 2877: ! 2878: lp = p->exprblock.leftp; ! 2879: rp = p->exprblock.rightp; ! 2880: ltype = lp->headblock.vtype; ! 2881: rtype = rp->headblock.vtype; ! 2882: ! 2883: if(ISICON(rp)) ! 2884: { ! 2885: if(rp->constblock.constant.ci == 0) ! 2886: { ! 2887: frexpr(p); ! 2888: if( ISINT(ltype) ) ! 2889: return( ICON(1) ); ! 2890: else ! 2891: { ! 2892: expptr pp; ! 2893: pp = mkconv(ltype, ICON(1)); ! 2894: return( pp ); ! 2895: } ! 2896: } ! 2897: if(rp->constblock.constant.ci < 0) ! 2898: { ! 2899: if( ISINT(ltype) ) ! 2900: { ! 2901: frexpr(p); ! 2902: err("integer**negative"); ! 2903: return( errnode() ); ! 2904: } ! 2905: rp->constblock.constant.ci = - rp->constblock.constant.ci; ! 2906: p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp)); ! 2907: } ! 2908: if(rp->constblock.constant.ci == 1) ! 2909: { ! 2910: frexpr(rp); ! 2911: free( (charptr) p ); ! 2912: return(lp); ! 2913: } ! 2914: ! 2915: if( ONEOF(ltype, MSKINT|MSKREAL) ) ! 2916: { ! 2917: p->exprblock.vtype = ltype; ! 2918: return(p); ! 2919: } ! 2920: } ! 2921: if( ISINT(rtype) ) ! 2922: { ! 2923: if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) ) ! 2924: q = call2(TYSHORT, "pow_hh", lp, rp); ! 2925: else { ! 2926: if(ltype == TYSHORT) ! 2927: { ! 2928: ltype = TYLONG; ! 2929: lp = mkconv(TYLONG,lp); ! 2930: } ! 2931: q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp)); ! 2932: } ! 2933: } ! 2934: else if( ISREAL( (mtype = maxtype(ltype,rtype)) )) ! 2935: { ! 2936: args = mklist( mkchain( mkconv(TYDREAL,lp), mkchain( mkconv(TYDREAL,rp), CHNULL ) ) ); ! 2937: fixargs(YES, args ); ! 2938: ap = builtin( TYDREAL, "pow" ); ! 2939: ap->vstg = STGINTR; ! 2940: q = fixexpr( mkexpr(OPCCALL, ap, args )); ! 2941: q->exprblock.vtype = mtype; ! 2942: } ! 2943: else { ! 2944: q = call2(TYDCOMPLEX, "pow_zz", ! 2945: mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp)); ! 2946: if(mtype == TYCOMPLEX) ! 2947: q = mkconv(TYCOMPLEX, q); ! 2948: } ! 2949: free( (charptr) p ); ! 2950: return(q); ! 2951: } ! 2952: ! 2953: ! 2954: ! 2955: /* Complex Division. Same code as in Runtime Library ! 2956: */ ! 2957: ! 2958: struct dcomplex { double dreal, dimag; }; ! 2959: ! 2960: ! 2961: LOCAL zdiv(c, a, b) ! 2962: register struct dcomplex *a, *b, *c; ! 2963: { ! 2964: double ratio, den; ! 2965: double abr, abi; ! 2966: ! 2967: setfpe(); ! 2968: ! 2969: if( (abr = b->dreal) < 0.) ! 2970: abr = - abr; ! 2971: if( (abi = b->dimag) < 0.) ! 2972: abi = - abi; ! 2973: if( abr <= abi ) ! 2974: { ! 2975: if(abi == 0) ! 2976: fatal("complex division by zero"); ! 2977: ratio = b->dreal / b->dimag ; ! 2978: den = b->dimag * (1 + ratio*ratio); ! 2979: c->dreal = (a->dreal*ratio + a->dimag) / den; ! 2980: c->dimag = (a->dimag*ratio - a->dreal) / den; ! 2981: } ! 2982: ! 2983: else ! 2984: { ! 2985: ratio = b->dimag / b->dreal ; ! 2986: den = b->dreal * (1 + ratio*ratio); ! 2987: c->dreal = (a->dreal + a->dimag*ratio) / den; ! 2988: c->dimag = (a->dimag - a->dreal*ratio) / den; ! 2989: } ! 2990: ! 2991: } ! 2992: ! 2993: expptr oftwo(e) ! 2994: expptr e; ! 2995: { ! 2996: int val,res; ! 2997: ! 2998: if (! ISCONST (e)) ! 2999: return (0); ! 3000: ! 3001: val = e->constblock.constant.ci; ! 3002: switch (val) ! 3003: { ! 3004: case 2: res = 1; break; ! 3005: case 4: res = 2; break; ! 3006: case 8: res = 3; break; ! 3007: case 16: res = 4; break; ! 3008: case 32: res = 5; break; ! 3009: case 64: res = 6; break; ! 3010: case 128: res = 7; break; ! 3011: case 256: res = 8; break; ! 3012: default: return (0); ! 3013: } ! 3014: return (ICON (res)); ! 3015: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.