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