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