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