|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)rval.c 1.5 10/28/80"; ! 4: ! 5: #include "whoami.h" ! 6: #include "0.h" ! 7: #include "tree.h" ! 8: #include "opcode.h" ! 9: #include "objfmt.h" ! 10: #ifdef PC ! 11: # include "pc.h" ! 12: # include "pcops.h" ! 13: #endif PC ! 14: ! 15: extern char *opnames[]; ! 16: ! 17: /* line number of the last record comparison warning */ ! 18: short reccompline = 0; ! 19: ! 20: #ifdef PC ! 21: char *relts[] = { ! 22: "_RELEQ" , "_RELNE" , ! 23: "_RELTLT" , "_RELTGT" , ! 24: "_RELTLE" , "_RELTGE" ! 25: }; ! 26: char *relss[] = { ! 27: "_RELEQ" , "_RELNE" , ! 28: "_RELSLT" , "_RELSGT" , ! 29: "_RELSLE" , "_RELSGE" ! 30: }; ! 31: long relops[] = { ! 32: P2EQ , P2NE , ! 33: P2LT , P2GT , ! 34: P2LE , P2GE ! 35: }; ! 36: long mathop[] = { P2MUL , P2PLUS , P2MINUS }; ! 37: char *setop[] = { "_MULT" , "_ADDT" , "_SUBT" }; ! 38: #endif PC ! 39: /* ! 40: * Rvalue - an expression. ! 41: * ! 42: * Contype is the type that the caller would prefer, nand is important ! 43: * if constant sets or constant strings are involved, the latter ! 44: * because of string padding. ! 45: * required is a flag whether an lvalue or an rvalue is required. ! 46: * only VARs and structured things can have gt their lvalue this way. ! 47: */ ! 48: struct nl * ! 49: rvalue(r, contype , required ) ! 50: int *r; ! 51: struct nl *contype; ! 52: int required; ! 53: { ! 54: register struct nl *p, *p1; ! 55: register struct nl *q; ! 56: int c, c1, *rt, w, g; ! 57: char *cp, *cp1, *opname; ! 58: long l; ! 59: double f; ! 60: extern int flagwas; ! 61: struct csetstr csetd; ! 62: # ifdef PC ! 63: struct nl *rettype; ! 64: long ctype; ! 65: long tempoff; ! 66: # endif PC ! 67: ! 68: if (r == NIL) ! 69: return (NIL); ! 70: if (nowexp(r)) ! 71: return (NIL); ! 72: /* ! 73: * Pick up the name of the operation ! 74: * for future error messages. ! 75: */ ! 76: if (r[0] <= T_IN) ! 77: opname = opnames[r[0]]; ! 78: ! 79: /* ! 80: * The root of the tree tells us what sort of expression we have. ! 81: */ ! 82: switch (r[0]) { ! 83: ! 84: /* ! 85: * The constant nil ! 86: */ ! 87: case T_NIL: ! 88: # ifdef OBJ ! 89: put(2, O_CON2, 0); ! 90: # endif OBJ ! 91: # ifdef PC ! 92: putleaf( P2ICON , 0 , 0 , P2PTR|P2UNDEF , 0 ); ! 93: # endif PC ! 94: return (nl+TNIL); ! 95: ! 96: /* ! 97: * Function call with arguments. ! 98: */ ! 99: case T_FCALL: ! 100: # ifdef OBJ ! 101: return (funccod(r)); ! 102: # endif OBJ ! 103: # ifdef PC ! 104: return (pcfunccod( r )); ! 105: # endif PC ! 106: ! 107: case T_VAR: ! 108: p = lookup(r[2]); ! 109: if (p == NIL || p->class == BADUSE) ! 110: return (NIL); ! 111: switch (p->class) { ! 112: case VAR: ! 113: /* ! 114: * If a variable is ! 115: * qualified then get ! 116: * the rvalue by a ! 117: * lvalue and an ind. ! 118: */ ! 119: if (r[3] != NIL) ! 120: goto ind; ! 121: q = p->type; ! 122: if (q == NIL) ! 123: return (NIL); ! 124: # ifdef OBJ ! 125: w = width(q); ! 126: switch (w) { ! 127: case 8: ! 128: put(2, O_RV8 | bn << 8+INDX, p->value[0]); ! 129: break; ! 130: case 4: ! 131: put(2, O_RV4 | bn << 8+INDX, p->value[0]); ! 132: break; ! 133: case 2: ! 134: put(2, O_RV2 | bn << 8+INDX, p->value[0]); ! 135: break; ! 136: case 1: ! 137: put(2, O_RV1 | bn << 8+INDX, p->value[0]); ! 138: break; ! 139: default: ! 140: put(3, O_RV | bn << 8+INDX, p->value[0], w); ! 141: } ! 142: # endif OBJ ! 143: # ifdef PC ! 144: if ( required == RREQ ) { ! 145: putRV( p -> symbol , bn , p -> value[0] ! 146: , p2type( q ) ); ! 147: } else { ! 148: putLV( p -> symbol , bn , p -> value[0] ! 149: , p2type( q ) ); ! 150: } ! 151: # endif PC ! 152: return (q); ! 153: ! 154: case WITHPTR: ! 155: case REF: ! 156: /* ! 157: * A lvalue for these ! 158: * is actually what one ! 159: * might consider a rvalue. ! 160: */ ! 161: ind: ! 162: q = lvalue(r, NOFLAGS , LREQ ); ! 163: if (q == NIL) ! 164: return (NIL); ! 165: # ifdef OBJ ! 166: w = width(q); ! 167: switch (w) { ! 168: case 8: ! 169: put(1, O_IND8); ! 170: break; ! 171: case 4: ! 172: put(1, O_IND4); ! 173: break; ! 174: case 2: ! 175: put(1, O_IND2); ! 176: break; ! 177: case 1: ! 178: put(1, O_IND1); ! 179: break; ! 180: default: ! 181: put(2, O_IND, w); ! 182: } ! 183: # endif OBJ ! 184: # ifdef PC ! 185: if ( required == RREQ ) { ! 186: putop( P2UNARY P2MUL , p2type( q ) ); ! 187: } ! 188: # endif PC ! 189: return (q); ! 190: ! 191: case CONST: ! 192: if (r[3] != NIL) { ! 193: error("%s is a constant and cannot be qualified", r[2]); ! 194: return (NIL); ! 195: } ! 196: q = p->type; ! 197: if (q == NIL) ! 198: return (NIL); ! 199: if (q == nl+TSTR) { ! 200: /* ! 201: * Find the size of the string ! 202: * constant if needed. ! 203: */ ! 204: cp = p->ptr[0]; ! 205: cstrng: ! 206: cp1 = cp; ! 207: for (c = 0; *cp++; c++) ! 208: continue; ! 209: if (contype != NIL && !opt('s')) { ! 210: if (width(contype) < c && classify(contype) == TSTR) { ! 211: error("Constant string too long"); ! 212: return (NIL); ! 213: } ! 214: c = width(contype); ! 215: } ! 216: # ifdef OBJ ! 217: put( 2 + (sizeof(char *)/sizeof(short)) ! 218: , O_CONG, c, cp1); ! 219: # endif OBJ ! 220: # ifdef PC ! 221: putCONG( cp1 , c , required ); ! 222: # endif PC ! 223: /* ! 224: * Define the string temporarily ! 225: * so later people can know its ! 226: * width. ! 227: * cleaned out by stat. ! 228: */ ! 229: q = defnl(0, STR, 0, c); ! 230: q->type = q; ! 231: return (q); ! 232: } ! 233: if (q == nl+T1CHAR) { ! 234: # ifdef OBJ ! 235: put(2, O_CONC, p->value[0]); ! 236: # endif OBJ ! 237: # ifdef PC ! 238: putleaf( P2ICON , p -> value[0] , 0 ! 239: , P2CHAR , 0 ); ! 240: # endif PC ! 241: return (q); ! 242: } ! 243: /* ! 244: * Every other kind of constant here ! 245: */ ! 246: switch (width(q)) { ! 247: case 8: ! 248: #ifndef DEBUG ! 249: # ifdef OBJ ! 250: put(2, O_CON8, p->real); ! 251: # endif OBJ ! 252: # ifdef PC ! 253: putCON8( p -> real ); ! 254: # endif PC ! 255: #else ! 256: if (hp21mx) { ! 257: f = p->real; ! 258: conv(&f); ! 259: l = f.plong; ! 260: put(2, O_CON4, l); ! 261: } else ! 262: # ifdef OBJ ! 263: put(2, O_CON8, p->real); ! 264: # endif OBJ ! 265: # ifdef PC ! 266: putCON8( p -> real ); ! 267: # endif PC ! 268: #endif ! 269: break; ! 270: case 4: ! 271: # ifdef OBJ ! 272: put(2, O_CON4, p->range[0]); ! 273: # endif OBJ ! 274: # ifdef PC ! 275: putleaf( P2ICON , p -> range[0] , 0 ! 276: , P2INT , 0 ); ! 277: # endif PC ! 278: break; ! 279: case 2: ! 280: # ifdef OBJ ! 281: put(2, O_CON2, ( short ) p->range[0]); ! 282: # endif OBJ ! 283: # ifdef PC ! 284: /* ! 285: * make short constants ints ! 286: */ ! 287: putleaf( P2ICON , (short) p -> range[0] ! 288: , 0 , P2INT , 0 ); ! 289: # endif PC ! 290: break; ! 291: case 1: ! 292: # ifdef OBJ ! 293: put(2, O_CON1, p->value[0]); ! 294: # endif OBJ ! 295: # ifdef PC ! 296: /* ! 297: * make char constants ints ! 298: */ ! 299: putleaf( P2ICON , p -> value[0] , 0 ! 300: , P2INT , 0 ); ! 301: # endif PC ! 302: break; ! 303: default: ! 304: panic("rval"); ! 305: } ! 306: return (q); ! 307: ! 308: case FUNC: ! 309: case FFUNC: ! 310: /* ! 311: * Function call with no arguments. ! 312: */ ! 313: if (r[3]) { ! 314: error("Can't qualify a function result value"); ! 315: return (NIL); ! 316: } ! 317: # ifdef OBJ ! 318: return (funccod((int *) r)); ! 319: # endif OBJ ! 320: # ifdef PC ! 321: return (pcfunccod( r )); ! 322: # endif PC ! 323: ! 324: case TYPE: ! 325: error("Type names (e.g. %s) allowed only in declarations", p->symbol); ! 326: return (NIL); ! 327: ! 328: case PROC: ! 329: case FPROC: ! 330: error("Procedure %s found where expression required", p->symbol); ! 331: return (NIL); ! 332: default: ! 333: panic("rvid"); ! 334: } ! 335: /* ! 336: * Constant sets ! 337: */ ! 338: case T_CSET: ! 339: # ifdef OBJ ! 340: if ( precset( r , contype , &csetd ) ) { ! 341: if ( csetd.csettype == NIL ) { ! 342: return NIL; ! 343: } ! 344: postcset( r , &csetd ); ! 345: } else { ! 346: put( 2, O_PUSH, -width(csetd.csettype)); ! 347: postcset( r , &csetd ); ! 348: setran( ( csetd.csettype ) -> type ); ! 349: put( 2, O_CON24, set.uprbp); ! 350: put( 2, O_CON24, set.lwrb); ! 351: put( 2, O_CTTOT, 5 + csetd.singcnt + 2 * csetd.paircnt); ! 352: } ! 353: return csetd.csettype; ! 354: # endif OBJ ! 355: # ifdef PC ! 356: if ( precset( r , contype , &csetd ) ) { ! 357: if ( csetd.csettype == NIL ) { ! 358: return NIL; ! 359: } ! 360: postcset( r , &csetd ); ! 361: } else { ! 362: putleaf( P2ICON , 0 , 0 ! 363: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 364: , "_CTTOT" ); ! 365: /* ! 366: * allocate a temporary and use it ! 367: */ ! 368: sizes[ cbn ].om_off -= lwidth( csetd.csettype ); ! 369: tempoff = sizes[ cbn ].om_off; ! 370: putlbracket( ftnno , -tempoff ); ! 371: if ( tempoff < sizes[ cbn ].om_max ) { ! 372: sizes[ cbn ].om_max = tempoff; ! 373: } ! 374: putLV( 0 , cbn , tempoff , P2PTR|P2STRTY ); ! 375: setran( ( csetd.csettype ) -> type ); ! 376: putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 ); ! 377: putop( P2LISTOP , P2INT ); ! 378: putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 ); ! 379: putop( P2LISTOP , P2INT ); ! 380: postcset( r , &csetd ); ! 381: putop( P2CALL , P2INT ); ! 382: } ! 383: return csetd.csettype; ! 384: # endif PC ! 385: ! 386: /* ! 387: * Unary plus and minus ! 388: */ ! 389: case T_PLUS: ! 390: case T_MINUS: ! 391: q = rvalue(r[2], NIL , RREQ ); ! 392: if (q == NIL) ! 393: return (NIL); ! 394: if (isnta(q, "id")) { ! 395: error("Operand of %s must be integer or real, not %s", opname, nameof(q)); ! 396: return (NIL); ! 397: } ! 398: if (r[0] == T_MINUS) { ! 399: # ifdef OBJ ! 400: put(1, O_NEG2 + (width(q) >> 2)); ! 401: # endif OBJ ! 402: # ifdef PC ! 403: putop( P2UNARY P2MINUS , p2type( q ) ); ! 404: # endif PC ! 405: return (isa(q, "d") ? q : nl+T4INT); ! 406: } ! 407: return (q); ! 408: ! 409: case T_NOT: ! 410: q = rvalue(r[2], NIL , RREQ ); ! 411: if (q == NIL) ! 412: return (NIL); ! 413: if (isnta(q, "b")) { ! 414: error("not must operate on a Boolean, not %s", nameof(q)); ! 415: return (NIL); ! 416: } ! 417: # ifdef OBJ ! 418: put(1, O_NOT); ! 419: # endif OBJ ! 420: # ifdef PC ! 421: putop( P2NOT , P2INT ); ! 422: # endif PC ! 423: return (nl+T1BOOL); ! 424: ! 425: case T_AND: ! 426: case T_OR: ! 427: p = rvalue(r[2], NIL , RREQ ); ! 428: p1 = rvalue(r[3], NIL , RREQ ); ! 429: if (p == NIL || p1 == NIL) ! 430: return (NIL); ! 431: if (isnta(p, "b")) { ! 432: error("Left operand of %s must be Boolean, not %s", opname, nameof(p)); ! 433: return (NIL); ! 434: } ! 435: if (isnta(p1, "b")) { ! 436: error("Right operand of %s must be Boolean, not %s", opname, nameof(p1)); ! 437: return (NIL); ! 438: } ! 439: # ifdef OBJ ! 440: put(1, r[0] == T_AND ? O_AND : O_OR); ! 441: # endif OBJ ! 442: # ifdef PC ! 443: /* ! 444: * note the use of & and | rather than && and || ! 445: * to force evaluation of all the expressions. ! 446: */ ! 447: putop( r[ 0 ] == T_AND ? P2AND : P2OR , P2INT ); ! 448: # endif PC ! 449: return (nl+T1BOOL); ! 450: ! 451: case T_DIVD: ! 452: # ifdef OBJ ! 453: p = rvalue(r[2], NIL , RREQ ); ! 454: p1 = rvalue(r[3], NIL , RREQ ); ! 455: # endif OBJ ! 456: # ifdef PC ! 457: /* ! 458: * force these to be doubles for the divide ! 459: */ ! 460: p = rvalue( r[ 2 ] , NIL , RREQ ); ! 461: if ( isnta( p , "d" ) ) { ! 462: putop( P2SCONV , P2DOUBLE ); ! 463: } ! 464: p1 = rvalue( r[ 3 ] , NIL , RREQ ); ! 465: if ( isnta( p1 , "d" ) ) { ! 466: putop( P2SCONV , P2DOUBLE ); ! 467: } ! 468: # endif PC ! 469: if (p == NIL || p1 == NIL) ! 470: return (NIL); ! 471: if (isnta(p, "id")) { ! 472: error("Left operand of / must be integer or real, not %s", nameof(p)); ! 473: return (NIL); ! 474: } ! 475: if (isnta(p1, "id")) { ! 476: error("Right operand of / must be integer or real, not %s", nameof(p1)); ! 477: return (NIL); ! 478: } ! 479: # ifdef OBJ ! 480: return gen(NIL, r[0], width(p), width(p1)); ! 481: # endif OBJ ! 482: # ifdef PC ! 483: putop( P2DIV , P2DOUBLE ); ! 484: return nl + TDOUBLE; ! 485: # endif PC ! 486: ! 487: case T_MULT: ! 488: case T_ADD: ! 489: case T_SUB: ! 490: # ifdef OBJ ! 491: /* ! 492: * If the context hasn't told us the type ! 493: * and a constant set is present ! 494: * we need to infer the type ! 495: * before generating code. ! 496: */ ! 497: if ( contype == NIL ) { ! 498: codeoff(); ! 499: contype = rvalue( r[3] , NIL , RREQ ); ! 500: codeon(); ! 501: if ( contype == lookup( intset ) -> type ) { ! 502: codeoff(); ! 503: contype = rvalue( r[2] , NIL , RREQ ); ! 504: codeon(); ! 505: } ! 506: } ! 507: if ( contype == NIL ) { ! 508: return NIL; ! 509: } ! 510: p = rvalue( r[2] , contype , RREQ ); ! 511: p1 = rvalue( r[3] , p , RREQ ); ! 512: if ( p == NIL || p1 == NIL ) ! 513: return NIL; ! 514: if (isa(p, "id") && isa(p1, "id")) ! 515: return (gen(NIL, r[0], width(p), width(p1))); ! 516: if (isa(p, "t") && isa(p1, "t")) { ! 517: if (p != p1) { ! 518: error("Set types of operands of %s must be identical", opname); ! 519: return (NIL); ! 520: } ! 521: gen(TSET, r[0], width(p), 0); ! 522: return (p); ! 523: } ! 524: # endif OBJ ! 525: # ifdef PC ! 526: /* ! 527: * the second pass can't do ! 528: * long op double or double op long ! 529: * so we have to know the type of both operands ! 530: * also, it gets tricky for sets, which are done ! 531: * by function calls. ! 532: */ ! 533: codeoff(); ! 534: p1 = rvalue( r[ 3 ] , contype , RREQ ); ! 535: codeon(); ! 536: if ( isa( p1 , "id" ) ) { ! 537: p = rvalue( r[ 2 ] , contype , RREQ ); ! 538: if ( ( p == NIL ) || ( p1 == NIL ) ) { ! 539: return NIL; ! 540: } ! 541: if ( isa( p , "i" ) && isa( p1 , "d" ) ) { ! 542: putop( P2SCONV , P2DOUBLE ); ! 543: } ! 544: p1 = rvalue( r[ 3 ] , contype , RREQ ); ! 545: if ( isa( p , "d" ) && isa( p1 , "i" ) ) { ! 546: putop( P2SCONV , P2DOUBLE ); ! 547: } ! 548: if ( isa( p , "id" ) ) { ! 549: if ( isa( p , "d" ) || isa( p1 , "d" ) ) { ! 550: ctype = P2DOUBLE; ! 551: rettype = nl + TDOUBLE; ! 552: } else { ! 553: ctype = P2INT; ! 554: rettype = nl + T4INT; ! 555: } ! 556: putop( mathop[ r[0] - T_MULT ] , ctype ); ! 557: return rettype; ! 558: } ! 559: } ! 560: if ( isa( p1 , "t" ) ) { ! 561: putleaf( P2ICON , 0 , 0 ! 562: , ADDTYPE( ADDTYPE( P2PTR | P2STRTY , P2FTN ) ! 563: , P2PTR ) ! 564: , setop[ r[0] - T_MULT ] ); ! 565: if ( contype == NIL ) { ! 566: contype = p1; ! 567: if ( contype == lookup( intset ) -> type ) { ! 568: codeoff(); ! 569: contype = rvalue( r[2] , NIL , LREQ ); ! 570: codeon(); ! 571: } ! 572: } ! 573: if ( contype == NIL ) { ! 574: return NIL; ! 575: } ! 576: /* ! 577: * allocate a temporary and use it ! 578: */ ! 579: sizes[ cbn ].om_off -= lwidth( contype ); ! 580: tempoff = sizes[ cbn ].om_off; ! 581: putlbracket( ftnno , -tempoff ); ! 582: if ( tempoff < sizes[ cbn ].om_max ) { ! 583: sizes[ cbn ].om_max = tempoff; ! 584: } ! 585: putLV( 0 , cbn , tempoff , P2PTR|P2STRTY ); ! 586: p = rvalue( r[2] , contype , LREQ ); ! 587: if ( isa( p , "t" ) ) { ! 588: putop( P2LISTOP , P2INT ); ! 589: if ( p == NIL || p1 == NIL ) { ! 590: return NIL; ! 591: } ! 592: p1 = rvalue( r[3] , p , LREQ ); ! 593: if ( p != p1 ) { ! 594: error("Set types of operands of %s must be identical", opname); ! 595: return NIL; ! 596: } ! 597: putop( P2LISTOP , P2INT ); ! 598: putleaf( P2ICON , lwidth( p1 ) / sizeof( long ) , 0 ! 599: , P2INT , 0 ); ! 600: putop( P2LISTOP , P2INT ); ! 601: putop( P2CALL , P2PTR | P2STRTY ); ! 602: return p; ! 603: } ! 604: } ! 605: if ( isnta( p1 , "idt" ) ) { ! 606: /* ! 607: * find type of left operand for error message. ! 608: */ ! 609: p = rvalue( r[2] , contype , RREQ ); ! 610: } ! 611: /* ! 612: * don't give spurious error messages. ! 613: */ ! 614: if ( p == NIL || p1 == NIL ) { ! 615: return NIL; ! 616: } ! 617: # endif PC ! 618: if (isnta(p, "idt")) { ! 619: error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p)); ! 620: return (NIL); ! 621: } ! 622: if (isnta(p1, "idt")) { ! 623: error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1)); ! 624: return (NIL); ! 625: } ! 626: error("Cannot mix sets with integers and reals as operands of %s", opname); ! 627: return (NIL); ! 628: ! 629: case T_MOD: ! 630: case T_DIV: ! 631: p = rvalue(r[2], NIL , RREQ ); ! 632: p1 = rvalue(r[3], NIL , RREQ ); ! 633: if (p == NIL || p1 == NIL) ! 634: return (NIL); ! 635: if (isnta(p, "i")) { ! 636: error("Left operand of %s must be integer, not %s", opname, nameof(p)); ! 637: return (NIL); ! 638: } ! 639: if (isnta(p1, "i")) { ! 640: error("Right operand of %s must be integer, not %s", opname, nameof(p1)); ! 641: return (NIL); ! 642: } ! 643: # ifdef OBJ ! 644: return (gen(NIL, r[0], width(p), width(p1))); ! 645: # endif OBJ ! 646: # ifdef PC ! 647: putop( r[ 0 ] == T_DIV ? P2DIV : P2MOD , P2INT ); ! 648: return ( nl + T4INT ); ! 649: # endif PC ! 650: ! 651: case T_EQ: ! 652: case T_NE: ! 653: case T_LT: ! 654: case T_GT: ! 655: case T_LE: ! 656: case T_GE: ! 657: /* ! 658: * Since there can be no, a priori, knowledge ! 659: * of the context type should a constant string ! 660: * or set arise, we must poke around to find such ! 661: * a type if possible. Since constant strings can ! 662: * always masquerade as identifiers, this is always ! 663: * necessary. ! 664: */ ! 665: codeoff(); ! 666: p1 = rvalue(r[3], NIL , RREQ ); ! 667: codeon(); ! 668: if (p1 == NIL) ! 669: return (NIL); ! 670: contype = p1; ! 671: # ifdef OBJ ! 672: if (p1->class == STR) { ! 673: /* ! 674: * For constant strings we want ! 675: * the longest type so as to be ! 676: * able to do padding (more importantly ! 677: * avoiding truncation). For clarity, ! 678: * we get this length here. ! 679: */ ! 680: codeoff(); ! 681: p = rvalue(r[2], NIL , RREQ ); ! 682: codeon(); ! 683: if (p == NIL) ! 684: return (NIL); ! 685: if (width(p) > width(p1)) ! 686: contype = p; ! 687: } else if ( isa( p1 , "t" ) ) { ! 688: if ( contype == lookup( intset ) -> type ) { ! 689: codeoff(); ! 690: contype = rvalue( r[2] , NIL , RREQ ); ! 691: codeon(); ! 692: if ( contype == NIL ) { ! 693: return NIL; ! 694: } ! 695: } ! 696: } ! 697: /* ! 698: * Now we generate code for ! 699: * the operands of the relational ! 700: * operation. ! 701: */ ! 702: p = rvalue(r[2], contype , RREQ ); ! 703: if (p == NIL) ! 704: return (NIL); ! 705: p1 = rvalue(r[3], p , RREQ ); ! 706: if (p1 == NIL) ! 707: return (NIL); ! 708: # endif OBJ ! 709: # ifdef PC ! 710: c1 = classify( p1 ); ! 711: if ( c1 == TSET || c1 == TSTR || c1 == TREC ) { ! 712: putleaf( P2ICON , 0 , 0 ! 713: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 714: , c1 == TSET ? relts[ r[0] - T_EQ ] ! 715: : relss[ r[0] - T_EQ ] ); ! 716: /* ! 717: * for [] and strings, comparisons are done on ! 718: * the maximum width of the two sides. ! 719: * for other sets, we have to ask the left side ! 720: * what type it is based on the type of the right. ! 721: * (this matters for intsets). ! 722: */ ! 723: if ( c1 == TSTR ) { ! 724: codeoff(); ! 725: p = rvalue( r[ 2 ] , NIL , LREQ ); ! 726: codeon(); ! 727: if ( p == NIL ) { ! 728: return NIL; ! 729: } ! 730: if ( lwidth( p ) > lwidth( p1 ) ) { ! 731: contype = p; ! 732: } ! 733: } else if ( c1 == TSET ) { ! 734: if ( contype == lookup( intset ) -> type ) { ! 735: codeoff(); ! 736: p = rvalue( r[ 2 ] , NIL , LREQ ); ! 737: codeon(); ! 738: if ( p == NIL ) { ! 739: return NIL; ! 740: } ! 741: contype = p; ! 742: } ! 743: } ! 744: /* ! 745: * put out the width of the comparison. ! 746: */ ! 747: putleaf( P2ICON , lwidth( contype ) , 0 , P2INT , 0 ); ! 748: /* ! 749: * and the left hand side, ! 750: * for sets, strings, records ! 751: */ ! 752: p = rvalue( r[ 2 ] , contype , LREQ ); ! 753: putop( P2LISTOP , P2INT ); ! 754: p1 = rvalue( r[ 3 ] , p , LREQ ); ! 755: putop( P2LISTOP , P2INT ); ! 756: putop( P2CALL , P2INT ); ! 757: } else { ! 758: /* ! 759: * the easy (scalar or error) case ! 760: */ ! 761: p = rvalue( r[ 2 ] , contype , RREQ ); ! 762: if ( p == NIL ) { ! 763: return NIL; ! 764: /* ! 765: * since the second pass can't do ! 766: * long op double or double op long ! 767: * we may have to do some coercing. ! 768: */ ! 769: if ( isa( p , "i" ) && isa( p1 , "d" ) ) ! 770: putop( P2SCONV , P2DOUBLE ); ! 771: } ! 772: p1 = rvalue( r[ 3 ] , p , RREQ ); ! 773: if ( isa( p , "d" ) && isa( p1 , "i" ) ) ! 774: putop( P2SCONV , P2DOUBLE ); ! 775: putop( relops[ r[0] - T_EQ ] , P2INT ); ! 776: } ! 777: # endif PC ! 778: c = classify(p); ! 779: c1 = classify(p1); ! 780: if (nocomp(c) || nocomp(c1)) ! 781: return (NIL); ! 782: g = NIL; ! 783: switch (c) { ! 784: case TBOOL: ! 785: case TCHAR: ! 786: if (c != c1) ! 787: goto clash; ! 788: break; ! 789: case TINT: ! 790: case TDOUBLE: ! 791: if (c1 != TINT && c1 != TDOUBLE) ! 792: goto clash; ! 793: break; ! 794: case TSCAL: ! 795: if (c1 != TSCAL) ! 796: goto clash; ! 797: if (scalar(p) != scalar(p1)) ! 798: goto nonident; ! 799: break; ! 800: case TSET: ! 801: if (c1 != TSET) ! 802: goto clash; ! 803: if (p != p1) ! 804: goto nonident; ! 805: g = TSET; ! 806: break; ! 807: case TREC: ! 808: if ( c1 != TREC ) { ! 809: goto clash; ! 810: } ! 811: if ( p != p1 ) { ! 812: goto nonident; ! 813: } ! 814: if (r[0] != T_EQ && r[0] != T_NE) { ! 815: error("%s not allowed on records - only allow = and <>" , opname ); ! 816: return (NIL); ! 817: } ! 818: g = TREC; ! 819: break; ! 820: case TPTR: ! 821: case TNIL: ! 822: if (c1 != TPTR && c1 != TNIL) ! 823: goto clash; ! 824: if (r[0] != T_EQ && r[0] != T_NE) { ! 825: error("%s not allowed on pointers - only allow = and <>" , opname ); ! 826: return (NIL); ! 827: } ! 828: break; ! 829: case TSTR: ! 830: if (c1 != TSTR) ! 831: goto clash; ! 832: if (width(p) != width(p1)) { ! 833: error("Strings not same length in %s comparison", opname); ! 834: return (NIL); ! 835: } ! 836: g = TSTR; ! 837: break; ! 838: default: ! 839: panic("rval2"); ! 840: } ! 841: # ifdef OBJ ! 842: return (gen(g, r[0], width(p), width(p1))); ! 843: # endif OBJ ! 844: # ifdef PC ! 845: return nl + TBOOL; ! 846: # endif PC ! 847: clash: ! 848: error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname); ! 849: return (NIL); ! 850: nonident: ! 851: error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname); ! 852: return (NIL); ! 853: ! 854: case T_IN: ! 855: rt = r[3]; ! 856: # ifdef OBJ ! 857: if (rt != NIL && rt[0] == T_CSET) { ! 858: precset( rt , NIL , &csetd ); ! 859: p1 = csetd.csettype; ! 860: if (p1 == NIL) ! 861: return NIL; ! 862: postcset( rt, &csetd); ! 863: } else { ! 864: p1 = stkrval(r[3], NIL , RREQ ); ! 865: rt = NIL; ! 866: } ! 867: # endif OBJ ! 868: # ifdef PC ! 869: if (rt != NIL && rt[0] == T_CSET) { ! 870: if ( precset( rt , NIL , &csetd ) ) { ! 871: putleaf( P2ICON , 0 , 0 ! 872: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 873: , "_IN" ); ! 874: } else { ! 875: putleaf( P2ICON , 0 , 0 ! 876: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 877: , "_INCT" ); ! 878: } ! 879: p1 = csetd.csettype; ! 880: if (p1 == NIL) ! 881: return NIL; ! 882: } else { ! 883: putleaf( P2ICON , 0 , 0 ! 884: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 885: , "_IN" ); ! 886: codeoff(); ! 887: p1 = rvalue(r[3], NIL , LREQ ); ! 888: codeon(); ! 889: } ! 890: # endif PC ! 891: p = stkrval(r[2], NIL , RREQ ); ! 892: if (p == NIL || p1 == NIL) ! 893: return (NIL); ! 894: if (p1->class != SET) { ! 895: error("Right operand of 'in' must be a set, not %s", nameof(p1)); ! 896: return (NIL); ! 897: } ! 898: if (incompat(p, p1->type, r[2])) { ! 899: cerror("Index type clashed with set component type for 'in'"); ! 900: return (NIL); ! 901: } ! 902: setran(p1->type); ! 903: # ifdef OBJ ! 904: if (rt == NIL || csetd.comptime) ! 905: put(4, O_IN, width(p1), set.lwrb, set.uprbp); ! 906: else ! 907: put(2, O_INCT, 3 + csetd.singcnt + 2*csetd.paircnt); ! 908: # endif OBJ ! 909: # ifdef PC ! 910: if ( rt == NIL || rt[0] != T_CSET ) { ! 911: putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 ); ! 912: putop( P2LISTOP , P2INT ); ! 913: putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 ); ! 914: putop( P2LISTOP , P2INT ); ! 915: p1 = rvalue( r[3] , NIL , LREQ ); ! 916: putop( P2LISTOP , P2INT ); ! 917: } else if ( csetd.comptime ) { ! 918: putleaf( P2ICON , set.lwrb , 0 , P2INT , 0 ); ! 919: putop( P2LISTOP , P2INT ); ! 920: putleaf( P2ICON , set.uprbp , 0 , P2INT , 0 ); ! 921: putop( P2LISTOP , P2INT ); ! 922: postcset( r[3] , &csetd ); ! 923: putop( P2LISTOP , P2INT ); ! 924: } else { ! 925: postcset( r[3] , &csetd ); ! 926: } ! 927: putop( P2CALL , P2INT ); ! 928: # endif PC ! 929: return (nl+T1BOOL); ! 930: default: ! 931: if (r[2] == NIL) ! 932: return (NIL); ! 933: switch (r[0]) { ! 934: default: ! 935: panic("rval3"); ! 936: ! 937: ! 938: /* ! 939: * An octal number ! 940: */ ! 941: case T_BINT: ! 942: f = a8tol(r[2]); ! 943: goto conint; ! 944: ! 945: /* ! 946: * A decimal number ! 947: */ ! 948: case T_INT: ! 949: f = atof(r[2]); ! 950: conint: ! 951: if (f > MAXINT || f < MININT) { ! 952: error("Constant too large for this implementation"); ! 953: return (NIL); ! 954: } ! 955: l = f; ! 956: if (bytes(l, l) <= 2) { ! 957: # ifdef OBJ ! 958: put(2, O_CON2, ( short ) l); ! 959: # endif OBJ ! 960: # ifdef PC ! 961: /* ! 962: * short constants are ints ! 963: */ ! 964: putleaf( P2ICON , l , 0 , P2INT , 0 ); ! 965: # endif PC ! 966: return (nl+T2INT); ! 967: } ! 968: # ifdef OBJ ! 969: put(2, O_CON4, l); ! 970: # endif OBJ ! 971: # ifdef PC ! 972: putleaf( P2ICON , l , 0 , P2INT , 0 ); ! 973: # endif PC ! 974: return (nl+T4INT); ! 975: ! 976: /* ! 977: * A floating point number ! 978: */ ! 979: case T_FINT: ! 980: # ifdef OBJ ! 981: put(2, O_CON8, atof(r[2])); ! 982: # endif OBJ ! 983: # ifdef PC ! 984: putCON8( atof( r[2] ) ); ! 985: # endif PC ! 986: return (nl+TDOUBLE); ! 987: ! 988: /* ! 989: * Constant strings. Note that constant characters ! 990: * are constant strings of length one; there is ! 991: * no constant string of length one. ! 992: */ ! 993: case T_STRNG: ! 994: cp = r[2]; ! 995: if (cp[1] == 0) { ! 996: # ifdef OBJ ! 997: put(2, O_CONC, cp[0]); ! 998: # endif OBJ ! 999: # ifdef PC ! 1000: putleaf( P2ICON , cp[0] , 0 , P2CHAR , 0 ); ! 1001: # endif PC ! 1002: return (nl+T1CHAR); ! 1003: } ! 1004: goto cstrng; ! 1005: } ! 1006: ! 1007: } ! 1008: } ! 1009: ! 1010: /* ! 1011: * Can a class appear ! 1012: * in a comparison ? ! 1013: */ ! 1014: nocomp(c) ! 1015: int c; ! 1016: { ! 1017: ! 1018: switch (c) { ! 1019: case TREC: ! 1020: if ( line != reccompline ) { ! 1021: reccompline = line; ! 1022: warning(); ! 1023: if ( opt( 's' ) ) { ! 1024: standard(); ! 1025: } ! 1026: error("record comparison is non-standard"); ! 1027: } ! 1028: break; ! 1029: case TFILE: ! 1030: case TARY: ! 1031: error("%ss may not participate in comparisons", clnames[c]); ! 1032: return (1); ! 1033: } ! 1034: return (NIL); ! 1035: } ! 1036: ! 1037: /* ! 1038: * this is sort of like gconst, except it works on expression trees ! 1039: * rather than declaration trees, and doesn't give error messages for ! 1040: * non-constant things. ! 1041: * as a side effect this fills in the con structure that gconst uses. ! 1042: * this returns TRUE or FALSE. ! 1043: */ ! 1044: constval(r) ! 1045: register int *r; ! 1046: { ! 1047: register struct nl *np; ! 1048: register *cn; ! 1049: char *cp; ! 1050: int negd, sgnd; ! 1051: long ci; ! 1052: ! 1053: con.ctype = NIL; ! 1054: cn = r; ! 1055: negd = sgnd = 0; ! 1056: loop: ! 1057: /* ! 1058: * cn[2] is nil if error recovery generated a T_STRNG ! 1059: */ ! 1060: if (cn == NIL || cn[2] == NIL) ! 1061: return FALSE; ! 1062: switch (cn[0]) { ! 1063: default: ! 1064: return FALSE; ! 1065: case T_MINUS: ! 1066: negd = 1 - negd; ! 1067: /* and fall through */ ! 1068: case T_PLUS: ! 1069: sgnd++; ! 1070: cn = cn[2]; ! 1071: goto loop; ! 1072: case T_NIL: ! 1073: con.cpval = NIL; ! 1074: con.cival = 0; ! 1075: con.crval = con.cival; ! 1076: con.ctype = nl + TNIL; ! 1077: break; ! 1078: case T_VAR: ! 1079: np = lookup(cn[2]); ! 1080: if (np == NIL || np->class != CONST) { ! 1081: return FALSE; ! 1082: } ! 1083: if ( cn[3] != NIL ) { ! 1084: return FALSE; ! 1085: } ! 1086: con.ctype = np->type; ! 1087: switch (classify(np->type)) { ! 1088: case TINT: ! 1089: con.crval = np->range[0]; ! 1090: break; ! 1091: case TDOUBLE: ! 1092: con.crval = np->real; ! 1093: break; ! 1094: case TBOOL: ! 1095: case TCHAR: ! 1096: case TSCAL: ! 1097: con.cival = np->value[0]; ! 1098: con.crval = con.cival; ! 1099: break; ! 1100: case TSTR: ! 1101: con.cpval = np->ptr[0]; ! 1102: break; ! 1103: default: ! 1104: con.ctype = NIL; ! 1105: return FALSE; ! 1106: } ! 1107: break; ! 1108: case T_BINT: ! 1109: con.crval = a8tol(cn[2]); ! 1110: goto restcon; ! 1111: case T_INT: ! 1112: con.crval = atof(cn[2]); ! 1113: if (con.crval > MAXINT || con.crval < MININT) { ! 1114: derror("Constant too large for this implementation"); ! 1115: con.crval = 0; ! 1116: } ! 1117: restcon: ! 1118: ci = con.crval; ! 1119: #ifndef PI0 ! 1120: if (bytes(ci, ci) <= 2) ! 1121: con.ctype = nl+T2INT; ! 1122: else ! 1123: #endif ! 1124: con.ctype = nl+T4INT; ! 1125: break; ! 1126: case T_FINT: ! 1127: con.ctype = nl+TDOUBLE; ! 1128: con.crval = atof(cn[2]); ! 1129: break; ! 1130: case T_STRNG: ! 1131: cp = cn[2]; ! 1132: if (cp[1] == 0) { ! 1133: con.ctype = nl+T1CHAR; ! 1134: con.cival = cp[0]; ! 1135: con.crval = con.cival; ! 1136: break; ! 1137: } ! 1138: con.ctype = nl+TSTR; ! 1139: con.cpval = cp; ! 1140: break; ! 1141: } ! 1142: if (sgnd) { ! 1143: if (isnta(con.ctype, "id")) { ! 1144: derror("%s constants cannot be signed", nameof(con.ctype)); ! 1145: return FALSE; ! 1146: } else if (negd) ! 1147: con.crval = -con.crval; ! 1148: } ! 1149: return TRUE; ! 1150: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.