xref: /csrg-svn/usr.bin/pascal/src/fend.c (revision 30037)
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.2 (Berkeley) 11/12/86";
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,
472 		roundup(-sizes[cbn].om_max, (long) A_STACK), 2);
473 #	endif OBJ
474 	cbn--;
475 	if (inpflist(fp->symbol)) {
476 		opop('l');
477 	}
478 }
479 
480 #ifdef PC
481     /*
482      *	construct the long name of a function based on it's static nesting.
483      *	into a caller-supplied buffer (that should be about BUFSIZ big).
484      */
485 sextname( buffer , name , level )
486     char	buffer[];
487     char	*name;
488     int		level;
489 {
490     char	*starthere;
491     int	i;
492 
493     starthere = &buffer[0];
494     for ( i = 1 ; i < level ; i++ ) {
495 	sprintf( starthere , EXTFORMAT , enclosing[ i ] );
496 	starthere += strlen( enclosing[ i ] ) + 1;
497     }
498     sprintf( starthere , EXTFORMAT , name );
499     starthere += strlen( name ) + 1;
500     if ( starthere >= &buffer[ BUFSIZ ] ) {
501 	panic( "sextname" );
502     }
503 }
504 
505     /*
506      *	code for main()
507      */
508 #ifdef vax
509 
510 codeformain()
511 {
512     putprintf("	.text" , 0 );
513     putprintf("	.align	1" , 0 );
514     putprintf("	.globl	_main" , 0 );
515     putprintf("_main:" , 0 );
516     putprintf("	.word	0" , 0 );
517     if ( opt ( 't' ) ) {
518 	putprintf("	pushl	$1" , 0 );
519     } else {
520 	putprintf("	pushl	$0" , 0 );
521     }
522     putprintf("	calls	$1,_PCSTART" , 0 );
523     putprintf("	movl	4(ap),__argc" , 0 );
524     putprintf("	movl	8(ap),__argv" , 0 );
525     putprintf("	calls	$0,_program" , 0 );
526     putprintf("	pushl	$0" , 0 );
527     putprintf("	calls	$1,_PCEXIT" , 0 );
528 }
529 
530     /*
531      *	prologue for the program.
532      *	different because it
533      *		doesn't have formal entry point
534      */
535 prog_prologue(eecookiep)
536     struct entry_exit_cookie	*eecookiep;
537 {
538     putprintf("	.text" , 0 );
539     putprintf("	.align	1" , 0 );
540     putprintf("	.globl	_program" , 0 );
541     putprintf("_program:" , 0 );
542 	/*
543 	 *	register save mask
544 	 */
545     eecookiep -> savlabel = (int) getlab();
546     putprintf("	.word	%s%d", 0, (int) SAVE_MASK_LABEL , eecookiep -> savlabel );
547 }
548 
549 fp_prologue(eecookiep)
550     struct entry_exit_cookie	*eecookiep;
551 {
552 
553     sextname( eecookiep -> extname, eecookiep -> nlp -> symbol , cbn - 1 );
554     putprintf( "	.text" , 0 );
555     putprintf( "	.align	1" , 0 );
556     putprintf( "	.globl	%s%s", 0, (int) FORMALPREFIX, (int) eecookiep -> extname );
557     putprintf( "	.globl	%s" , 0 , (int) eecookiep -> extname );
558     putprintf( "%s:" , 0 , (int) eecookiep -> extname );
559 	/*
560 	 *	register save mask
561 	 */
562     eecookiep -> savlabel = (int) getlab();
563     putprintf("	.word	%s%d", 0, (int) SAVE_MASK_LABEL , eecookiep -> savlabel );
564 }
565 
566     /*
567      *	code before any user code.
568      *	or code that is machine dependent.
569      */
570 fp_entrycode(eecookiep)
571     struct entry_exit_cookie	*eecookiep;
572 {
573     int	ftnno = eecookiep -> nlp -> value[NL_ENTLOC];
574     int	proflabel = (int) getlab();
575     int	setjmp0 = (int) getlab();
576 
577 	/*
578 	 *	top of code;  destination of jump from formal entry code.
579 	 */
580     eecookiep -> toplabel = (int) getlab();
581     (void) putlab( (char *) eecookiep -> toplabel );
582     putprintf("	subl2	$%s%d,sp" , 0 , (int) FRAME_SIZE_LABEL, ftnno );
583     if ( profflag ) {
584 	    /*
585 	     *	call mcount for profiling
586 	     */
587 	putprintf( "	moval	" , 1 );
588 	putprintf( PREFIXFORMAT , 1 , (int) LABELPREFIX , proflabel );
589 	putprintf( ",r0" , 0 );
590 	putprintf( "	jsb	mcount" , 0 );
591 	putprintf( "	.data" , 0 );
592 	putprintf( "	.align	2" , 0 );
593 	(void) putlab( (char *) proflabel );
594 	putprintf( "	.long	0" , 0 );
595 	putprintf( "	.text" , 0 );
596     }
597 	/*
598 	 *	if there are nested procedures that access our variables
599 	 *	we must save the display.
600 	 */
601     if ( parts[ cbn ] & NONLOCALVAR ) {
602 	    /*
603 	     *	save old display
604 	     */
605 	putprintf( "	movq	%s+%d,%d(%s)" , 0
606 		, (int) DISPLAYNAME , cbn * sizeof(struct dispsave)
607 		, DSAVEOFFSET , (int) P2FPNAME );
608 	    /*
609 	     *	set up new display by saving AP and FP in appropriate
610 	     *	slot in display structure.
611 	     */
612 	putprintf( "	movq	%s,%s+%d" , 0
613 		, (int) P2APNAME , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) );
614     }
615 	/*
616 	 *	set underflow checking if runtime tests
617 	 */
618     if ( opt( 't' ) ) {
619 	putprintf( "	bispsw	$0xe0" , 0 );
620     }
621 	/*
622 	 *	zero local variables if checking is on
623 	 *	by calling blkclr( bytes of locals , starting local address );
624 	 */
625     if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
626 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
627 		, "_blkclr" );
628 	putLV((char *) 0 , cbn , (int) sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR );
629 	putleaf( PCC_ICON ,  (int) (( -sizes[ cbn ].om_max ) - DPOFF1)
630 		, 0 , PCCT_INT ,(char *) 0 );
631 	putop( PCC_CM , PCCT_INT );
632 	putop( PCC_CALL , PCCT_INT );
633 	putdot( filename , line );
634     }
635 	/*
636 	 *  set up goto vector if non-local goto to this frame
637 	 */
638     if ( parts[ cbn ] & NONLOCALGOTO ) {
639 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
640 		, "_setjmp" );
641 	putLV( (char *) 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
642 	putop( PCC_CALL , PCCT_INT );
643 	putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
644 	putop( PCC_NE , PCCT_INT );
645 	putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , (char *) 0 );
646 	putop( PCC_CBRANCH , PCCT_INT );
647 	putdot( filename , line );
648 	    /*
649 	     *	on non-local goto, setjmp returns with address to
650 	     *	be branched to.
651 	     */
652 	putprintf( "	jmp	(r0)" , 0 );
653 	(void) putlab((char *) setjmp0);
654     }
655 }
656 
657 fp_exitcode(eecookiep)
658     struct entry_exit_cookie	*eecookiep;
659 {
660 	/*
661 	 *	if there were file variables declared at this level
662 	 *	call PCLOSE( ap ) to clean them up.
663 	 */
664     if ( dfiles[ cbn ] ) {
665 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
666 		, "_PCLOSE" );
667 	putleaf( PCC_REG , 0 , P2AP , PCCM_ADDTYPE( PCCT_CHAR , PCCTM_PTR ) , (char *) 0 );
668 	putop( PCC_CALL , PCCT_INT );
669 	putdot( filename , line );
670     }
671 	/*
672 	 *	if this is a function,
673 	 *	the function variable is the return value.
674 	 *	if it's a scalar valued function, return scalar,
675 	 *	else, return a pointer to the structure value.
676 	 */
677     if ( eecookiep-> nlp -> class == FUNC ) {
678 	struct nl	*fvar = eecookiep-> nlp -> ptr[ NL_FVAR ];
679 	long		fvartype = p2type( fvar -> type );
680 	long		label;
681 	char		labelname[ BUFSIZ ];
682 
683 	switch ( classify( fvar -> type ) ) {
684 	    case TBOOL:
685 	    case TCHAR:
686 	    case TINT:
687 	    case TSCAL:
688 	    case TDOUBLE:
689 	    case TPTR:
690 		putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
691 			fvar -> value[ NL_OFFS ] ,
692 			fvar -> extra_flags ,
693 			(int) fvartype );
694 		putop( PCC_FORCE , (int) fvartype );
695 		break;
696 	    default:
697 		label = (int) getlab();
698 		sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label );
699 		putprintf( "	.data" , 0 );
700 		aligndot(A_STRUCT);
701 		putprintf( "	.lcomm	%s,%d" , 0 ,
702 			    (int) labelname , (int) lwidth( fvar -> type ) );
703 		putprintf( "	.text" , 0 );
704 		putleaf( PCC_NAME , 0 , 0 , (int) fvartype , labelname );
705 		putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
706 			fvar -> value[ NL_OFFS ] ,
707 			fvar -> extra_flags ,
708 			(int) fvartype );
709 		putstrop( PCC_STASG , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR) ,
710 			(int) lwidth( fvar -> type ) ,
711 			align( fvar -> type ) );
712 		putdot( filename , line );
713 		putleaf( PCC_ICON , 0 , 0 , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR), labelname );
714 		putop( PCC_FORCE , (int) PCCM_ADDTYPE(fvartype, PCCTM_PTR) );
715 		break;
716 	}
717 	putdot( filename , line );
718     }
719 	/*
720 	 *	if there are nested procedures we must save the display.
721 	 */
722     if ( parts[ cbn ] & NONLOCALVAR ) {
723 	    /*
724 	     *	restore old display entry from save area
725 	     */
726 	putprintf( "	movq	%d(%s),%s+%d" , 0
727 	    , DSAVEOFFSET , (int) P2FPNAME
728 	    , (int) DISPLAYNAME , cbn * sizeof(struct dispsave) );
729     }
730 }
731 
732 fp_epilogue(eecookiep)
733     struct entry_exit_cookie	*eecookiep;
734 {
735     stabline(line);
736     putprintf("	ret" , 0 );
737 	/*
738 	 *	set the register save mask.
739 	 */
740     putprintf("	.set	%s%d,0x%x", 0,
741 		(int) SAVE_MASK_LABEL, eecookiep -> savlabel, savmask());
742 }
743 
744 fp_formalentry(eecookiep)
745     struct entry_exit_cookie	*eecookiep;
746 {
747 
748     putprintf("	.align 1", 0);
749     putprintf("%s%s:" , 0 , (int) FORMALPREFIX , (int) eecookiep -> extname );
750     putprintf("	.word	%s%d", 0, (int) SAVE_MASK_LABEL, eecookiep -> savlabel );
751     putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_FCALL" );
752     putRV((char *) 0 , cbn ,
753 	eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) ,
754 	NPARAM , PCCTM_PTR | PCCT_STRTY );
755     putRV((char *) 0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, PCCTM_PTR|PCCT_STRTY);
756     putop( PCC_CM , PCCT_INT );
757     putop( PCC_CALL , PCCT_INT );
758     putdot( filename , line );
759     putjbr( (long) eecookiep -> toplabel );
760 }
761 #endif vax
762 
763 #ifdef mc68000
764 
765 codeformain()
766 {
767     putprintf("	.text", 0);
768     putprintf("	.globl	_main", 0);
769     putprintf("_main:", 0);
770     putprintf("	link	%s,#0", 0, P2FPNAME);
771     if (opt('t')) {
772 	putprintf("	pea	1", 0);
773     } else {
774 	putprintf("	pea	0", 0);
775     }
776     putprintf("	jbsr	_PCSTART", 0);
777     putprintf("	addql	#4,sp", 0);
778     putprintf("	movl	%s@(8),__argc", 0, P2FPNAME);
779     putprintf("	movl	%s@(12),__argv", 0, P2FPNAME);
780     putprintf("	jbsr	_program", 0);
781     putprintf("	pea	0", 0);
782     putprintf("	jbsr	_PCEXIT", 0);
783 }
784 
785 prog_prologue(eecookiep)
786     struct entry_exit_cookie	*eecookiep;
787 {
788     int	ftnno = eecookiep -> nlp -> value[NL_ENTLOC];
789 
790     putprintf("	.text", 0);
791     putprintf("	.globl	_program", 0);
792     putprintf("_program:", 0);
793     putprintf("	link	%s,#0", 0, P2FPNAME);
794     putprintf("	addl	#-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno);
795 	/* touch new end of stack, to break more stack space */
796     putprintf("	tstb	sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno);
797     putprintf("	moveml	#%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno);
798 }
799 
800 fp_prologue(eecookiep)
801     struct entry_exit_cookie	*eecookiep;
802 {
803     int		ftnno = eecookiep -> nlp -> value[NL_ENTLOC];
804 
805     sextname(eecookiep -> extname, eecookiep -> nlp -> symbol, cbn - 1);
806     putprintf("	.text", 0);
807     putprintf("	.globl	%s%s", 0, FORMALPREFIX, eecookiep -> extname);
808     putprintf("	.globl	%s", 0, eecookiep -> extname);
809     putprintf("%s:", 0, eecookiep -> extname);
810     putprintf("	link	%s,#0", 0, P2FPNAME);
811     putprintf("	addl	#-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno);
812 	/* touch new end of stack, to break more stack space */
813     putprintf("	tstb	sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno);
814     putprintf("	moveml	#%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno);
815 }
816 
817 fp_entrycode(eecookiep)
818     struct entry_exit_cookie	*eecookiep;
819 {
820     char *proflabel = getlab();
821     char *setjmp0 = getlab();
822 
823 	/*
824 	 *	fill in the label cookie
825 	 */
826     eecookiep -> toplabel = getlab();
827     (void) putlab(eecookiep -> toplabel);
828 	/*
829 	 *	call mcount if we are profiling.
830 	 */
831     if ( profflag ) {
832 	putprintf("	movl	#%s%d,a0", 0, LABELPREFIX,  proflabel);
833 	putprintf("	jsr	mcount", 0);
834 	putprintf("	.data", 0);
835 	putprintf("	.even", 0);
836 	(void) putlab(proflabel);
837 	putprintf("	.long	0", 0);
838 	putprintf("	.text", 0);
839     }
840 	/*
841 	 *	if there are nested procedures that access our variables
842 	 *	we must save the display
843 	 */
844     if (parts[cbn] & NONLOCALVAR) {
845 	    /*
846 	     *	save the old display
847 	     */
848 	putprintf("	movl	%s+%d,%s@(%d)", 0,
849 		    DISPLAYNAME, cbn * sizeof(struct dispsave),
850 		    P2FPNAME, DSAVEOFFSET);
851 	    /*
852 	     *	set up the new display by saving the framepointer
853 	     *	in the display structure.
854 	     */
855 	putprintf("	movl	%s,%s+%d", 0,
856 		    P2FPNAME, DISPLAYNAME, cbn * sizeof(struct dispsave));
857     }
858 	/*
859 	 *	zero local variables if checking is on
860 	 *	by calling blkclr( bytes of locals , starting local address );
861 	 */
862     if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
863 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
864 		, "_blkclr" );
865 	putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , PCCT_CHAR );
866 	putleaf( PCC_ICON ,  ( -sizes[ cbn ].om_max ) - DPOFF1
867 		, 0 , PCCT_INT , 0 );
868 	putop( PCC_CM , PCCT_INT );
869 	putop( PCC_CALL , PCCT_INT );
870 	putdot( filename , line );
871     }
872 	/*
873 	 *  set up goto vector if non-local goto to this frame
874 	 */
875     if ( parts[ cbn ] & NONLOCALGOTO ) {
876 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
877 		, "_setjmp" );
878 	putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
879 	putop( PCC_CALL , PCCT_INT );
880 	putleaf( PCC_ICON , 0 , 0 , PCCT_INT , 0 );
881 	putop( PCC_NE , PCCT_INT );
882 	putleaf( PCC_ICON , setjmp0 , 0 , PCCT_INT , 0 );
883 	putop( PCC_CBRANCH , PCCT_INT );
884 	putdot( filename , line );
885 	    /*
886 	     *	on non-local goto, setjmp returns with address to
887 	     *	be branched to.
888 	     */
889 	putprintf("	movl	d0,a0", 0);
890 	putprintf("	jmp	a0@", 0);
891 	(void) putlab(setjmp0);
892     }
893 }
894 
895 fp_exitcode(eecookiep)
896     struct entry_exit_cookie	*eecookiep;
897 {
898 	/*
899 	 *	if there were file variables declared at this level
900 	 *	call PCLOSE( ap ) to clean them up.
901 	 */
902     if ( dfiles[ cbn ] ) {
903 	putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
904 		, "_PCLOSE" );
905 	putleaf( PCC_REG , 0 , P2AP , PCCM_ADDTYPE( PCCT_CHAR , PCCTM_PTR ) , 0 );
906 	putop( PCC_CALL , PCCT_INT );
907 	putdot( filename , line );
908     }
909 	/*
910 	 *	if this is a function,
911 	 *	the function variable is the return value.
912 	 *	if it's a scalar valued function, return scalar,
913 	 *	else, return a pointer to the structure value.
914 	 */
915     if ( eecookiep -> nlp -> class == FUNC ) {
916 	struct nl	*fvar = eecookiep -> nlp -> ptr[ NL_FVAR ];
917 	long		fvartype = p2type( fvar -> type );
918 	char		*label;
919 	char		labelname[ BUFSIZ ];
920 
921 	switch ( classify( fvar -> type ) ) {
922 	    case TBOOL:
923 	    case TCHAR:
924 	    case TINT:
925 	    case TSCAL:
926 	    case TDOUBLE:
927 	    case TPTR:
928 		putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
929 			fvar -> value[ NL_OFFS ] ,
930 			fvar -> extra_flags ,
931 			fvartype );
932 		putop( PCC_FORCE , fvartype );
933 		break;
934 	    default:
935 		label = getlab();
936 		sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label );
937 		putprintf("	.lcomm	%s,%d", 0,
938 			labelname, lwidth(fvar -> type));
939 		putleaf( PCC_NAME , 0 , 0 , fvartype , labelname );
940 		putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
941 			fvar -> value[ NL_OFFS ] ,
942 			fvar -> extra_flags ,
943 			fvartype );
944 		putstrop( PCC_STASG , PCCM_ADDTYPE(fvartype, PCCTM_PTR) ,
945 			lwidth( fvar -> type ) ,
946 			align( fvar -> type ) );
947 		putdot( filename , line );
948 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE(fvartype, PCCTM_PTR), labelname );
949 		putop( PCC_FORCE , PCCM_ADDTYPE(fvartype, PCCTM_PTR) );
950 		break;
951 	}
952 	putdot( filename , line );
953     }
954 	/*
955 	 *	if we saved a display, we must restore it.
956 	 */
957     if ( parts[ cbn ] & NONLOCALVAR ) {
958 	    /*
959 	     *	restore old display entry from save area
960 	     */
961 	putprintf("	movl	%s@(%d),%s+%d", 0,
962 		    P2FPNAME, DSAVEOFFSET,
963 		    DISPLAYNAME, cbn * sizeof(struct dispsave));
964     }
965 }
966 
967 fp_epilogue(eecookiep)
968     struct entry_exit_cookie	*eecookiep;
969 {
970     /*
971      *	all done by the second pass.
972      */
973 }
974 
975 fp_formalentry(eecookiep)
976     struct entry_exit_cookie	*eecookiep;
977 {
978     putprintf( "%s%s:" , 0 , FORMALPREFIX , eecookiep -> extname );
979     putprintf("	link	%s,#0", 0, P2FPNAME);
980     putprintf("	addl	#-%s%d,sp", 0, FRAME_SIZE_LABEL, ftnno);
981 	/* touch new end of stack, to break more stack space */
982     putprintf("	tstb	sp@(-%s%d)", 0, PAGE_BREAK_LABEL, ftnno);
983     putprintf("	moveml	#%s%d,sp@", 0, SAVE_MASK_LABEL, ftnno);
984     putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_FCALL" );
985     putRV( 0 , cbn ,
986 	eecookiep -> nlp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) ,
987 	NPARAM , PCCTM_PTR | PCCT_STRTY );
988     putRV(0, cbn, eecookiep -> nlp -> value[NL_OFFS], NPARAM, PCCTM_PTR|PCCT_STRTY);
989     putop( PCC_CM , PCCT_INT );
990     putop( PCC_CALL , PCCT_INT );
991     putdot( filename , line );
992     putjbr( eecookiep -> toplabel );
993 }
994 #endif mc68000
995 #endif PC
996