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