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