1775Speter /* Copyright (c) 1979 Regents of the University of California */ 2775Speter 3*14743Sthien #ifndef lint 4*14743Sthien static char sccsid[] = "@(#)stkrval.c 1.8 08/19/83"; 5*14743Sthien #endif 6775Speter 7775Speter #include "whoami.h" 8775Speter #include "0.h" 9775Speter #include "tree.h" 10775Speter #include "opcode.h" 11775Speter #include "objfmt.h" 12775Speter #ifdef PC 13775Speter # include "pcops.h" 14775Speter #endif PC 15*14743Sthien #include "tree_ty.h" 16775Speter 17775Speter /* 18775Speter * stkrval Rvalue - an expression, and coerce it to be a stack quantity. 19775Speter * 20775Speter * Contype is the type that the caller would prefer, nand is important 21775Speter * if constant sets or constant strings are involved, the latter 22775Speter * because of string padding. 23775Speter */ 24775Speter /* 25775Speter * for the obj version, this is a copy of rvalue hacked to use fancy new 26775Speter * push-onto-stack-and-convert opcodes. 27775Speter * for the pc version, i just call rvalue and convert if i have to, 28775Speter * based on the return type of rvalue. 29775Speter */ 30775Speter struct nl * 31775Speter stkrval(r, contype , required ) 32*14743Sthien register struct tnode *r; 33775Speter struct nl *contype; 34775Speter long required; 35775Speter { 36775Speter register struct nl *p; 37775Speter register struct nl *q; 38775Speter register char *cp, *cp1; 39775Speter register int c, w; 40*14743Sthien struct tnode *pt; 41775Speter long l; 42*14743Sthien union 43*14743Sthien { 44*14743Sthien double pdouble; 45*14743Sthien long plong[2]; 46*14743Sthien }f; 47775Speter 48*14743Sthien if (r == TR_NIL) 49*14743Sthien return (NLNIL); 50775Speter if (nowexp(r)) 51*14743Sthien return (NLNIL); 52775Speter /* 53775Speter * The root of the tree tells us what sort of expression we have. 54775Speter */ 55*14743Sthien switch (r->tag) { 56775Speter 57775Speter /* 58775Speter * The constant nil 59775Speter */ 60775Speter case T_NIL: 61775Speter # ifdef OBJ 62*14743Sthien (void) put(2, O_CON14, 0); 63775Speter # endif OBJ 64775Speter # ifdef PC 65*14743Sthien putleaf( P2ICON , 0 , 0 , P2INT , (char *) 0 ); 66775Speter # endif PC 67775Speter return (nl+TNIL); 68775Speter 69775Speter case T_FCALL: 70775Speter case T_VAR: 71*14743Sthien p = lookup(r->var_node.cptr); 72*14743Sthien if (p == NLNIL || p->class == BADUSE) 73*14743Sthien return (NLNIL); 74775Speter switch (p->class) { 75775Speter case VAR: 76775Speter /* 773080Smckusic * if a variable is 78775Speter * qualified then get 79775Speter * the rvalue by a 80775Speter * stklval and an ind. 81775Speter */ 82*14743Sthien if (r->var_node.qual != TR_NIL) 83775Speter goto ind; 84775Speter q = p->type; 85*14743Sthien if (q == NLNIL) 86*14743Sthien return (NLNIL); 87775Speter if (classify(q) == TSTR) 88775Speter return(stklval(r, NOFLAGS)); 89775Speter # ifdef OBJ 9010568Smckusick return (stackRV(p)); 91775Speter # endif OBJ 92775Speter # ifdef PC 93*14743Sthien q = rvalue( r , contype , (int) required ); 9410360Smckusick if (isa(q, "sbci")) { 9510360Smckusick sconv(p2type(q),P2INT); 9610360Smckusick } 9710360Smckusick return q; 98775Speter # endif PC 99775Speter 100775Speter case WITHPTR: 101775Speter case REF: 102775Speter /* 103775Speter * A stklval for these 104775Speter * is actually what one 105775Speter * might consider a rvalue. 106775Speter */ 107775Speter ind: 108775Speter q = stklval(r, NOFLAGS); 109*14743Sthien if (q == NLNIL) 110*14743Sthien return (NLNIL); 111775Speter if (classify(q) == TSTR) 112775Speter return(q); 113775Speter # ifdef OBJ 114775Speter w = width(q); 115775Speter switch (w) { 116775Speter case 8: 117*14743Sthien (void) put(1, O_IND8); 118775Speter return(q); 119775Speter case 4: 120*14743Sthien (void) put(1, O_IND4); 121775Speter return(q); 122775Speter case 2: 123*14743Sthien (void) put(1, O_IND24); 124775Speter return(q); 125775Speter case 1: 126*14743Sthien (void) put(1, O_IND14); 127775Speter return(q); 128775Speter default: 129*14743Sthien (void) put(2, O_IND, w); 130775Speter return(q); 131775Speter } 132775Speter # endif OBJ 133775Speter # ifdef PC 134775Speter if ( required == RREQ ) { 135775Speter putop( P2UNARY P2MUL , p2type( q ) ); 13610360Smckusick if (isa(q,"sbci")) { 13710360Smckusick sconv(p2type(q),P2INT); 13810360Smckusick } 139775Speter } 140775Speter return q; 141775Speter # endif PC 142775Speter 143775Speter case CONST: 144*14743Sthien if (r->var_node.qual != TR_NIL) { 145*14743Sthien error("%s is a constant and cannot be qualified", r->var_node.cptr); 146*14743Sthien return (NLNIL); 147775Speter } 148775Speter q = p->type; 149*14743Sthien if (q == NLNIL) 150*14743Sthien return (NLNIL); 151775Speter if (q == nl+TSTR) { 152775Speter /* 153775Speter * Find the size of the string 154775Speter * constant if needed. 155775Speter */ 156*14743Sthien cp = (char *) p->ptr[0]; 157775Speter cstrng: 158775Speter cp1 = cp; 159775Speter for (c = 0; *cp++; c++) 160775Speter continue; 16110841Speter w = c; 162775Speter if (contype != NIL && !opt('s')) { 163775Speter if (width(contype) < c && classify(contype) == TSTR) { 164775Speter error("Constant string too long"); 165*14743Sthien return (NLNIL); 166775Speter } 16710841Speter w = width(contype); 168775Speter } 169775Speter # ifdef OBJ 170*14743Sthien (void) put(2, O_LVCON, lenstr(cp1, w - c)); 17110841Speter putstr(cp1, w - c); 172775Speter # endif OBJ 173775Speter # ifdef PC 17410841Speter putCONG( cp1 , w , LREQ ); 175775Speter # endif PC 176775Speter /* 177775Speter * Define the string temporarily 178775Speter * so later people can know its 179775Speter * width. 180775Speter * cleaned out by stat. 181775Speter */ 182*14743Sthien q = defnl((char *) 0, STR, NLNIL, w); 183775Speter q->type = q; 184775Speter return (q); 185775Speter } 186775Speter if (q == nl+T1CHAR) { 187775Speter # ifdef OBJ 188*14743Sthien (void) put(2, O_CONC4, (int)p->value[0]); 189775Speter # endif OBJ 190775Speter # ifdef PC 191*14743Sthien putleaf(P2ICON, p -> value[0], 0, P2INT, 192*14743Sthien (char *) 0); 193775Speter # endif PC 194775Speter return(q); 195775Speter } 196775Speter /* 197775Speter * Every other kind of constant here 198775Speter */ 199775Speter # ifdef OBJ 200775Speter switch (width(q)) { 201775Speter case 8: 202775Speter #ifndef DEBUG 203*14743Sthien (void) put(2, O_CON8, p->real); 204775Speter return(q); 205775Speter #else 206775Speter if (hp21mx) { 207*14743Sthien f.pdouble = p->real; 208*14743Sthien conv((int *) (&f.pdouble)); 209*14743Sthien l = f.plong[1]; 210*14743Sthien (void) put(2, O_CON4, l); 211775Speter } else 212*14743Sthien (void) put(2, O_CON8, p->real); 213775Speter return(q); 214775Speter #endif 215775Speter case 4: 216*14743Sthien (void) put(2, O_CON4, p->range[0]); 217775Speter return(q); 218775Speter case 2: 219*14743Sthien (void) put(2, O_CON24, (short)p->range[0]); 220775Speter return(q); 221775Speter case 1: 222*14743Sthien (void) put(2, O_CON14, p->value[0]); 223775Speter return(q); 224775Speter default: 225775Speter panic("stkrval"); 226775Speter } 227775Speter # endif OBJ 228775Speter # ifdef PC 229*14743Sthien q = rvalue( r , contype , (int) required ); 23010360Smckusick if (isa(q,"sbci")) { 23110360Smckusick sconv(p2type(q),P2INT); 23210360Smckusick } 23310360Smckusick return q; 234775Speter # endif PC 235775Speter 236775Speter case FUNC: 2371201Speter case FFUNC: 238775Speter /* 239775Speter * Function call 240775Speter */ 241*14743Sthien pt = r->var_node.qual; 242*14743Sthien if (pt != TR_NIL) { 243*14743Sthien switch (pt->list_node.list->tag) { 244775Speter case T_PTR: 245775Speter case T_ARGL: 246775Speter case T_ARY: 247775Speter case T_FIELD: 248775Speter error("Can't qualify a function result value"); 249*14743Sthien return (NLNIL); 250775Speter } 251775Speter } 252775Speter # ifdef OBJ 253775Speter q = p->type; 254775Speter if (classify(q) == TSTR) { 255775Speter c = width(q); 256*14743Sthien (void) put(2, O_LVCON, even(c+1)); 257775Speter putstr("", c); 258*14743Sthien (void) put(1, PTR_DUP); 259775Speter p = funccod(r); 260*14743Sthien (void) put(2, O_AS, c); 261775Speter return(p); 262775Speter } 263775Speter p = funccod(r); 264775Speter if (width(p) <= 2) 265*14743Sthien (void) put(1, O_STOI); 266775Speter # endif OBJ 267775Speter # ifdef PC 268775Speter p = pcfunccod( r ); 26910360Smckusick if (isa(p,"sbci")) { 27010360Smckusick sconv(p2type(p),P2INT); 27110360Smckusick } 272775Speter # endif PC 273775Speter return (p); 274775Speter 275775Speter case TYPE: 276775Speter error("Type names (e.g. %s) allowed only in declarations", p->symbol); 277*14743Sthien return (NLNIL); 278775Speter 279775Speter case PROC: 2801201Speter case FPROC: 281775Speter error("Procedure %s found where expression required", p->symbol); 282*14743Sthien return (NLNIL); 283775Speter default: 284775Speter panic("stkrvid"); 285775Speter } 286775Speter case T_PLUS: 287775Speter case T_MINUS: 288775Speter case T_NOT: 289775Speter case T_AND: 290775Speter case T_OR: 291775Speter case T_DIVD: 292775Speter case T_MULT: 293775Speter case T_SUB: 294775Speter case T_ADD: 295775Speter case T_MOD: 296775Speter case T_DIV: 297775Speter case T_EQ: 298775Speter case T_NE: 299775Speter case T_GE: 300775Speter case T_LE: 301775Speter case T_GT: 302775Speter case T_LT: 303775Speter case T_IN: 304*14743Sthien p = rvalue(r, contype , (int) required ); 305775Speter # ifdef OBJ 306775Speter if (width(p) <= 2) 307*14743Sthien (void) put(1, O_STOI); 308775Speter # endif OBJ 30910360Smckusick # ifdef PC 31010360Smckusick if (isa(p,"sbci")) { 31110360Smckusick sconv(p2type(p),P2INT); 31210360Smckusick } 31310360Smckusick # endif PC 314775Speter return (p); 315909Speter case T_CSET: 316*14743Sthien p = rvalue(r, contype , (int) required ); 317909Speter return (p); 318775Speter default: 319*14743Sthien if (r->const_node.cptr == (char *) NIL) 320*14743Sthien return (NLNIL); 321*14743Sthien switch (r->tag) { 322775Speter default: 323775Speter panic("stkrval3"); 324775Speter 325775Speter /* 326775Speter * An octal number 327775Speter */ 328775Speter case T_BINT: 329*14743Sthien f.pdouble = a8tol(r->const_node.cptr); 330775Speter goto conint; 331775Speter 332775Speter /* 333775Speter * A decimal number 334775Speter */ 335775Speter case T_INT: 336*14743Sthien f.pdouble = atof(r->const_node.cptr); 337775Speter conint: 338*14743Sthien if (f.pdouble > MAXINT || f.pdouble < MININT) { 339775Speter error("Constant too large for this implementation"); 340*14743Sthien return (NLNIL); 341775Speter } 342*14743Sthien l = f.pdouble; 343775Speter if (bytes(l, l) <= 2) { 344775Speter # ifdef OBJ 345*14743Sthien (void) put(2, O_CON24, (short)l); 346775Speter # endif OBJ 347775Speter # ifdef PC 348*14743Sthien putleaf( P2ICON , (short) l , 0 , P2INT , 349*14743Sthien (char *) 0 ); 350775Speter # endif PC 351775Speter return(nl+T4INT); 352775Speter } 353775Speter # ifdef OBJ 354*14743Sthien (void) put(2, O_CON4, l); 355775Speter # endif OBJ 356775Speter # ifdef PC 357*14743Sthien putleaf( P2ICON , (int) l , 0 , P2INT , (char *) 0 ); 358775Speter # endif PC 359775Speter return (nl+T4INT); 360775Speter 361775Speter /* 362775Speter * A floating point number 363775Speter */ 364775Speter case T_FINT: 365775Speter # ifdef OBJ 366*14743Sthien (void) put(2, O_CON8, atof(r->const_node.cptr)); 367775Speter # endif OBJ 368775Speter # ifdef PC 369*14743Sthien putCON8( atof( r->const_node.cptr ) ); 370775Speter # endif PC 371775Speter return (nl+TDOUBLE); 372775Speter 373775Speter /* 374775Speter * Constant strings. Note that constant characters 375775Speter * are constant strings of length one; there is 376775Speter * no constant string of length one. 377775Speter */ 378775Speter case T_STRNG: 379*14743Sthien cp = r->const_node.cptr; 380775Speter if (cp[1] == 0) { 381775Speter # ifdef OBJ 382*14743Sthien (void) put(2, O_CONC4, cp[0]); 383775Speter # endif OBJ 384775Speter # ifdef PC 385*14743Sthien putleaf( P2ICON , cp[0] , 0 , P2INT , 386*14743Sthien (char *) 0 ); 387775Speter # endif PC 388775Speter return(nl+T1CHAR); 389775Speter } 390775Speter goto cstrng; 391775Speter } 392775Speter 393775Speter } 394775Speter } 39510568Smckusick 39610568Smckusick #ifdef OBJ 39710568Smckusick /* 39810568Smckusick * push a value onto the interpreter stack, longword aligned. 39910568Smckusick */ 400*14743Sthien struct nl 401*14743Sthien *stackRV(p) 40210568Smckusick struct nl *p; 40310568Smckusick { 40410568Smckusick struct nl *q; 40510568Smckusick int w, bn; 40610568Smckusick 40710568Smckusick q = p->type; 408*14743Sthien if (q == NLNIL) 409*14743Sthien return (NLNIL); 41010568Smckusick bn = BLOCKNO(p->nl_block); 41110568Smckusick w = width(q); 41210568Smckusick switch (w) { 41310568Smckusick case 8: 414*14743Sthien (void) put(2, O_RV8 | bn << 8+INDX, (int)p->value[0]); 41510568Smckusick break; 41610568Smckusick case 4: 417*14743Sthien (void) put(2, O_RV4 | bn << 8+INDX, (int)p->value[0]); 41810568Smckusick break; 41910568Smckusick case 2: 420*14743Sthien (void) put(2, O_RV24 | bn << 8+INDX, (int)p->value[0]); 42110568Smckusick break; 42210568Smckusick case 1: 423*14743Sthien (void) put(2, O_RV14 | bn << 8+INDX, (int)p->value[0]); 42410568Smckusick break; 42510568Smckusick default: 426*14743Sthien (void) put(3, O_RV | bn << 8+INDX, (int)p->value[0], w); 42710568Smckusick break; 42810568Smckusick } 42910568Smckusick return (q); 43010568Smckusick } 43110568Smckusick #endif OBJ 432