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