|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)fhdr.c 1.6 2/1/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:
12: /*
13: * this array keeps the pxp counters associated with
14: * functions and procedures, so that they can be output
15: * when their bodies are encountered
16: */
17: int bodycnts[ DSPLYSZ ];
18:
19: #ifdef PC
20: # include "pc.h"
21: # include "pcops.h"
22: #endif PC
23:
24: #ifdef OBJ
25: int cntpatch;
26: int nfppatch;
27: #endif OBJ
28:
29: /*
30: * Funchdr inserts
31: * declaration of a the
32: * prog/proc/func into the
33: * namelist. It also handles
34: * the arguments and puts out
35: * a transfer which defines
36: * the entry point of a procedure.
37: */
38:
39: struct nl *
40: funchdr(r)
41: int *r;
42: {
43: register struct nl *p;
44: register *il, **rl;
45: struct nl *cp, *dp;
46: int s, o, *pp;
47:
48: if (inpflist(r[2])) {
49: opush('l');
50: yyretrieve(); /* kludge */
51: }
52: pfcnt++;
53: parts[ cbn ] |= RPRT;
54: line = r[1];
55: if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) {
56: /*
57: * Symbol already defined
58: * in this block. it is either
59: * a redeclared symbol (error)
60: * a forward declaration,
61: * or an external declaration.
62: * check that forwards are of the right kind:
63: * if this fails, we are trying to redefine it
64: * and enter() will complain.
65: */
66: if ( ( ( p->nl_flags & NFORWD ) != 0 )
67: && ( ( p->class == FUNC && r[0] == T_FDEC )
68: || ( p->class == PROC && r[0] == T_PDEC ) ) ) {
69: /*
70: * Grammar doesnt forbid
71: * types on a resolution
72: * of a forward function
73: * declaration.
74: */
75: if (p->class == FUNC && r[4])
76: error("Function type should be given only in forward declaration");
77: /*
78: * get another counter for the actual
79: */
80: if ( monflg ) {
81: bodycnts[ cbn ] = getcnt();
82: }
83: # ifdef PC
84: enclosing[ cbn ] = p -> symbol;
85: # endif PC
86: # ifdef PTREE
87: /*
88: * mark this proc/func as forward
89: * in the pTree.
90: */
91: pDEF( p -> inTree ).PorFForward = TRUE;
92: # endif PTREE
93: return (p);
94: }
95: }
96:
97: /* if a routine segment is being compiled,
98: * do level one processing.
99: */
100:
101: if ((r[0] != T_PROG) && (!progseen))
102: level1();
103:
104:
105: /*
106: * Declare the prog/proc/func
107: */
108: switch (r[0]) {
109: case T_PROG:
110: progseen = TRUE;
111: if (opt('z'))
112: monflg = TRUE;
113: program = p = defnl(r[2], PROG, 0, 0);
114: p->value[3] = r[1];
115: break;
116: case T_PDEC:
117: if (r[4] != NIL)
118: error("Procedures do not have types, only functions do");
119: p = enter(defnl(r[2], PROC, 0, 0));
120: p->nl_flags |= NMOD;
121: # ifdef PC
122: enclosing[ cbn ] = r[2];
123: p -> extra_flags |= NGLOBAL;
124: # endif PC
125: break;
126: case T_FDEC:
127: il = r[4];
128: if (il == NIL)
129: error("Function type must be specified");
130: else if (il[0] != T_TYID) {
131: il = NIL;
132: error("Function type can be specified only by using a type identifier");
133: } else
134: il = gtype(il);
135: p = enter(defnl(r[2], FUNC, il, NIL));
136: p->nl_flags |= NMOD;
137: /*
138: * An arbitrary restriction
139: */
140: switch (o = classify(p->type)) {
141: case TFILE:
142: case TARY:
143: case TREC:
144: case TSET:
145: case TSTR:
146: warning();
147: if (opt('s')) {
148: standard();
149: }
150: error("Functions should not return %ss", clnames[o]);
151: }
152: # ifdef PC
153: enclosing[ cbn ] = r[2];
154: p -> extra_flags |= NGLOBAL;
155: # endif PC
156: break;
157: default:
158: panic("funchdr");
159: }
160: if (r[0] != T_PROG) {
161: /*
162: * Mark this proc/func as
163: * being forward declared
164: */
165: p->nl_flags |= NFORWD;
166: /*
167: * Enter the parameters
168: * in the next block for
169: * the time being
170: */
171: if (++cbn >= DSPLYSZ) {
172: error("Procedure/function nesting too deep");
173: pexit(ERRS);
174: }
175: /*
176: * For functions, the function variable
177: */
178: if (p->class == FUNC) {
179: # ifdef OBJ
180: cp = defnl(r[2], FVAR, p->type, 0);
181: # endif OBJ
182: # ifdef PC
183: /*
184: * fvars used to be allocated and deallocated
185: * by the caller right before the arguments.
186: * the offset of the fvar was kept in
187: * value[NL_OFFS] of function (very wierd,
188: * but see asgnop).
189: * now, they are locals to the function
190: * with the offset kept in the fvar.
191: */
192:
193: cp = defnl(r[2], FVAR, p->type,
194: (int)-leven(roundup(
195: (int)(DPOFF1+lwidth(p->type)),
196: (long)align(p->type))));
197: cp -> extra_flags |= NLOCAL;
198: # endif PC
199: cp->chain = p;
200: p->ptr[NL_FVAR] = cp;
201: }
202: /*
203: * Enter the parameters
204: * and compute total size
205: */
206: p->value[NL_OFFS] = params(p, r[3]);
207: /*
208: * because NL_LINENO field in the function
209: * namelist entry has been used (as have all
210: * the other fields), the line number is
211: * stored in the NL_LINENO field of its fvar.
212: */
213: if (p->class == FUNC)
214: p->ptr[NL_FVAR]->value[NL_LINENO] = r[1];
215: else
216: p->value[NL_LINENO] = r[1];
217: cbn--;
218: } else {
219: /*
220: * The wonderful
221: * program statement!
222: */
223: # ifdef OBJ
224: if (monflg) {
225: put(1, O_PXPBUF);
226: cntpatch = put(2, O_CASE4, (long)0);
227: nfppatch = put(2, O_CASE4, (long)0);
228: }
229: # endif OBJ
230: cp = p;
231: for (rl = r[3]; rl; rl = rl[2]) {
232: if (rl[1] == NIL)
233: continue;
234: dp = defnl(rl[1], VAR, 0, 0);
235: cp->chain = dp;
236: cp = dp;
237: }
238: }
239: /*
240: * Define a branch at
241: * the "entry point" of
242: * the prog/proc/func.
243: */
244: p->value[NL_ENTLOC] = getlab();
245: if (monflg) {
246: bodycnts[ cbn ] = getcnt();
247: p->value[ NL_CNTR ] = 0;
248: }
249: # ifdef OBJ
250: put(2, O_TRA4, (long)p->value[NL_ENTLOC]);
251: # endif OBJ
252: # ifdef PTREE
253: {
254: pPointer PF = tCopy( r );
255:
256: pSeize( PorFHeader[ nesting ] );
257: if ( r[0] != T_PROG ) {
258: pPointer *PFs;
259:
260: PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs );
261: *PFs = ListAppend( *PFs , PF );
262: } else {
263: pDEF( PorFHeader[ nesting ] ).GlobProg = PF;
264: }
265: pRelease( PorFHeader[ nesting ] );
266: }
267: # endif PTREE
268: return (p);
269: }
270:
271: /*
272: * deal with the parameter declaration for a routine.
273: * p is the namelist entry of the routine.
274: * formalist is the parse tree for the parameter declaration.
275: * formalist [0] T_LISTPP
276: * [1] pointer to a formal
277: * [2] pointer to next formal
278: * for by-value or by-reference formals, the formal is
279: * formal [0] T_PVAL or T_PVAR
280: * [1] pointer to id_list
281: * [2] pointer to type (error if not typeid)
282: * for function and procedure formals, the formal is
283: * formal [0] T_PFUNC or T_PPROC
284: * [1] pointer to id_list (error if more than one)
285: * [2] pointer to type (error if not typeid, or proc)
286: * [3] pointer to formalist for this routine.
287: */
288: fparams(p, formal)
289: register struct nl *p;
290: int *formal;
291: {
292: params(p, formal[3]);
293: p -> value[ NL_LINENO ] = formal[4];
294: p -> ptr[ NL_FCHAIN ] = p -> chain;
295: p -> chain = NIL;
296: }
297:
298: params(p, formalist)
299: register struct nl *p;
300: int *formalist;
301: {
302: struct nl *chainp, *savedp;
303: struct nl *dp;
304: register int **formalp; /* an element of the formal list */
305: register int *formal; /* a formal */
306: int *typ, *idlist;
307: int w, o;
308:
309: /*
310: * Enter the parameters
311: * and compute total size
312: */
313: chainp = savedp = p;
314:
315: # ifdef OBJ
316: o = 0;
317: # endif OBJ
318: # ifdef PC
319: /*
320: * parameters used to be allocated backwards,
321: * then fixed. for pc, they are allocated correctly.
322: * also, they are aligned.
323: */
324: o = DPOFF2;
325: # endif PC
326: for (formalp = formalist; formalp != NIL; formalp = formalp[2]) {
327: p = NIL;
328: formal = formalp[1];
329: if (formal == NIL)
330: continue;
331: /*
332: * Parametric procedures
333: * don't have types !?!
334: */
335: typ = formal[2];
336: if ( typ == NIL ) {
337: if ( formal[0] != T_PPROC ) {
338: error("Types must be specified for arguments");
339: p = NIL;
340: }
341: } else {
342: if ( formal[0] == T_PPROC ) {
343: error("Procedures cannot have types");
344: p = NIL;
345: } else {
346: if (typ[0] != T_TYID) {
347: error("Types for arguments can be specified only by using type identifiers");
348: p = NIL;
349: } else {
350: p = gtype(typ);
351: }
352: }
353: }
354: for (idlist = formal[1]; idlist != NIL; idlist = idlist[2]) {
355: switch (formal[0]) {
356: default:
357: panic("funchdr2");
358: case T_PVAL:
359: if (p != NIL) {
360: if (p->class == FILET)
361: error("Files cannot be passed by value");
362: else if (p->nl_flags & NFILES)
363: error("Files cannot be a component of %ss passed by value",
364: nameof(p));
365: }
366: # ifdef OBJ
367: w = lwidth(p);
368: o -= even(w);
369: # ifdef DEC11
370: dp = defnl(idlist[1], VAR, p, o);
371: # else
372: dp = defnl(idlist[1], VAR, p,
373: (w < 2) ? o + 1 : o);
374: # endif DEC11
375: # endif OBJ
376: # ifdef PC
377: o = roundup(o, A_STACK);
378: w = lwidth(p);
379: # ifndef DEC11
380: if (w <= sizeof(int)) {
381: o += sizeof(int) - w;
382: }
383: # endif not DEC11
384: dp = defnl(idlist[1], VAR, p, o);
385: o += w;
386: # endif PC
387: dp->nl_flags |= NMOD;
388: break;
389: case T_PVAR:
390: # ifdef OBJ
391: dp = defnl(idlist[1], REF, p, o -= sizeof ( int * ) );
392: # endif OBJ
393: # ifdef PC
394: dp = defnl( idlist[1] , REF , p
395: , o = roundup( o , (long)A_STACK ) );
396: o += sizeof(char *);
397: # endif PC
398: break;
399: case T_PFUNC:
400: if (idlist[2] != NIL) {
401: error("Each function argument must be declared separately");
402: idlist[2] = NIL;
403: }
404: # ifdef OBJ
405: dp = defnl(idlist[1], FFUNC, p, o -= sizeof ( int * ) );
406: # endif OBJ
407: # ifdef PC
408: dp = defnl( idlist[1] , FFUNC , p
409: , o = roundup( o , (long)A_STACK ) );
410: o += sizeof(char *);
411: # endif PC
412: dp -> nl_flags |= NMOD;
413: fparams(dp, formal);
414: break;
415: case T_PPROC:
416: if (idlist[2] != NIL) {
417: error("Each procedure argument must be declared separately");
418: idlist[2] = NIL;
419: }
420: # ifdef OBJ
421: dp = defnl(idlist[1], FPROC, p, o -= sizeof ( int * ) );
422: # endif OBJ
423: # ifdef PC
424: dp = defnl( idlist[1] , FPROC , p
425: , o = roundup( o , (long)A_STACK ) );
426: o += sizeof(char *);
427: # endif PC
428: dp -> nl_flags |= NMOD;
429: fparams(dp, formal);
430: break;
431: }
432: if (dp != NIL) {
433: # ifdef PC
434: dp -> extra_flags |= NPARAM;
435: # endif PC
436: chainp->chain = dp;
437: chainp = dp;
438: }
439: }
440: }
441: p = savedp;
442: # ifdef OBJ
443: /*
444: * Correct the naivete (naivety)
445: * of our above code to
446: * calculate offsets
447: */
448: for (dp = p->chain; dp != NIL; dp = dp->chain)
449: dp->value[NL_OFFS] += -o + DPOFF2;
450: return (-o + DPOFF2);
451: # endif OBJ
452: # ifdef PC
453: return roundup( o , (long)A_STACK );
454: # endif PC
455: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.