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