xref: /original-bsd/usr.bin/f77/pass1.vax/exec.c (revision f1656be1)
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.6 (Berkeley) 01/03/88";
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.constant.ci);
387 		n = strlen(q);
388 		if(n > 0)
389 			{
390 			p->constblock.constant.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  constant[0]
419 #define CONSTLIMIT constant[1]
420 #define CONSTINCR  constant[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 constant[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 	constant[i] = mkconv(dotype, q);
475       else
476 	{
477 	  frexpr(q);
478 	  constant[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 }
872