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