Commit | Line | Data |
---|---|---|
252367af DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
28e6b83a | 6 | |
72fbef68 | 7 | #ifndef lint |
ca67e7b4 | 8 | static char sccsid[] = "@(#)stkrval.c 5.2 (Berkeley) 11/12/86"; |
252367af | 9 | #endif not lint |
28e6b83a PK |
10 | |
11 | #include "whoami.h" | |
12 | #include "0.h" | |
13 | #include "tree.h" | |
14 | #include "opcode.h" | |
15 | #include "objfmt.h" | |
8d36ce22 | 16 | #include "align.h" |
28e6b83a | 17 | #ifdef PC |
c60bfb0d | 18 | # include <pcc.h> |
28e6b83a | 19 | #endif PC |
72fbef68 | 20 | #include "tree_ty.h" |
28e6b83a PK |
21 | |
22 | /* | |
23 | * stkrval Rvalue - an expression, and coerce it to be a stack quantity. | |
24 | * | |
25 | * Contype is the type that the caller would prefer, nand is important | |
26 | * if constant sets or constant strings are involved, the latter | |
27 | * because of string padding. | |
28 | */ | |
29 | /* | |
30 | * for the obj version, this is a copy of rvalue hacked to use fancy new | |
31 | * push-onto-stack-and-convert opcodes. | |
32 | * for the pc version, i just call rvalue and convert if i have to, | |
33 | * based on the return type of rvalue. | |
34 | */ | |
35 | struct nl * | |
36 | stkrval(r, contype , required ) | |
72fbef68 | 37 | register struct tnode *r; |
28e6b83a PK |
38 | struct nl *contype; |
39 | long required; | |
40 | { | |
41 | register struct nl *p; | |
42 | register struct nl *q; | |
43 | register char *cp, *cp1; | |
44 | register int c, w; | |
72fbef68 | 45 | struct tnode *pt; |
28e6b83a | 46 | long l; |
72fbef68 RT |
47 | union |
48 | { | |
49 | double pdouble; | |
50 | long plong[2]; | |
51 | }f; | |
28e6b83a | 52 | |
72fbef68 RT |
53 | if (r == TR_NIL) |
54 | return (NLNIL); | |
28e6b83a | 55 | if (nowexp(r)) |
72fbef68 | 56 | return (NLNIL); |
28e6b83a PK |
57 | /* |
58 | * The root of the tree tells us what sort of expression we have. | |
59 | */ | |
72fbef68 | 60 | switch (r->tag) { |
28e6b83a PK |
61 | |
62 | /* | |
63 | * The constant nil | |
64 | */ | |
65 | case T_NIL: | |
66 | # ifdef OBJ | |
72fbef68 | 67 | (void) put(2, O_CON14, 0); |
28e6b83a PK |
68 | # endif OBJ |
69 | # ifdef PC | |
c60bfb0d | 70 | putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 ); |
28e6b83a PK |
71 | # endif PC |
72 | return (nl+TNIL); | |
73 | ||
74 | case T_FCALL: | |
75 | case T_VAR: | |
72fbef68 RT |
76 | p = lookup(r->var_node.cptr); |
77 | if (p == NLNIL || p->class == BADUSE) | |
78 | return (NLNIL); | |
28e6b83a PK |
79 | switch (p->class) { |
80 | case VAR: | |
81 | /* | |
6cbd3a07 | 82 | * if a variable is |
28e6b83a PK |
83 | * qualified then get |
84 | * the rvalue by a | |
85 | * stklval and an ind. | |
86 | */ | |
72fbef68 | 87 | if (r->var_node.qual != TR_NIL) |
28e6b83a PK |
88 | goto ind; |
89 | q = p->type; | |
72fbef68 RT |
90 | if (q == NLNIL) |
91 | return (NLNIL); | |
28e6b83a PK |
92 | if (classify(q) == TSTR) |
93 | return(stklval(r, NOFLAGS)); | |
94 | # ifdef OBJ | |
28ff62b7 | 95 | return (stackRV(p)); |
28e6b83a PK |
96 | # endif OBJ |
97 | # ifdef PC | |
72fbef68 | 98 | q = rvalue( r , contype , (int) required ); |
1c91288f | 99 | if (isa(q, "sbci")) { |
c60bfb0d | 100 | sconv(p2type(q),PCCT_INT); |
1c91288f KM |
101 | } |
102 | return q; | |
28e6b83a PK |
103 | # endif PC |
104 | ||
105 | case WITHPTR: | |
106 | case REF: | |
107 | /* | |
108 | * A stklval for these | |
109 | * is actually what one | |
110 | * might consider a rvalue. | |
111 | */ | |
112 | ind: | |
113 | q = stklval(r, NOFLAGS); | |
72fbef68 RT |
114 | if (q == NLNIL) |
115 | return (NLNIL); | |
28e6b83a PK |
116 | if (classify(q) == TSTR) |
117 | return(q); | |
118 | # ifdef OBJ | |
119 | w = width(q); | |
120 | switch (w) { | |
121 | case 8: | |
72fbef68 | 122 | (void) put(1, O_IND8); |
28e6b83a PK |
123 | return(q); |
124 | case 4: | |
72fbef68 | 125 | (void) put(1, O_IND4); |
28e6b83a PK |
126 | return(q); |
127 | case 2: | |
72fbef68 | 128 | (void) put(1, O_IND24); |
28e6b83a PK |
129 | return(q); |
130 | case 1: | |
72fbef68 | 131 | (void) put(1, O_IND14); |
28e6b83a PK |
132 | return(q); |
133 | default: | |
72fbef68 | 134 | (void) put(2, O_IND, w); |
28e6b83a PK |
135 | return(q); |
136 | } | |
137 | # endif OBJ | |
138 | # ifdef PC | |
139 | if ( required == RREQ ) { | |
c60bfb0d | 140 | putop( PCCOM_UNARY PCC_MUL , p2type( q ) ); |
1c91288f | 141 | if (isa(q,"sbci")) { |
c60bfb0d | 142 | sconv(p2type(q),PCCT_INT); |
1c91288f | 143 | } |
28e6b83a PK |
144 | } |
145 | return q; | |
146 | # endif PC | |
147 | ||
148 | case CONST: | |
72fbef68 RT |
149 | if (r->var_node.qual != TR_NIL) { |
150 | error("%s is a constant and cannot be qualified", r->var_node.cptr); | |
151 | return (NLNIL); | |
28e6b83a PK |
152 | } |
153 | q = p->type; | |
72fbef68 RT |
154 | if (q == NLNIL) |
155 | return (NLNIL); | |
28e6b83a PK |
156 | if (q == nl+TSTR) { |
157 | /* | |
158 | * Find the size of the string | |
159 | * constant if needed. | |
160 | */ | |
72fbef68 | 161 | cp = (char *) p->ptr[0]; |
28e6b83a PK |
162 | cstrng: |
163 | cp1 = cp; | |
164 | for (c = 0; *cp++; c++) | |
165 | continue; | |
4e63fd2a | 166 | w = c; |
28e6b83a PK |
167 | if (contype != NIL && !opt('s')) { |
168 | if (width(contype) < c && classify(contype) == TSTR) { | |
169 | error("Constant string too long"); | |
72fbef68 | 170 | return (NLNIL); |
28e6b83a | 171 | } |
4e63fd2a | 172 | w = width(contype); |
28e6b83a PK |
173 | } |
174 | # ifdef OBJ | |
72fbef68 | 175 | (void) put(2, O_LVCON, lenstr(cp1, w - c)); |
4e63fd2a | 176 | putstr(cp1, w - c); |
28e6b83a PK |
177 | # endif OBJ |
178 | # ifdef PC | |
4e63fd2a | 179 | putCONG( cp1 , w , LREQ ); |
28e6b83a PK |
180 | # endif PC |
181 | /* | |
182 | * Define the string temporarily | |
183 | * so later people can know its | |
184 | * width. | |
185 | * cleaned out by stat. | |
186 | */ | |
72fbef68 | 187 | q = defnl((char *) 0, STR, NLNIL, w); |
28e6b83a PK |
188 | q->type = q; |
189 | return (q); | |
190 | } | |
191 | if (q == nl+T1CHAR) { | |
192 | # ifdef OBJ | |
72fbef68 | 193 | (void) put(2, O_CONC4, (int)p->value[0]); |
28e6b83a PK |
194 | # endif OBJ |
195 | # ifdef PC | |
c60bfb0d | 196 | putleaf(PCC_ICON, p -> value[0], 0, PCCT_INT, |
72fbef68 | 197 | (char *) 0); |
28e6b83a PK |
198 | # endif PC |
199 | return(q); | |
200 | } | |
201 | /* | |
202 | * Every other kind of constant here | |
203 | */ | |
204 | # ifdef OBJ | |
205 | switch (width(q)) { | |
206 | case 8: | |
207 | #ifndef DEBUG | |
72fbef68 | 208 | (void) put(2, O_CON8, p->real); |
28e6b83a PK |
209 | return(q); |
210 | #else | |
211 | if (hp21mx) { | |
72fbef68 RT |
212 | f.pdouble = p->real; |
213 | conv((int *) (&f.pdouble)); | |
214 | l = f.plong[1]; | |
215 | (void) put(2, O_CON4, l); | |
28e6b83a | 216 | } else |
72fbef68 | 217 | (void) put(2, O_CON8, p->real); |
28e6b83a PK |
218 | return(q); |
219 | #endif | |
220 | case 4: | |
72fbef68 | 221 | (void) put(2, O_CON4, p->range[0]); |
28e6b83a PK |
222 | return(q); |
223 | case 2: | |
72fbef68 | 224 | (void) put(2, O_CON24, (short)p->range[0]); |
28e6b83a PK |
225 | return(q); |
226 | case 1: | |
72fbef68 | 227 | (void) put(2, O_CON14, p->value[0]); |
28e6b83a PK |
228 | return(q); |
229 | default: | |
230 | panic("stkrval"); | |
231 | } | |
232 | # endif OBJ | |
233 | # ifdef PC | |
72fbef68 | 234 | q = rvalue( r , contype , (int) required ); |
1c91288f | 235 | if (isa(q,"sbci")) { |
c60bfb0d | 236 | sconv(p2type(q),PCCT_INT); |
1c91288f KM |
237 | } |
238 | return q; | |
28e6b83a PK |
239 | # endif PC |
240 | ||
241 | case FUNC: | |
c4e911b6 | 242 | case FFUNC: |
28e6b83a PK |
243 | /* |
244 | * Function call | |
245 | */ | |
72fbef68 RT |
246 | pt = r->var_node.qual; |
247 | if (pt != TR_NIL) { | |
248 | switch (pt->list_node.list->tag) { | |
28e6b83a PK |
249 | case T_PTR: |
250 | case T_ARGL: | |
251 | case T_ARY: | |
252 | case T_FIELD: | |
253 | error("Can't qualify a function result value"); | |
72fbef68 | 254 | return (NLNIL); |
28e6b83a PK |
255 | } |
256 | } | |
257 | # ifdef OBJ | |
258 | q = p->type; | |
259 | if (classify(q) == TSTR) { | |
260 | c = width(q); | |
8d36ce22 KM |
261 | (void) put(2, O_LVCON, |
262 | roundup(c+1, (long) A_SHORT)); | |
28e6b83a | 263 | putstr("", c); |
72fbef68 | 264 | (void) put(1, PTR_DUP); |
28e6b83a | 265 | p = funccod(r); |
72fbef68 | 266 | (void) put(2, O_AS, c); |
28e6b83a PK |
267 | return(p); |
268 | } | |
269 | p = funccod(r); | |
270 | if (width(p) <= 2) | |
72fbef68 | 271 | (void) put(1, O_STOI); |
28e6b83a PK |
272 | # endif OBJ |
273 | # ifdef PC | |
274 | p = pcfunccod( r ); | |
1c91288f | 275 | if (isa(p,"sbci")) { |
c60bfb0d | 276 | sconv(p2type(p),PCCT_INT); |
1c91288f | 277 | } |
28e6b83a PK |
278 | # endif PC |
279 | return (p); | |
280 | ||
281 | case TYPE: | |
282 | error("Type names (e.g. %s) allowed only in declarations", p->symbol); | |
72fbef68 | 283 | return (NLNIL); |
28e6b83a PK |
284 | |
285 | case PROC: | |
c4e911b6 | 286 | case FPROC: |
28e6b83a | 287 | error("Procedure %s found where expression required", p->symbol); |
72fbef68 | 288 | return (NLNIL); |
28e6b83a PK |
289 | default: |
290 | panic("stkrvid"); | |
291 | } | |
28e6b83a PK |
292 | case T_PLUS: |
293 | case T_MINUS: | |
294 | case T_NOT: | |
295 | case T_AND: | |
296 | case T_OR: | |
297 | case T_DIVD: | |
298 | case T_MULT: | |
299 | case T_SUB: | |
300 | case T_ADD: | |
301 | case T_MOD: | |
302 | case T_DIV: | |
303 | case T_EQ: | |
304 | case T_NE: | |
305 | case T_GE: | |
306 | case T_LE: | |
307 | case T_GT: | |
308 | case T_LT: | |
309 | case T_IN: | |
72fbef68 | 310 | p = rvalue(r, contype , (int) required ); |
28e6b83a PK |
311 | # ifdef OBJ |
312 | if (width(p) <= 2) | |
72fbef68 | 313 | (void) put(1, O_STOI); |
28e6b83a | 314 | # endif OBJ |
1c91288f KM |
315 | # ifdef PC |
316 | if (isa(p,"sbci")) { | |
c60bfb0d | 317 | sconv(p2type(p),PCCT_INT); |
1c91288f KM |
318 | } |
319 | # endif PC | |
28e6b83a | 320 | return (p); |
a26d837a | 321 | case T_CSET: |
72fbef68 | 322 | p = rvalue(r, contype , (int) required ); |
a26d837a | 323 | return (p); |
28e6b83a | 324 | default: |
72fbef68 RT |
325 | if (r->const_node.cptr == (char *) NIL) |
326 | return (NLNIL); | |
327 | switch (r->tag) { | |
28e6b83a PK |
328 | default: |
329 | panic("stkrval3"); | |
330 | ||
331 | /* | |
332 | * An octal number | |
333 | */ | |
334 | case T_BINT: | |
72fbef68 | 335 | f.pdouble = a8tol(r->const_node.cptr); |
28e6b83a PK |
336 | goto conint; |
337 | ||
338 | /* | |
339 | * A decimal number | |
340 | */ | |
341 | case T_INT: | |
72fbef68 | 342 | f.pdouble = atof(r->const_node.cptr); |
28e6b83a | 343 | conint: |
72fbef68 | 344 | if (f.pdouble > MAXINT || f.pdouble < MININT) { |
28e6b83a | 345 | error("Constant too large for this implementation"); |
72fbef68 | 346 | return (NLNIL); |
28e6b83a | 347 | } |
72fbef68 | 348 | l = f.pdouble; |
28e6b83a PK |
349 | if (bytes(l, l) <= 2) { |
350 | # ifdef OBJ | |
72fbef68 | 351 | (void) put(2, O_CON24, (short)l); |
28e6b83a PK |
352 | # endif OBJ |
353 | # ifdef PC | |
c60bfb0d | 354 | putleaf( PCC_ICON , (short) l , 0 , PCCT_INT , |
72fbef68 | 355 | (char *) 0 ); |
28e6b83a PK |
356 | # endif PC |
357 | return(nl+T4INT); | |
358 | } | |
359 | # ifdef OBJ | |
72fbef68 | 360 | (void) put(2, O_CON4, l); |
28e6b83a PK |
361 | # endif OBJ |
362 | # ifdef PC | |
c60bfb0d | 363 | putleaf( PCC_ICON , (int) l , 0 , PCCT_INT , (char *) 0 ); |
28e6b83a PK |
364 | # endif PC |
365 | return (nl+T4INT); | |
366 | ||
367 | /* | |
368 | * A floating point number | |
369 | */ | |
370 | case T_FINT: | |
371 | # ifdef OBJ | |
72fbef68 | 372 | (void) put(2, O_CON8, atof(r->const_node.cptr)); |
28e6b83a PK |
373 | # endif OBJ |
374 | # ifdef PC | |
72fbef68 | 375 | putCON8( atof( r->const_node.cptr ) ); |
28e6b83a PK |
376 | # endif PC |
377 | return (nl+TDOUBLE); | |
378 | ||
379 | /* | |
380 | * Constant strings. Note that constant characters | |
381 | * are constant strings of length one; there is | |
382 | * no constant string of length one. | |
383 | */ | |
384 | case T_STRNG: | |
72fbef68 | 385 | cp = r->const_node.cptr; |
28e6b83a PK |
386 | if (cp[1] == 0) { |
387 | # ifdef OBJ | |
72fbef68 | 388 | (void) put(2, O_CONC4, cp[0]); |
28e6b83a PK |
389 | # endif OBJ |
390 | # ifdef PC | |
c60bfb0d | 391 | putleaf( PCC_ICON , cp[0] , 0 , PCCT_INT , |
72fbef68 | 392 | (char *) 0 ); |
28e6b83a PK |
393 | # endif PC |
394 | return(nl+T1CHAR); | |
395 | } | |
396 | goto cstrng; | |
397 | } | |
398 | ||
399 | } | |
400 | } | |
28ff62b7 KM |
401 | |
402 | #ifdef OBJ | |
403 | /* | |
404 | * push a value onto the interpreter stack, longword aligned. | |
405 | */ | |
72fbef68 RT |
406 | struct nl |
407 | *stackRV(p) | |
28ff62b7 KM |
408 | struct nl *p; |
409 | { | |
410 | struct nl *q; | |
411 | int w, bn; | |
412 | ||
413 | q = p->type; | |
72fbef68 RT |
414 | if (q == NLNIL) |
415 | return (NLNIL); | |
28ff62b7 KM |
416 | bn = BLOCKNO(p->nl_block); |
417 | w = width(q); | |
418 | switch (w) { | |
419 | case 8: | |
72fbef68 | 420 | (void) put(2, O_RV8 | bn << 8+INDX, (int)p->value[0]); |
28ff62b7 KM |
421 | break; |
422 | case 4: | |
72fbef68 | 423 | (void) put(2, O_RV4 | bn << 8+INDX, (int)p->value[0]); |
28ff62b7 KM |
424 | break; |
425 | case 2: | |
72fbef68 | 426 | (void) put(2, O_RV24 | bn << 8+INDX, (int)p->value[0]); |
28ff62b7 KM |
427 | break; |
428 | case 1: | |
72fbef68 | 429 | (void) put(2, O_RV14 | bn << 8+INDX, (int)p->value[0]); |
28ff62b7 KM |
430 | break; |
431 | default: | |
72fbef68 | 432 | (void) put(3, O_RV | bn << 8+INDX, (int)p->value[0], w); |
28ff62b7 KM |
433 | break; |
434 | } | |
435 | return (q); | |
436 | } | |
437 | #endif OBJ |