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