148116Sbostic /*-
2*62211Sbostic * Copyright (c) 1980, 1993
3*62211Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622165Sdist */
73191Smckusick
814731Sthien #ifndef lint
9*62211Sbostic static char sccsid[] = "@(#)fhdr.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
113191Smckusick
123191Smckusick #include "whoami.h"
133191Smckusick #include "0.h"
143191Smckusick #include "tree.h"
153191Smckusick #include "opcode.h"
163191Smckusick #include "objfmt.h"
173191Smckusick #include "align.h"
1814731Sthien #include "tree_ty.h"
193191Smckusick
203191Smckusick /*
213191Smckusick * this array keeps the pxp counters associated with
223191Smckusick * functions and procedures, so that they can be output
233191Smckusick * when their bodies are encountered
243191Smckusick */
253191Smckusick int bodycnts[ DSPLYSZ ];
263191Smckusick
273191Smckusick #ifdef PC
283191Smckusick # include "pc.h"
293191Smckusick #endif PC
303191Smckusick
313191Smckusick #ifdef OBJ
323191Smckusick int cntpatch;
333191Smckusick int nfppatch;
343191Smckusick #endif OBJ
353191Smckusick
363191Smckusick /*
373191Smckusick * Funchdr inserts
383191Smckusick * declaration of a the
393191Smckusick * prog/proc/func into the
403191Smckusick * namelist. It also handles
413191Smckusick * the arguments and puts out
423191Smckusick * a transfer which defines
433191Smckusick * the entry point of a procedure.
443191Smckusick */
453191Smckusick
463191Smckusick struct nl *
funchdr(r)473191Smckusick funchdr(r)
4814731Sthien struct tnode *r;
493191Smckusick {
503191Smckusick register struct nl *p;
5114731Sthien register struct tnode *rl;
5214731Sthien struct nl *cp, *dp, *temp;
5314731Sthien int o;
543191Smckusick
5514731Sthien if (inpflist(r->p_dec.id_ptr)) {
563191Smckusick opush('l');
573191Smckusick yyretrieve(); /* kludge */
583191Smckusick }
593191Smckusick pfcnt++;
603191Smckusick parts[ cbn ] |= RPRT;
6114731Sthien line = r->p_dec.line_no;
6214731Sthien if (r->p_dec.param_list == TR_NIL &&
6314731Sthien (p=lookup1(r->p_dec.id_ptr)) != NIL && bn == cbn) {
643191Smckusick /*
653191Smckusick * Symbol already defined
663191Smckusick * in this block. it is either
673191Smckusick * a redeclared symbol (error)
683191Smckusick * a forward declaration,
693191Smckusick * or an external declaration.
707589Speter * check that forwards are of the right kind:
717589Speter * if this fails, we are trying to redefine it
727589Speter * and enter() will complain.
733191Smckusick */
747589Speter if ( ( ( p->nl_flags & NFORWD ) != 0 )
7514731Sthien && ( ( p->class == FUNC && r->tag == T_FDEC )
7614731Sthien || ( p->class == PROC && r->tag == T_PDEC ) ) ) {
773191Smckusick /*
783191Smckusick * Grammar doesnt forbid
793191Smckusick * types on a resolution
803191Smckusick * of a forward function
813191Smckusick * declaration.
823191Smckusick */
8314731Sthien if (p->class == FUNC && r->p_dec.type)
843191Smckusick error("Function type should be given only in forward declaration");
853191Smckusick /*
863191Smckusick * get another counter for the actual
873191Smckusick */
883191Smckusick if ( monflg ) {
893191Smckusick bodycnts[ cbn ] = getcnt();
903191Smckusick }
913191Smckusick # ifdef PC
923191Smckusick enclosing[ cbn ] = p -> symbol;
933191Smckusick # endif PC
943191Smckusick # ifdef PTREE
953191Smckusick /*
963191Smckusick * mark this proc/func as forward
973191Smckusick * in the pTree.
983191Smckusick */
993191Smckusick pDEF( p -> inTree ).PorFForward = TRUE;
1003191Smckusick # endif PTREE
1013191Smckusick return (p);
1023191Smckusick }
1033191Smckusick }
1043191Smckusick
1053191Smckusick /* if a routine segment is being compiled,
1063191Smckusick * do level one processing.
1073191Smckusick */
1083191Smckusick
10914731Sthien if ((r->tag != T_PROG) && (!progseen))
1103191Smckusick level1();
1113191Smckusick
1123191Smckusick
1133191Smckusick /*
1143191Smckusick * Declare the prog/proc/func
1153191Smckusick */
11614731Sthien switch (r->tag) {
1173191Smckusick case T_PROG:
1183191Smckusick progseen = TRUE;
1193191Smckusick if (opt('z'))
1203191Smckusick monflg = TRUE;
12114731Sthien program = p = defnl(r->p_dec.id_ptr, PROG, NLNIL, 0);
12214731Sthien p->value[3] = r->p_dec.line_no;
1233191Smckusick break;
1243191Smckusick case T_PDEC:
12514731Sthien if (r->p_dec.type != TR_NIL)
1263191Smckusick error("Procedures do not have types, only functions do");
12714731Sthien p = enter(defnl(r->p_dec.id_ptr, PROC, NLNIL, 0));
1283191Smckusick p->nl_flags |= NMOD;
1293191Smckusick # ifdef PC
13014731Sthien enclosing[ cbn ] = r->p_dec.id_ptr;
1313838Speter p -> extra_flags |= NGLOBAL;
1323191Smckusick # endif PC
1333191Smckusick break;
1343191Smckusick case T_FDEC:
13514731Sthien {
13614731Sthien register struct tnode *il;
13714731Sthien il = r->p_dec.type;
13818136Smckusick if (il == TR_NIL) {
13918136Smckusick temp = NLNIL;
1403191Smckusick error("Function type must be specified");
14118136Smckusick } else if (il->tag != T_TYID) {
14214731Sthien temp = NLNIL;
1433191Smckusick error("Function type can be specified only by using a type identifier");
1443191Smckusick } else
14514731Sthien temp = gtype(il);
14614731Sthien }
14718136Smckusick p = enter(defnl(r->p_dec.id_ptr, FUNC, temp, NIL));
1483191Smckusick p->nl_flags |= NMOD;
1493191Smckusick /*
1503191Smckusick * An arbitrary restriction
1513191Smckusick */
1523191Smckusick switch (o = classify(p->type)) {
1533191Smckusick case TFILE:
1543191Smckusick case TARY:
1553191Smckusick case TREC:
1563191Smckusick case TSET:
1573191Smckusick case TSTR:
1583191Smckusick warning();
1593191Smckusick if (opt('s')) {
1603191Smckusick standard();
1613191Smckusick }
1623191Smckusick error("Functions should not return %ss", clnames[o]);
1633191Smckusick }
1643191Smckusick # ifdef PC
16514731Sthien enclosing[ cbn ] = r->p_dec.id_ptr;
1663838Speter p -> extra_flags |= NGLOBAL;
1673191Smckusick # endif PC
1683191Smckusick break;
1693191Smckusick default:
1703191Smckusick panic("funchdr");
1713191Smckusick }
17214731Sthien if (r->tag != T_PROG) {
1733191Smckusick /*
1743191Smckusick * Mark this proc/func as
1753191Smckusick * being forward declared
1763191Smckusick */
1773191Smckusick p->nl_flags |= NFORWD;
1783191Smckusick /*
1793191Smckusick * Enter the parameters
1803191Smckusick * in the next block for
1813191Smckusick * the time being
1823191Smckusick */
1833191Smckusick if (++cbn >= DSPLYSZ) {
1843191Smckusick error("Procedure/function nesting too deep");
1853191Smckusick pexit(ERRS);
1863191Smckusick }
1873191Smckusick /*
1883191Smckusick * For functions, the function variable
1893191Smckusick */
1903191Smckusick if (p->class == FUNC) {
1913191Smckusick # ifdef OBJ
19214731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type, 0);
1933191Smckusick # endif OBJ
1943191Smckusick # ifdef PC
1953191Smckusick /*
1963191Smckusick * fvars used to be allocated and deallocated
1973191Smckusick * by the caller right before the arguments.
1983191Smckusick * the offset of the fvar was kept in
1993191Smckusick * value[NL_OFFS] of function (very wierd,
2003191Smckusick * but see asgnop).
2013191Smckusick * now, they are locals to the function
2023191Smckusick * with the offset kept in the fvar.
2033191Smckusick */
2043191Smckusick
20514731Sthien cp = defnl(r->p_dec.id_ptr, FVAR, p->type,
20630037Smckusick (int)-roundup(roundup(
2073302Smckusic (int)(DPOFF1+lwidth(p->type)),
20830037Smckusick (long)align(p->type))), (long) A_STACK);
2093838Speter cp -> extra_flags |= NLOCAL;
2103191Smckusick # endif PC
2113191Smckusick cp->chain = p;
2123191Smckusick p->ptr[NL_FVAR] = cp;
2133191Smckusick }
2143191Smckusick /*
2153191Smckusick * Enter the parameters
2163191Smckusick * and compute total size
2173191Smckusick */
21814731Sthien p->value[NL_OFFS] = params(p, r->p_dec.param_list);
2193302Smckusic /*
2203302Smckusic * because NL_LINENO field in the function
2213302Smckusic * namelist entry has been used (as have all
2223302Smckusic * the other fields), the line number is
2233302Smckusic * stored in the NL_LINENO field of its fvar.
2243302Smckusic */
2253302Smckusic if (p->class == FUNC)
22614731Sthien p->ptr[NL_FVAR]->value[NL_LINENO] = r->p_dec.line_no;
2273302Smckusic else
22814731Sthien p->value[NL_LINENO] = r->p_dec.line_no;
2293191Smckusick cbn--;
2303191Smckusick } else {
2313191Smckusick /*
2323191Smckusick * The wonderful
2333191Smckusick * program statement!
2343191Smckusick */
2353191Smckusick # ifdef OBJ
2363191Smckusick if (monflg) {
23714731Sthien (void) put(1, O_PXPBUF);
2383191Smckusick cntpatch = put(2, O_CASE4, (long)0);
2393191Smckusick nfppatch = put(2, O_CASE4, (long)0);
2403191Smckusick }
2413191Smckusick # endif OBJ
2423191Smckusick cp = p;
24314731Sthien for (rl = r->p_dec.param_list; rl; rl = rl->list_node.next) {
24414731Sthien if (rl->list_node.list == TR_NIL)
2453191Smckusick continue;
24614731Sthien dp = defnl((char *) rl->list_node.list, VAR, NLNIL, 0);
2473191Smckusick cp->chain = dp;
2483191Smckusick cp = dp;
2493191Smckusick }
2503191Smckusick }
2513191Smckusick /*
2523191Smckusick * Define a branch at
2533191Smckusick * the "entry point" of
2543191Smckusick * the prog/proc/func.
2553191Smckusick */
25614731Sthien p->value[NL_ENTLOC] = (int) getlab();
2573191Smckusick if (monflg) {
2583191Smckusick bodycnts[ cbn ] = getcnt();
2593191Smckusick p->value[ NL_CNTR ] = 0;
2603191Smckusick }
2613191Smckusick # ifdef OBJ
26214731Sthien (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]);
2633191Smckusick # endif OBJ
2643191Smckusick # ifdef PTREE
2653191Smckusick {
2663191Smckusick pPointer PF = tCopy( r );
2673191Smckusick
2683191Smckusick pSeize( PorFHeader[ nesting ] );
26914731Sthien if ( r->tag != T_PROG ) {
2703191Smckusick pPointer *PFs;
2713191Smckusick
2723191Smckusick PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs );
2733191Smckusick *PFs = ListAppend( *PFs , PF );
2743191Smckusick } else {
2753191Smckusick pDEF( PorFHeader[ nesting ] ).GlobProg = PF;
2763191Smckusick }
2773191Smckusick pRelease( PorFHeader[ nesting ] );
2783191Smckusick }
2793191Smckusick # endif PTREE
2803191Smckusick return (p);
2813191Smckusick }
2823302Smckusic
2833302Smckusic /*
2843302Smckusic * deal with the parameter declaration for a routine.
2853302Smckusic * p is the namelist entry of the routine.
2863302Smckusic * formalist is the parse tree for the parameter declaration.
2873302Smckusic * formalist [0] T_LISTPP
2883302Smckusic * [1] pointer to a formal
2893302Smckusic * [2] pointer to next formal
2903302Smckusic * for by-value or by-reference formals, the formal is
2913302Smckusic * formal [0] T_PVAL or T_PVAR
2923302Smckusic * [1] pointer to id_list
2933302Smckusic * [2] pointer to type (error if not typeid)
2943302Smckusic * for function and procedure formals, the formal is
2953302Smckusic * formal [0] T_PFUNC or T_PPROC
2963302Smckusic * [1] pointer to id_list (error if more than one)
2973302Smckusic * [2] pointer to type (error if not typeid, or proc)
2983302Smckusic * [3] pointer to formalist for this routine.
2993302Smckusic */
fparams(p,formal)3003302Smckusic fparams(p, formal)
3013302Smckusic register struct nl *p;
30214731Sthien struct tnode *formal; /* T_PFUNC or T_PPROC */
3033302Smckusic {
30414731Sthien (void) params(p, formal->pfunc_node.param_list);
30514731Sthien p -> value[ NL_LINENO ] = formal->pfunc_node.line_no;
3063302Smckusic p -> ptr[ NL_FCHAIN ] = p -> chain;
3073302Smckusic p -> chain = NIL;
3083302Smckusic }
3093302Smckusic
params(p,formalist)3103302Smckusic params(p, formalist)
3113302Smckusic register struct nl *p;
31214731Sthien struct tnode *formalist; /* T_LISTPP */
3133302Smckusic {
3143302Smckusic struct nl *chainp, *savedp;
3153302Smckusic struct nl *dp;
31614731Sthien register struct tnode *formalp; /* an element of the formal list */
31714731Sthien register struct tnode *formal; /* a formal */
31815969Smckusick struct tnode *r, *s, *t, *typ, *idlist;
3193302Smckusic int w, o;
3203302Smckusic
3213302Smckusic /*
3223302Smckusic * Enter the parameters
3233302Smckusic * and compute total size
3243302Smckusic */
3253302Smckusic chainp = savedp = p;
3263302Smckusic
3273302Smckusic # ifdef OBJ
3283302Smckusic o = 0;
3293302Smckusic # endif OBJ
3303302Smckusic # ifdef PC
3313302Smckusic /*
3323302Smckusic * parameters used to be allocated backwards,
3333302Smckusic * then fixed. for pc, they are allocated correctly.
3343302Smckusic * also, they are aligned.
3353302Smckusic */
3363302Smckusic o = DPOFF2;
3373302Smckusic # endif PC
33814731Sthien for (formalp = formalist; formalp != TR_NIL;
33914731Sthien formalp = formalp->list_node.next) {
34014731Sthien formal = formalp->list_node.list;
34114731Sthien if (formal == TR_NIL)
3423302Smckusic continue;
3433302Smckusic /*
3443302Smckusic * Parametric procedures
3453302Smckusic * don't have types !?!
3463302Smckusic */
34714731Sthien typ = formal->pfunc_node.type;
34824051Smckusick p = NLNIL;
34914731Sthien if ( typ == TR_NIL ) {
35014731Sthien if ( formal->tag != T_PPROC ) {
3513302Smckusic error("Types must be specified for arguments");
3523302Smckusic }
3533302Smckusic } else {
35414731Sthien if ( formal->tag == T_PPROC ) {
3553302Smckusic error("Procedures cannot have types");
3563302Smckusic } else {
35715969Smckusick p = gtype(typ);
3583302Smckusic }
3593302Smckusic }
36014731Sthien for (idlist = formal->param.id_list; idlist != TR_NIL;
36114731Sthien idlist = idlist->list_node.next) {
36214731Sthien switch (formal->tag) {
3633302Smckusic default:
3643302Smckusic panic("funchdr2");
3653302Smckusic case T_PVAL:
36614731Sthien if (p != NLNIL) {
3673302Smckusic if (p->class == FILET)
3683302Smckusic error("Files cannot be passed by value");
3693302Smckusic else if (p->nl_flags & NFILES)
3703302Smckusic error("Files cannot be a component of %ss passed by value",
3713302Smckusic nameof(p));
3723302Smckusic }
3733302Smckusic # ifdef OBJ
3743302Smckusic w = lwidth(p);
37530037Smckusick o -= roundup(w, (long) A_STACK);
3763302Smckusic # ifdef DEC11
37714731Sthien dp = defnl((char *) idlist->list_node.list,
37814731Sthien VAR, p, o);
3793302Smckusic # else
38014731Sthien dp = defnl((char *) idlist->list_node.list,
38114731Sthien VAR,p, (w < 2) ? o + 1 : o);
3823302Smckusic # endif DEC11
3833302Smckusic # endif OBJ
3843302Smckusic # ifdef PC
38514731Sthien o = roundup(o, (long) A_STACK);
38610654Speter w = lwidth(p);
38710654Speter # ifndef DEC11
38810654Speter if (w <= sizeof(int)) {
38910654Speter o += sizeof(int) - w;
39010654Speter }
39110654Speter # endif not DEC11
39214731Sthien dp = defnl((char *) idlist->list_node.list,VAR,
39314731Sthien p, o);
39410654Speter o += w;
3953302Smckusic # endif PC
3963302Smckusic dp->nl_flags |= NMOD;
3973302Smckusic break;
3983302Smckusic case T_PVAR:
3993302Smckusic # ifdef OBJ
40014731Sthien dp = defnl((char *) idlist->list_node.list, REF,
40114731Sthien p, o -= sizeof ( int * ) );
4023302Smckusic # endif OBJ
4033302Smckusic # ifdef PC
40414731Sthien dp = defnl( (char *) idlist->list_node.list, REF,
40514731Sthien p ,
40614731Sthien o = roundup( o , (long)A_STACK ) );
4073302Smckusic o += sizeof(char *);
4083302Smckusic # endif PC
4093302Smckusic break;
4103302Smckusic case T_PFUNC:
41114731Sthien if (idlist->list_node.next != TR_NIL) {
4123302Smckusic error("Each function argument must be declared separately");
41314731Sthien idlist->list_node.next = TR_NIL;
4143302Smckusic }
4153302Smckusic # ifdef OBJ
41614731Sthien dp = defnl((char *) idlist->list_node.list,FFUNC,
41714731Sthien p, o -= sizeof ( int * ) );
4183302Smckusic # endif OBJ
4193302Smckusic # ifdef PC
42014731Sthien dp = defnl( (char *) idlist->list_node.list ,
42114731Sthien FFUNC , p ,
42214731Sthien o = roundup( o , (long)A_STACK ) );
4233302Smckusic o += sizeof(char *);
4243302Smckusic # endif PC
4253302Smckusic dp -> nl_flags |= NMOD;
4263302Smckusic fparams(dp, formal);
4273302Smckusic break;
4283302Smckusic case T_PPROC:
42914731Sthien if (idlist->list_node.next != TR_NIL) {
4303302Smckusic error("Each procedure argument must be declared separately");
43114731Sthien idlist->list_node.next = TR_NIL;
4323302Smckusic }
4333302Smckusic # ifdef OBJ
43414731Sthien dp = defnl((char *) idlist->list_node.list,
43514731Sthien FPROC, p, o -= sizeof ( int * ) );
4363302Smckusic # endif OBJ
4373302Smckusic # ifdef PC
43814731Sthien dp = defnl( (char *) idlist->list_node.list ,
43914731Sthien FPROC , p,
44014731Sthien o = roundup( o , (long)A_STACK ) );
4413302Smckusic o += sizeof(char *);
4423302Smckusic # endif PC
4433302Smckusic dp -> nl_flags |= NMOD;
4443302Smckusic fparams(dp, formal);
4453302Smckusic break;
4463302Smckusic }
44714731Sthien if (dp != NLNIL) {
4483838Speter # ifdef PC
4493838Speter dp -> extra_flags |= NPARAM;
4503838Speter # endif PC
4513302Smckusic chainp->chain = dp;
4523302Smckusic chainp = dp;
4533302Smckusic }
4543302Smckusic }
45524051Smckusick if (typ != TR_NIL && typ->tag == T_TYCARY) {
45615969Smckusick # ifdef OBJ
45730037Smckusick w = -roundup(lwidth(p->chain), (long) A_STACK);
45815969Smckusick # ifndef DEC11
45915969Smckusick w = (w > -2)? w + 1 : w;
46015969Smckusick # endif
46115969Smckusick # endif OBJ
46215969Smckusick # ifdef PC
46315969Smckusick w = lwidth(p->chain);
46415969Smckusick o = roundup(o, (long)A_STACK);
46515969Smckusick # endif PC
46615969Smckusick /*
46715969Smckusick * Allocate space for upper and
46815969Smckusick * lower bounds and width.
46915969Smckusick */
47015969Smckusick for (s=typ; s->tag == T_TYCARY; s = s->ary_ty.type) {
47115969Smckusick for (r=s->ary_ty.type_list; r != TR_NIL;
47215969Smckusick r = r->list_node.next) {
47315969Smckusick t = r->list_node.list;
47415969Smckusick p = p->chain;
47515969Smckusick # ifdef OBJ
47615969Smckusick o += w;
47715969Smckusick # endif OBJ
47815969Smckusick chainp->chain = defnl(t->crang_ty.lwb_var,
47915969Smckusick VAR, p, o);
48015969Smckusick chainp = chainp->chain;
48115969Smckusick chainp->nl_flags |= (NMOD | NUSED);
48215969Smckusick p->nptr[0] = chainp;
48315969Smckusick o += w;
48415969Smckusick chainp->chain = defnl(t->crang_ty.upb_var,
48515969Smckusick VAR, p, o);
48615969Smckusick chainp = chainp->chain;
48715969Smckusick chainp->nl_flags |= (NMOD | NUSED);
48815969Smckusick p->nptr[1] = chainp;
48915969Smckusick o += w;
49015969Smckusick chainp->chain = defnl(0, VAR, p, o);
49115969Smckusick chainp = chainp->chain;
49215969Smckusick chainp->nl_flags |= (NMOD | NUSED);
49315969Smckusick p->nptr[2] = chainp;
49415969Smckusick # ifdef PC
49515969Smckusick o += w;
49615969Smckusick # endif PC
49715969Smckusick }
49815969Smckusick }
49915969Smckusick }
5003302Smckusic }
5013302Smckusic p = savedp;
5023302Smckusic # ifdef OBJ
5033302Smckusic /*
5043302Smckusic * Correct the naivete (naivety)
5053302Smckusic * of our above code to
5063302Smckusic * calculate offsets
5073302Smckusic */
50814731Sthien for (dp = p->chain; dp != NLNIL; dp = dp->chain)
5093302Smckusic dp->value[NL_OFFS] += -o + DPOFF2;
5103302Smckusic return (-o + DPOFF2);
5113302Smckusic # endif OBJ
5123302Smckusic # ifdef PC
5133302Smckusic return roundup( o , (long)A_STACK );
5143302Smckusic # endif PC
5153302Smckusic }
516