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