1b85afe43Sbostic /*-
2*14bff7dfSbostic * Copyright (c) 1980, 1993
3*14bff7dfSbostic * The Regents of the University of California. All rights reserved.
4b85afe43Sbostic *
5b85afe43Sbostic * %sccs.include.redist.c%
6f0040ab9Sdist */
714ea4644Speter
821e3cc22Sthien #ifndef lint
9*14bff7dfSbostic static char sccsid[] = "@(#)stkrval.c 8.1 (Berkeley) 06/06/93";
10b85afe43Sbostic #endif /* not lint */
1114ea4644Speter
1214ea4644Speter #include "whoami.h"
1314ea4644Speter #include "0.h"
1414ea4644Speter #include "tree.h"
1514ea4644Speter #include "opcode.h"
1614ea4644Speter #include "objfmt.h"
1771395e85Smckusick #include "align.h"
1814ea4644Speter #ifdef PC
19fdbf02bfSralph # include <pcc.h>
2014ea4644Speter #endif PC
2121e3cc22Sthien #include "tree_ty.h"
2214ea4644Speter
2314ea4644Speter /*
2414ea4644Speter * stkrval Rvalue - an expression, and coerce it to be a stack quantity.
2514ea4644Speter *
2614ea4644Speter * Contype is the type that the caller would prefer, nand is important
2714ea4644Speter * if constant sets or constant strings are involved, the latter
2814ea4644Speter * because of string padding.
2914ea4644Speter */
3014ea4644Speter /*
3114ea4644Speter * for the obj version, this is a copy of rvalue hacked to use fancy new
3214ea4644Speter * push-onto-stack-and-convert opcodes.
3314ea4644Speter * for the pc version, i just call rvalue and convert if i have to,
3414ea4644Speter * based on the return type of rvalue.
3514ea4644Speter */
3614ea4644Speter struct nl *
stkrval(r,contype,required)3714ea4644Speter stkrval(r, contype , required )
3821e3cc22Sthien register struct tnode *r;
3914ea4644Speter struct nl *contype;
4014ea4644Speter long required;
4114ea4644Speter {
4214ea4644Speter register struct nl *p;
4314ea4644Speter register struct nl *q;
4414ea4644Speter register char *cp, *cp1;
4514ea4644Speter register int c, w;
4621e3cc22Sthien struct tnode *pt;
4714ea4644Speter long l;
4821e3cc22Sthien union
4921e3cc22Sthien {
5021e3cc22Sthien double pdouble;
5121e3cc22Sthien long plong[2];
5221e3cc22Sthien }f;
5314ea4644Speter
5421e3cc22Sthien if (r == TR_NIL)
5521e3cc22Sthien return (NLNIL);
5614ea4644Speter if (nowexp(r))
5721e3cc22Sthien return (NLNIL);
5814ea4644Speter /*
5914ea4644Speter * The root of the tree tells us what sort of expression we have.
6014ea4644Speter */
6121e3cc22Sthien switch (r->tag) {
6214ea4644Speter
6314ea4644Speter /*
6414ea4644Speter * The constant nil
6514ea4644Speter */
6614ea4644Speter case T_NIL:
6714ea4644Speter # ifdef OBJ
6821e3cc22Sthien (void) put(2, O_CON14, 0);
6914ea4644Speter # endif OBJ
7014ea4644Speter # ifdef PC
71fdbf02bfSralph putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
7214ea4644Speter # endif PC
7314ea4644Speter return (nl+TNIL);
7414ea4644Speter
7514ea4644Speter case T_FCALL:
7614ea4644Speter case T_VAR:
7721e3cc22Sthien p = lookup(r->var_node.cptr);
7821e3cc22Sthien if (p == NLNIL || p->class == BADUSE)
7921e3cc22Sthien return (NLNIL);
8014ea4644Speter switch (p->class) {
8114ea4644Speter case VAR:
8214ea4644Speter /*
836334a5ecSmckusic * if a variable is
8414ea4644Speter * qualified then get
8514ea4644Speter * the rvalue by a
8614ea4644Speter * stklval and an ind.
8714ea4644Speter */
8821e3cc22Sthien if (r->var_node.qual != TR_NIL)
8914ea4644Speter goto ind;
9014ea4644Speter q = p->type;
9121e3cc22Sthien if (q == NLNIL)
9221e3cc22Sthien return (NLNIL);
9314ea4644Speter if (classify(q) == TSTR)
9414ea4644Speter return(stklval(r, NOFLAGS));
9514ea4644Speter # ifdef OBJ
96a7017dacSmckusick return (stackRV(p));
9714ea4644Speter # endif OBJ
9814ea4644Speter # ifdef PC
9921e3cc22Sthien q = rvalue( r , contype , (int) required );
100cf237f00Smckusick if (isa(q, "sbci")) {
101fdbf02bfSralph sconv(p2type(q),PCCT_INT);
102cf237f00Smckusick }
103cf237f00Smckusick return q;
10414ea4644Speter # endif PC
10514ea4644Speter
10614ea4644Speter case WITHPTR:
10714ea4644Speter case REF:
10814ea4644Speter /*
10914ea4644Speter * A stklval for these
11014ea4644Speter * is actually what one
11114ea4644Speter * might consider a rvalue.
11214ea4644Speter */
11314ea4644Speter ind:
11414ea4644Speter q = stklval(r, NOFLAGS);
11521e3cc22Sthien if (q == NLNIL)
11621e3cc22Sthien return (NLNIL);
11714ea4644Speter if (classify(q) == TSTR)
11814ea4644Speter return(q);
11914ea4644Speter # ifdef OBJ
12014ea4644Speter w = width(q);
12114ea4644Speter switch (w) {
12214ea4644Speter case 8:
12321e3cc22Sthien (void) put(1, O_IND8);
12414ea4644Speter return(q);
12514ea4644Speter case 4:
12621e3cc22Sthien (void) put(1, O_IND4);
12714ea4644Speter return(q);
12814ea4644Speter case 2:
12921e3cc22Sthien (void) put(1, O_IND24);
13014ea4644Speter return(q);
13114ea4644Speter case 1:
13221e3cc22Sthien (void) put(1, O_IND14);
13314ea4644Speter return(q);
13414ea4644Speter default:
13521e3cc22Sthien (void) put(2, O_IND, w);
13614ea4644Speter return(q);
13714ea4644Speter }
13814ea4644Speter # endif OBJ
13914ea4644Speter # ifdef PC
14014ea4644Speter if ( required == RREQ ) {
141fdbf02bfSralph putop( PCCOM_UNARY PCC_MUL , p2type( q ) );
142cf237f00Smckusick if (isa(q,"sbci")) {
143fdbf02bfSralph sconv(p2type(q),PCCT_INT);
144cf237f00Smckusick }
14514ea4644Speter }
14614ea4644Speter return q;
14714ea4644Speter # endif PC
14814ea4644Speter
14914ea4644Speter case CONST:
15021e3cc22Sthien if (r->var_node.qual != TR_NIL) {
15121e3cc22Sthien error("%s is a constant and cannot be qualified", r->var_node.cptr);
15221e3cc22Sthien return (NLNIL);
15314ea4644Speter }
15414ea4644Speter q = p->type;
15521e3cc22Sthien if (q == NLNIL)
15621e3cc22Sthien return (NLNIL);
15714ea4644Speter if (q == nl+TSTR) {
15814ea4644Speter /*
15914ea4644Speter * Find the size of the string
16014ea4644Speter * constant if needed.
16114ea4644Speter */
16221e3cc22Sthien cp = (char *) p->ptr[0];
16314ea4644Speter cstrng:
16414ea4644Speter cp1 = cp;
16514ea4644Speter for (c = 0; *cp++; c++)
16614ea4644Speter continue;
167946687beSpeter w = c;
16814ea4644Speter if (contype != NIL && !opt('s')) {
16914ea4644Speter if (width(contype) < c && classify(contype) == TSTR) {
17014ea4644Speter error("Constant string too long");
17121e3cc22Sthien return (NLNIL);
17214ea4644Speter }
173946687beSpeter w = width(contype);
17414ea4644Speter }
17514ea4644Speter # ifdef OBJ
17621e3cc22Sthien (void) put(2, O_LVCON, lenstr(cp1, w - c));
177946687beSpeter putstr(cp1, w - c);
17814ea4644Speter # endif OBJ
17914ea4644Speter # ifdef PC
180946687beSpeter putCONG( cp1 , w , LREQ );
18114ea4644Speter # endif PC
18214ea4644Speter /*
18314ea4644Speter * Define the string temporarily
18414ea4644Speter * so later people can know its
18514ea4644Speter * width.
18614ea4644Speter * cleaned out by stat.
18714ea4644Speter */
18821e3cc22Sthien q = defnl((char *) 0, STR, NLNIL, w);
18914ea4644Speter q->type = q;
19014ea4644Speter return (q);
19114ea4644Speter }
19214ea4644Speter if (q == nl+T1CHAR) {
19314ea4644Speter # ifdef OBJ
19421e3cc22Sthien (void) put(2, O_CONC4, (int)p->value[0]);
19514ea4644Speter # endif OBJ
19614ea4644Speter # ifdef PC
197fdbf02bfSralph putleaf(PCC_ICON, p -> value[0], 0, PCCT_INT,
19821e3cc22Sthien (char *) 0);
19914ea4644Speter # endif PC
20014ea4644Speter return(q);
20114ea4644Speter }
20214ea4644Speter /*
20314ea4644Speter * Every other kind of constant here
20414ea4644Speter */
20514ea4644Speter # ifdef OBJ
20614ea4644Speter switch (width(q)) {
20714ea4644Speter case 8:
20814ea4644Speter #ifndef DEBUG
20921e3cc22Sthien (void) put(2, O_CON8, p->real);
21014ea4644Speter return(q);
21114ea4644Speter #else
21214ea4644Speter if (hp21mx) {
21321e3cc22Sthien f.pdouble = p->real;
21421e3cc22Sthien conv((int *) (&f.pdouble));
21521e3cc22Sthien l = f.plong[1];
21621e3cc22Sthien (void) put(2, O_CON4, l);
21714ea4644Speter } else
21821e3cc22Sthien (void) put(2, O_CON8, p->real);
21914ea4644Speter return(q);
22014ea4644Speter #endif
22114ea4644Speter case 4:
22221e3cc22Sthien (void) put(2, O_CON4, p->range[0]);
22314ea4644Speter return(q);
22414ea4644Speter case 2:
22521e3cc22Sthien (void) put(2, O_CON24, (short)p->range[0]);
22614ea4644Speter return(q);
22714ea4644Speter case 1:
22821e3cc22Sthien (void) put(2, O_CON14, p->value[0]);
22914ea4644Speter return(q);
23014ea4644Speter default:
23114ea4644Speter panic("stkrval");
23214ea4644Speter }
23314ea4644Speter # endif OBJ
23414ea4644Speter # ifdef PC
23521e3cc22Sthien q = rvalue( r , contype , (int) required );
236cf237f00Smckusick if (isa(q,"sbci")) {
237fdbf02bfSralph sconv(p2type(q),PCCT_INT);
238cf237f00Smckusick }
239cf237f00Smckusick return q;
24014ea4644Speter # endif PC
24114ea4644Speter
24214ea4644Speter case FUNC:
2435ff17cbdSpeter case FFUNC:
24414ea4644Speter /*
24514ea4644Speter * Function call
24614ea4644Speter */
24721e3cc22Sthien pt = r->var_node.qual;
24821e3cc22Sthien if (pt != TR_NIL) {
24921e3cc22Sthien switch (pt->list_node.list->tag) {
25014ea4644Speter case T_PTR:
25114ea4644Speter case T_ARGL:
25214ea4644Speter case T_ARY:
25314ea4644Speter case T_FIELD:
25414ea4644Speter error("Can't qualify a function result value");
25521e3cc22Sthien return (NLNIL);
25614ea4644Speter }
25714ea4644Speter }
25814ea4644Speter # ifdef OBJ
25914ea4644Speter q = p->type;
26014ea4644Speter if (classify(q) == TSTR) {
26114ea4644Speter c = width(q);
26271395e85Smckusick (void) put(2, O_LVCON,
26371395e85Smckusick roundup(c+1, (long) A_SHORT));
26414ea4644Speter putstr("", c);
26521e3cc22Sthien (void) put(1, PTR_DUP);
26614ea4644Speter p = funccod(r);
26721e3cc22Sthien (void) put(2, O_AS, c);
26814ea4644Speter return(p);
26914ea4644Speter }
27014ea4644Speter p = funccod(r);
27114ea4644Speter if (width(p) <= 2)
27221e3cc22Sthien (void) put(1, O_STOI);
27314ea4644Speter # endif OBJ
27414ea4644Speter # ifdef PC
27514ea4644Speter p = pcfunccod( r );
276cf237f00Smckusick if (isa(p,"sbci")) {
277fdbf02bfSralph sconv(p2type(p),PCCT_INT);
278cf237f00Smckusick }
27914ea4644Speter # endif PC
28014ea4644Speter return (p);
28114ea4644Speter
28214ea4644Speter case TYPE:
28314ea4644Speter error("Type names (e.g. %s) allowed only in declarations", p->symbol);
28421e3cc22Sthien return (NLNIL);
28514ea4644Speter
28614ea4644Speter case PROC:
2875ff17cbdSpeter case FPROC:
28814ea4644Speter error("Procedure %s found where expression required", p->symbol);
28921e3cc22Sthien return (NLNIL);
29014ea4644Speter default:
29114ea4644Speter panic("stkrvid");
29214ea4644Speter }
29314ea4644Speter case T_PLUS:
29414ea4644Speter case T_MINUS:
29514ea4644Speter case T_NOT:
29614ea4644Speter case T_AND:
29714ea4644Speter case T_OR:
29814ea4644Speter case T_DIVD:
29914ea4644Speter case T_MULT:
30014ea4644Speter case T_SUB:
30114ea4644Speter case T_ADD:
30214ea4644Speter case T_MOD:
30314ea4644Speter case T_DIV:
30414ea4644Speter case T_EQ:
30514ea4644Speter case T_NE:
30614ea4644Speter case T_GE:
30714ea4644Speter case T_LE:
30814ea4644Speter case T_GT:
30914ea4644Speter case T_LT:
31014ea4644Speter case T_IN:
31121e3cc22Sthien p = rvalue(r, contype , (int) required );
31214ea4644Speter # ifdef OBJ
31314ea4644Speter if (width(p) <= 2)
31421e3cc22Sthien (void) put(1, O_STOI);
31514ea4644Speter # endif OBJ
316cf237f00Smckusick # ifdef PC
317cf237f00Smckusick if (isa(p,"sbci")) {
318fdbf02bfSralph sconv(p2type(p),PCCT_INT);
319cf237f00Smckusick }
320cf237f00Smckusick # endif PC
32114ea4644Speter return (p);
32205640cc4Speter case T_CSET:
32321e3cc22Sthien p = rvalue(r, contype , (int) required );
32405640cc4Speter return (p);
32514ea4644Speter default:
32621e3cc22Sthien if (r->const_node.cptr == (char *) NIL)
32721e3cc22Sthien return (NLNIL);
32821e3cc22Sthien switch (r->tag) {
32914ea4644Speter default:
33014ea4644Speter panic("stkrval3");
33114ea4644Speter
33214ea4644Speter /*
33314ea4644Speter * An octal number
33414ea4644Speter */
33514ea4644Speter case T_BINT:
33621e3cc22Sthien f.pdouble = a8tol(r->const_node.cptr);
33714ea4644Speter goto conint;
33814ea4644Speter
33914ea4644Speter /*
34014ea4644Speter * A decimal number
34114ea4644Speter */
34214ea4644Speter case T_INT:
34321e3cc22Sthien f.pdouble = atof(r->const_node.cptr);
34414ea4644Speter conint:
34521e3cc22Sthien if (f.pdouble > MAXINT || f.pdouble < MININT) {
34614ea4644Speter error("Constant too large for this implementation");
34721e3cc22Sthien return (NLNIL);
34814ea4644Speter }
34921e3cc22Sthien l = f.pdouble;
35014ea4644Speter if (bytes(l, l) <= 2) {
35114ea4644Speter # ifdef OBJ
35221e3cc22Sthien (void) put(2, O_CON24, (short)l);
35314ea4644Speter # endif OBJ
35414ea4644Speter # ifdef PC
355fdbf02bfSralph putleaf( PCC_ICON , (short) l , 0 , PCCT_INT ,
35621e3cc22Sthien (char *) 0 );
35714ea4644Speter # endif PC
35814ea4644Speter return(nl+T4INT);
35914ea4644Speter }
36014ea4644Speter # ifdef OBJ
36121e3cc22Sthien (void) put(2, O_CON4, l);
36214ea4644Speter # endif OBJ
36314ea4644Speter # ifdef PC
364fdbf02bfSralph putleaf( PCC_ICON , (int) l , 0 , PCCT_INT , (char *) 0 );
36514ea4644Speter # endif PC
36614ea4644Speter return (nl+T4INT);
36714ea4644Speter
36814ea4644Speter /*
36914ea4644Speter * A floating point number
37014ea4644Speter */
37114ea4644Speter case T_FINT:
37214ea4644Speter # ifdef OBJ
37321e3cc22Sthien (void) put(2, O_CON8, atof(r->const_node.cptr));
37414ea4644Speter # endif OBJ
37514ea4644Speter # ifdef PC
37621e3cc22Sthien putCON8( atof( r->const_node.cptr ) );
37714ea4644Speter # endif PC
37814ea4644Speter return (nl+TDOUBLE);
37914ea4644Speter
38014ea4644Speter /*
38114ea4644Speter * Constant strings. Note that constant characters
38214ea4644Speter * are constant strings of length one; there is
38314ea4644Speter * no constant string of length one.
38414ea4644Speter */
38514ea4644Speter case T_STRNG:
38621e3cc22Sthien cp = r->const_node.cptr;
38714ea4644Speter if (cp[1] == 0) {
38814ea4644Speter # ifdef OBJ
38921e3cc22Sthien (void) put(2, O_CONC4, cp[0]);
39014ea4644Speter # endif OBJ
39114ea4644Speter # ifdef PC
392fdbf02bfSralph putleaf( PCC_ICON , cp[0] , 0 , PCCT_INT ,
39321e3cc22Sthien (char *) 0 );
39414ea4644Speter # endif PC
39514ea4644Speter return(nl+T1CHAR);
39614ea4644Speter }
39714ea4644Speter goto cstrng;
39814ea4644Speter }
39914ea4644Speter
40014ea4644Speter }
40114ea4644Speter }
402a7017dacSmckusick
403a7017dacSmckusick #ifdef OBJ
404a7017dacSmckusick /*
405a7017dacSmckusick * push a value onto the interpreter stack, longword aligned.
406a7017dacSmckusick */
40721e3cc22Sthien struct nl
stackRV(p)40821e3cc22Sthien *stackRV(p)
409a7017dacSmckusick struct nl *p;
410a7017dacSmckusick {
411a7017dacSmckusick struct nl *q;
412a7017dacSmckusick int w, bn;
413a7017dacSmckusick
414a7017dacSmckusick q = p->type;
41521e3cc22Sthien if (q == NLNIL)
41621e3cc22Sthien return (NLNIL);
417a7017dacSmckusick bn = BLOCKNO(p->nl_block);
418a7017dacSmckusick w = width(q);
419a7017dacSmckusick switch (w) {
420a7017dacSmckusick case 8:
42121e3cc22Sthien (void) put(2, O_RV8 | bn << 8+INDX, (int)p->value[0]);
422a7017dacSmckusick break;
423a7017dacSmckusick case 4:
42421e3cc22Sthien (void) put(2, O_RV4 | bn << 8+INDX, (int)p->value[0]);
425a7017dacSmckusick break;
426a7017dacSmckusick case 2:
42721e3cc22Sthien (void) put(2, O_RV24 | bn << 8+INDX, (int)p->value[0]);
428a7017dacSmckusick break;
429a7017dacSmckusick case 1:
43021e3cc22Sthien (void) put(2, O_RV14 | bn << 8+INDX, (int)p->value[0]);
431a7017dacSmckusick break;
432a7017dacSmckusick default:
43321e3cc22Sthien (void) put(3, O_RV | bn << 8+INDX, (int)p->value[0], w);
434a7017dacSmckusick break;
435a7017dacSmckusick }
436a7017dacSmckusick return (q);
437a7017dacSmckusick }
438a7017dacSmckusick #endif OBJ
439