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