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.2 (Berkeley) 04/07/87"; 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 # ifdef tahoe 653 /* prepare for ediv workaround, see below. */ 654 if (r->tag == T_MOD) { 655 (void) rvalue(r->expr_node.lhs, NLNIL, RREQ); 656 sconv(p2type(p), PCCT_INT); 657 } 658 # endif tahoe 659 # endif PC 660 p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 661 # ifdef PC 662 sconv(p2type(p1), PCCT_INT); 663 # endif PC 664 if (p == NLNIL || p1 == NLNIL) 665 return (NLNIL); 666 if (isnta(p, "i")) { 667 error("Left operand of %s must be integer, not %s", opname, nameof(p)); 668 return (NLNIL); 669 } 670 if (isnta(p1, "i")) { 671 error("Right operand of %s must be integer, not %s", opname, nameof(p1)); 672 return (NLNIL); 673 } 674 # ifdef OBJ 675 return (gen(NIL, r->tag, width(p), width(p1))); 676 # endif OBJ 677 # ifdef PC 678 # ifndef tahoe 679 putop( r->tag == T_DIV ? PCC_DIV : PCC_MOD , PCCT_INT ); 680 return ( nl + T4INT ); 681 # else tahoe 682 putop( PCC_DIV , PCCT_INT ); 683 if (r->tag == T_MOD) { 684 /* 685 * avoid f1 bug: PCC_MOD would generate an 'ediv', 686 * which would reuire too many registers to evaluate 687 * things like 688 * var i:boolean;j:integer; i := (j+1) = (j mod 2); 689 * so, instead of 690 * PCC_MOD 691 * / \ 692 * p p1 693 * we put 694 * PCC_MINUS 695 * / \ 696 * p PCC_MUL 697 * / \ 698 * PCC_DIV p1 699 * / \ 700 * p p1 701 * 702 * we already have put p, p, p1, PCC_DIV. and now... 703 */ 704 rvalue(r->expr_node.rhs, NLNIL , RREQ ); 705 sconv(p2type(p1), PCCT_INT); 706 putop( PCC_MUL, PCCT_INT ); 707 putop( PCC_MINUS, PCCT_INT ); 708 } 709 return ( nl + T4INT ); 710 # endif tahoe 711 # endif PC 712 713 case T_EQ: 714 case T_NE: 715 case T_LT: 716 case T_GT: 717 case T_LE: 718 case T_GE: 719 /* 720 * Since there can be no, a priori, knowledge 721 * of the context type should a constant string 722 * or set arise, we must poke around to find such 723 * a type if possible. Since constant strings can 724 * always masquerade as identifiers, this is always 725 * necessary. 726 * see the note in the obj section of case T_MULT above 727 * for the determination of the base type of empty sets. 728 */ 729 codeoff(); 730 p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ ); 731 codeon(); 732 if (p1 == NLNIL) 733 return (NLNIL); 734 contype = p1; 735 # ifdef OBJ 736 if (p1->class == STR) { 737 /* 738 * For constant strings we want 739 * the longest type so as to be 740 * able to do padding (more importantly 741 * avoiding truncation). For clarity, 742 * we get this length here. 743 */ 744 codeoff(); 745 p = rvalue(r->expr_node.lhs, NLNIL , RREQ ); 746 codeon(); 747 if (p == NLNIL) 748 return (NLNIL); 749 if (width(p) > width(p1)) 750 contype = p; 751 } 752 if (isa(p1, "t")) { 753 codeoff(); 754 contype = rvalue(r->expr_node.lhs, p1, RREQ); 755 codeon(); 756 if (contype == NLNIL) { 757 return NLNIL; 758 } 759 } 760 /* 761 * Now we generate code for 762 * the operands of the relational 763 * operation. 764 */ 765 p = rvalue(r->expr_node.lhs, contype , RREQ ); 766 if (p == NLNIL) 767 return (NLNIL); 768 p1 = rvalue(r->expr_node.rhs, p , RREQ ); 769 if (p1 == NLNIL) 770 return (NLNIL); 771 # endif OBJ 772 # ifdef PC 773 c1 = classify( p1 ); 774 if ( c1 == TSET || c1 == TSTR || c1 == TREC ) { 775 putleaf( PCC_ICON , 0 , 0 776 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 777 , c1 == TSET ? relts[ r->tag - T_EQ ] 778 : relss[ r->tag - T_EQ ] ); 779 /* 780 * for [] and strings, comparisons are done on 781 * the maximum width of the two sides. 782 * for other sets, we have to ask the left side 783 * what type it is based on the type of the right. 784 * (this matters for intsets). 785 */ 786 if ( c1 == TSTR ) { 787 codeoff(); 788 p = rvalue( r->expr_node.lhs , NLNIL , LREQ ); 789 codeon(); 790 if ( p == NLNIL ) { 791 return NLNIL; 792 } 793 if ( lwidth( p ) > lwidth( p1 ) ) { 794 contype = p; 795 } 796 } else if ( c1 == TSET ) { 797 codeoff(); 798 contype = rvalue(r->expr_node.lhs, p1, LREQ); 799 codeon(); 800 if (contype == NLNIL) { 801 return NLNIL; 802 } 803 } 804 /* 805 * put out the width of the comparison. 806 */ 807 putleaf(PCC_ICON, (int) lwidth(contype), 0, PCCT_INT, (char *) 0); 808 /* 809 * and the left hand side, 810 * for sets, strings, records 811 */ 812 p = rvalue( r->expr_node.lhs , contype , LREQ ); 813 if ( p == NLNIL ) { 814 return NLNIL; 815 } 816 putop( PCC_CM , PCCT_INT ); 817 p1 = rvalue( r->expr_node.rhs , p , LREQ ); 818 if ( p1 == NLNIL ) { 819 return NLNIL; 820 } 821 putop( PCC_CM , PCCT_INT ); 822 putop( PCC_CALL , PCCT_INT ); 823 } else { 824 /* 825 * the easy (scalar or error) case 826 */ 827 p = rvalue( r->expr_node.lhs , contype , RREQ ); 828 if ( p == NLNIL ) { 829 return NLNIL; 830 } 831 /* 832 * since the second pass can't do 833 * long op double or double op long 834 * we may have to do some coercing. 835 */ 836 tuac(p, p1, &rettype, (int *) (&ctype)); 837 p1 = rvalue( r->expr_node.rhs , p , RREQ ); 838 if ( p1 == NLNIL ) { 839 return NLNIL; 840 } 841 tuac(p1, p, &rettype, (int *) (&ctype)); 842 putop((int) relops[ r->tag - T_EQ ] , PCCT_INT ); 843 sconv(PCCT_INT, PCCT_CHAR); 844 } 845 # endif PC 846 c = classify(p); 847 c1 = classify(p1); 848 if (nocomp(c) || nocomp(c1)) 849 return (NLNIL); 850 # ifdef OBJ 851 g = NIL; 852 # endif 853 switch (c) { 854 case TBOOL: 855 case TCHAR: 856 if (c != c1) 857 goto clash; 858 break; 859 case TINT: 860 case TDOUBLE: 861 if (c1 != TINT && c1 != TDOUBLE) 862 goto clash; 863 break; 864 case TSCAL: 865 if (c1 != TSCAL) 866 goto clash; 867 if (scalar(p) != scalar(p1)) 868 goto nonident; 869 break; 870 case TSET: 871 if (c1 != TSET) 872 goto clash; 873 if ( opt( 's' ) && 874 ( ( r->tag == T_LT) || (r->tag == T_GT) ) && 875 ( line != nssetline ) ) { 876 nssetline = line; 877 standard(); 878 error("%s comparison on sets is non-standard" , opname ); 879 } 880 if (p != p1) 881 goto nonident; 882 # ifdef OBJ 883 g = TSET; 884 # endif 885 break; 886 case TREC: 887 if ( c1 != TREC ) { 888 goto clash; 889 } 890 if ( p != p1 ) { 891 goto nonident; 892 } 893 if (r->tag != T_EQ && r->tag != T_NE) { 894 error("%s not allowed on records - only allow = and <>" , opname ); 895 return (NLNIL); 896 } 897 # ifdef OBJ 898 g = TREC; 899 # endif 900 break; 901 case TPTR: 902 case TNIL: 903 if (c1 != TPTR && c1 != TNIL) 904 goto clash; 905 if (r->tag != T_EQ && r->tag != T_NE) { 906 error("%s not allowed on pointers - only allow = and <>" , opname ); 907 return (NLNIL); 908 } 909 if (p != nl+TNIL && p1 != nl+TNIL && p != p1) 910 goto nonident; 911 break; 912 case TSTR: 913 if (c1 != TSTR) 914 goto clash; 915 if (width(p) != width(p1)) { 916 error("Strings not same length in %s comparison", opname); 917 return (NLNIL); 918 } 919 # ifdef OBJ 920 g = TSTR; 921 # endif OBJ 922 break; 923 default: 924 panic("rval2"); 925 } 926 # ifdef OBJ 927 return (gen(g, r->tag, width(p), width(p1))); 928 # endif OBJ 929 # ifdef PC 930 return nl + TBOOL; 931 # endif PC 932 clash: 933 error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname); 934 return (NLNIL); 935 nonident: 936 error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname); 937 return (NLNIL); 938 939 case T_IN: 940 rt = r->expr_node.rhs; 941 # ifdef OBJ 942 if (rt != TR_NIL && rt->tag == T_CSET) { 943 (void) precset( rt , NLNIL , &csetd ); 944 p1 = csetd.csettype; 945 if (p1 == NLNIL) 946 return NLNIL; 947 postcset( rt, &csetd); 948 } else { 949 p1 = stkrval(r->expr_node.rhs, NLNIL , (long) RREQ ); 950 rt = TR_NIL; 951 } 952 # endif OBJ 953 # ifdef PC 954 if (rt != TR_NIL && rt->tag == T_CSET) { 955 if ( precset( rt , NLNIL , &csetd ) ) { 956 putleaf( PCC_ICON , 0 , 0 957 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 958 , "_IN" ); 959 } else { 960 putleaf( PCC_ICON , 0 , 0 961 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 962 , "_INCT" ); 963 } 964 p1 = csetd.csettype; 965 if (p1 == NIL) 966 return NLNIL; 967 } else { 968 putleaf( PCC_ICON , 0 , 0 969 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 970 , "_IN" ); 971 codeoff(); 972 p1 = rvalue(r->expr_node.rhs, NLNIL , LREQ ); 973 codeon(); 974 } 975 # endif PC 976 p = stkrval(r->expr_node.lhs, NLNIL , (long) RREQ ); 977 if (p == NIL || p1 == NIL) 978 return (NLNIL); 979 if (p1->class != (char) SET) { 980 error("Right operand of 'in' must be a set, not %s", nameof(p1)); 981 return (NLNIL); 982 } 983 if (incompat(p, p1->type, r->expr_node.lhs)) { 984 cerror("Index type clashed with set component type for 'in'"); 985 return (NLNIL); 986 } 987 setran(p1->type); 988 # ifdef OBJ 989 if (rt == TR_NIL || csetd.comptime) 990 (void) put(4, O_IN, width(p1), set.lwrb, set.uprbp); 991 else 992 (void) put(2, O_INCT, 993 (int)(3 + csetd.singcnt + 2*csetd.paircnt)); 994 # endif OBJ 995 # ifdef PC 996 if ( rt == TR_NIL || rt->tag != T_CSET ) { 997 putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 998 putop( PCC_CM , PCCT_INT ); 999 putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 1000 putop( PCC_CM , PCCT_INT ); 1001 p1 = rvalue( r->expr_node.rhs , NLNIL , LREQ ); 1002 if ( p1 == NLNIL ) { 1003 return NLNIL; 1004 } 1005 putop( PCC_CM , PCCT_INT ); 1006 } else if ( csetd.comptime ) { 1007 putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 ); 1008 putop( PCC_CM , PCCT_INT ); 1009 putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 ); 1010 putop( PCC_CM , PCCT_INT ); 1011 postcset( r->expr_node.rhs , &csetd ); 1012 putop( PCC_CM , PCCT_INT ); 1013 } else { 1014 postcset( r->expr_node.rhs , &csetd ); 1015 } 1016 putop( PCC_CALL , PCCT_INT ); 1017 sconv(PCCT_INT, PCCT_CHAR); 1018 # endif PC 1019 return (nl+T1BOOL); 1020 default: 1021 if (r->expr_node.lhs == TR_NIL) 1022 return (NLNIL); 1023 switch (r->tag) { 1024 default: 1025 panic("rval3"); 1026 1027 1028 /* 1029 * An octal number 1030 */ 1031 case T_BINT: 1032 f.pdouble = a8tol(r->const_node.cptr); 1033 goto conint; 1034 1035 /* 1036 * A decimal number 1037 */ 1038 case T_INT: 1039 f.pdouble = atof(r->const_node.cptr); 1040 conint: 1041 if (f.pdouble > MAXINT || f.pdouble < MININT) { 1042 error("Constant too large for this implementation"); 1043 return (NLNIL); 1044 } 1045 l = f.pdouble; 1046 # ifdef OBJ 1047 if (bytes(l, l) <= 2) { 1048 (void) put(2, O_CON2, ( short ) l); 1049 return (nl+T2INT); 1050 } 1051 (void) put(2, O_CON4, l); 1052 return (nl+T4INT); 1053 # endif OBJ 1054 # ifdef PC 1055 switch (bytes(l, l)) { 1056 case 1: 1057 putleaf(PCC_ICON, (int) l, 0, PCCT_CHAR, 1058 (char *) 0); 1059 return nl+T1INT; 1060 case 2: 1061 putleaf(PCC_ICON, (int) l, 0, PCCT_SHORT, 1062 (char *) 0); 1063 return nl+T2INT; 1064 case 4: 1065 putleaf(PCC_ICON, (int) l, 0, PCCT_INT, 1066 (char *) 0); 1067 return nl+T4INT; 1068 } 1069 # endif PC 1070 1071 /* 1072 * A floating point number 1073 */ 1074 case T_FINT: 1075 # ifdef OBJ 1076 (void) put(2, O_CON8, atof(r->const_node.cptr)); 1077 # endif OBJ 1078 # ifdef PC 1079 putCON8( atof( r->const_node.cptr ) ); 1080 # endif PC 1081 return (nl+TDOUBLE); 1082 1083 /* 1084 * Constant strings. Note that constant characters 1085 * are constant strings of length one; there is 1086 * no constant string of length one. 1087 */ 1088 case T_STRNG: 1089 cp = r->const_node.cptr; 1090 if (cp[1] == 0) { 1091 # ifdef OBJ 1092 (void) put(2, O_CONC, cp[0]); 1093 # endif OBJ 1094 # ifdef PC 1095 putleaf( PCC_ICON , cp[0] , 0 , PCCT_CHAR , 1096 (char *) 0 ); 1097 # endif PC 1098 return (nl+T1CHAR); 1099 } 1100 goto cstrng; 1101 } 1102 1103 } 1104 } 1105 1106 /* 1107 * Can a class appear 1108 * in a comparison ? 1109 */ 1110 nocomp(c) 1111 int c; 1112 { 1113 1114 switch (c) { 1115 case TREC: 1116 if ( line != reccompline ) { 1117 reccompline = line; 1118 warning(); 1119 if ( opt( 's' ) ) { 1120 standard(); 1121 } 1122 error("record comparison is non-standard"); 1123 } 1124 break; 1125 case TFILE: 1126 case TARY: 1127 error("%ss may not participate in comparisons", clnames[c]); 1128 return (1); 1129 } 1130 return (NIL); 1131 } 1132 1133 /* 1134 * this is sort of like gconst, except it works on expression trees 1135 * rather than declaration trees, and doesn't give error messages for 1136 * non-constant things. 1137 * as a side effect this fills in the con structure that gconst uses. 1138 * this returns TRUE or FALSE. 1139 */ 1140 1141 bool 1142 constval(r) 1143 register struct tnode *r; 1144 { 1145 register struct nl *np; 1146 register struct tnode *cn; 1147 char *cp; 1148 int negd, sgnd; 1149 long ci; 1150 1151 con.ctype = NIL; 1152 cn = r; 1153 negd = sgnd = 0; 1154 loop: 1155 /* 1156 * cn[2] is nil if error recovery generated a T_STRNG 1157 */ 1158 if (cn == TR_NIL || cn->expr_node.lhs == TR_NIL) 1159 return FALSE; 1160 switch (cn->tag) { 1161 default: 1162 return FALSE; 1163 case T_MINUS: 1164 negd = 1 - negd; 1165 /* and fall through */ 1166 case T_PLUS: 1167 sgnd++; 1168 cn = cn->un_expr.expr; 1169 goto loop; 1170 case T_NIL: 1171 con.cpval = NIL; 1172 con.cival = 0; 1173 con.crval = con.cival; 1174 con.ctype = nl + TNIL; 1175 break; 1176 case T_VAR: 1177 np = lookup(cn->var_node.cptr); 1178 if (np == NLNIL || np->class != CONST) { 1179 return FALSE; 1180 } 1181 if ( cn->var_node.qual != TR_NIL ) { 1182 return FALSE; 1183 } 1184 con.ctype = np->type; 1185 switch (classify(np->type)) { 1186 case TINT: 1187 con.crval = np->range[0]; 1188 break; 1189 case TDOUBLE: 1190 con.crval = np->real; 1191 break; 1192 case TBOOL: 1193 case TCHAR: 1194 case TSCAL: 1195 con.cival = np->value[0]; 1196 con.crval = con.cival; 1197 break; 1198 case TSTR: 1199 con.cpval = (char *) np->ptr[0]; 1200 break; 1201 default: 1202 con.ctype = NIL; 1203 return FALSE; 1204 } 1205 break; 1206 case T_BINT: 1207 con.crval = a8tol(cn->const_node.cptr); 1208 goto restcon; 1209 case T_INT: 1210 con.crval = atof(cn->const_node.cptr); 1211 if (con.crval > MAXINT || con.crval < MININT) { 1212 derror("Constant too large for this implementation"); 1213 con.crval = 0; 1214 } 1215 restcon: 1216 ci = con.crval; 1217 #ifndef PI0 1218 if (bytes(ci, ci) <= 2) 1219 con.ctype = nl+T2INT; 1220 else 1221 #endif 1222 con.ctype = nl+T4INT; 1223 break; 1224 case T_FINT: 1225 con.ctype = nl+TDOUBLE; 1226 con.crval = atof(cn->const_node.cptr); 1227 break; 1228 case T_STRNG: 1229 cp = cn->const_node.cptr; 1230 if (cp[1] == 0) { 1231 con.ctype = nl+T1CHAR; 1232 con.cival = cp[0]; 1233 con.crval = con.cival; 1234 break; 1235 } 1236 con.ctype = nl+TSTR; 1237 con.cpval = cp; 1238 break; 1239 } 1240 if (sgnd) { 1241 if (isnta(con.ctype, "id")) { 1242 derror("%s constants cannot be signed", nameof(con.ctype)); 1243 return FALSE; 1244 } else if (negd) 1245 con.crval = -con.crval; 1246 } 1247 return TRUE; 1248 } 1249