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