xref: /original-bsd/usr.bin/pascal/src/fend.c (revision c3e32dec)
1 /*-
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)fend.c	8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11 
12 #include "whoami.h"
13 #include "0.h"
14 #include "tree.h"
15 #include "opcode.h"
16 #include "objfmt.h"
17 #include "align.h"
18 #include "tmps.h"
19 
20 /*
21  * this array keeps the pxp counters associated with
22  * functions and procedures, so that they can be output
23  * when their bodies are encountered
24  */
25 int	bodycnts[ DSPLYSZ ];
26 
27 #ifdef PC
28 #   include "pc.h"
29 #   include <pcc.h>
30 #endif PC
31 
32 #ifdef OBJ
33 int	cntpatch;
34 int	nfppatch;
35 #endif OBJ
36 
37 #include "tree_ty.h"
38 
39 struct	nl *Fp;
40 int	pnumcnt;
41 /*
42  * Funcend is called to
43  * finish a block by generating
44  * the code for the statements.
45  * It then looks for unresolved declarations
46  * of labels, procedures and functions,
47  * and cleans up the name list.
48  * For the program, it checks the
49  * semantics of the program
50  * statement (yuchh).
51  */
52 funcend(fp, bundle, endline)
53 	struct nl *fp;
54 	struct tnode *bundle;
55 	int endline;
56 {
57 	register struct nl *p;
58 	register int i, b;
59 	int inp, out;
60 	struct tnode *blk;
61 	bool chkref;
62 	struct nl *iop;
63 	char *cp;
64 	extern int cntstat;
65 #	ifdef PC
66 	    struct entry_exit_cookie	eecookie;
67 #	endif PC
68 #	ifndef PC
69 	int var;
70 #	endif PC
71 
72 	cntstat = 0;
73 /*
74  *	yyoutline();
75  */
76 	if (program != NIL)
77 		line = program->value[3];
78 	blk = bundle->stmnt_blck.stmnt_list;
79 	if (fp == NIL) {
80 		cbn--;
81 #		ifdef PTREE
82 		    nesting--;
83 #		endif PTREE
84 		return;
85 	}
86 #ifdef OBJ
87 	/*
88 	 * Patch the branch to the entry point of the function.
89 	 * Assure alignment of O_BEG structure.
90 	 */
91 	if (((int)lc & 02) == 0)
92 		word(0);
93 	patch4((PTR_DCL) fp->value[NL_ENTLOC]);
94 	/*
95 	 * Put out the block entrance code and the block name.
96 	 * HDRSZE is the number of bytes of info in the static
97 	 * BEG data area exclusive of the proc name. It is
98 	 * currently defined as:
99 	/*	struct hdr {
100 	/*		long framesze;	/* number of bytes of local vars */
101 	/*		long nargs;	/* number of bytes of arguments */
102 	/*		bool tests;	/* TRUE => perform runtime tests */
103 	/*		short offset;	/* offset of procedure in source file */
104 	/*		char name[1];	/* name of active procedure */
105 	/*	};
106 	 */
107 #	define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool))
108 	var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8)
109 		| (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0);
110 	    /*
111 	     *  output the number of bytes of arguments
112 	     *  this is only checked on formal calls.
113 	     */
114 	(void) put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2));
115 	    /*
116 	     *	Output the runtime test mode for the routine
117 	     */
118 	(void) put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE);
119 	    /*
120 	     *	Output line number and routine name
121 	     */
122 	(void) put(2, O_CASE2, bundle->stmnt_blck.line_no);
123 	putstr(fp->symbol, 0);
124 #endif OBJ
125 #ifdef PC
126 	/*
127 	 * put out the procedure entry code
128 	 */
129 	eecookie.nlp = fp;
130 	if ( fp -> class == PROG ) {
131 		/*
132 		 *	If there is a label declaration in the main routine
133 		 *	then there may be a non-local goto to it that does
134 		 *	not appear in this module. We have to assume that
135 		 *	such a reference may occur and generate code to
136 		 *	prepare for it.
137 		 */
138 	    if ( parts[ cbn ] & LPRT ) {
139 		parts[ cbn ] |= ( NONLOCALVAR | NONLOCALGOTO );
140 	    }
141 	    codeformain();
142 	    ftnno = fp -> value[NL_ENTLOC];
143 	    prog_prologue(&eecookie);
144 	    stabline(bundle->stmnt_blck.line_no);
145 	    stabfunc(fp, "program", bundle->stmnt_blck.line_no , (long) 0 );
146 	} else {
147 	    ftnno = fp -> value[NL_ENTLOC];
148 	    fp_prologue(&eecookie);
149 	    stabline(bundle->stmnt_blck.line_no);
150 	    stabfunc(fp, fp->symbol, bundle->stmnt_blck.line_no,
151 		(long)(cbn - 1));
152 	    for ( p = fp -> chain ; p != NIL ; p = p -> chain ) {
153 		stabparam( p , p -> value[ NL_OFFS ] , (int) lwidth(p->type));
154 	    }
155 	    if ( fp -> class == FUNC ) {
156 		    /*
157 		     *	stab the function variable
158 		     */
159 		p = fp -> ptr[ NL_FVAR ];
160 		stablvar( p , p -> value[ NL_OFFS ] , (int) lwidth( p -> type));
161 	    }
162 		/*
163 		 *	stab local variables
164 		 *	rummage down hash chain links.
165 		 */
166 	    for ( i = 0 ; i <= 077 ; i++ ) {
167 		for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) {
168 		    if ( ( p -> nl_block & 037 ) != cbn ) {
169 			break;
170 		    }
171 		    /*
172 		     *	stab locals (not parameters)
173 		     */
174 		    if ( p -> symbol != NIL ) {
175 			if ( p -> class == VAR && p -> value[ NL_OFFS ] < 0 ) {
176 			    stablvar( p , p -> value[ NL_OFFS ] ,
177 				(int) lwidth( p -> type ) );
178 			} else if ( p -> class == CONST ) {
179 			    stabconst( p );
180 			}
181 		    }
182 		}
183 	    }
184 	}
185 	stablbrac( cbn );
186 	    /*
187 	     *	ask second pass to allocate known locals
188 	     */
189 	putlbracket(ftnno, &sizes[cbn]);
190 	fp_entrycode(&eecookie);
191 #endif PC
192 	if ( monflg ) {
193 		if ( fp -> value[ NL_CNTR ] != 0 ) {
194 			inccnt( fp -> value [ NL_CNTR ] );
195 		}
196 		inccnt( bodycnts[ fp -> nl_block & 037 ] );
197 	}
198 	if (fp->class == PROG) {
199 		/*
200 		 * The glorious buffers option.
201 		 *          0 = don't buffer output
202 		 *          1 = line buffer output
203 		 *          2 = 512 byte buffer output
204 		 */
205 #		ifdef OBJ
206 		    if (opt('b') != 1)
207 			    (void) put(1, O_BUFF | opt('b') << 8);
208 #		endif OBJ
209 #		ifdef PC
210 		    if ( opt( 'b' ) != 1 ) {
211 			putleaf( PCC_ICON , 0 , 0
212 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_BUFF" );
213 			putleaf( PCC_ICON , opt( 'b' ) , 0 , PCCT_INT , (char *) 0 );
214 			putop( PCC_CALL , PCCT_INT );
215 			putdot( filename , line );
216 		    }
217 #		endif PC
218 		inp = 0;
219 		out = 0;
220 		for (p = fp->chain; p != NIL; p = p->chain) {
221 			if (pstrcmp(p->symbol, input->symbol) == 0) {
222 				inp++;
223 				continue;
224 			}
225 			if (pstrcmp(p->symbol, output->symbol) == 0) {
226 				out++;
227 				continue;
228 			}
229 			iop = lookup1(p->symbol);
230 			if (iop == NIL || bn != cbn) {
231 				error("File %s listed in program statement but not declared", p->symbol);
232 				continue;
233 			}
234 			if (iop->class != VAR) {
235 				error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]);
236 				continue;
237 			}
238 			if (iop->type == NIL)
239 				continue;
240 			if (iop->type->class != FILET) {
241 				error("File %s listed in program statement but defined as %s",
242 					p->symbol, nameof(iop->type));
243 				continue;
244 			}
245 #			ifdef OBJ
246 			    (void) put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type));
247 			    i = lenstr(p->symbol,0);
248 			    (void) put(2, O_CON24, i);
249 			    (void) put(2, O_LVCON, i);
250 			    putstr(p->symbol, 0);
251 			    (void) put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]);
252 			    (void) put(1, O_DEFNAME);
253 #			endif OBJ
254 #			ifdef PC
255 			    putleaf( PCC_ICON , 0 , 0
256 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
257 				    , "_DEFNAME" );
258 			    putLV( p -> symbol , bn , iop -> value[NL_OFFS] ,
259 				    iop -> extra_flags , p2type( iop ) );
260 			    putCONG( p -> symbol , strlen( p -> symbol )
261 				    , LREQ );
262 			    putop( PCC_CM , PCCT_INT );
263 			    putleaf( PCC_ICON , strlen( p -> symbol )
264 				    , 0 , PCCT_INT , (char *) 0 );
265 			    putop( PCC_CM , PCCT_INT );
266 			    putleaf( PCC_ICON
267 				, text(iop->type) ? 0 : width(iop->type->type)
268 				, 0 , PCCT_INT , (char *) 0 );
269 			    putop( PCC_CM , PCCT_INT );
270 			    putop( PCC_CALL , PCCT_INT );
271 			    putdot( filename , line );
272 #			endif PC
273 		}
274 	}
275 	/*
276 	 * Process the prog/proc/func body
277 	 */
278 	noreach = FALSE;
279 	line = bundle->stmnt_blck.line_no;
280 	statlist(blk);
281 #	ifdef PTREE
282 	    {
283 		pPointer Body = tCopy( blk );
284 
285 		pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body;
286 	    }
287 #	endif PTREE
288 #	ifdef OBJ
289 	    if (cbn== 1 && monflg != FALSE) {
290 		    patchfil((PTR_DCL) (cntpatch - 2), (long)cnts, 2);
291 		    patchfil((PTR_DCL) (nfppatch - 2), (long)pfcnt, 2);
292 	    }
293 #	endif OBJ
294 #	ifdef PC
295 	    if ( fp -> class == PROG && monflg ) {
296 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
297 			, "_PMFLUSH" );
298 		putleaf( PCC_ICON , cnts , 0 , PCCT_INT , (char *) 0 );
299 		putleaf( PCC_ICON , pfcnt , 0 , PCCT_INT , (char *) 0 );
300 		putop( PCC_CM , PCCT_INT );
301 		putLV( PCPCOUNT , 0 , 0 , NGLOBAL , PCCT_INT );
302 		putop( PCC_CM , PCCT_INT );
303 		putop( PCC_CALL , PCCT_INT );
304 		putdot( filename , line );
305 	    }
306 #	endif PC
307 	/*
308 	 * Clean up the symbol table displays and check for unresolves
309 	 */
310 	line = endline;
311 	if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) {
312 		recovered();
313 		error("Input is used but not defined in the program statement");
314 	}
315 	if (fp->class == PROG && out == 0 && (output->nl_flags & (NUSED|NMOD)) != 0) {
316 		recovered();
317 		error("Output is used but not defined in the program statement");
318 	}
319 	b = cbn;
320 	Fp = fp;
321 	chkref = (syneflg == errcnt[cbn] && opt('w') == 0)?TRUE:FALSE;
322 	for (i = 0; i <= 077; i++) {
323 		for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
324 			/*
325 			 * Check for variables defined
326 			 * but not referenced
327 			 */
328 			if (chkref && p->symbol != NIL)
329 			switch (p->class) {
330 				case FIELD:
331 					/*
332 					 * If the corresponding record is
333 					 * unused, we shouldn't complain about
334 					 * the fields.
335 					 */
336 				default:
337 					if ((p->nl_flags & (NUSED|NMOD)) == 0) {
338 						warning();
339 						nerror("%s %s is neither used nor set", classes[p->class], p->symbol);
340 						break;
341 					}
342 					/*
343 					 * If a var parameter is either
344 					 * modified or used that is enough.
345 					 */
346 					if (p->class == REF)
347 						continue;
348 #					ifdef OBJ
349 					    if ((p->nl_flags & NUSED) == 0) {
350 						warning();
351 						nerror("%s %s is never used", classes[p->class], p->symbol);
352 						break;
353 					    }
354 #					endif OBJ
355 #					ifdef PC
356 					    if (((p->nl_flags & NUSED) == 0) && ((p->extra_flags & NEXTERN) == 0)) {
357 						warning();
358 						nerror("%s %s is never used", classes[p->class], p->symbol);
359 						break;
360 					    }
361 #					endif PC
362 					if ((p->nl_flags & NMOD) == 0) {
363 						warning();
364 						nerror("%s %s is used but never set", classes[p->class], p->symbol);
365 						break;
366 					}
367 				case LABEL:
368 				case FVAR:
369 				case BADUSE:
370 					break;
371 			}
372 			switch (p->class) {
373 				case BADUSE:
374 					cp = "s";
375 					/* This used to say ud_next
376 					   that is not a member of nl so
377 					   i changed it to nl_next,
378 					   which may be wrong */
379 					if (p->chain->nl_next == NIL)
380 						cp++;
381 					eholdnl();
382 					if (p->value[NL_KINDS] & ISUNDEF)
383 						nerror("%s undefined on line%s", p->symbol, cp);
384 					else
385 						nerror("%s improperly used on line%s", p->symbol, cp);
386 					pnumcnt = 10;
387 					pnums((struct udinfo *) p->chain);
388 					pchr('\n');
389 					break;
390 
391 				case FUNC:
392 				case PROC:
393 #					ifdef OBJ
394 					    if ((p->nl_flags & NFORWD))
395 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
396 #					endif OBJ
397 #					ifdef PC
398 					    if ((p->nl_flags & NFORWD) && ((p->extra_flags & NEXTERN) == 0))
399 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
400 #					endif PC
401 					break;
402 
403 				case LABEL:
404 					if (p->nl_flags & NFORWD)
405 						nerror("label %s was declared but not defined", p->symbol);
406 					break;
407 				case FVAR:
408 					if ((p->nl_flags & NMOD) == 0)
409 						nerror("No assignment to the function variable");
410 					break;
411 			}
412 		}
413 		/*
414 		 * Pop this symbol
415 		 * table slot
416 		 */
417 		disptab[i] = p;
418 	}
419 
420 #	ifdef OBJ
421 	    (void) put(1, O_END);
422 #	endif OBJ
423 #	ifdef PC
424 	    fp_exitcode(&eecookie);
425 	    stabrbrac(cbn);
426 	    putrbracket(ftnno);
427 	    fp_epilogue(&eecookie);
428 	    if (fp -> class != PROG) {
429 		fp_formalentry(&eecookie);
430 	    }
431 		/*
432 		 *	declare pcp counters, if any
433 		 */
434 	    if ( monflg && fp -> class == PROG ) {
435 		putprintf( "	.data" , 0 );
436 		aligndot(PCCT_INT);
437 		putprintf( "	.comm	" , 1 );
438 		putprintf( PCPCOUNT , 1 );
439 		putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) );
440 		putprintf( "	.text" , 0 );
441 	    }
442 #	endif PC
443 #ifdef DEBUG
444 	dumpnl(fp->ptr[2], (int) fp->symbol);
445 #endif
446 
447 #ifdef OBJ
448 	/*
449 	 * save the namelist for the debugger pdx
450 	 */
451 
452 	savenl(fp->ptr[2], (int) fp->symbol);
453 #endif
454 
455 	/*
456 	 * Restore the
457 	 * (virtual) name list
458 	 * position
459 	 */
460 	nlfree(fp->ptr[2]);
461 	/*
462 	 * Proc/func has been
463 	 * resolved
464 	 */
465 	fp->nl_flags &= ~NFORWD;
466 	/*
467 	 * Patch the beg
468 	 * of the proc/func to
469 	 * the proper variable size
470 	 */
471 	if (Fp == NIL)
472 		elineon();
473 #	ifdef OBJ
474 	    patchfil((PTR_DCL) var,
475 		roundup(-sizes[cbn].om_max, (long) A_STACK), 2);
476 #	endif OBJ
477 	cbn--;
478 	if (inpflist(fp->symbol)) {
479 		opop('l');
480 	}
481 }
482 
483 #ifdef PC
484     /*
485      *	construct the long name of a function based on it's static nesting.
486      *	into a caller-supplied buffer (that should be about BUFSIZ big).
487      */
488 sextname( buffer , name , level )
489     char	buffer[];
490     char	*name;
491     int		level;
492 {
493     char	*starthere;
494     int	i;
495 
496     starthere = &buffer[0];
497     for ( i = 1 ; i < level ; i++ ) {
498 	sprintf( starthere , EXTFORMAT , enclosing[ i ] );
499 	starthere += strlen( enclosing[ i ] ) + 1;
500     }
501     sprintf( starthere , EXTFORMAT , name );
502     starthere += strlen( name ) + 1;
503     if ( starthere >= &buffer[ BUFSIZ ] ) {
504 	panic( "sextname" );
505     }
506 }
507 
508     /*
509      *	code for main()
510      */
511 #ifdef vax
512 
513 codeformain()
514 {
515     putprintf("	.text" , 0 );
516     putprintf("	.align	1" , 0 );
517     putprintf("	.globl	_main" , 0 );
518     putprintf("_main:" , 0 );
519     putprintf("	.word	0" , 0 );
520     if ( opt ( 't' ) ) {
521 	putprintf("	pushl	$1" , 0 );
522     } else {
523 	putprintf("	pushl	$0" , 0 );
524     }
525     putprintf("	calls	$1,_PCSTART" , 0 );
526     putprintf("	movl	4(ap),__argc" , 0 );
527     putprintf("	movl	8(ap),__argv" , 0 );
528     putprintf("	calls	$0,_program" , 0 );
529     putprintf("	pushl	$0" , 0 );
530     putprintf("	calls	$1,_PCEXIT" , 0 );
531 }
532 #endif vax
533 
534 #ifdef tahoe
535 codeformain()
536 {
537     putprintf("	.text" , 0 );
538     putprintf("	.align	1" , 0 );
539     putprintf("	.globl	_main" , 0 );
540     putprintf("_main:" , 0 );
541     putprintf("	.word	0" , 0 );
542     if ( opt ( 't' ) ) {
543 	putprintf("	pushl	$1" , 0 );
544     } else {
545 	putprintf("	pushl	$0" , 0 );
546     }
547     putprintf("	callf	$8,_PCSTART" , 0 );
548     putprintf("	movl	4(fp),__argc" , 0 );
549     putprintf("	movl	8(fp),__argv" , 0 );
550     putprintf("	callf	$4,_program" , 0 );
551     putprintf("	pushl	$0" , 0 );
552     putprintf("	callf	$8,_PCEXIT" , 0 );
553 }
554 #endif tahoe
555 
556     /*
557      *	prologue for the program.
558      *	different because it
559      *		doesn't have formal entry point
560      */
561 #if defined(vax) || defined(tahoe)
562 prog_prologue(eecookiep)
563     struct entry_exit_cookie	*eecookiep;
564 {
565     putprintf("	.text" , 0 );
566     putprintf("	.align	1" , 0 );
567     putprintf("	.globl	_program" , 0 );
568     putprintf("_program:" , 0 );
569 	/*
570 	 *	register save mask
571 	 */
572     eecookiep -> savlabel = (int) getlab();
573     putprintf("	.word	%s%d", 0, (int) SAVE_MASK_LABEL , eecookiep -> savlabel );
574 }
575 
576 fp_prologue(eecookiep)
577     struct entry_exit_cookie	*eecookiep;
578 {
579 
580     sextname( eecookiep -> extname, eecookiep -> nlp -> symbol , cbn - 1 );
581     putprintf( "	.text" , 0 );
582     putprintf( "	.align	1" , 0 );
583     putprintf( "	.globl	%s%s", 0, (int) FORMALPREFIX, (int) eecookiep -> extname );
584     putprintf( "	.globl	%s" , 0 , (int) eecookiep -> extname );
585     putprintf( "%s:" , 0 , (int) eecookiep -> extname );
586 	/*
587 	 *	register save mask
588 	 */
589     eecookiep -> savlabel = (int) getlab();
590     putprintf("	.word	%s%d", 0, (int) SAVE_MASK_LABEL , eecookiep -> savlabel );
591 }
592 #endif vax || tahoe
593 
594     /*
595      *	code before any user code.
596      *	or code that is machine dependent.
597      */
598 #ifdef vax
599 fp_entrycode(eecookiep)
600     struct entry_exit_cookie	*eecookiep;
601 {
602     int	ftnno = eecookiep -> nlp -> value[NL_ENTLOC];
603     int	proflabel = (int) getlab();
604     int	setjmp0 = (int) getlab();
605 
606 	/*
607 	 *	top of code;  destination of jump from formal entry code.
608 	 */
609     eecookiep -> toplabel = (int) getlab();
610     (void) putlab( (char *) eecookiep -> toplabel );
611     putprintf("	subl2	$%s%d,sp" , 0 , (int) FRAME_SIZE_LABEL, ftnno );
612     if ( profflag ) {
613 	    /*
614 	     *	call mcount for profiling
615 	     */
616 	putprintf( "	moval	" , 1 );
617 	putprintf( PREFIXFORMAT , 1 , (int) LABELPREFIX , proflabel );
618 	putprintf( ",r0" , 0 );
619 	putprintf( "	jsb	mcount" , 0 );
620 	putprintf( "	.data" , 0 );
621 	putprintf( "	.align	2" , 0 );
622 	(void) putlab( (char *) proflabel );
623 	putprintf( "	.long	0" , 0 );
624 	putprintf( "	.text" , 0 );
625     }
626 	/*
627 	 *	if there are nested procedures that access our variables
628 	 *	we must save the display.
629 	 */
630     if ( parts[ cbn ] & NONLOCALVAR ) {
631 	    /*
632 	     *	save old display
633 	     */
634 	putprintf( "	movq	%s+%d,%d(%s)" , 0
635 		, (int) DISPLAYNAME , cbn * sizeof(struct dispsave)
636 		, DSAVEOFFSET , (int) P2FPNAME );
637 	    /*
638 	     *	set up new display by saving AP and FP in appropriate
639 	     *	slot in display structure.
640 	     */
641 	putprintf( "	movq	%s,%s+%d" , 0
642 		, (int) P2APNAME , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) );
643     }
644 	/*
645 	 *	set underflow checking if runtime tests
646 	 */
647     if ( opt( 't' ) ) {
648 	putprintf( "	bispsw	$0xe0" , 0 );
649     }
650 	/*
651 	 *	zero local variables if checking is on
652 	 *	by calling blkclr( bytes of locals , starting local address );
653 	 */
654     if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
655 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
656 		, "_blkclr" );
657 	putLV((char *) 0 , cbn , (int) sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR );
658 	putleaf( PCC_ICON ,  (int) (( -sizes[ cbn ].om_max ) - DPOFF1)
659 		, 0 , PCCT_INT ,(char *) 0 );
660 	putop( PCC_CM , PCCT_INT );
661 	putop( PCC_CALL , PCCT_INT );
662 	putdot( filename , line );
663     }
664 	/*
665 	 *  set up goto vector if non-local goto to this frame
666 	 */
667     if ( parts[ cbn ] & NONLOCALGOTO ) {
668 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
669 		, "_setjmp" );
670 	putLV( (char *) 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
671 	putop( PCC_CALL , PCCT_INT );
672 	putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
673 	putop( PCC_NE , PCCT_INT );
674 	putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , (char *) 0 );
675 	putop( PCC_CBRANCH , PCCT_INT );
676 	putdot( filename , line );
677 	    /*
678 	     *	on non-local goto, setjmp returns with address to
679 	     *	be branched to.
680 	     */
681 	putprintf( "	jmp	(r0)" , 0 );
682 	(void) putlab((char *) setjmp0);
683     }
684 }
685 #endif vax
686 
687 #ifdef tahoe
688 fp_entrycode(eecookiep)
689     struct entry_exit_cookie	*eecookiep;
690 {
691     int	ftnno = eecookiep -> nlp -> value[NL_ENTLOC];
692     int	proflabel = (int) getlab();
693     int	setjmp0 = (int) getlab();
694 
695 	/*
696 	 *	top of code;  destination of jump from formal entry code.
697 	 */
698     eecookiep -> toplabel = (int) getlab();
699     (void) putlab( (char *) eecookiep -> toplabel );
700     putprintf("	subl3	$%s%d,fp,sp" , 0 , (int) FRAME_SIZE_LABEL, ftnno );
701     if ( profflag ) {
702 	    /*
703 	     *	call mcount for profiling
704 	     */
705 	putprintf( "	pushal	" , 1 );
706 	putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , proflabel );
707 	putprintf( "	callf	$8,mcount" , 0 );
708 	putprintf( "	.data" , 0 );
709 	putprintf( "	.align	2" , 0 );
710 	(void) putlab( (char *) proflabel );
711 	putprintf( "	.long	0" , 0 );
712 	putprintf( "	.text" , 0 );
713     }
714 	/*
715 	 *	if there are nested procedures that access our variables
716 	 *	we must save the display.
717 	 */
718     if ( parts[ cbn ] & NONLOCALVAR ) {
719 	    /*
720 	     *	save old display
721 	     */
722 	putprintf( "	movl	%s+%d,%d(%s)" , 0
723 		, (int) DISPLAYNAME , cbn * sizeof(struct dispsave)
724 		, DSAVEOFFSET , (int) P2FPNAME );
725 	    /*
726 	     *	set up new display by saving FP in appropriate
727 	     *	slot in display structure.
728 	     */
729 	putprintf( "	movl	%s,%s+%d" , 0
730 		, (int) P2FPNAME , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) );
731     }
732 	/*
733 	 *	set underflow checking if runtime tests
734 	 */
735     if ( opt( 't' ) ) {
736 	putprintf( "	bicpsw	$0x20" , 0 );
737     }
738 	/*
739 	 *	zero local variables if checking is on
740 	 *	by calling blkclr( bytes of locals , starting local address );
741 	 */
742     if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
743 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
744 		, "_blkclr" );
745 	putLV((char *) 0 , cbn , (int) sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR );
746 	putleaf( PCC_ICON ,  (int) (( -sizes[ cbn ].om_max ) - DPOFF1)
747 		, 0 , PCCT_INT ,(char *) 0 );
748 	putop( PCC_CM , PCCT_INT );
749 	putop( PCC_CALL , PCCT_INT );
750 	putdot( filename , line );
751     }
752 	/*
753 	 *  set up goto vector if non-local goto to this frame
754 	 */
755     if ( parts[ cbn ] & NONLOCALGOTO ) {
756 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
757 		, "_setjmp" );
758 	putLV( (char *) 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
759 	putop( PCC_CALL , PCCT_INT );
760 	putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
761 	putop( PCC_NE , PCCT_INT );
762 	putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , (char *) 0 );
763 	putop( PCC_CBRANCH , PCCT_INT );
764 	putdot( filename , line );
765 	    /*
766 	     *	on non-local goto, setjmp returns with address to
767 	     *	be branched to.
768 	     */
769 	putprintf( "	jmp	(r0)" , 0 );
770 	(void) putlab((char *) setjmp0);
771     }
772 }
773 #endif tahoe
774 
775 #if defined(vax) || defined(tahoe)
776 fp_exitcode(eecookiep)
777     struct entry_exit_cookie	*eecookiep;
778 {
779 	/*
780 	 *	if there were file variables declared at this level
781 	 *	call PCLOSE( ap ) to clean them up.
782 	 */
783     if ( dfiles[ cbn ] ) {
784 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
785 		, "_PCLOSE" );
786 	putleaf( PCC_REG , 0 , P2AP , PCCM_ADDTYPE( PCCT_CHAR , PCCTM_PTR ) , (char *) 0 );
787 	putop( PCC_CALL , PCCT_INT );
788 	putdot( filename , line );
789     }
790 	/*
791 	 *	if this is a function,
792 	 *	the function variable is the return value.
793 	 *	if it's a scalar valued function, return scalar,
794 	 *	else, return a pointer to the structure value.
795 	 */
796     if ( eecookiep-> nlp -> class == FUNC ) {
797 	struct nl	*fvar = eecookiep-> nlp -> ptr[ NL_FVAR ];
798 	long		fvartype = p2type( fvar -> type );
799 	long		label;
800 	char		labelname[ BUFSIZ ];
801 
802 	switch ( classify( fvar -> type ) ) {
803 	    case TBOOL:
804 	    case TCHAR:
805 	    case TINT:
806 	    case TSCAL:
807 	    case TDOUBLE:
808 	    case TPTR:
809 		putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
810 			fvar -> value[ NL_OFFS ] ,
811 			fvar -> extra_flags ,
812 			(int) fvartype );
813 		putop( PCC_FORCE , (int) fvartype );
814 		break;
815 	    default:
816 		label = (int) getlab();
817 		sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label );
818 		putprintf( "	.data" , 0 );
819 		aligndot(A_STRUCT);
820 		putprintf( "	.lcomm	%s,%d" , 0 ,
821 			    (int) labelname , (int) lwidth( fvar -> type ) );
822 		putprintf( "	.text" , 0 );
823 		putleaf( PCC_NAME , 0 , 0 , (int) fvartype , labelname );
824 		putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
825 			fvar -> value[ NL_OFFS ] ,
826 			fvar -> extra_flags ,
827 			(int) fvartype );
828 		putstrop( PCC_STASG , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR) ,
829 			(int) lwidth( fvar -> type ) ,
830 			align( fvar -> type ) );
831 		putdot( filename , line );
832 		putleaf( PCC_ICON , 0 , 0 , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR), labelname );
833 		putop( PCC_FORCE , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR) );
834 		break;
835 	}
836 	putdot( filename , line );
837     }
838 	/*
839 	 *	if there are nested procedures we must save the display.
840 	 */
841     if ( parts[ cbn ] & NONLOCALVAR ) {
842 	    /*
843 	     *	restore old display entry from save area
844 	     */
845 #ifdef vax
846 	putprintf( "	movq	%d(%s),%s+%d" , 0
847 	    , DSAVEOFFSET , (int) P2FPNAME
848 	    , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) );
849 #endif
850 #ifdef tahoe
851 	putprintf( "	movl	%d(%s),%s+%d" , 0
852 	    , DSAVEOFFSET , (int) P2FPNAME
853 	    , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) );
854 #endif
855     }
856 }
857 #endif vax || tahoe
858 
859 #if defined(vax) || defined(tahoe)
860 fp_epilogue(eecookiep)
861     struct entry_exit_cookie	*eecookiep;
862 {
863     stabline(line);
864     putprintf("	ret" , 0 );
865 	/*
866 	 *	set the register save mask.
867 	 */
868     putprintf("	.set	%s%d,0x%x", 0,
869 		(int) SAVE_MASK_LABEL, eecookiep -> savlabel, savmask());
870 }
871 #endif vax || tahoe
872 
873 #if defined(vax) || defined(tahoe)
874 fp_formalentry(eecookiep)
875     struct entry_exit_cookie	*eecookiep;
876 {
877 
878     putprintf("	.align 1", 0);
879     putprintf("%s%s:" , 0 , (int) FORMALPREFIX , (int) eecookiep -> extname );
880     putprintf("	.word	%s%d", 0, (int) SAVE_MASK_LABEL, eecookiep -> savlabel );
881     putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_FCALL" );
882     putRV((char *) 0 , cbn ,
883 	eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) ,
884 	NPARAM , PCCTM_PTR | PCCT_STRTY );
885     putRV((char *) 0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, PCCTM_PTR|PCCT_STRTY);
886     putop( PCC_CM , PCCT_INT );
887     putop( PCC_CALL , PCCT_INT );
888     putdot( filename , line );
889     putjbr( (long) eecookiep -> toplabel );
890 }
891 #endif vax || tahoe
892 
893 #ifdef mc68000
894 
895 codeformain()
896 {
897     putprintf("	.text", 0);
898     putprintf("	.globl	_main", 0);
899     putprintf("_main:", 0);
900     putprintf("	link	%s,#0", 0, P2FPNAME);
901     if (opt('t')) {
902 	putprintf("	pea	1", 0);
903     } else {
904 	putprintf("	pea	0", 0);
905     }
906     putprintf("	jbsr	_PCSTART", 0);
907     putprintf("	addql	#4,sp", 0);
908     putprintf("	movl	%s@(8),__argc", 0, P2FPNAME);
909     putprintf("	movl	%s@(12),__argv", 0, P2FPNAME);
910     putprintf("	jbsr	_program", 0);
911     putprintf("	pea	0", 0);
912     putprintf("	jbsr	_PCEXIT", 0);
913 }
914 
915 prog_prologue(eecookiep)
916     struct entry_exit_cookie	*eecookiep;
917 {
918     int	ftnno = eecookiep -> nlp -> value[NL_ENTLOC];
919 
920     putprintf("	.text", 0);
921     putprintf("	.globl	_program", 0);
922     putprintf("_program:", 0);
923     putprintf("	link	%s,#0", 0, P2FPNAME);
924     putprintf("	addl	#-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno);
925 	/* touch new end of stack, to break more stack space */
926     putprintf("	tstb	sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno);
927     putprintf("	moveml	#%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno);
928 }
929 
930 fp_prologue(eecookiep)
931     struct entry_exit_cookie	*eecookiep;
932 {
933     int		ftnno = eecookiep -> nlp -> value[NL_ENTLOC];
934 
935     sextname(eecookiep -> extname, eecookiep -> nlp -> symbol, cbn - 1);
936     putprintf("	.text", 0);
937     putprintf("	.globl	%s%s", 0, FORMALPREFIX, eecookiep -> extname);
938     putprintf("	.globl	%s", 0, eecookiep -> extname);
939     putprintf("%s:", 0, eecookiep -> extname);
940     putprintf("	link	%s,#0", 0, P2FPNAME);
941     putprintf("	addl	#-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno);
942 	/* touch new end of stack, to break more stack space */
943     putprintf("	tstb	sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno);
944     putprintf("	moveml	#%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno);
945 }
946 
947 fp_entrycode(eecookiep)
948     struct entry_exit_cookie	*eecookiep;
949 {
950     char *proflabel = getlab();
951     char *setjmp0 = getlab();
952 
953 	/*
954 	 *	fill in the label cookie
955 	 */
956     eecookiep -> toplabel = getlab();
957     (void) putlab(eecookiep -> toplabel);
958 	/*
959 	 *	call mcount if we are profiling.
960 	 */
961     if ( profflag ) {
962 	putprintf("	movl	#%s%d,a0", 0, LABELPREFIX,  proflabel);
963 	putprintf("	jsr	mcount", 0);
964 	putprintf("	.data", 0);
965 	putprintf("	.even", 0);
966 	(void) putlab(proflabel);
967 	putprintf("	.long	0", 0);
968 	putprintf("	.text", 0);
969     }
970 	/*
971 	 *	if there are nested procedures that access our variables
972 	 *	we must save the display
973 	 */
974     if (parts[cbn] & NONLOCALVAR) {
975 	    /*
976 	     *	save the old display
977 	     */
978 	putprintf("	movl	%s+%d,%s@(%d)", 0,
979 		    DISPLAYNAME, cbn * sizeof(struct dispsave),
980 		    P2FPNAME, DSAVEOFFSET);
981 	    /*
982 	     *	set up the new display by saving the framepointer
983 	     *	in the display structure.
984 	     */
985 	putprintf("	movl	%s,%s+%d", 0,
986 		    P2FPNAME, DISPLAYNAME, cbn * sizeof(struct dispsave));
987     }
988 	/*
989 	 *	zero local variables if checking is on
990 	 *	by calling blkclr( bytes of locals , starting local address );
991 	 */
992     if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
993 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
994 		, "_blkclr" );
995 	putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR );
996 	putleaf( PCC_ICON ,  ( -sizes[ cbn ].om_max ) - DPOFF1
997 		, 0 , PCCT_INT , 0 );
998 	putop( PCC_CM , PCCT_INT );
999 	putop( PCC_CALL , PCCT_INT );
1000 	putdot( filename , line );
1001     }
1002 	/*
1003 	 *  set up goto vector if non-local goto to this frame
1004 	 */
1005     if ( parts[ cbn ] & NONLOCALGOTO ) {
1006 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1007 		, "_setjmp" );
1008 	putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
1009 	putop( PCC_CALL , PCCT_INT );
1010 	putleaf( PCC_ICON , 0 , 0 , PCCT_INT , 0 );
1011 	putop( PCC_NE , PCCT_INT );
1012 	putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , 0 );
1013 	putop( PCC_CBRANCH , PCCT_INT );
1014 	putdot( filename , line );
1015 	    /*
1016 	     *	on non-local goto, setjmp returns with address to
1017 	     *	be branched to.
1018 	     */
1019 	putprintf("	movl	d0,a0", 0);
1020 	putprintf("	jmp	a0@", 0);
1021 	(void) putlab(setjmp0);
1022     }
1023 }
1024 
1025 fp_exitcode(eecookiep)
1026     struct entry_exit_cookie	*eecookiep;
1027 {
1028 	/*
1029 	 *	if there were file variables declared at this level
1030 	 *	call PCLOSE( ap ) to clean them up.
1031 	 */
1032     if ( dfiles[ cbn ] ) {
1033 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1034 		, "_PCLOSE" );
1035 	putleaf( PCC_REG , 0 , P2AP , PCCM_ADDTYPE( PCCT_CHAR , PCCTM_PTR ) , 0 );
1036 	putop( PCC_CALL , PCCT_INT );
1037 	putdot( filename , line );
1038     }
1039 	/*
1040 	 *	if this is a function,
1041 	 *	the function variable is the return value.
1042 	 *	if it's a scalar valued function, return scalar,
1043 	 *	else, return a pointer to the structure value.
1044 	 */
1045     if ( eecookiep -> nlp -> class == FUNC ) {
1046 	struct nl	*fvar = eecookiep -> nlp -> ptr[ NL_FVAR ];
1047 	long		fvartype = p2type( fvar -> type );
1048 	char		*label;
1049 	char		labelname[ BUFSIZ ];
1050 
1051 	switch ( classify( fvar -> type ) ) {
1052 	    case TBOOL:
1053 	    case TCHAR:
1054 	    case TINT:
1055 	    case TSCAL:
1056 	    case TDOUBLE:
1057 	    case TPTR:
1058 		putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
1059 			fvar -> value[ NL_OFFS ] ,
1060 			fvar -> extra_flags ,
1061 			fvartype );
1062 		putop( PCC_FORCE , fvartype );
1063 		break;
1064 	    default:
1065 		label = getlab();
1066 		sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label );
1067 		putprintf("	.lcomm	%s,%d", 0,
1068 			labelname, lwidth(fvar -> type));
1069 		putleaf( PCC_NAME , 0 , 0 , fvartype , labelname );
1070 		putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
1071 			fvar -> value[ NL_OFFS ] ,
1072 			fvar -> extra_flags ,
1073 			fvartype );
1074 		putstrop( PCC_STASG , PCCM_ADDTYPE(fvartype, PCCTM_PTR) ,
1075 			lwidth( fvar -> type ) ,
1076 			align( fvar -> type ) );
1077 		putdot( filename , line );
1078 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE(fvartype, PCCTM_PTR), labelname );
1079 		putop( PCC_FORCE , PCCM_ADDTYPE(fvartype, PCCTM_PTR) );
1080 		break;
1081 	}
1082 	putdot( filename , line );
1083     }
1084 	/*
1085 	 *	if we saved a display, we must restore it.
1086 	 */
1087     if ( parts[ cbn ] & NONLOCALVAR ) {
1088 	    /*
1089 	     *	restore old display entry from save area
1090 	     */
1091 	putprintf("	movl	%s@(%d),%s+%d", 0,
1092 		    P2FPNAME, DSAVEOFFSET,
1093 		    DISPLAYNAME, cbn * sizeof(struct dispsave));
1094     }
1095 }
1096 
1097 fp_epilogue(eecookiep)
1098     struct entry_exit_cookie	*eecookiep;
1099 {
1100     /*
1101      *	all done by the second pass.
1102      */
1103 }
1104 
1105 fp_formalentry(eecookiep)
1106     struct entry_exit_cookie	*eecookiep;
1107 {
1108     putprintf( "%s%s:" , 0 , FORMALPREFIX , eecookiep -> extname );
1109     putprintf("	link	%s,#0", 0, P2FPNAME);
1110     putprintf("	addl	#-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno);
1111 	/* touch new end of stack, to break more stack space */
1112     putprintf("	tstb	sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno);
1113     putprintf("	moveml	#%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno);
1114     putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_FCALL" );
1115     putRV( 0 , cbn ,
1116 	eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) ,
1117 	NPARAM , PCCTM_PTR | PCCT_STRTY );
1118     putRV(0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, PCCTM_PTR|PCCT_STRTY);
1119     putop( PCC_CM , PCCT_INT );
1120     putop( PCC_CALL , PCCT_INT );
1121     putdot( filename , line );
1122     putjbr( eecookiep -> toplabel );
1123 }
1124 #endif mc68000
1125 #endif PC
1126