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