|
|
1.1 ! root 1: /* ! 2: * n0/expr.c ! 3: * C compiler. ! 4: * Expressions et al. ! 5: */ ! 6: ! 7: #ifdef vax ! 8: #include "INC$LIB:cc0.h" ! 9: #else ! 10: #include "cc0.h" ! 11: #endif ! 12: ! 13: #define LOW 0 ! 14: #define HIGH 0177 ! 15: #define INARGS 0200 ! 16: ! 17: #define bcvint(p) bconvert((p), T_INT, NULL, NULL, NULL) ! 18: #define isfloat(t) ((t)==T_FLOAT || (t)==T_DOUBLE) ! 19: #define isshift(op) ((op)==ASHL || (op)==ASHR || (op)==SHL || (op)==SHR) ! 20: #define issgnint(t) ((t)== T_CHAR || (t)== T_SHORT || (t)== T_INT || (t)== T_LONG) ! 21: #define isunsint(t) ((t)==T_UCHAR || (t)==T_USHORT || (t)==T_UINT || (t)==T_ULONG) ! 22: ! 23: static char tclash[] = "type clash"; ! 24: ! 25: /* ! 26: * Read a tree. ! 27: * This is the top level routine that is called by the user. ! 28: * The mysterious call to "build" with opcode "NOP" is to get any function or ! 29: * array name conversions applied, even if the top of the tree is a term. ! 30: * Ditto for getting types converted to computables. ! 31: */ ! 32: TREE * ! 33: expr() ! 34: { ! 35: if (notvariant(VCPP)) { ! 36: bput(LINE); ! 37: iput((ival_t) line); ! 38: } ! 39: return build(NOP, tree(LOW), NULL); ! 40: } ! 41: ! 42: /* ! 43: * Read in a tree. ! 44: * The "n" argument is a firewall precedence. ! 45: * You continue reading until the precedence of the operator ! 46: * in the input is less than the priority "n". ! 47: * The "INARGS" flag is or'ed into the priority to indicate ! 48: * that the expression is an argument list, and that "," is special. ! 49: * Passing it in this unconventional way lets you pass a single ! 50: * parameter to "tree". ! 51: */ ! 52: TREE * ! 53: tree(n) ! 54: { ! 55: register TREE *lp, *rp; ! 56: register SYM *sp; ! 57: DIM *dp; ! 58: TREE *tp, *fp; ! 59: int c, d, op, p, isarray, isinargs; ! 60: ! 61: isinargs = 0; ! 62: if ((n&INARGS) != 0) { ! 63: ++isinargs; ! 64: n &= ~INARGS; ! 65: } ! 66: lp = term(); ! 67: for (;;) { ! 68: switch (s) { ! 69: ! 70: case LPAREN: ! 71: lex(); ! 72: rp = NULL; ! 73: if (s != RPAREN) ! 74: rp = tree(LOW|INARGS); ! 75: mustbe(RPAREN); ! 76: lp = build(CALL, lp, rp); ! 77: break; ! 78: ! 79: case LBRACK: ! 80: lex(); ! 81: lp = build(ADD, lp, tree(LOW)); ! 82: adjust(lp, lp->t_type, lp->t_dp, lp->t_ip); ! 83: lp = build(STAR, lp, NULL); ! 84: mustbe(RBRACK); ! 85: break; ! 86: ! 87: case DOT: ! 88: case ARROW: ! 89: lp = build((s==DOT?ADDR:NOP), lp, NULL); ! 90: if (lex() != ID) { ! 91: cerror("missing member"); ! 92: break; ! 93: } ! 94: sp = moslookup(lp); ! 95: if (bitcompat(T_PTR, tltype(lp)) == 0) ! 96: cerror("left side of \"%s\" not usable", ! 97: s==DOT?".":"->"); ! 98: if (sp==NULL || ((c=sp->s_class)!=C_MOS && c!=C_MOU)) { ! 99: cerror("member \"%s\" is not defined", id); ! 100: sp = fakedef(SL_MOS); ! 101: } else if (isvariant(VSMEMB)) ! 102: csmemb(lp, sp); ! 103: lex(); ! 104: tp = talloc(); ! 105: tp->t_op = ADD; ! 106: tp->t_lp = lp; ! 107: tp->t_rp = bicon(sp->s_value); ! 108: lp = tp; ! 109: isarray = 0; ! 110: dp = sp->s_dp; ! 111: if (dp!=NULL && dp->d_type==D_ARRAY) { ! 112: ++isarray; ! 113: dp = tdalloc(dp->d_dp, D_MOSAR, dp->d_bound); ! 114: } else ! 115: dp = tdalloc(dp, D_PTR, (sizeof_t)0); ! 116: adjust(lp, sp->s_type, dp, sp->s_ip); ! 117: if (!isarray) ! 118: lp = build(STAR, lp, NULL); ! 119: if (sp->s_width != 0) { ! 120: fp = talloc(); ! 121: fp->t_op = FIELD; ! 122: fp->t_type = lp->t_type; ! 123: fp->t_lp = lp; ! 124: fp->t_width = sp->s_width; ! 125: fp->t_base = sp->s_offset; ! 126: lp = fp; ! 127: } ! 128: break; ! 129: ! 130: case INCBEF: ! 131: case DECBEF: ! 132: op = s+INCAFT-INCBEF; ! 133: lex(); ! 134: lp = build(op, lp, bicon((ival_t)1)); ! 135: break; ! 136: ! 137: default: ! 138: if ((s==COMMA && ininit!=0 && isinargs==0) ! 139: || (s==COLON)) ! 140: goto out; ! 141: if (s<MIOBASE || s>=MDOBASE) ! 142: goto out; ! 143: d = opdope[s-MIOBASE]; ! 144: if ((p=(d&PRIO)) == 0) ! 145: goto out; ! 146: if (p<n || ((d&RAS)==0 && p==n)) ! 147: goto out; ! 148: if ((op = s) == QUEST) { ! 149: lex(); ! 150: rp = tree(LOW); ! 151: mustbe(COLON); ! 152: rp = build(COLON, rp, tree(--p)); ! 153: lp = build(QUEST, lp, rp); ! 154: break; ! 155: } ! 156: if (op==COMMA && isinargs!=0) ! 157: op = ARGLST; ! 158: lex(); ! 159: lp = build(op, lp, tree(p)); ! 160: } ! 161: } ! 162: out: ! 163: return lp; ! 164: } ! 165: ! 166: /* ! 167: * Check that a structure member is ! 168: * indeed a member of the left hand structure. ! 169: * If the member is untagged, don't object to any clash. ! 170: * The structure declaration reader sets the S_TAG bit ! 171: * in the flags word of all tagged structures. ! 172: */ ! 173: csmemb(lp, sp) ! 174: TREE *lp; ! 175: SYM *sp; ! 176: { ! 177: register INFO *ip; ! 178: register SYM *tsp; ! 179: register int type; ! 180: char *msg; ! 181: int i; ! 182: ! 183: type = lp->t_type; ! 184: if (lp->t_dp==NULL || lp->t_dp->d_type!=D_PTR ! 185: || type<T_STRUCT || type>T_FUNION) { ! 186: cstrict("potentially nonportable structure access"); ! 187: return; ! 188: } ! 189: if ((type==T_STRUCT || type==T_UNION) && (sp->s_flag&S_TAG)!=0) { ! 190: ip = lp->t_ip; ! 191: if (ip != NULL) { ! 192: for (i=0; i<ip->i_nsp && ip->i_sp[i]!=sp; ++i) ! 193: ; ! 194: if (i >= ip->i_nsp) { ! 195: tsp = taglookup(ip); ! 196: if (tsp != NULL) { ! 197: msg = (tsp->s_class == C_UTAG) ? "union" : "structure"; ! 198: if (tsp->s_id[0] != '.') ! 199: cstrict("%s \"%s\" does not contain member \"%s\"", ! 200: msg, tsp->s_id, sp->s_id); ! 201: else ! 202: cstrict("%s does not contain member \"%s\"", ! 203: msg, sp->s_id); ! 204: } ! 205: } ! 206: } ! 207: } ! 208: } ! 209: ! 210: /* ! 211: * Read a term. ! 212: * Handle all of the leaf nodes and the unary operations here. ! 213: */ ! 214: TREE * ! 215: term() ! 216: { ! 217: register TREE *tp; ! 218: register SYM *sp; ! 219: register int op; ! 220: TREE *cp; ! 221: DIM *dp; ! 222: int tt, lt, n; ! 223: ! 224: switch (op = s) { ! 225: ! 226: case ICON: ! 227: tp = bicon(ival); ! 228: tp->t_type = tval; ! 229: lex(); ! 230: break; ! 231: ! 232: case LCON: ! 233: tp = talloc(); ! 234: tp->t_op = LCON; ! 235: tp->t_type = tval; ! 236: tp->t_lval = lval; ! 237: lex(); ! 238: break; ! 239: ! 240: case DCON: ! 241: tp = talloc(); ! 242: tp->t_op = DCON; ! 243: tp->t_type = tval; ! 244: memcpy((char *)tp->t_dval, (char *)dval, sizeof(dval_t)); ! 245: lex(); ! 246: break; ! 247: ! 248: case STRING: ! 249: tp = bstring(); ! 250: break; ! 251: ! 252: case ID: ! 253: if ((sp=reflookup(SL_VAR)) == NULL) { ! 254: /* ! 255: * An undefined name followed by a "(" is declared ! 256: * to be a function that returns an integer. ! 257: * So says the manual. ! 258: */ ! 259: TOK *tp; ! 260: tp = idp; ! 261: if (spnextis('(')) { ! 262: setid(tp->t_id); ! 263: sp = deflookup(SL_VAR, 0); ! 264: dp = tackdim(NULL, D_FUNC, 0); ! 265: sp = declare(sp, C_CXT, T_INT, dp, NULL, 0); ! 266: } else ! 267: setid(tp->t_id); ! 268: if (sp == NULL) { ! 269: cerror("identifier \"%s\" is not defined", id); ! 270: sp = fakedef(SL_VAR); ! 271: } ! 272: } ! 273: tp = bid(sp); ! 274: lex(); ! 275: break; ! 276: ! 277: case LPAREN: ! 278: lex(); ! 279: if ((cp=cast()) != NULL) { ! 280: if (cp->t_type==T_FLOAT && cp->t_dp==NULL) ! 281: cp->t_type = T_DOUBLE; ! 282: cp->t_lp = build(NOP, tree(HIGH), NULL); ! 283: tt = tltype(cp); ! 284: lt = tltype(cp->t_lp); ! 285: if (tt == T_STRUCT) ! 286: cerror("cannot cast to structure or union"); ! 287: if (lt == T_STRUCT) ! 288: cerror("cannot cast structure or union"); ! 289: if (tt == T_PTR && isfloat(lt)) ! 290: cerror("cannot cast double to pointer"); ! 291: if (isfloat(tt) && lt == T_PTR) ! 292: cerror("cannot cast pointer to double"); ! 293: if (bitcompat(tt, lt)) { ! 294: tp = cp->t_lp; ! 295: adjust(tp, cp->t_type, cp->t_dp, cp->t_ip); ! 296: if (tp->t_op == CONVERT && tp->t_rp == NULL) ! 297: tp->t_op = CAST; ! 298: } else ! 299: tp = cp; ! 300: break; ! 301: } ! 302: n = ininit; ! 303: ininit = 0; ! 304: tp = tree(LOW); ! 305: ininit = n; ! 306: mustbe(RPAREN); ! 307: break; ! 308: ! 309: case SIZEOF: ! 310: lex(); ! 311: if (s == LPAREN) { ! 312: lex(); ! 313: if ((tp=cast()) == NULL) { ! 314: tp = tree(LOW); ! 315: mustbe(RPAREN); ! 316: } ! 317: } else ! 318: tp = tree(HIGH); ! 319: tp = build(SIZEOF, tp, NULL); ! 320: break; ! 321: ! 322: case NOT: ! 323: lex(); ! 324: tp = build(EQ, tree(HIGH), bicon((ival_t)0)); ! 325: break; ! 326: ! 327: case SUB: ! 328: op = NEG; ! 329: goto unary; ! 330: case ADD: /* Unary plus == no rearrangement FIX.ME */ ! 331: lex(); ! 332: tp = tree(HIGH); /* ignored for present */ ! 333: break; ! 334: op = POS; ! 335: goto unary; ! 336: case MUL: ! 337: op = STAR; ! 338: goto unary; ! 339: case AND: ! 340: op = ADDR; ! 341: goto unary; ! 342: case COM: ! 343: unary: ! 344: lex(); ! 345: tp = build(op, tree(HIGH), NULL); ! 346: break; ! 347: ! 348: case INCBEF: ! 349: case DECBEF: ! 350: lex(); ! 351: tp = build(op, tree(HIGH), bicon((ival_t)1)); ! 352: break; ! 353: ! 354: default: ! 355: cerror("error in expression syntax"); ! 356: while (s!=EOF && s!=SEMI && s!=LBRACE && s!=RBRACE) ! 357: skip(); ! 358: return bicon((ival_t)0); ! 359: } ! 360: return tp; ! 361: } ! 362: ! 363: /* ! 364: * Given an operator "op" and left and right subtrees "lp" and "rp", ! 365: * build a tree node, folding any constant expressions ! 366: * that can be folded, supplying any required type conversions. ! 367: * All of the conversions that are possible are added; ! 368: * the routine "transform" may remove some of them. ! 369: */ ! 370: TREE * ! 371: build(op, lp, rp) int op; TREE *lp; TREE *rp; ! 372: { ! 373: TREE *tp, *gtp, gt; ! 374: DIM *dp; ! 375: int rt, lt, d, cv; ! 376: sizeof_t ll, lr; ! 377: ! 378: if (op == SIZEOF) ! 379: return bzcon(tsize(lp)); ! 380: rt = T_NONE; ! 381: if (rp != NULL) { ! 382: chmos(rp); ! 383: rp = chfun(charray(rp)); ! 384: rt = tltype(rp); ! 385: } ! 386: chmos(lp); ! 387: lp = charray(lp); ! 388: if (op!=ADDR && op!=CALL) ! 389: lp = chfun(lp); ! 390: lt = tltype(lp); ! 391: if (op == NOP) ! 392: goto conversion; ! 393: /* ! 394: * Make sure that the operands are ! 395: * suitable as operands of the specified operation. ! 396: * Look mainly at the type, although some consideration ! 397: * is made of storage class. ! 398: */ ! 399: if (lt==T_VOID || rt==T_VOID) { ! 400: if ((op!=COMMA && op!=QUEST && op!=COLON) ! 401: || (op==COLON && lt!=rt) ! 402: || (op==QUEST && lt==T_VOID)) { ! 403: cerror("illegal operation on \"void\" type"); ! 404: lt = T_INT; ! 405: rt = T_INT; ! 406: } ! 407: } ! 408: if (op==ADDR && lp->t_op==REG) ! 409: cerror("cannot apply unary '&' to a register variable"); ! 410: if (op==ADDR && lp->t_op==FIELD) ! 411: cerror("cannot apply unary '&' to a bit field"); ! 412: if (op==ADDR && lp->t_op==GID && lp->t_seg==SALIEN) ! 413: cerror("cannot apply unary '&' to an alien function"); ! 414: d = opdope[op-MIOBASE]; ! 415: if ((d&RLVL) != 0 ! 416: && (lp->t_op<=DCON ! 417: || (lp->t_op>=MIOBASE && lp->t_op!=STAR && lp->t_op!=FIELD ! 418: && (lp->t_op!=CALL || lp->t_type!=T_STRUCT || lp->t_dp!=NULL) ! 419: ))) ! 420: cerror("lvalue required"); ! 421: if ((d&NFLT)!=0 && (isfloat(lt) || isfloat(rt))) ! 422: cerror("illegal use of floating point"); ! 423: if (((d&NPTL)!=0 && lt==T_PTR) || ((d&NPTR)!=0 && rt==T_PTR)) ! 424: cerror("illegal use of a pointer"); ! 425: if (((d&NSTL)!=0 && lt==T_STRUCT) || ((d&NSTR)!=0 && rt==T_STRUCT)) ! 426: cerror("illegal use of a structure or union"); ! 427: if ((d&RTOL) != 0) ! 428: truth(lp); ! 429: if ((d&RTOR) != 0) ! 430: truth(rp); ! 431: /* ! 432: * The operation may just fold away to nothing. ! 433: * If so, return a pointer to the new, constant tree node. ! 434: */ ! 435: if ((tp=fold0(op, lp, rp)) != NULL) ! 436: return tp; ! 437: /* ! 438: * Insert conversion nodes. ! 439: */ ! 440: conversion: ! 441: gt.t_op = CONVERT; ! 442: gt.t_dp = NULL; ! 443: gt.t_ip = NULL; ! 444: switch (op) { ! 445: ! 446: case QUEST: ! 447: if (rp->t_op != COLON) ! 448: cerror("mismatched conditional"); ! 449: /* Make sure the condition type 'lt' is computational. */ ! 450: gt.t_type = (cvdope[13 * (lt - T_CHAR) + lt - T_CHAR] & GOAL); ! 451: gt.t_dp = lp->t_dp; ! 452: gt.t_ip = lp->t_ip; ! 453: if (bitcompat(tltype(>), lt) == 0) ! 454: lp = bcvt(lp, >); ! 455: /* then fall through... */ ! 456: ! 457: case COMMA: ! 458: case ARGLST: ! 459: gt.t_type = rp->t_type; ! 460: gt.t_dp = rp->t_dp; ! 461: gt.t_ip = rp->t_ip; ! 462: break; ! 463: ! 464: case ANDAND: ! 465: case OROR: ! 466: case NOT: ! 467: gt.t_type = T_INT; ! 468: break; ! 469: ! 470: case CALL: ! 471: if ((dp = lp->t_dp)!=NULL && dp->d_type==D_FUNC) ! 472: gt.t_dp = dp->d_dp; ! 473: else if ((dp = lp->t_dp)!=NULL ! 474: && dp->d_type==D_PTR ! 475: && dp->d_dp->d_type==D_FUNC) { ! 476: cwarn("implicit '*' added to function call"); ! 477: lp = build(STAR, lp, NULL); ! 478: gt.t_dp = dp->d_dp->d_dp; ! 479: } else ! 480: cerror("call of non function"); ! 481: if (rp != NULL && rp->t_op != ARGLST) { ! 482: rp = build(NOP, rp, NULL); ! 483: rt = tltype(rp); ! 484: } ! 485: gt.t_type = lp->t_type; ! 486: gt.t_ip = lp->t_ip; ! 487: break; ! 488: ! 489: case STAR: ! 490: if ((dp = lp->t_dp)!=NULL && dp->d_type==D_PTR) ! 491: gt.t_dp = dp->d_dp; ! 492: else ! 493: cerror("indirection through non pointer"); ! 494: gt.t_type = lp->t_type; ! 495: gt.t_ip = lp->t_ip; ! 496: break; ! 497: ! 498: case ADDR: ! 499: gt.t_type = lp->t_type; ! 500: gt.t_dp = tdalloc(lp->t_dp, D_PTR, (sizeof_t)0); ! 501: gt.t_ip = lp->t_ip; ! 502: break; ! 503: ! 504: default: ! 505: if (rt == T_NONE) ! 506: rt = lt; ! 507: if (isshift(op)) { ! 508: /* ! 509: * Shift ops: convert right op to T_INT, ! 510: * read dope table accordingly. ! 511: */ ! 512: if (bitcompat(T_INT, rt) == 0) ! 513: rp = bcvint(rp); ! 514: rt = T_INT; ! 515: } ! 516: cv = cvdope[13*(lt-T_CHAR) + rt - T_CHAR]; ! 517: if (noconvert(op, lt, rt)) ! 518: cv &= ~(CVL|CVR|CVRA|CARA); ! 519: else if (isshift(op)) ! 520: cv &= ~(CVR|CVRA); ! 521: gt.t_type = cv&GOAL; ! 522: gt.t_rp = NULL; ! 523: if ((cv&(GTL|GTR)) != 0) { ! 524: gtp = ((cv>L)!=0) ? lp : rp; ! 525: gt.t_type = gtp->t_type; ! 526: gt.t_dp = gtp->t_dp; ! 527: gt.t_ip = gtp->t_ip; ! 528: if ((cv&(CVL|CVR|CVRA)) != 0) ! 529: gt.t_rp = bzcon(psize(gtp)); ! 530: } ! 531: if (gt.t_type == T_NONE && op!=NOP && lt!=T_VOID) ! 532: cerror(tclash); ! 533: if ((d&ASGN) != 0) { ! 534: gt.t_type = lp->t_type; ! 535: gt.t_dp = lp->t_dp; ! 536: gt.t_ip = lp->t_ip; ! 537: if (gt.t_dp == NULL) { ! 538: if (gt.t_type==T_CHAR ! 539: || gt.t_type==T_UCHAR ! 540: || gt.t_type==T_SHORT ! 541: || gt.t_type==T_ENUM ! 542: || gt.t_type==T_FENUM) ! 543: gt.t_type = T_INT; ! 544: if (gt.t_type == T_USHORT) ! 545: gt.t_type = T_UINT; ! 546: if (gt.t_type == T_FLOAT) ! 547: gt.t_type = T_DOUBLE; ! 548: } ! 549: /* ! 550: * The following ADIV and AREM type conversion code is somewhat bogus. ! 551: * The basic problem is that C requires "a op= b;" to give the same ! 552: * result as "a = a op b;". ! 553: * The code below makes sure that an unsigned right op remains unsigned, ! 554: * so the code tables can generate an unsigned op rather than a signed op. ! 555: * Actually, the problem is more general; "i *= 1.5;" should have the same ! 556: * effect as "i = (double)i * 1.5;" but it currently does "i *= (int) 1.5;". ! 557: * This code the most obvious inconsistencies, though. ! 558: */ ! 559: if ((cv&CVRA) != 0) { ! 560: if ((op == ADIV || op == AREM) ! 561: && issgnint(gt.t_type) && isunsint(rt)) { ! 562: gt.t_type = sgn2uns(gt.t_type); ! 563: rp = bcvt(rp, >); ! 564: gt.t_type = uns2sgn(gt.t_type); ! 565: } else ! 566: rp = bcvt(rp, >); ! 567: } else if ((cv&CARA) != 0) { ! 568: gt.t_op = CAST; ! 569: gt.t_rp = NULL; ! 570: rp = bcvt(rp, >); ! 571: } ! 572: } else { ! 573: if (op>=INCBEF && op<=DECAFT) ! 574: cv &= ~CVL; ! 575: if (op == COLON && lt != rt) { ! 576: if (lt == T_PTR) { ! 577: if (iszero(rp)) { ! 578: gt.t_op = CAST; ! 579: gt.t_rp = NULL; ! 580: } else ! 581: cerror(tclash); ! 582: } else if (rt == T_PTR) { ! 583: if (iszero(lp)) { ! 584: gt.t_op = CAST; ! 585: gt.t_rp = NULL; ! 586: } else ! 587: cerror(tclash); ! 588: } ! 589: } else if (op == COLON && lt==T_VOID && rt==T_VOID) ! 590: gt.t_type = T_VOID; ! 591: if ((cv&CVL) != 0) ! 592: lp = bcvt(lp, >); ! 593: if (op==SHL || op==SHR) { ! 594: gt.t_type = lp->t_type; ! 595: gt.t_dp = lp->t_dp; ! 596: gt.t_ip = lp->t_ip; ! 597: } else if (rp!=NULL && (cv&CVR)!=0) ! 598: rp = bcvt(rp, >); ! 599: if ((cv&UREL)!=0 && (op>=GT && op<=LT)) ! 600: op += UGT-GT; ! 601: if (op>=EQ && op<=ULT) { ! 602: gt.t_type = T_INT; ! 603: gt.t_dp = gt.t_ip = NULL; ! 604: } ! 605: } ! 606: } ! 607: if (op==NOP) ! 608: return lp; ! 609: tp = talloc(); ! 610: tp->t_op = op; ! 611: tp->t_type = gt.t_type; ! 612: tp->t_dp = gt.t_dp; ! 613: tp->t_ip = gt.t_ip; ! 614: tp->t_lp = lp; ! 615: tp->t_rp = rp; ! 616: if (lt==T_PTR && rt==T_PTR) { ! 617: if (op == ADD) ! 618: cerror("cannot add pointers"); ! 619: if (op == SUB) { ! 620: if ((ll=psize(lp)) != (lr=psize(rp))) ! 621: cerror("illegal subtraction of pointers"); ! 622: tp = bconvert(tp, T_INT, NULL, NULL, bzcon(ll)); ! 623: } ! 624: } ! 625: if (op==ASSIGN && lt==T_STRUCT && rt==T_STRUCT) { ! 626: notbook(); ! 627: if ((ll=tsize(lp)) != (lr=tsize(rp))) ! 628: cerror("illegal structure assignment"); ! 629: } ! 630: if (isvariant(VSPVAL) && lt != rt ! 631: && ((lt==T_PTR && !iszero(rp)) || (rt==T_PTR && !iszero(lp)))) { ! 632: if (op == ASSIGN) ! 633: cstrict("integer pointer pun"); ! 634: else if (op >= EQ && op <= ULT) ! 635: cstrict("integer pointer comparison"); ! 636: } ! 637: return tp; ! 638: } ! 639: ! 640: /* ! 641: * If the first entry in the dimensions of tree "tp" is a ! 642: * MOS array, stomp it into the pointer it truly is. ! 643: */ ! 644: chmos(tp) ! 645: TREE *tp; ! 646: { ! 647: register struct dim *dp; ! 648: ! 649: if ((dp = tp->t_dp)!=NULL && dp->d_type==D_MOSAR) { ! 650: dp->d_type = D_PTR; ! 651: dp->d_bound = 0; ! 652: } ! 653: } ! 654: ! 655: /* ! 656: * Read constant expression. ! 657: * Call the standard expression reader, and make sure that ! 658: * the folder has squashed it down to nothing. ! 659: * Return the value. ! 660: */ ! 661: ival_t ! 662: iconexpr() ! 663: { ! 664: register TREE *tp; ! 665: ! 666: tp = expr(); ! 667: while (tp->t_op == CAST || tp->t_op == CONVERT) ! 668: tp = tp->t_lp; ! 669: if (tp->t_op == ICON) ! 670: return tp->t_ival; ! 671: if (tp->t_op == LCON && (ival_t)tp->t_lval == tp->t_lval) ! 672: return (ival_t)tp->t_lval; ! 673: if (tp->t_op == ZCON && (ival_t)tp->t_zval == tp->t_zval) ! 674: return (ival_t)tp->t_zval; ! 675: cerror("int constant expression required"); ! 676: return (ival_t)0; ! 677: } ! 678: ! 679: /* ! 680: * Look for a constant zero of integral type. ! 681: */ ! 682: iszero(tp) ! 683: register TREE *tp; ! 684: { ! 685: register int op; ! 686: ! 687: if (tp != NULL) { ! 688: while ((op = tp->t_op) == CONVERT || op == CAST) ! 689: tp = tp->t_lp; ! 690: if (op == ICON && tp->t_ival == 0) ! 691: return 1; ! 692: if (op == LCON && tp->t_lval == 0L) ! 693: return 1; ! 694: } ! 695: return 0; ! 696: } ! 697: ! 698: /* ! 699: * Build a conversion node. ! 700: * Used by build and stat when bcvt is unsuitable. ! 701: */ ! 702: TREE * ! 703: bconvert(lp, gt, gdp, gip, rp) ! 704: TREE *lp, *rp; ! 705: DIM *gdp; ! 706: INFO *gip; ! 707: { ! 708: TREE t; ! 709: ! 710: t.t_op = CONVERT; ! 711: t.t_type = gt; ! 712: t.t_dp = gdp; ! 713: t.t_ip = gip; ! 714: t.t_rp = rp; ! 715: return bcvt(lp, &t); ! 716: } ! 717: ! 718: /* ! 719: * Build a conversion or cast node. ! 720: */ ! 721: TREE * ! 722: bcvt(lp, gtp) ! 723: TREE *lp, *gtp; ! 724: { ! 725: register TREE *tp; ! 726: ! 727: tp = lp; ! 728: tp = talloc(); ! 729: tp->t_op = gtp->t_op; ! 730: tp->t_type = gtp->t_type; ! 731: tp->t_dp = gtp->t_dp; ! 732: tp->t_ip = gtp->t_ip; ! 733: tp->t_lp = lp; ! 734: tp->t_rp = gtp->t_rp; ! 735: return tp; ! 736: } ! 737: ! 738: /* ! 739: * Given a pointer to its symbol table node, ! 740: * return a pointer to the tree node for an identifier. ! 741: * Enumeration tags get changed into integer constants here. ! 742: */ ! 743: TREE * ! 744: bid(sp) ! 745: register SYM *sp; ! 746: { ! 747: register TREE *tp; ! 748: ! 749: sp->s_flag |= S_USED; ! 750: if (sp->s_class == C_MOE) ! 751: return bicon(sp->s_value); ! 752: tp = talloc(); ! 753: switch (sp->s_class) { ! 754: ! 755: case C_AUTO: ! 756: tp->t_op = AID; ! 757: tp->t_offs = sp->s_value; ! 758: break; ! 759: ! 760: case C_PAUTO: ! 761: tp->t_op = PID; ! 762: tp->t_offs = sp->s_value; ! 763: break; ! 764: ! 765: case C_SIN: ! 766: tp->t_op = LID; ! 767: tp->t_seg = sp->s_seg; ! 768: tp->t_label = sp->s_value; ! 769: break; ! 770: ! 771: case C_REG: ! 772: tp->t_op = REG; ! 773: tp->t_reg = sp->s_value; ! 774: break; ! 775: ! 776: case C_GDEF: ! 777: case C_GREF: ! 778: case C_CXT: ! 779: case C_SEX: ! 780: tp->t_op = GID; ! 781: tp->t_seg = sp->s_seg; ! 782: tp->t_sp = sp; ! 783: break; ! 784: ! 785: default: ! 786: cerror("identifier \"%s\" not usable", sp->s_id); ! 787: tp->t_op = ICON; ! 788: tp->t_type = T_INT; ! 789: return tp; ! 790: } ! 791: tp->t_type = sp->s_type; ! 792: tp->t_dp = sp->s_dp; ! 793: tp->t_ip = sp->s_ip; ! 794: return tp; ! 795: } ! 796: ! 797: /* ! 798: * Build ICON tree node. ! 799: */ ! 800: TREE * ! 801: bicon(n) ival_t n; ! 802: { ! 803: register TREE *tp; ! 804: ! 805: tp = talloc(); ! 806: tp->t_op = ICON; ! 807: tp->t_type = T_INT; ! 808: tp->t_ival = n; ! 809: return tp; ! 810: } ! 811: ! 812: TREE * ! 813: bzcon(n) ! 814: sizeof_t n; ! 815: { ! 816: register TREE *tp; ! 817: ! 818: tp = talloc(); ! 819: tp->t_op = ZCON; ! 820: tp->t_type = T_UINT; ! 821: tp->t_zval = n; ! 822: return tp; ! 823: } ! 824: ! 825: /* ! 826: * Read in a string and hide it in the string section. ! 827: * Return a pointer to a local identifier node; ! 828: * the local identifier is planted at the start of the string. ! 829: * The type of the node is set to array of char. ! 830: */ ! 831: static ! 832: TREE * ! 833: bstring() ! 834: { ! 835: register TREE *tp; ! 836: register int c, nbb, nbs; ! 837: int old, lab, adj; ! 838: char bb[11]; ! 839: ! 840: old = newseg(SSTRN); ! 841: lab = here(); ! 842: nbb = nbs = adj = 0; ! 843: again: ! 844: instring = '"'; ! 845: while ((c=getmap('\"')) >= 0) { ! 846: ++nbs; ! 847: if (nbb >= 10) { /* Leave space for NUL */ ! 848: bsflush(bb, nbb); ! 849: nbb = 0; ! 850: } ! 851: bb[nbb++] = c; ! 852: } ! 853: instring = 0; ! 854: if (lex() == STRING) { /* e.g. "Hello " "world" */ ! 855: ++adj; ! 856: goto again; ! 857: } ! 858: bb[nbb++] = 0; ! 859: bsflush(bb, nbb); ! 860: if (adj) ! 861: notbook(); ! 862: newseg(old); ! 863: tp = talloc(); ! 864: tp->t_op = LID; ! 865: tp->t_type = T_CHAR; ! 866: tp->t_dp = tdalloc(NULL, D_ARRAY, (sizeof_t)nbs+1); ! 867: tp->t_label = lab; ! 868: tp->t_seg = SSTRN; ! 869: return tp; ! 870: } ! 871: ! 872: /* ! 873: * Dump out the string buffer. ! 874: */ ! 875: bsflush(bb, nbb) ! 876: register unsigned char *bb; ! 877: register int nbb; ! 878: { ! 879: bput(IBLOCK); ! 880: bput(nbb); ! 881: while (nbb--) ! 882: bput(*bb++); ! 883: } ! 884: ! 885: /* ! 886: * Make all the types and dims in a tree agree with the viewpoint at the top. ! 887: * This is used by casts and the code that builds up structure access trees. ! 888: */ ! 889: adjust(tp, t, dp, ip) ! 890: register TREE *tp; ! 891: register DIM *dp; ! 892: INFO *ip; ! 893: { ! 894: register int op; ! 895: ! 896: again: ! 897: tp->t_type = t; ! 898: tp->t_dp = dp; ! 899: tp->t_ip = ip; ! 900: if ((op = tp->t_op) == ADDR) { ! 901: if (dp==NULL || (dp->d_type!=D_PTR && dp->d_type!=D_MOSAR)) ! 902: return; ! 903: dp = dp->d_dp; ! 904: tp = tp->t_lp; ! 905: goto again; ! 906: } ! 907: if (op == STAR) { ! 908: dp = tdalloc(dp, D_PTR, (sizeof_t)0); ! 909: tp = tp->t_lp; ! 910: goto again; ! 911: } ! 912: if (dp!=NULL && dp->d_type==D_MOSAR) ! 913: dp = tdalloc(dp->d_dp, D_PTR, (sizeof_t)0); ! 914: if (op==CAST && bitcompat(tltype(tp), tltype(tp->t_lp))) { ! 915: tp = tp->t_lp; ! 916: goto again; ! 917: } ! 918: } ! 919: ! 920: /* ! 921: * If the tree "tp" is a pointer, ! 922: * return the size of the item to which the pointer points; ! 923: * if it is not a pointer, return 1. ! 924: */ ! 925: sizeof_t psize(tp) ! 926: register TREE *tp; ! 927: { ! 928: register DIM *dp; ! 929: register sizeof_t n; ! 930: ! 931: dp = tp->t_dp; ! 932: if (dp==NULL || dp->d_type!=D_PTR) ! 933: return 1; ! 934: tp->t_dp = dp->d_dp; ! 935: n = tsize(tp); ! 936: tp->t_dp = dp; ! 937: return n; ! 938: } ! 939: ! 940: /* ! 941: * Check if a tree has type "function returning ...". ! 942: * If it does, modify the tree to add the free "address of". ! 943: */ ! 944: TREE * ! 945: chfun(tp) ! 946: register TREE *tp; ! 947: { ! 948: register DIM *dp; ! 949: ! 950: dp = tp->t_dp; ! 951: if (dp!=NULL && dp->d_type==D_FUNC) { ! 952: tp = build(ADDR, tp, NULL); ! 953: adjust(tp, tp->t_type, tp->t_dp, tp->t_ip); ! 954: } ! 955: return tp; ! 956: } ! 957: ! 958: /* ! 959: * Check for arrays. ! 960: * Add the free '&' operation. ! 961: * We build the node ourselves (rather than calling build) ! 962: * to avoid a recursive call to this routine on ! 963: * a multidimensional structure. ! 964: */ ! 965: TREE * ! 966: charray(tp) ! 967: register TREE *tp; ! 968: { ! 969: register TREE *ap; ! 970: register DIM *dp; ! 971: ! 972: dp = tp->t_dp; ! 973: if (dp!=NULL && dp->d_type==D_ARRAY) { ! 974: ap = talloc(); ! 975: ap->t_op = ADDR; ! 976: ap->t_type = tp->t_type; ! 977: ap->t_dp = tdalloc(dp->d_dp, D_PTR, (sizeof_t)0); ! 978: ap->t_ip = tp->t_ip; ! 979: ap->t_lp = tp; ! 980: tp = ap; ! 981: adjust(tp, tp->t_type, tp->t_dp, tp->t_ip); ! 982: } ! 983: return tp; ! 984: } ! 985: ! 986: /* ! 987: * Given a tree node, get a type for the tree that is ! 988: * usable for indexing into the type conversion tables. ! 989: * All non-scalars are pointers. ! 990: * All structures and unions are structures. ! 991: * All enumerations are set right. ! 992: */ ! 993: tltype(tp) ! 994: register TREE *tp; ! 995: { ! 996: register int type; ! 997: ! 998: if (tp->t_dp != NULL) ! 999: return T_PTR; ! 1000: if ((type=tp->t_type) == T_FENUM) ! 1001: return T_INT; ! 1002: if (type == T_ENUM) ! 1003: return tp->t_ip->i_type; ! 1004: if (type > T_VOID) ! 1005: return T_STRUCT; ! 1006: return type; ! 1007: } ! 1008: ! 1009: /* ! 1010: * Check if two linear types are "bit compatable". ! 1011: */ ! 1012: bitcompat(t1, t2) ! 1013: { ! 1014: return noconvert(CAST, t1, t2); ! 1015: } ! 1016: ! 1017: /* ! 1018: * Allocate a new dim structure in the tree area. ! 1019: * Used to create pointers in the tree. ! 1020: */ ! 1021: DIM * ! 1022: tdalloc(p, t, b) ! 1023: DIM *p; ! 1024: int t; ! 1025: sizeof_t b; ! 1026: { ! 1027: register DIM *dp; ! 1028: ! 1029: dp = (struct dim *) talloc(); ! 1030: dp->d_dp = p; ! 1031: dp->d_type = t; ! 1032: dp->d_bound = b; ! 1033: return dp; ! 1034: } ! 1035: ! 1036: /* ! 1037: * Output a tree. ! 1038: */ ! 1039: tput(why, lab, tp) ! 1040: register why; ! 1041: register TREE *tp; ! 1042: { ! 1043: tp = transform(tp, why, -1); ! 1044: bput(why); ! 1045: if (why==TEXPR || why==FEXPR) ! 1046: iput((ival_t) lab); ! 1047: tput1(tp); ! 1048: } ! 1049: ! 1050: /* ! 1051: * Output a tree, part II. ! 1052: */ ! 1053: tput1(tp) ! 1054: register TREE *tp; ! 1055: { ! 1056: register int op; ! 1057: ! 1058: if (tp == NULL) { ! 1059: iput((ival_t) NIL); ! 1060: return; ! 1061: } ! 1062: op = tp->t_op; ! 1063: iput((ival_t) op); ! 1064: bput(tp->t_type); ! 1065: if (tp->t_type == BLK) ! 1066: iput((ival_t)tp->t_ip->i_size); ! 1067: switch (op) { ! 1068: ! 1069: case ICON: ! 1070: iput((ival_t) tp->t_ival); ! 1071: break; ! 1072: ! 1073: case LCON: ! 1074: lput(tp->t_lval); ! 1075: break; ! 1076: ! 1077: case ZCON: ! 1078: zput(tp->t_zval); ! 1079: break; ! 1080: ! 1081: case DCON: ! 1082: dput(tp->t_dval); /* An array */ ! 1083: break; ! 1084: ! 1085: case AID: ! 1086: case PID: ! 1087: case LID: ! 1088: case GID: ! 1089: zput(tp->t_offs); ! 1090: if (op==LID || op==GID) { ! 1091: bput(tp->t_seg); ! 1092: if (op == LID) ! 1093: iput((ival_t) tp->t_label); ! 1094: else ! 1095: nput(tp->t_sp->s_id); ! 1096: } ! 1097: break; ! 1098: ! 1099: case REG: ! 1100: iput((ival_t) tp->t_reg); ! 1101: break; ! 1102: ! 1103: case FIELD: ! 1104: bput(tp->t_width); ! 1105: bput(tp->t_base); ! 1106: tput1(tp->t_lp); ! 1107: break; ! 1108: ! 1109: default: ! 1110: tput1(tp->t_lp); ! 1111: tput1(tp->t_rp); ! 1112: } ! 1113: } ! 1114: ! 1115: /* end of n0/expr.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.