BSD 4 release
[unix-history] / usr / src / cmd / pi / call.c
CommitLineData
81504920
PK
1/* Copyright (c) 1979 Regents of the University of California */
2
31cef89c 3static char sccsid[] = "@(#)call.c 1.3 10/2/80";
81504920
PK
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
c4e911b6
PK
15bool slenflag = 0;
16bool floatflag = 0;
17
81504920
PK
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 */
27struct nl *
28call(p, argv, porf, psbn)
29 struct nl *p;
30 int *argv, porf, psbn;
31{
32 register struct nl *p1, *q;
33 int *r;
34
c4e911b6
PK
35# ifdef OBJ
36 int cnt;
37# endif OBJ
81504920
PK
38# ifdef PC
39 long temp;
40 int firsttime;
41 int rettype;
42# endif PC
43
44# ifdef OBJ
c4e911b6
PK
45 if (p->class == FFUNC || p->class == FPROC)
46 put(2, PTR_RV | cbn << 8+INDX, p->value[NL_OFFS]);
81504920
PK
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 }
c4e911b6
PK
70 switch ( p -> class ) {
71 case FUNC:
72 case PROC:
73 {
74 char extname[ BUFSIZ ];
75 char *starthere;
76 int funcbn;
77 int i;
81504920 78
c4e911b6
PK
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");
81504920
PK
109 }
110 firsttime = TRUE;
111# endif PC
112 /*
113 * Loop and process each of
114 * arguments to the proc/func.
115 */
c4e911b6
PK
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 */
81504920 144# ifdef OBJ
c4e911b6 145 q = rvalue(argv[1], p1->type , RREQ );
81504920
PK
146# endif OBJ
147# ifdef PC
c4e911b6
PK
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)
81504920 178 break;
c4e911b6
PK
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);
81504920
PK
181 break;
182 }
81504920 183# ifdef OBJ
c4e911b6
PK
184 if (isa(p1->type, "bcsi"))
185 rangechk(p1->type, q);
186 if (q->class != STR)
187 convert(q, p1->type);
81504920
PK
188# endif OBJ
189# ifdef PC
c4e911b6
PK
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 }
81504920 201# endif PC
c4e911b6
PK
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");
81504920 226 }
c4e911b6
PK
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 }
81504920 237# endif PC
c4e911b6
PK
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");
81504920
PK
325 }
326# ifdef OBJ
c4e911b6
PK
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 }
81504920
PK
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:
c4e911b6 345 if ( firsttime ) {
81504920
PK
346 putop( P2UNARY P2CALL , rettype );
347 } else {
348 putop( P2CALL , rettype );
349 }
c4e911b6
PK
350 if (p -> class == FFUNC || p -> class == FPROC ) {
351 putop( P2LISTOP , P2INT );
352 putop( P2CALL , rettype );
353 }
81504920
PK
354 break;
355 default:
c4e911b6 356 if ( firsttime ) {
81504920
PK
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 }
c4e911b6
PK
367 if (p -> class == FFUNC || p -> class == FPROC ) {
368 putop( P2LISTOP , P2INT );
369 putop( P2CALL , ADDTYPE( rettype , P2PTR ) );
370 }
81504920
PK
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 {
c4e911b6 378 if ( firsttime ) {
81504920
PK
379 putop( P2UNARY P2CALL , P2INT );
380 } else {
381 putop( P2CALL , P2INT );
382 }
c4e911b6
PK
383 if (p -> class == FFUNC || p -> class == FPROC ) {
384 putop( P2LISTOP , P2INT );
385 putop( P2CALL , P2INT );
386 }
81504920
PK
387 putdot( filename , line );
388 }
389# endif PC
390 return (p->type);
391}
392
393rvlist(al)
394 register int *al;
395{
396
397 for (; al != NIL; al = al[2])
398 rvalue( (int *) al[1], NLNIL , RREQ );
399}