1: # 2: /* 3: * C compiler 4: * 5: * 6: */ 7: 8: #include "c0.h" 9: 10: /* 11: * Reduce the degree-of-reference by one. 12: * e.g. turn "ptr-to-int" into "int". 13: */ 14: decref(at) 15: { 16: register t; 17: 18: t = at; 19: if ((t & ~TYPE) == 0) { 20: error("Illegal indirection"); 21: return(t); 22: } 23: return((t>>TYLEN) & ~TYPE | t&TYPE); 24: } 25: 26: /* 27: * Increase the degree of reference by 28: * one; e.g. turn "int" to "ptr-to-int". 29: */ 30: incref(t) 31: { 32: return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR); 33: } 34: 35: /* 36: * Make a tree that causes a branch to lbl 37: * if the tree's value is non-zero together with the cond. 38: */ 39: cbranch(t, lbl, cond) 40: struct tnode *t; 41: { 42: treeout(t, 0); 43: outcode("BNNN", CBRANCH, lbl, cond, line); 44: } 45: 46: /* 47: * Write out a tree. 48: */ 49: rcexpr(atp) 50: struct tnode *atp; 51: { 52: register struct tnode *tp; 53: 54: /* 55: * Special optimization 56: */ 57: if ((tp=atp)->op==INIT && tp->tr1->op==CON) { 58: if (tp->type==CHAR) { 59: outcode("B1N0", BDATA, tp->tr1->value); 60: return; 61: } else if (tp->type==INT || tp->type==UNSIGN) { 62: outcode("BN", SINIT, tp->tr1->value); 63: return; 64: } 65: } 66: treeout(tp, 0); 67: outcode("BN", EXPR, line); 68: } 69: 70: treeout(atp, isstruct) 71: struct tnode *atp; 72: { 73: register struct tnode *tp; 74: register struct hshtab *hp; 75: register nextisstruct; 76: 77: if ((tp = atp) == 0) { 78: outcode("B", NULLOP); 79: return; 80: } 81: nextisstruct = tp->type==STRUCT; 82: switch(tp->op) { 83: 84: case NAME: 85: hp = tp->tr1; 86: if (hp->hclass==TYPEDEF) 87: error("Illegal use of type name"); 88: outcode("BNN", NAME, hp->hclass==0?STATIC:hp->hclass, tp->type); 89: if (hp->hclass==EXTERN) 90: outcode("S", hp->name); 91: else 92: outcode("N", hp->hoffset); 93: break; 94: 95: case LCON: 96: outcode("BNNN", tp->op, tp->type, tp->lvalue); 97: break; 98: 99: case CON: 100: outcode("BNN", tp->op, tp->type, tp->value); 101: break; 102: 103: case FCON: 104: outcode("BNF", tp->op, tp->type, tp->cstr); 105: break; 106: 107: case STRING: 108: outcode("BNNN", NAME, STATIC, tp->type, tp->tr1); 109: break; 110: 111: case FSEL: 112: treeout(tp->tr1, nextisstruct); 113: outcode("BNNN",tp->op,tp->type,tp->tr2->bitoffs,tp->tr2->flen); 114: break; 115: 116: case ETYPE: 117: error("Illegal use of type"); 118: break; 119: 120: case AMPER: 121: treeout(tp->tr1, 1); 122: outcode("BN", tp->op, tp->type); 123: break; 124: 125: 126: case CALL: 127: treeout(tp->tr1, 1); 128: treeout(tp->tr2, 0); 129: outcode("BN", CALL, tp->type); 130: break; 131: 132: default: 133: treeout(tp->tr1, nextisstruct); 134: if (opdope[tp->op]&BINARY) 135: treeout(tp->tr2, nextisstruct); 136: outcode("BN", tp->op, tp->type); 137: break; 138: } 139: if (nextisstruct && isstruct==0) 140: outcode("BNN", STRASG, STRUCT, tp->strp->ssize); 141: } 142: 143: /* 144: * Generate a branch 145: */ 146: branch(lab) 147: { 148: outcode("BN", BRANCH, lab); 149: } 150: 151: /* 152: * Generate a label 153: */ 154: label(l) 155: { 156: outcode("BN", LABEL, l); 157: } 158: 159: /* 160: * ap is a tree node whose type 161: * is some kind of pointer; return the size of the object 162: * to which the pointer points. 163: */ 164: plength(ap) 165: struct tname *ap; 166: { 167: register t, l; 168: register struct tnode *p; 169: 170: p = ap; 171: if (p==0 || ((t=p->type)&~TYPE) == 0) /* not a reference */ 172: return(1); 173: p->type = decref(t); 174: l = length(p); 175: p->type = t; 176: return(l); 177: } 178: 179: /* 180: * return the number of bytes in the object 181: * whose tree node is acs. 182: */ 183: length(acs) 184: struct tnode *acs; 185: { 186: register t, elsz; 187: long n; 188: register struct tnode *cs; 189: int nd; 190: 191: cs = acs; 192: t = cs->type; 193: n = 1; 194: nd = 0; 195: while ((t&XTYPE) == ARRAY) { 196: t = decref(t); 197: n =* cs->subsp[nd++]; 198: } 199: if ((t&~TYPE)==FUNC) 200: return(0); 201: if (t>=PTR) 202: elsz = SZPTR; 203: else switch(t&TYPE) { 204: 205: case INT: 206: case UNSIGN: 207: elsz = SZINT; 208: break; 209: 210: case CHAR: 211: elsz = 1; 212: break; 213: 214: case FLOAT: 215: elsz = SZFLOAT; 216: break; 217: 218: case LONG: 219: elsz = SZLONG; 220: break; 221: 222: case DOUBLE: 223: elsz = SZDOUB; 224: break; 225: 226: case STRUCT: 227: if ((elsz = cs->strp->ssize) == 0) 228: error("Undefined structure"); 229: break; 230: default: 231: error("Compiler error (length)"); 232: return(0); 233: } 234: n *= elsz; 235: if (n >= (unsigned)50000) { 236: error("Warning: very large data structure"); 237: nerror--; 238: } 239: return(n); 240: } 241: 242: /* 243: * The number of bytes in an object, rounded up to a word. 244: */ 245: rlength(cs) 246: struct tnode *cs; 247: { 248: return((length(cs)+ALIGN) & ~ALIGN); 249: } 250: 251: /* 252: * After an "if (...) goto", look to see if the transfer 253: * is to a simple label. 254: */ 255: simplegoto() 256: { 257: register struct hshtab *csp; 258: 259: if ((peeksym=symbol())==NAME && nextchar()==';') { 260: csp = csym; 261: if (csp->hblklev == 0) 262: pushdecl(csp); 263: if (csp->hclass==0 && csp->htype==0) { 264: csp->htype = ARRAY; 265: csp->hflag =| FLABL; 266: if (csp->hoffset==0) 267: csp->hoffset = isn++; 268: } 269: if ((csp->hclass==0||csp->hclass==STATIC) 270: && csp->htype==ARRAY) { 271: peeksym = -1; 272: return(csp->hoffset); 273: } 274: } 275: return(0); 276: } 277: 278: /* 279: * Return the next non-white-space character 280: */ 281: nextchar() 282: { 283: while (spnextchar()==' ') 284: peekc = 0; 285: return(peekc); 286: } 287: 288: /* 289: * Return the next character, translating all white space 290: * to blank and handling line-ends. 291: */ 292: spnextchar() 293: { 294: register c; 295: 296: if ((c = peekc)==0) 297: c = getchar(); 298: if (c=='\t' || c=='\014') /* FF */ 299: c = ' '; 300: else if (c=='\n') { 301: c = ' '; 302: if (inhdr==0) 303: line++; 304: inhdr = 0; 305: } else if (c=='\001') { /* SOH, insert marker */ 306: inhdr++; 307: c = ' '; 308: } 309: peekc = c; 310: return(c); 311: } 312: 313: /* 314: * is a break or continue legal? 315: */ 316: chconbrk(l) 317: { 318: if (l==0) 319: error("Break/continue error"); 320: } 321: 322: /* 323: * The goto statement. 324: */ 325: dogoto() 326: { 327: register struct tnode *np; 328: 329: *cp++ = tree(); 330: build(STAR); 331: chkw(np = *--cp, -1); 332: rcexpr(block(JUMP,0,NULL,NULL,np)); 333: } 334: 335: /* 336: * The return statement, which has to convert 337: * the returned object to the function's type. 338: */ 339: doret() 340: { 341: register struct tnode *t; 342: 343: if (nextchar() != ';') { 344: t = tree(); 345: *cp++ = &funcblk; 346: *cp++ = t; 347: build(ASSIGN); 348: cp[-1] = cp[-1]->tr2; 349: if (funcblk.type==CHAR) 350: cp[-1] = block(ITOC, INT, NULL, NULL, cp[-1]); 351: build(RFORCE); 352: rcexpr(*--cp); 353: } 354: branch(retlab); 355: } 356: 357: /* 358: * Write a character on the error output. 359: */ 360: /* 361: * Coded output: 362: * B: beginning of line; an operator 363: * N: a number 364: * S: a symbol (external) 365: * 1: number 1 366: * 0: number 0 367: */ 368: outcode(s, a) 369: char *s; 370: { 371: register *ap; 372: register FILE *bufp; 373: int n; 374: register char *np; 375: 376: bufp = stdout; 377: if (strflg) 378: bufp = sbufp; 379: ap = &a; 380: for (;;) switch(*s++) { 381: case 'B': 382: putc(*ap++, bufp); 383: putc(0376, bufp); 384: continue; 385: 386: case 'N': 387: putc(*ap, bufp); 388: putc(*ap++>>8, bufp); 389: continue; 390: 391: case 'F': 392: n = 1000; 393: np = *ap++; 394: goto str; 395: 396: case 'S': 397: n = NCPS; 398: np = *ap++; 399: if (*np) 400: putc('_', bufp); 401: str: 402: while (n-- && *np) { 403: putc(*np++&0177, bufp); 404: } 405: putc(0, bufp); 406: continue; 407: 408: case '1': 409: putc(1, bufp); 410: putc(0, bufp); 411: continue; 412: 413: case '0': 414: putc(0, bufp); 415: putc(0, bufp); 416: continue; 417: 418: case '\0': 419: if (ferror(bufp)) { 420: error("Write error on temp"); 421: exit(1); 422: } 423: return; 424: 425: default: 426: error("Botch in outcode"); 427: } 428: }