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