148116Sbostic /*-
2*62217Sbostic * Copyright (c) 1980, 1993
3*62217Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622194Sdist */
7775Speter
814743Sthien #ifndef lint
9*62217Sbostic static char sccsid[] = "@(#)stkrval.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11775Speter
12775Speter #include "whoami.h"
13775Speter #include "0.h"
14775Speter #include "tree.h"
15775Speter #include "opcode.h"
16775Speter #include "objfmt.h"
1730037Smckusick #include "align.h"
18775Speter #ifdef PC
1918471Sralph # include <pcc.h>
20775Speter #endif PC
2114743Sthien #include "tree_ty.h"
22775Speter
23775Speter /*
24775Speter * stkrval Rvalue - an expression, and coerce it to be a stack quantity.
25775Speter *
26775Speter * Contype is the type that the caller would prefer, nand is important
27775Speter * if constant sets or constant strings are involved, the latter
28775Speter * because of string padding.
29775Speter */
30775Speter /*
31775Speter * for the obj version, this is a copy of rvalue hacked to use fancy new
32775Speter * push-onto-stack-and-convert opcodes.
33775Speter * for the pc version, i just call rvalue and convert if i have to,
34775Speter * based on the return type of rvalue.
35775Speter */
36775Speter struct nl *
stkrval(r,contype,required)37775Speter stkrval(r, contype , required )
3814743Sthien register struct tnode *r;
39775Speter struct nl *contype;
40775Speter long required;
41775Speter {
42775Speter register struct nl *p;
43775Speter register struct nl *q;
44775Speter register char *cp, *cp1;
45775Speter register int c, w;
4614743Sthien struct tnode *pt;
47775Speter long l;
4814743Sthien union
4914743Sthien {
5014743Sthien double pdouble;
5114743Sthien long plong[2];
5214743Sthien }f;
53775Speter
5414743Sthien if (r == TR_NIL)
5514743Sthien return (NLNIL);
56775Speter if (nowexp(r))
5714743Sthien return (NLNIL);
58775Speter /*
59775Speter * The root of the tree tells us what sort of expression we have.
60775Speter */
6114743Sthien switch (r->tag) {
62775Speter
63775Speter /*
64775Speter * The constant nil
65775Speter */
66775Speter case T_NIL:
67775Speter # ifdef OBJ
6814743Sthien (void) put(2, O_CON14, 0);
69775Speter # endif OBJ
70775Speter # ifdef PC
7118471Sralph putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
72775Speter # endif PC
73775Speter return (nl+TNIL);
74775Speter
75775Speter case T_FCALL:
76775Speter case T_VAR:
7714743Sthien p = lookup(r->var_node.cptr);
7814743Sthien if (p == NLNIL || p->class == BADUSE)
7914743Sthien return (NLNIL);
80775Speter switch (p->class) {
81775Speter case VAR:
82775Speter /*
833080Smckusic * if a variable is
84775Speter * qualified then get
85775Speter * the rvalue by a
86775Speter * stklval and an ind.
87775Speter */
8814743Sthien if (r->var_node.qual != TR_NIL)
89775Speter goto ind;
90775Speter q = p->type;
9114743Sthien if (q == NLNIL)
9214743Sthien return (NLNIL);
93775Speter if (classify(q) == TSTR)
94775Speter return(stklval(r, NOFLAGS));
95775Speter # ifdef OBJ
9610568Smckusick return (stackRV(p));
97775Speter # endif OBJ
98775Speter # ifdef PC
9914743Sthien q = rvalue( r , contype , (int) required );
10010360Smckusick if (isa(q, "sbci")) {
10118471Sralph sconv(p2type(q),PCCT_INT);
10210360Smckusick }
10310360Smckusick return q;
104775Speter # endif PC
105775Speter
106775Speter case WITHPTR:
107775Speter case REF:
108775Speter /*
109775Speter * A stklval for these
110775Speter * is actually what one
111775Speter * might consider a rvalue.
112775Speter */
113775Speter ind:
114775Speter q = stklval(r, NOFLAGS);
11514743Sthien if (q == NLNIL)
11614743Sthien return (NLNIL);
117775Speter if (classify(q) == TSTR)
118775Speter return(q);
119775Speter # ifdef OBJ
120775Speter w = width(q);
121775Speter switch (w) {
122775Speter case 8:
12314743Sthien (void) put(1, O_IND8);
124775Speter return(q);
125775Speter case 4:
12614743Sthien (void) put(1, O_IND4);
127775Speter return(q);
128775Speter case 2:
12914743Sthien (void) put(1, O_IND24);
130775Speter return(q);
131775Speter case 1:
13214743Sthien (void) put(1, O_IND14);
133775Speter return(q);
134775Speter default:
13514743Sthien (void) put(2, O_IND, w);
136775Speter return(q);
137775Speter }
138775Speter # endif OBJ
139775Speter # ifdef PC
140775Speter if ( required == RREQ ) {
14118471Sralph putop( PCCOM_UNARY PCC_MUL , p2type( q ) );
14210360Smckusick if (isa(q,"sbci")) {
14318471Sralph sconv(p2type(q),PCCT_INT);
14410360Smckusick }
145775Speter }
146775Speter return q;
147775Speter # endif PC
148775Speter
149775Speter case CONST:
15014743Sthien if (r->var_node.qual != TR_NIL) {
15114743Sthien error("%s is a constant and cannot be qualified", r->var_node.cptr);
15214743Sthien return (NLNIL);
153775Speter }
154775Speter q = p->type;
15514743Sthien if (q == NLNIL)
15614743Sthien return (NLNIL);
157775Speter if (q == nl+TSTR) {
158775Speter /*
159775Speter * Find the size of the string
160775Speter * constant if needed.
161775Speter */
16214743Sthien cp = (char *) p->ptr[0];
163775Speter cstrng:
164775Speter cp1 = cp;
165775Speter for (c = 0; *cp++; c++)
166775Speter continue;
16710841Speter w = c;
168775Speter if (contype != NIL && !opt('s')) {
169775Speter if (width(contype) < c && classify(contype) == TSTR) {
170775Speter error("Constant string too long");
17114743Sthien return (NLNIL);
172775Speter }
17310841Speter w = width(contype);
174775Speter }
175775Speter # ifdef OBJ
17614743Sthien (void) put(2, O_LVCON, lenstr(cp1, w - c));
17710841Speter putstr(cp1, w - c);
178775Speter # endif OBJ
179775Speter # ifdef PC
18010841Speter putCONG( cp1 , w , LREQ );
181775Speter # endif PC
182775Speter /*
183775Speter * Define the string temporarily
184775Speter * so later people can know its
185775Speter * width.
186775Speter * cleaned out by stat.
187775Speter */
18814743Sthien q = defnl((char *) 0, STR, NLNIL, w);
189775Speter q->type = q;
190775Speter return (q);
191775Speter }
192775Speter if (q == nl+T1CHAR) {
193775Speter # ifdef OBJ
19414743Sthien (void) put(2, O_CONC4, (int)p->value[0]);
195775Speter # endif OBJ
196775Speter # ifdef PC
19718471Sralph putleaf(PCC_ICON, p -> value[0], 0, PCCT_INT,
19814743Sthien (char *) 0);
199775Speter # endif PC
200775Speter return(q);
201775Speter }
202775Speter /*
203775Speter * Every other kind of constant here
204775Speter */
205775Speter # ifdef OBJ
206775Speter switch (width(q)) {
207775Speter case 8:
208775Speter #ifndef DEBUG
20914743Sthien (void) put(2, O_CON8, p->real);
210775Speter return(q);
211775Speter #else
212775Speter if (hp21mx) {
21314743Sthien f.pdouble = p->real;
21414743Sthien conv((int *) (&f.pdouble));
21514743Sthien l = f.plong[1];
21614743Sthien (void) put(2, O_CON4, l);
217775Speter } else
21814743Sthien (void) put(2, O_CON8, p->real);
219775Speter return(q);
220775Speter #endif
221775Speter case 4:
22214743Sthien (void) put(2, O_CON4, p->range[0]);
223775Speter return(q);
224775Speter case 2:
22514743Sthien (void) put(2, O_CON24, (short)p->range[0]);
226775Speter return(q);
227775Speter case 1:
22814743Sthien (void) put(2, O_CON14, p->value[0]);
229775Speter return(q);
230775Speter default:
231775Speter panic("stkrval");
232775Speter }
233775Speter # endif OBJ
234775Speter # ifdef PC
23514743Sthien q = rvalue( r , contype , (int) required );
23610360Smckusick if (isa(q,"sbci")) {
23718471Sralph sconv(p2type(q),PCCT_INT);
23810360Smckusick }
23910360Smckusick return q;
240775Speter # endif PC
241775Speter
242775Speter case FUNC:
2431201Speter case FFUNC:
244775Speter /*
245775Speter * Function call
246775Speter */
24714743Sthien pt = r->var_node.qual;
24814743Sthien if (pt != TR_NIL) {
24914743Sthien switch (pt->list_node.list->tag) {
250775Speter case T_PTR:
251775Speter case T_ARGL:
252775Speter case T_ARY:
253775Speter case T_FIELD:
254775Speter error("Can't qualify a function result value");
25514743Sthien return (NLNIL);
256775Speter }
257775Speter }
258775Speter # ifdef OBJ
259775Speter q = p->type;
260775Speter if (classify(q) == TSTR) {
261775Speter c = width(q);
26230037Smckusick (void) put(2, O_LVCON,
26330037Smckusick roundup(c+1, (long) A_SHORT));
264775Speter putstr("", c);
26514743Sthien (void) put(1, PTR_DUP);
266775Speter p = funccod(r);
26714743Sthien (void) put(2, O_AS, c);
268775Speter return(p);
269775Speter }
270775Speter p = funccod(r);
271775Speter if (width(p) <= 2)
27214743Sthien (void) put(1, O_STOI);
273775Speter # endif OBJ
274775Speter # ifdef PC
275775Speter p = pcfunccod( r );
27610360Smckusick if (isa(p,"sbci")) {
27718471Sralph sconv(p2type(p),PCCT_INT);
27810360Smckusick }
279775Speter # endif PC
280775Speter return (p);
281775Speter
282775Speter case TYPE:
283775Speter error("Type names (e.g. %s) allowed only in declarations", p->symbol);
28414743Sthien return (NLNIL);
285775Speter
286775Speter case PROC:
2871201Speter case FPROC:
288775Speter error("Procedure %s found where expression required", p->symbol);
28914743Sthien return (NLNIL);
290775Speter default:
291775Speter panic("stkrvid");
292775Speter }
293775Speter case T_PLUS:
294775Speter case T_MINUS:
295775Speter case T_NOT:
296775Speter case T_AND:
297775Speter case T_OR:
298775Speter case T_DIVD:
299775Speter case T_MULT:
300775Speter case T_SUB:
301775Speter case T_ADD:
302775Speter case T_MOD:
303775Speter case T_DIV:
304775Speter case T_EQ:
305775Speter case T_NE:
306775Speter case T_GE:
307775Speter case T_LE:
308775Speter case T_GT:
309775Speter case T_LT:
310775Speter case T_IN:
31114743Sthien p = rvalue(r, contype , (int) required );
312775Speter # ifdef OBJ
313775Speter if (width(p) <= 2)
31414743Sthien (void) put(1, O_STOI);
315775Speter # endif OBJ
31610360Smckusick # ifdef PC
31710360Smckusick if (isa(p,"sbci")) {
31818471Sralph sconv(p2type(p),PCCT_INT);
31910360Smckusick }
32010360Smckusick # endif PC
321775Speter return (p);
322909Speter case T_CSET:
32314743Sthien p = rvalue(r, contype , (int) required );
324909Speter return (p);
325775Speter default:
32614743Sthien if (r->const_node.cptr == (char *) NIL)
32714743Sthien return (NLNIL);
32814743Sthien switch (r->tag) {
329775Speter default:
330775Speter panic("stkrval3");
331775Speter
332775Speter /*
333775Speter * An octal number
334775Speter */
335775Speter case T_BINT:
33614743Sthien f.pdouble = a8tol(r->const_node.cptr);
337775Speter goto conint;
338775Speter
339775Speter /*
340775Speter * A decimal number
341775Speter */
342775Speter case T_INT:
34314743Sthien f.pdouble = atof(r->const_node.cptr);
344775Speter conint:
34514743Sthien if (f.pdouble > MAXINT || f.pdouble < MININT) {
346775Speter error("Constant too large for this implementation");
34714743Sthien return (NLNIL);
348775Speter }
34914743Sthien l = f.pdouble;
350775Speter if (bytes(l, l) <= 2) {
351775Speter # ifdef OBJ
35214743Sthien (void) put(2, O_CON24, (short)l);
353775Speter # endif OBJ
354775Speter # ifdef PC
35518471Sralph putleaf( PCC_ICON , (short) l , 0 , PCCT_INT ,
35614743Sthien (char *) 0 );
357775Speter # endif PC
358775Speter return(nl+T4INT);
359775Speter }
360775Speter # ifdef OBJ
36114743Sthien (void) put(2, O_CON4, l);
362775Speter # endif OBJ
363775Speter # ifdef PC
36418471Sralph putleaf( PCC_ICON , (int) l , 0 , PCCT_INT , (char *) 0 );
365775Speter # endif PC
366775Speter return (nl+T4INT);
367775Speter
368775Speter /*
369775Speter * A floating point number
370775Speter */
371775Speter case T_FINT:
372775Speter # ifdef OBJ
37314743Sthien (void) put(2, O_CON8, atof(r->const_node.cptr));
374775Speter # endif OBJ
375775Speter # ifdef PC
37614743Sthien putCON8( atof( r->const_node.cptr ) );
377775Speter # endif PC
378775Speter return (nl+TDOUBLE);
379775Speter
380775Speter /*
381775Speter * Constant strings. Note that constant characters
382775Speter * are constant strings of length one; there is
383775Speter * no constant string of length one.
384775Speter */
385775Speter case T_STRNG:
38614743Sthien cp = r->const_node.cptr;
387775Speter if (cp[1] == 0) {
388775Speter # ifdef OBJ
38914743Sthien (void) put(2, O_CONC4, cp[0]);
390775Speter # endif OBJ
391775Speter # ifdef PC
39218471Sralph putleaf( PCC_ICON , cp[0] , 0 , PCCT_INT ,
39314743Sthien (char *) 0 );
394775Speter # endif PC
395775Speter return(nl+T1CHAR);
396775Speter }
397775Speter goto cstrng;
398775Speter }
399775Speter
400775Speter }
401775Speter }
40210568Smckusick
40310568Smckusick #ifdef OBJ
40410568Smckusick /*
40510568Smckusick * push a value onto the interpreter stack, longword aligned.
40610568Smckusick */
40714743Sthien struct nl
stackRV(p)40814743Sthien *stackRV(p)
40910568Smckusick struct nl *p;
41010568Smckusick {
41110568Smckusick struct nl *q;
41210568Smckusick int w, bn;
41310568Smckusick
41410568Smckusick q = p->type;
41514743Sthien if (q == NLNIL)
41614743Sthien return (NLNIL);
41710568Smckusick bn = BLOCKNO(p->nl_block);
41810568Smckusick w = width(q);
41910568Smckusick switch (w) {
42010568Smckusick case 8:
42114743Sthien (void) put(2, O_RV8 | bn << 8+INDX, (int)p->value[0]);
42210568Smckusick break;
42310568Smckusick case 4:
42414743Sthien (void) put(2, O_RV4 | bn << 8+INDX, (int)p->value[0]);
42510568Smckusick break;
42610568Smckusick case 2:
42714743Sthien (void) put(2, O_RV24 | bn << 8+INDX, (int)p->value[0]);
42810568Smckusick break;
42910568Smckusick case 1:
43014743Sthien (void) put(2, O_RV14 | bn << 8+INDX, (int)p->value[0]);
43110568Smckusick break;
43210568Smckusick default:
43314743Sthien (void) put(3, O_RV | bn << 8+INDX, (int)p->value[0], w);
43410568Smckusick break;
43510568Smckusick }
43610568Smckusick return (q);
43710568Smckusick }
43810568Smckusick #endif OBJ
439