|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)call.c 1.3 10/2/80";
4:
5: #include "whoami.h"
6: #include "0.h"
7: #include "tree.h"
8: #include "opcode.h"
9: #include "objfmt.h"
10: #ifdef PC
11: # include "pc.h"
12: # include "pcops.h"
13: #endif PC
14:
15: bool slenflag = 0;
16: bool floatflag = 0;
17:
18: /*
19: * Call generates code for calls to
20: * user defined procedures and functions
21: * and is called by proc and funccod.
22: * P is the result of the lookup
23: * of the procedure/function symbol,
24: * and porf is PROC or FUNC.
25: * Psbn is the block number of p.
26: */
27: struct nl *
28: call(p, argv, porf, psbn)
29: struct nl *p;
30: int *argv, porf, psbn;
31: {
32: register struct nl *p1, *q;
33: int *r;
34:
35: # ifdef OBJ
36: int cnt;
37: # endif OBJ
38: # ifdef PC
39: long temp;
40: int firsttime;
41: int rettype;
42: # endif PC
43:
44: # ifdef OBJ
45: if (p->class == FFUNC || p->class == FPROC)
46: put(2, PTR_RV | cbn << 8+INDX, p->value[NL_OFFS]);
47: if (porf == FUNC)
48: /*
49: * Push some space
50: * for the function return type
51: */
52: put2(O_PUSH, even(-width(p->type)));
53: # endif OBJ
54: # ifdef PC
55: if ( porf == FUNC ) {
56: switch( classify( p -> type ) ) {
57: case TSTR:
58: case TSET:
59: case TREC:
60: case TFILE:
61: case TARY:
62: temp = sizes[ cbn ].om_off -= width( p -> type );
63: putlbracket( ftnno , -sizes[cbn].om_off );
64: if (sizes[cbn].om_off < sizes[cbn].om_max) {
65: sizes[cbn].om_max = sizes[cbn].om_off;
66: }
67: putRV( 0 , cbn , temp , P2STRTY );
68: }
69: }
70: switch ( p -> class ) {
71: case FUNC:
72: case PROC:
73: {
74: char extname[ BUFSIZ ];
75: char *starthere;
76: int funcbn;
77: int i;
78:
79: starthere = &extname[0];
80: funcbn = p -> nl_block & 037;
81: for ( i = 1 ; i < funcbn ; i++ ) {
82: sprintf( starthere , EXTFORMAT , enclosing[ i ] );
83: starthere += strlen( enclosing[ i ] ) + 1;
84: }
85: sprintf( starthere , EXTFORMAT , p -> symbol );
86: starthere += strlen( p -> symbol ) + 1;
87: if ( starthere >= &extname[ BUFSIZ ] ) {
88: panic( "call namelength" );
89: }
90: putleaf( P2ICON , 0 , 0 , p2type( p ) , extname );
91: }
92: break;
93: case FFUNC:
94: case FPROC:
95: /*
96: * start one of these:
97: * FRTN( frtn , ( *FCALL( frtn ) )(...args...) )
98: */
99: putleaf( P2ICON , 0 , 0 , p2type( p ) , "_FRTN" );
100: putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY );
101: putleaf( P2ICON , 0 , 0
102: , ADDTYPE( P2PTR , ADDTYPE( P2FTN , p2type( p ) ) )
103: , "_FCALL" );
104: putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY );
105: putop( P2CALL , p2type( p ) );
106: break;
107: default:
108: panic("call class");
109: }
110: firsttime = TRUE;
111: # endif PC
112: /*
113: * Loop and process each of
114: * arguments to the proc/func.
115: */
116: if ( p -> class == FUNC || p -> class == PROC ) {
117: for (p1 = p->chain; p1 != NIL; p1 = p1->chain) {
118: if (argv == NIL) {
119: error("Not enough arguments to %s", p->symbol);
120: return (NIL);
121: }
122: switch (p1->class) {
123: case REF:
124: /*
125: * Var parameter
126: */
127: r = argv[1];
128: if (r != NIL && r[0] != T_VAR) {
129: error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol);
130: break;
131: }
132: q = lvalue( (int *) argv[1], MOD , LREQ );
133: if (q == NIL)
134: break;
135: if (q != p1->type) {
136: error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol);
137: break;
138: }
139: break;
140: case VAR:
141: /*
142: * Value parameter
143: */
144: # ifdef OBJ
145: q = rvalue(argv[1], p1->type , RREQ );
146: # endif OBJ
147: # ifdef PC
148: /*
149: * structure arguments require lvalues,
150: * scalars use rvalue.
151: */
152: switch( classify( p1 -> type ) ) {
153: case TFILE:
154: case TARY:
155: case TREC:
156: case TSET:
157: case TSTR:
158: q = rvalue( argv[1] , p1 -> type , LREQ );
159: break;
160: case TINT:
161: case TSCAL:
162: case TBOOL:
163: case TCHAR:
164: precheck( p1 -> type , "_RANG4" , "_RSNG4" );
165: q = rvalue( argv[1] , p1 -> type , RREQ );
166: postcheck( p1 -> type );
167: break;
168: default:
169: q = rvalue( argv[1] , p1 -> type , RREQ );
170: if ( isa( p1 -> type , "d" )
171: && isa( q , "i" ) ) {
172: putop( P2SCONV , P2DOUBLE );
173: }
174: break;
175: }
176: # endif PC
177: if (q == NIL)
178: break;
179: if (incompat(q, p1->type, argv[1])) {
180: cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol);
181: break;
182: }
183: # ifdef OBJ
184: if (isa(p1->type, "bcsi"))
185: rangechk(p1->type, q);
186: if (q->class != STR)
187: convert(q, p1->type);
188: # endif OBJ
189: # ifdef PC
190: switch( classify( p1 -> type ) ) {
191: case TFILE:
192: case TARY:
193: case TREC:
194: case TSET:
195: case TSTR:
196: putstrop( P2STARG
197: , p2type( p1 -> type )
198: , lwidth( p1 -> type )
199: , align( p1 -> type ) );
200: }
201: # endif PC
202: break;
203: case FFUNC:
204: /*
205: * function parameter
206: */
207: q = flvalue( (int *) argv[1] , FFUNC );
208: if (q == NIL)
209: break;
210: if (q != p1->type) {
211: error("Function type not identical to type of function parameter %s of %s", p1->symbol, p->symbol);
212: break;
213: }
214: break;
215: case FPROC:
216: /*
217: * procedure parameter
218: */
219: q = flvalue( (int *) argv[1] , FPROC );
220: if (q != NIL) {
221: error("Procedure parameter %s of %s cannot have a type", p1->symbol, p->symbol);
222: }
223: break;
224: default:
225: panic("call");
226: }
227: # ifdef PC
228: /*
229: * if this is the nth (>1) argument,
230: * hang it on the left linear list of arguments
231: */
232: if ( firsttime ) {
233: firsttime = FALSE;
234: } else {
235: putop( P2LISTOP , P2INT );
236: }
237: # endif PC
238: argv = argv[2];
239: }
240: if (argv != NIL) {
241: error("Too many arguments to %s", p->symbol);
242: rvlist(argv);
243: return (NIL);
244: }
245: } else if ( p -> class == FFUNC || p -> class == FPROC ) {
246: /*
247: * formal routines can only have by-value parameters.
248: * this will lose for integer actuals passed to real
249: * formals, and strings which people want blank padded.
250: */
251: # ifdef OBJ
252: cnt = 0;
253: # endif OBJ
254: for ( ; argv != NIL ; argv = argv[2] ) {
255: # ifdef OBJ
256: q = rvalue(argv[1], NIL, RREQ );
257: cnt += even(lwidth(q));
258: # endif OBJ
259: # ifdef PC
260: /*
261: * structure arguments require lvalues,
262: * scalars use rvalue.
263: */
264: codeoff();
265: p1 = rvalue( argv[1] , NIL , RREQ );
266: codeon();
267: switch( classify( p1 ) ) {
268: case TSTR:
269: if ( p1 -> class == STR && slenflag == 0 ) {
270: if ( opt( 's' ) ) {
271: standard();
272: } else {
273: warning();
274: }
275: error("Implementation can't construct equal length strings");
276: slenflag++;
277: }
278: /* and fall through */
279: case TFILE:
280: case TARY:
281: case TREC:
282: case TSET:
283: q = rvalue( argv[1] , p1 , LREQ );
284: break;
285: case TINT:
286: if ( floatflag == 0 ) {
287: if ( opt( 's' ) ) {
288: standard();
289: } else {
290: warning();
291: }
292: error("Implementation can't coerice integer to real");
293: floatflag++;
294: }
295: /* and fall through */
296: case TSCAL:
297: case TBOOL:
298: case TCHAR:
299: default:
300: q = rvalue( argv[1] , p1 , RREQ );
301: break;
302: }
303: switch( classify( p1 ) ) {
304: case TFILE:
305: case TARY:
306: case TREC:
307: case TSET:
308: case TSTR:
309: putstrop( P2STARG , p2type( p1 ) ,
310: lwidth( p1 ) , align( p1 ) );
311: }
312: /*
313: * if this is the nth (>1) argument,
314: * hang it on the left linear list of arguments
315: */
316: if ( firsttime ) {
317: firsttime = FALSE;
318: } else {
319: putop( P2LISTOP , P2INT );
320: }
321: # endif PC
322: }
323: } else {
324: panic("call class");
325: }
326: # ifdef OBJ
327: if ( p -> class == FFUNC || p -> class == FPROC ) {
328: put(2, PTR_RV | cbn << 8+INDX, p->value[NL_OFFS]);
329: put(2, O_FCALL, cnt);
330: put(2, O_FRTN, even(lwidth(p->type)));
331: } else {
332: put2(O_CALL | psbn << 8+INDX, p->entloc);
333: }
334: # endif OBJ
335: # ifdef PC
336: if ( porf == FUNC ) {
337: rettype = p2type( p -> type );
338: switch ( classify( p -> type ) ) {
339: case TBOOL:
340: case TCHAR:
341: case TINT:
342: case TSCAL:
343: case TDOUBLE:
344: case TPTR:
345: if ( firsttime ) {
346: putop( P2UNARY P2CALL , rettype );
347: } else {
348: putop( P2CALL , rettype );
349: }
350: if (p -> class == FFUNC || p -> class == FPROC ) {
351: putop( P2LISTOP , P2INT );
352: putop( P2CALL , rettype );
353: }
354: break;
355: default:
356: if ( firsttime ) {
357: putstrop( P2UNARY P2STCALL
358: , ADDTYPE( rettype , P2PTR )
359: , lwidth( p -> type )
360: , align( p -> type ) );
361: } else {
362: putstrop( P2STCALL
363: , ADDTYPE( rettype , P2PTR )
364: , lwidth( p -> type )
365: , align( p -> type ) );
366: }
367: if (p -> class == FFUNC || p -> class == FPROC ) {
368: putop( P2LISTOP , P2INT );
369: putop( P2CALL , ADDTYPE( rettype , P2PTR ) );
370: }
371: putstrop( P2STASG , rettype , lwidth( p -> type )
372: , align( p -> type ) );
373: putLV( 0 , cbn , temp , rettype );
374: putop( P2COMOP , P2INT );
375: break;
376: }
377: } else {
378: if ( firsttime ) {
379: putop( P2UNARY P2CALL , P2INT );
380: } else {
381: putop( P2CALL , P2INT );
382: }
383: if (p -> class == FFUNC || p -> class == FPROC ) {
384: putop( P2LISTOP , P2INT );
385: putop( P2CALL , P2INT );
386: }
387: putdot( filename , line );
388: }
389: # endif PC
390: return (p->type);
391: }
392:
393: rvlist(al)
394: register int *al;
395: {
396:
397: for (; al != NIL; al = al[2])
398: rvalue( (int *) al[1], NLNIL , RREQ );
399: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.