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[] = "@(#)exec.c 5.2 (Berkeley) 6/7/85"; 9 #endif not lint 10 11 /* 12 * exec.c 13 * 14 * Routines for handling the semantics of control structures. 15 * F77 compiler, pass 1. 16 * 17 * University of Utah CS Dept modification history: 18 * 19 * Revision 2.3 85/03/18 08:03:31 donn 20 * Hacks for conversions from type address to numeric type -- prevent addresses 21 * from being stored in shorts and prevent warnings about implicit conversions. 22 * 23 * Revision 2.2 84/09/03 23:18:30 donn 24 * When a DO loop had the same variable as its loop variable and its limit, 25 * the limit temporary was assigned to AFTER the original value of the variable 26 * was destroyed by assigning the initial value to the loop variable. I 27 * swapped the operands of a comparison and changed the direction of the 28 * operator... This only affected programs when optimizing. (This may not 29 * be enough if something alters the order of evaluation of side effects 30 * later on... sigh.) 31 * 32 * Revision 2.1 84/07/19 12:02:53 donn 33 * Changed comment headers for UofU. 34 * 35 * Revision 1.3 84/07/12 18:35:12 donn 36 * Added change to enddo() to detect open 'if' blocks at the ends of loops. 37 * 38 * Revision 1.2 84/06/08 11:22:53 donn 39 * Fixed bug in exdo() -- if a loop parameter contained an instance of the loop 40 * variable and the optimizer was off, the loop variable got converted to 41 * register before the parameters were processed and so the loop parameters 42 * were initialized from garbage in the register instead of the memory version 43 * of the loop variable. 44 * 45 */ 46 47 #include "defs.h" 48 #include "optim.h" 49 50 51 /* Logical IF codes 52 */ 53 54 55 exif(p) 56 expptr p; 57 { 58 register int k; 59 pushctl(CTLIF); 60 ctlstack->elselabel = newlabel(); 61 62 if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL) 63 { 64 if(k != TYERROR) 65 err("non-logical expression in IF statement"); 66 frexpr(p); 67 } 68 else if (optimflag) 69 optbuff (SKIFN, p, ctlstack->elselabel, 0); 70 else 71 putif (p, ctlstack->elselabel); 72 } 73 74 75 76 exelif(p) 77 expptr p; 78 { 79 int k,oldelse; 80 81 if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL) 82 { 83 if(k != TYERROR) 84 err("non-logical expression in IF statement"); 85 frexpr(p); 86 } 87 else { 88 if(ctlstack->ctltype == CTLIF) 89 { 90 if(ctlstack->endlabel == 0) ctlstack->endlabel = newlabel(); 91 oldelse=ctlstack->elselabel; 92 ctlstack->elselabel = newlabel(); 93 if (optimflag) 94 { 95 optbuff (SKGOTO, 0, ctlstack->endlabel, 0); 96 optbuff (SKLABEL, 0, oldelse, 0); 97 optbuff (SKIFN, p, ctlstack->elselabel, 0); 98 } 99 else 100 { 101 putgoto (ctlstack->endlabel); 102 putlabel (oldelse); 103 putif (p, ctlstack->elselabel); 104 } 105 } 106 else execerr("elseif out of place", CNULL); 107 } 108 } 109 110 111 112 113 114 exelse() 115 { 116 if(ctlstack->ctltype==CTLIF) 117 { 118 if(ctlstack->endlabel == 0) 119 ctlstack->endlabel = newlabel(); 120 ctlstack->ctltype = CTLELSE; 121 if (optimflag) 122 { 123 optbuff (SKGOTO, 0, ctlstack->endlabel, 0); 124 optbuff (SKLABEL, 0, ctlstack->elselabel, 0); 125 } 126 else 127 { 128 putgoto (ctlstack->endlabel); 129 putlabel (ctlstack->elselabel); 130 } 131 } 132 133 else execerr("else out of place", CNULL); 134 } 135 136 137 exendif() 138 { 139 if (ctlstack->ctltype == CTLIF) 140 { 141 if (optimflag) 142 { 143 optbuff (SKLABEL, 0, ctlstack->elselabel, 0); 144 if (ctlstack->endlabel) 145 optbuff (SKLABEL, 0, ctlstack->endlabel, 0); 146 } 147 else 148 { 149 putlabel (ctlstack->elselabel); 150 if (ctlstack->endlabel) 151 putlabel (ctlstack->endlabel); 152 } 153 popctl (); 154 } 155 else if (ctlstack->ctltype == CTLELSE) 156 { 157 if (optimflag) 158 optbuff (SKLABEL, 0, ctlstack->endlabel, 0); 159 else 160 putlabel (ctlstack->endlabel); 161 popctl (); 162 } 163 else 164 execerr("endif out of place", CNULL); 165 } 166 167 168 169 LOCAL pushctl(code) 170 int code; 171 { 172 register int i; 173 174 /* fprintf(diagfile,"old blklevel %d \n",blklevel); dmpframe(ctlstack); */ 175 if(++ctlstack >= lastctl) 176 many("loops or if-then-elses", 'c'); 177 ctlstack->ctltype = code; 178 for(i = 0 ; i < 4 ; ++i) 179 ctlstack->ctlabels[i] = 0; 180 ++blklevel; 181 } 182 183 184 LOCAL popctl() 185 { 186 if( ctlstack-- < ctls ) 187 fatal("control stack empty"); 188 --blklevel; 189 } 190 191 192 193 LOCAL poplab() 194 { 195 register struct Labelblock *lp; 196 197 for(lp = labeltab ; lp < highlabtab ; ++lp) 198 if(lp->labdefined) 199 { 200 /* mark all labels in inner blocks unreachable */ 201 if(lp->blklevel > blklevel) 202 lp->labinacc = YES; 203 } 204 else if(lp->blklevel > blklevel) 205 { 206 /* move all labels referred to in inner blocks out a level */ 207 lp->blklevel = blklevel; 208 } 209 } 210 211 212 213 /* BRANCHING CODE 214 */ 215 216 exgoto(lab) 217 struct Labelblock *lab; 218 { 219 if (optimflag) 220 optbuff (SKGOTO, 0, lab->labelno, 0); 221 else 222 putgoto (lab->labelno); 223 } 224 225 226 227 228 229 230 231 exequals(lp, rp) 232 register struct Primblock *lp; 233 register expptr rp; 234 { 235 register Namep np; 236 237 if(lp->tag != TPRIM) 238 { 239 err("assignment to a non-variable"); 240 frexpr(lp); 241 frexpr(rp); 242 } 243 else if(lp->namep->vclass!=CLVAR && lp->argsp) 244 { 245 if(parstate >= INEXEC) 246 err("assignment to an undimemsioned array"); 247 else 248 mkstfunct(lp, rp); 249 } 250 else 251 { 252 np = (Namep) lp->namep; 253 if (np->vclass == CLPROC && np->vprocclass == PTHISPROC 254 && proctype == TYSUBR) 255 { 256 err("assignment to a subroutine name"); 257 return; 258 } 259 if(parstate < INDATA) 260 enddcl(); 261 if (optimflag) 262 optbuff (SKEQ, mkexpr(OPASSIGN, mklhs(lp), fixtype(rp)), 0, 0); 263 else 264 puteq (mklhs(lp), fixtype(rp)); 265 } 266 } 267 268 269 270 mkstfunct(lp, rp) 271 struct Primblock *lp; 272 expptr rp; 273 { 274 register struct Primblock *p; 275 register Namep np; 276 chainp args; 277 278 if(parstate < INDATA) 279 { 280 enddcl(); 281 parstate = INDATA; 282 } 283 284 np = lp->namep; 285 if(np->vclass == CLUNKNOWN) 286 np->vclass = CLPROC; 287 else 288 { 289 dclerr("redeclaration of statement function", np); 290 return; 291 } 292 np->vprocclass = PSTFUNCT; 293 np->vstg = STGSTFUNCT; 294 impldcl(np); 295 args = (lp->argsp ? lp->argsp->listp : CHNULL); 296 np->varxptr.vstfdesc = mkchain(args , rp ); 297 298 for( ; args ; args = args->nextp) 299 if( args->datap->tag!=TPRIM || 300 (p = (struct Primblock *) (args->datap) )->argsp || 301 p->fcharp || p->lcharp ) 302 err("non-variable argument in statement function definition"); 303 else 304 { 305 args->datap = (tagptr) (p->namep); 306 vardcl(p->namep); 307 free(p); 308 } 309 } 310 311 312 313 excall(name, args, nstars, labels) 314 Namep name; 315 struct Listblock *args; 316 int nstars; 317 struct Labelblock *labels[ ]; 318 { 319 register expptr p; 320 321 settype(name, TYSUBR, ENULL); 322 p = mkfunct( mkprim(name, args, CHNULL) ); 323 p->exprblock.vtype = p->exprblock.leftp->headblock.vtype = TYINT; 324 if (nstars > 0) 325 if (optimflag) 326 optbuff (SKCMGOTO, p, nstars, labels); 327 else 328 putcmgo (p, nstars, labels); 329 else 330 if (optimflag) 331 optbuff (SKCALL, p, 0, 0); 332 else 333 putexpr (p); 334 } 335 336 337 338 exstop(stop, p) 339 int stop; 340 register expptr p; 341 { 342 char *q; 343 int n; 344 expptr mkstrcon(); 345 346 if(p) 347 { 348 if( ! ISCONST(p) ) 349 { 350 execerr("pause/stop argument must be constant", CNULL); 351 frexpr(p); 352 p = mkstrcon(0, CNULL); 353 } 354 else if( ISINT(p->constblock.vtype) ) 355 { 356 q = convic(p->constblock.const.ci); 357 n = strlen(q); 358 if(n > 0) 359 { 360 p->constblock.const.ccp = copyn(n, q); 361 p->constblock.vtype = TYCHAR; 362 p->constblock.vleng = (expptr) ICON(n); 363 } 364 else 365 p = (expptr) mkstrcon(0, CNULL); 366 } 367 else if(p->constblock.vtype != TYCHAR) 368 { 369 execerr("pause/stop argument must be integer or string", CNULL); 370 p = (expptr) mkstrcon(0, CNULL); 371 } 372 } 373 else p = (expptr) mkstrcon(0, CNULL); 374 375 if (optimflag) 376 optbuff ((stop ? SKSTOP : SKPAUSE), p, 0, 0); 377 else 378 putexpr (call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p)); 379 } 380 381 382 /* UCB DO LOOP CODE */ 383 384 #define DOINIT par[0] 385 #define DOLIMIT par[1] 386 #define DOINCR par[2] 387 388 #define CONSTINIT const[0] 389 #define CONSTLIMIT const[1] 390 #define CONSTINCR const[2] 391 392 #define VARSTEP 0 393 #define POSSTEP 1 394 #define NEGSTEP 2 395 396 397 exdo(range, spec) 398 int range; 399 chainp spec; 400 401 { 402 register expptr p, q; 403 expptr q1; 404 register Namep np; 405 chainp cp; 406 register int i; 407 int dotype, incsign; 408 Addrp dovarp, dostgp; 409 expptr par[3]; 410 expptr const[3]; 411 Slotp doslot; 412 413 pushctl(CTLDO); 414 dorange = ctlstack->dolabel = range; 415 np = (Namep) (spec->datap); 416 ctlstack->donamep = NULL; 417 if(np->vdovar) 418 { 419 errstr("nested loops with variable %s", varstr(VL,np->varname)); 420 return; 421 } 422 423 dovarp = mkplace(np); 424 dotype = dovarp->vtype; 425 426 if( ! ONEOF(dotype, MSKINT|MSKREAL) ) 427 { 428 err("bad type on DO variable"); 429 return; 430 } 431 432 433 for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp) 434 { 435 p = fixtype((expptr) cpexpr((tagptr) q = cp->datap)); 436 if(!ONEOF(p->headblock.vtype, MSKINT|MSKREAL) ) 437 { 438 err("bad type on DO parameter"); 439 return; 440 } 441 442 443 if (ISCONST(q)) 444 const[i] = mkconv(dotype, q); 445 else 446 { 447 frexpr(q); 448 const[i] = NULL; 449 } 450 451 par[i++] = mkconv(dotype, p); 452 } 453 454 frchain(&spec); 455 switch(i) 456 { 457 case 0: 458 case 1: 459 err("too few DO parameters"); 460 return; 461 462 case 2: 463 DOINCR = (expptr) ICON(1); 464 CONSTINCR = ICON(1); 465 466 case 3: 467 break; 468 469 default: 470 err("too many DO parameters"); 471 return; 472 } 473 474 ctlstack->donamep = np; 475 476 np->vdovar = YES; 477 if( !optimflag && enregister(np) ) 478 { 479 /* stgp points to a storage version, varp to a register version */ 480 dostgp = dovarp; 481 dovarp = mkplace(np); 482 } 483 else 484 dostgp = NULL; 485 486 for (i = 0; i < 4; i++) 487 ctlstack->ctlabels[i] = newlabel(); 488 489 if( CONSTLIMIT ) 490 ctlstack->domax = DOLIMIT; 491 else 492 ctlstack->domax = (expptr) mktemp(dotype, PNULL); 493 494 if( CONSTINCR ) 495 { 496 ctlstack->dostep = DOINCR; 497 if( (incsign = conssgn(CONSTINCR)) == 0) 498 err("zero DO increment"); 499 ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP); 500 } 501 else 502 { 503 ctlstack->dostep = (expptr) mktemp(dotype, PNULL); 504 ctlstack->dostepsign = VARSTEP; 505 } 506 507 if (optimflag) 508 doslot = optbuff (SKDOHEAD,0,0,ctlstack); 509 510 if( CONSTLIMIT && CONSTINIT && ctlstack->dostepsign!=VARSTEP) 511 { 512 if (optimflag) 513 optbuff (SKEQ,mkexpr(OPASSIGN,cpexpr(dovarp),cpexpr(DOINIT)), 514 0,0); 515 else 516 puteq (cpexpr(dovarp), cpexpr(DOINIT)); 517 if( ! onetripflag ) 518 { 519 q = mkexpr(OPMINUS, cpexpr(CONSTLIMIT), cpexpr(CONSTINIT)); 520 if((incsign * conssgn(q)) == -1) 521 { 522 warn("DO range never executed"); 523 if (optimflag) 524 optbuff (SKGOTO,0,ctlstack->endlabel,0); 525 else 526 putgoto (ctlstack->endlabel); 527 } 528 frexpr(q); 529 } 530 } 531 532 533 else if (ctlstack->dostepsign != VARSTEP && !onetripflag) 534 { 535 if (CONSTLIMIT) 536 q = (expptr) cpexpr(ctlstack->domax); 537 else 538 q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT); 539 q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT); 540 q = mkexpr( (ctlstack->dostepsign == POSSTEP ? OPGE : OPLE), 541 q, q1); 542 if (optimflag) 543 optbuff (SKIFN,q, ctlstack->endlabel,0); 544 else 545 putif (q, ctlstack->endlabel); 546 } 547 else 548 { 549 if (!CONSTLIMIT) 550 if (optimflag) 551 optbuff (SKEQ, 552 mkexpr(OPASSIGN,cpexpr(ctlstack->domax),DOLIMIT),0,0); 553 else 554 puteq (cpexpr(ctlstack->domax), DOLIMIT); 555 q = DOINIT; 556 if (!onetripflag) 557 q = mkexpr(OPMINUS, q, 558 mkexpr(OPASSIGN, cpexpr(ctlstack->dostep), 559 DOINCR) ); 560 if (optimflag) 561 optbuff (SKEQ,mkexpr(OPASSIGN,cpexpr(dovarp), q),0,0); 562 else 563 puteq (cpexpr(dovarp), q); 564 if (onetripflag && ctlstack->dostepsign == VARSTEP) 565 if (optimflag) 566 optbuff (SKEQ, 567 mkexpr(OPASSIGN,cpexpr(ctlstack->dostep),DOINCR),0,0); 568 else 569 puteq (cpexpr(ctlstack->dostep), DOINCR); 570 } 571 572 if (ctlstack->dostepsign == VARSTEP) 573 { 574 expptr incr,test; 575 if (onetripflag) 576 if (optimflag) 577 optbuff (SKGOTO,0,ctlstack->dobodylabel,0); 578 else 579 putgoto (ctlstack->dobodylabel); 580 else 581 if (optimflag) 582 optbuff (SKIFN,mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)), 583 ctlstack->doneglabel,0); 584 else 585 putif (mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)), 586 ctlstack->doneglabel); 587 if (optimflag) 588 optbuff (SKLABEL,0,ctlstack->doposlabel,0); 589 else 590 putlabel (ctlstack->doposlabel); 591 incr = mkexpr(OPPLUSEQ, cpexpr(dovarp), cpexpr(ctlstack->dostep)); 592 test = mkexpr(OPLE, incr, cpexpr(ctlstack->domax)); 593 if (optimflag) 594 optbuff (SKIFN,test, ctlstack->endlabel,0); 595 else 596 putif (test, ctlstack->endlabel); 597 } 598 599 if (optimflag) 600 optbuff (SKLABEL,0,ctlstack->dobodylabel,0); 601 else 602 putlabel (ctlstack->dobodylabel); 603 if (dostgp) 604 { 605 if (optimflag) 606 optbuff (SKEQ,mkexpr(OPASSIGN,dostgp, dovarp),0,0); 607 else 608 puteq (dostgp, dovarp); 609 } 610 else 611 frexpr(dovarp); 612 if (optimflag) 613 doslot->nullslot = optbuff (SKNULL,0,0,0); 614 615 frexpr(CONSTINIT); 616 frexpr(CONSTLIMIT); 617 frexpr(CONSTINCR); 618 } 619 620 621 enddo(here) 622 int here; 623 624 { 625 register struct Ctlframe *q; 626 Namep np; 627 Addrp ap, rv; 628 expptr t; 629 register int i; 630 Slotp doslot; 631 632 while (here == dorange) 633 { 634 while (ctlstack->ctltype == CTLIF || ctlstack->ctltype == CTLELSE) 635 { 636 execerr("missing endif", CNULL); 637 exendif(); 638 } 639 640 if (np = ctlstack->donamep) 641 { 642 rv = mkplace (np); 643 644 t = mkexpr(OPPLUSEQ, cpexpr(rv), cpexpr(ctlstack->dostep) ); 645 646 if (optimflag) 647 doslot = optbuff (SKENDDO,0,0,ctlstack); 648 649 if (ctlstack->dostepsign == VARSTEP) 650 if (optimflag) 651 { 652 optbuff (SKIFN, 653 mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)), 654 ctlstack->doposlabel,0); 655 optbuff (SKLABEL,0,ctlstack->doneglabel,0); 656 optbuff (SKIFN,mkexpr(OPLT, t, ctlstack->domax), 657 ctlstack->dobodylabel,0); 658 } 659 else 660 { 661 putif (mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)), 662 ctlstack->doposlabel); 663 putlabel (ctlstack->doneglabel); 664 putif (mkexpr(OPLT, t, ctlstack->domax), 665 ctlstack->dobodylabel); 666 } 667 else 668 { 669 int op; 670 op = (ctlstack->dostepsign == POSSTEP ? OPGT : OPLT); 671 if (optimflag) 672 optbuff (SKIFN, mkexpr(op,t,ctlstack->domax), 673 ctlstack->dobodylabel,0); 674 else 675 putif (mkexpr(op, t, ctlstack->domax), 676 ctlstack->dobodylabel); 677 } 678 if (optimflag) 679 optbuff (SKLABEL,0,ctlstack->endlabel,0); 680 else 681 putlabel (ctlstack->endlabel); 682 683 if (ap = memversion(np)) 684 { 685 if (optimflag) 686 optbuff (SKEQ,mkexpr(OPASSIGN,ap, rv),0,0); 687 else 688 puteq (ap, rv); 689 } 690 else 691 frexpr(rv); 692 for (i = 0; i < 4; i++) 693 ctlstack->ctlabels[i] = 0; 694 if (!optimflag) 695 deregister(ctlstack->donamep); 696 ctlstack->donamep->vdovar = NO; 697 if (optimflag) 698 doslot->nullslot = optbuff (SKNULL,0,0,0); 699 } 700 701 popctl(); 702 poplab(); 703 704 dorange = 0; 705 for (q = ctlstack; q >= ctls; --q) 706 if (q->ctltype == CTLDO) 707 { 708 dorange = q->dolabel; 709 break; 710 } 711 } 712 } 713 714 715 exassign(vname, labelval) 716 Namep vname; 717 struct Labelblock *labelval; 718 { 719 Addrp p; 720 expptr mkaddcon(); 721 722 p = mkplace(vname); 723 #if SZADDR > SZSHORT 724 if( p->vtype == TYSHORT ) 725 err("insufficient precision in ASSIGN variable"); 726 else 727 #endif 728 if( ! ONEOF(p->vtype, MSKINT|MSKADDR) ) 729 err("noninteger assign variable"); 730 else 731 { 732 if (optimflag) 733 optbuff (SKASSIGN, p, labelval->labelno, 0); 734 else 735 puteq (p, intrconv(p->vtype, mkaddcon(labelval->labelno))); 736 } 737 } 738 739 740 741 exarif(expr, neglab, zerlab, poslab) 742 expptr expr; 743 struct Labelblock *neglab, *zerlab, *poslab; 744 { 745 register int lm, lz, lp; 746 struct Labelblock *labels[3]; 747 748 lm = neglab->labelno; 749 lz = zerlab->labelno; 750 lp = poslab->labelno; 751 expr = fixtype(expr); 752 753 if( ! ONEOF(expr->headblock.vtype, MSKINT|MSKREAL) ) 754 { 755 err("invalid type of arithmetic if expression"); 756 frexpr(expr); 757 } 758 else 759 { 760 if(lm == lz) 761 exar2(OPLE, expr, lm, lp); 762 else if(lm == lp) 763 exar2(OPNE, expr, lm, lz); 764 else if(lz == lp) 765 exar2(OPGE, expr, lz, lm); 766 else 767 if (optimflag) 768 { 769 labels[0] = neglab; 770 labels[1] = zerlab; 771 labels[2] = poslab; 772 optbuff (SKARIF, expr, 0, labels); 773 } 774 else 775 prarif(expr, lm, lz, lp); 776 } 777 } 778 779 780 781 LOCAL exar2 (op, e, l1, l2) 782 int op; 783 expptr e; 784 int l1,l2; 785 { 786 if (optimflag) 787 { 788 optbuff (SKIFN, mkexpr(op, e, ICON(0)), l2, 0); 789 optbuff (SKGOTO, 0, l1, 0); 790 } 791 else 792 { 793 putif (mkexpr(op, e, ICON(0)), l2); 794 putgoto (l1); 795 } 796 } 797 798 799 exreturn(p) 800 register expptr p; 801 { 802 if(procclass != CLPROC) 803 warn("RETURN statement in main or block data"); 804 if(p && (proctype!=TYSUBR || procclass!=CLPROC) ) 805 { 806 err("alternate return in nonsubroutine"); 807 p = 0; 808 } 809 810 if(p) 811 if (optimflag) 812 optbuff (SKRETURN, p, retlabel, 0); 813 else 814 { 815 putforce (TYINT, p); 816 putgoto (retlabel); 817 } 818 else 819 if (optimflag) 820 optbuff (SKRETURN, p, 821 (proctype==TYSUBR ? ret0label : retlabel), 0); 822 else 823 putgoto (proctype==TYSUBR ? ret0label : retlabel); 824 } 825 826 827 828 exasgoto(labvar) 829 struct Hashentry *labvar; 830 { 831 register Addrp p; 832 833 p = mkplace(labvar); 834 if( ! ISINT(p->vtype) ) 835 err("assigned goto variable must be integer"); 836 else 837 if (optimflag) 838 optbuff (SKASGOTO, p, 0, 0); 839 else 840 putbranch (p); 841 } 842