1: /* @(#)c01.c 2.1 SCCS id keyword */ 2: # 3: /* 4: * C compiler 5: * 6: * 7: */ 8: 9: #include "c0.h" 10: 11: /* 12: * Called from tree, this routine takes the top 1, 2, or 3 13: * operands on the expression stack, makes a new node with 14: * the operator op, and puts it on the stack. 15: * Essentially all the work is in inserting 16: * appropriate conversions. 17: */ 18: build(op) 19: { 20: register int t1; 21: int t2, t; 22: register struct tnode *p1, *p2; 23: struct tnode *p3; 24: int dope, leftc, cvn, pcvn; 25: 26: /* 27: * a[i] => *(a+i) 28: */ 29: if (op==LBRACK) { 30: build(PLUS); 31: op = STAR; 32: } 33: dope = opdope[op]; 34: if ((dope&BINARY)!=0) { 35: p2 = chkfun(disarray(*--cp)); 36: t2 = p2->type; 37: } 38: p1 = *--cp; 39: /* 40: * sizeof gets turned into a number here. 41: */ 42: if (op==SIZEOF) { 43: t1 = cblock(length(p1)); 44: t1->type = UNSIGN; 45: *cp++ = t1; 46: return; 47: } 48: if (op!=AMPER) { 49: p1 = disarray(p1); 50: if (op!=CALL) 51: p1 = chkfun(p1); 52: } 53: t1 = p1->type; 54: pcvn = 0; 55: t = INT; 56: switch (op) { 57: 58: case CAST: 59: if ((t1&XTYPE)==FUNC || (t1&XTYPE)==ARRAY) 60: error("Disallowed conversion"); 61: if (t1==UNSIGN && t2==CHAR) { 62: t2 = INT; 63: p2 = block(AND,INT,NULL,NULL,p2,cblock(0377)); 64: } 65: break; 66: 67: /* end of expression */ 68: case 0: 69: *cp++ = p1; 70: return; 71: 72: /* no-conversion operators */ 73: case QUEST: 74: if (p2->op!=COLON) 75: error("Illegal conditional"); 76: else 77: if (fold(QUEST, p1, p2)) 78: return; 79: 80: case SEQNC: 81: t = t2; 82: 83: case COMMA: 84: case LOGAND: 85: case LOGOR: 86: *cp++ = block(op, t, NULL, NULL, p1, p2); 87: return; 88: 89: case EXCLA: 90: t1 = INT; 91: break; 92: 93: case CALL: 94: if ((t1&XTYPE) != FUNC) 95: error("Call of non-function"); 96: *cp++ = block(CALL,decref(t1),p1->subsp,p1->strp,p1,p2); 97: return; 98: 99: case STAR: 100: if ((t1&XTYPE) == FUNC) 101: error("Illegal indirection"); 102: *cp++ = block(STAR, decref(t1), p1->subsp, p1->strp, p1); 103: return; 104: 105: case AMPER: 106: if (p1->op==NAME || p1->op==STAR) { 107: *cp++ = block(op,incref(t1),p1->subsp,p1->strp,p1); 108: return; 109: } 110: error("Illegal lvalue"); 111: break; 112: 113: /* 114: * a.b goes to (&a)->b 115: */ 116: case DOT: 117: if (p1->op==CALL && t1==STRUCT) { 118: t1 = incref(t1); 119: setype(p1, t1, p1); 120: } else { 121: *cp++ = p1; 122: build(AMPER); 123: p1 = *--cp; 124: } 125: 126: /* 127: * In a->b, a is given the type ptr-to-structure element; 128: * then the offset is added in without conversion; 129: * then * is tacked on to access the member. 130: */ 131: case ARROW: 132: if (p2->op!=NAME || p2->tr1->hclass!=MOS) { 133: error("Illegal structure ref"); 134: *cp++ = p1; 135: return; 136: } 137: if (t2==INT && p2->tr1->hflag&FFIELD) 138: t2 = UNSIGN; 139: t = incref(t2); 140: chkw(p1, -1); 141: setype(p1, t, p2); 142: *cp++ = block(PLUS,t,p2->subsp,p2->strp,p1,cblock(p2->tr1->hoffset)); 143: build(STAR); 144: if (p2->tr1->hflag&FFIELD) 145: *cp++ = block(FSEL,UNSIGN,NULL,NULL,*--cp,p2->tr1->hstrp); 146: return; 147: } 148: if ((dope&LVALUE)!=0) 149: chklval(p1); 150: if ((dope&LWORD)!=0) 151: chkw(p1, LONG); 152: if ((dope&RWORD)!=0) 153: chkw(p2, LONG); 154: if ((dope&BINARY)==0) { 155: if (op==ITOF) 156: t1 = DOUBLE; 157: else if (op==FTOI) 158: t1 = INT; 159: if (!fold(op, p1, 0)) 160: *cp++ = block(op,t1,p1->subsp,p1->strp,p1); 161: return; 162: } 163: cvn = 0; 164: if (t1==STRUCT || t2==STRUCT) { 165: if (t1!=t2 || p1->strp != p2->strp) 166: error("Incompatible structures"); 167: cvn = 0; 168: } else 169: cvn = cvtab[lintyp(t1)][lintyp(t2)]; 170: leftc = (cvn>>4)&017; 171: cvn =& 017; 172: t = leftc? t2:t1; 173: if ((t==INT||t==CHAR) && (t1==UNSIGN||t2==UNSIGN)) 174: t = UNSIGN; 175: if (dope&ASSGOP || op==CAST) { 176: t = t1; 177: if (op==ASSIGN || op==CAST) { 178: if (cvn==ITP||cvn==PTI) 179: cvn = leftc = 0; 180: else if (cvn==LTP) { 181: if (leftc==0) 182: cvn = LTI; 183: else { 184: cvn = ITL; 185: leftc = 0; 186: } 187: } 188: } 189: if (leftc) 190: cvn = leftc; 191: leftc = 0; 192: } else if (op==COLON || op==MAX || op==MIN) { 193: if (t1>=PTR && t1==t2) 194: cvn = 0; 195: if (op!=COLON && (t1>=PTR || t2>=PTR)) 196: op =+ MAXP-MAX; 197: } else if (dope&RELAT) { 198: if (op>=LESSEQ && (t1>=PTR||t2>=PTR||(t1==UNSIGN||t2==UNSIGN) 199: && (t==INT||t==CHAR||t==UNSIGN))) 200: op =+ LESSEQP-LESSEQ; 201: if (cvn==ITP || cvn==PTI) 202: cvn = 0; 203: } 204: if (cvn==PTI) { 205: cvn = 0; 206: if (op==MINUS) { 207: t = INT; 208: pcvn++; 209: } else { 210: if (t1!=t2 || t1!=(PTR+CHAR)) 211: cvn = XX; 212: } 213: } 214: if (cvn) { 215: t1 = plength(p1); 216: t2 = plength(p2); 217: if (cvn==XX || (cvn==PTI&&t1!=t2)) 218: error("Illegal conversion"); 219: else if (leftc) 220: p1 = convert(p1, t, cvn, t2); 221: else 222: p2 = convert(p2, t, cvn, t1); 223: } 224: if (dope&RELAT) 225: t = INT; 226: if (t==FLOAT) 227: t = DOUBLE; 228: if (t==CHAR) 229: t = INT; 230: if (op==CAST) { 231: if (t!=DOUBLE && (t!=INT || p2->type!=CHAR)) { 232: p2->type = t; 233: p2->subsp = p1->subsp; 234: p2->strp = p1->strp; 235: } 236: if (t==INT && p1->type==CHAR) 237: p2 = block(ITOC, INT, NULL, NULL, p2); 238: *cp++ = p2; 239: return; 240: } 241: if (fold(op, p1, p2)==0) { 242: p3 = leftc?p2:p1; 243: *cp++ = block(op, t, p3->subsp, p3->strp, p1, p2); 244: } 245: if (pcvn && t1!=(PTR+CHAR)) { 246: p1 = *--cp; 247: *cp++ = convert(p1, 0, PTI, plength(p1->tr1)); 248: } 249: } 250: 251: /* 252: * Generate the appropriate conversion operator. 253: */ 254: struct tnode * 255: convert(p, t, cvn, len) 256: struct tnode *p; 257: { 258: register int op; 259: 260: op = cvntab[cvn]; 261: if (opdope[op]&BINARY) { 262: if (len==0) 263: error("Illegal conversion"); 264: return(block(op, t, NULL, NULL, p, cblock(len))); 265: } 266: return(block(op, t, NULL, NULL, p)); 267: } 268: 269: /* 270: * Traverse an expression tree, adjust things 271: * so the types of things in it are consistent 272: * with the view that its top node has 273: * type at. 274: * Used with structure references. 275: */ 276: setype(ap, at, anewp) 277: struct tnode *ap, *anewp; 278: { 279: register struct tnode *p, *newp; 280: register t; 281: 282: p = ap; 283: t = at; 284: newp = anewp; 285: for (;; p = p->tr1) { 286: p->subsp = newp->subsp; 287: p->strp = newp->strp; 288: p->type = t; 289: if (p->op==AMPER) 290: t = decref(t); 291: else if (p->op==STAR) 292: t = incref(t); 293: else if (p->op!=PLUS) 294: break; 295: } 296: } 297: 298: /* 299: * A mention of a function name is turned into 300: * a pointer to that function. 301: */ 302: struct tnode * 303: chkfun(ap) 304: struct tnode *ap; 305: { 306: register struct tnode *p; 307: register int t; 308: 309: p = ap; 310: if (((t = p->type)&XTYPE)==FUNC && p->op!=ETYPE) 311: return(block(AMPER,incref(t),p->subsp,p->strp,p)); 312: return(p); 313: } 314: 315: /* 316: * A mention of an array is turned into 317: * a pointer to the base of the array. 318: */ 319: struct tnode * 320: disarray(ap) 321: struct tnode *ap; 322: { 323: register int t; 324: register struct tnode *p; 325: 326: p = ap; 327: /* check array & not MOS and not typer */ 328: if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->tr1->hclass==MOS 329: || p->op==ETYPE) 330: return(p); 331: p->subsp++; 332: *cp++ = p; 333: setype(p, decref(t), p); 334: build(AMPER); 335: return(*--cp); 336: } 337: 338: /* 339: * make sure that p is a ptr to a node 340: * with type int or char or 'okt.' 341: * okt might be nonexistent or 'long' 342: * (e.g. for <<). 343: */ 344: chkw(p, okt) 345: struct tnode *p; 346: { 347: register int t; 348: 349: if ((t=p->type)!=INT && t<PTR && t!=CHAR && t!=UNSIGN && t!=okt) 350: error("Illegal type of operand"); 351: return; 352: } 353: 354: /* 355: *'linearize' a type for looking up in the 356: * conversion table 357: */ 358: lintyp(t) 359: { 360: switch(t) { 361: 362: case INT: 363: case CHAR: 364: case UNSIGN: 365: return(0); 366: 367: case FLOAT: 368: case DOUBLE: 369: return(1); 370: 371: case LONG: 372: return(2); 373: 374: default: 375: return(3); 376: } 377: } 378: 379: /* 380: * Report an error. 381: */ 382: error(s, p1, p2, p3, p4, p5, p6) 383: { 384: nerror++; 385: if (filename[0]) 386: fprintf(stderr, "%s:", filename); 387: fprintf(stderr, "%d: ", line); 388: fprintf(stderr, s, p1, p2, p3, p4, p5, p6); 389: fprintf(stderr, "\n"); 390: } 391: 392: /* 393: * Generate a node in an expression tree, 394: * setting the operator, type, dimen/struct table ptrs, 395: * and the operands. 396: */ 397: struct tnode * 398: block(op, t, subs, str, p1,p2) 399: int *subs; 400: struct str *str; 401: struct tnode *p1, *p2; 402: { 403: register struct tnode *p; 404: 405: p = gblock(sizeof(*p)); 406: p->op = op; 407: p->type = t; 408: p->subsp = subs; 409: p->strp = str; 410: p->tr1 = p1; 411: if (opdope[op]&BINARY) 412: p->tr2 = p2; 413: else 414: p->tr2 = NULL; 415: return(p); 416: } 417: 418: struct tnode * 419: nblock(ads) 420: struct hshtab *ads; 421: { 422: register struct hshtab *ds; 423: 424: ds = ads; 425: return(block(NAME, ds->htype, ds->hsubsp, ds->hstrp, ds)); 426: } 427: 428: /* 429: * Generate a block for a constant 430: */ 431: struct cnode * 432: cblock(v) 433: { 434: register struct cnode *p; 435: 436: p = gblock(sizeof(*p)); 437: p->op = CON; 438: p->type = INT; 439: p->subsp = NULL; 440: p->strp = NULL; 441: p->value = v; 442: return(p); 443: } 444: 445: /* 446: * A block for a float or long constant 447: */ 448: struct fnode * 449: fblock(t, string) 450: char *string; 451: { 452: register struct fnode *p; 453: 454: p = gblock(sizeof(*p)); 455: p->op = FCON; 456: p->type = t; 457: p->subsp = NULL; 458: p->strp = NULL; 459: p->cstr = string; 460: return(p); 461: } 462: 463: /* 464: * Assign a block for use in the 465: * expression tree. 466: */ 467: char * 468: gblock(n) 469: { 470: register int *p; 471: 472: p = curbase; 473: if ((curbase =+ n) >= coremax) { 474: if (sbrk(1024) == -1) { 475: error("Out of space"); 476: exit(1); 477: } 478: coremax =+ 1024; 479: } 480: return(p); 481: } 482: 483: /* 484: * Check that a tree can be used as an lvalue. 485: */ 486: chklval(ap) 487: struct tnode *ap; 488: { 489: register struct tnode *p; 490: 491: p = ap; 492: if (p->op==FSEL) 493: p = p->tr1; 494: if (p->op!=NAME && p->op!=STAR) 495: error("Lvalue required"); 496: } 497: 498: /* 499: * reduce some forms of `constant op constant' 500: * to a constant. More of this is done in the next pass 501: * but this is used to allow constant expressions 502: * to be used in switches and array bounds. 503: */ 504: fold(op, ap1, ap2) 505: struct tnode *ap1, *ap2; 506: { 507: register struct tnode *p1; 508: register int v1, v2; 509: int unsignf; 510: 511: p1 = ap1; 512: if (p1->op!=CON) 513: return(0); 514: unsignf = p1->type==UNSIGN; 515: if (op==QUEST) { 516: if (ap2->tr1->op==CON && ap2->tr2->op==CON) { 517: p1->value = p1->value? ap2->tr1->value: ap2->tr2->value; 518: *cp++ = p1; 519: return(1); 520: } 521: return(0); 522: } 523: if (ap2) { 524: if (ap2->op!=CON) 525: return(0); 526: v2 = ap2->value; 527: unsignf |= ap2->type==UNSIGN; 528: } 529: v1 = p1->value; 530: switch (op) { 531: 532: case PLUS: 533: v1 =+ v2; 534: break; 535: 536: case MINUS: 537: v1 =- v2; 538: break; 539: 540: case TIMES: 541: v1 =* v2; 542: break; 543: 544: case DIVIDE: 545: if (v2==0) 546: goto divchk; 547: if (unsignf) { 548: v1 = (unsigned)v1 / v2; 549: break; 550: } 551: v1 =/ v2; 552: break; 553: 554: case MOD: 555: if (v2==0) 556: goto divchk; 557: if (unsignf) { 558: v1 = (unsigned)v1 % v2; 559: break; 560: } 561: v1 =% v2; 562: break; 563: 564: case AND: 565: v1 =& v2; 566: break; 567: 568: case OR: 569: v1 =| v2; 570: break; 571: 572: case EXOR: 573: v1 =^ v2; 574: break; 575: 576: case NEG: 577: v1 = - v1; 578: break; 579: 580: case COMPL: 581: v1 = ~ v1; 582: break; 583: 584: case LSHIFT: 585: v1 =<< v2; 586: break; 587: 588: case RSHIFT: 589: if (unsignf) { 590: v1 = (unsigned)v1 >> v2; 591: break; 592: } 593: v1 =>> v2; 594: break; 595: 596: case EQUAL: 597: v1 = v1==v2; 598: break; 599: 600: case NEQUAL: 601: v1 = v1!=v2; 602: break; 603: 604: case LESS: 605: v1 = v1<v2; 606: break; 607: 608: case GREAT: 609: v1 = v1>v2; 610: break; 611: 612: case LESSEQ: 613: v1 = v1<=v2; 614: break; 615: 616: case GREATEQ: 617: v1 = v1>=v2; 618: break; 619: 620: divchk: 621: error("Divide check"); 622: default: 623: return(0); 624: } 625: p1->value = v1; 626: *cp++ = p1; 627: return(1); 628: } 629: 630: /* 631: * Compile an expression expected to have constant value, 632: * for example an array bound or a case value. 633: */ 634: conexp() 635: { 636: register struct tnode *t; 637: 638: initflg++; 639: if (t = tree()) 640: if (t->op != CON) 641: error("Constant required"); 642: initflg--; 643: curbase = funcbase; 644: return(t->value); 645: }