1: #
   2: /*
   3:  * C compiler
   4:  *
   5:  *
   6:  */
   7: 
   8: #include "c0h.c"
   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:     register int t1;
  19:     int t2, t3, t;
  20:     struct tnode *p3, *disarray();
  21:     register struct tnode *p1, *p2;
  22:     int d, dope, leftc, cvn, pcvn;
  23: 
  24:     /*
  25: 	 * a[i] => *(a+i)
  26: 	 */
  27:     if (op==LBRACK) {
  28:         build(PLUS);
  29:         op = STAR;
  30:     }
  31:     dope = opdope[op];
  32:     if ((dope&BINARY)!=0) {
  33:         p2 = chkfun(disarray(*--cp));
  34:         t2 = p2->type;
  35:     }
  36:     p1 = *--cp;
  37:     /*
  38: 	 * sizeof gets turned into a number here.
  39: 	 * Bug: sizeof(structure-member-array) is 2 because
  40: 	 * the array has been turned into a ptr already.
  41: 	 */
  42:     if (op==SIZEOF) {
  43:         t1 = length(p1);
  44:         p1->op = CON;
  45:         p1->type = INT;
  46:         p1->dimp = 0;
  47:         p1->value = t1;
  48:         *cp++ = p1;
  49:         return;
  50:     }
  51:     if (op!=AMPER) {
  52:         p1 = disarray(p1);
  53:         if (op!=CALL)
  54:             p1 = chkfun(p1);
  55:     }
  56:     t1 = p1->type;
  57:     pcvn = 0;
  58:     t = INT;
  59:     switch (op) {
  60: 
  61:     /* end of expression */
  62:     case 0:
  63:         *cp++ = p1;
  64:         return;
  65: 
  66:     /* no-conversion operators */
  67:     case QUEST:
  68:         if (p2->op!=COLON)
  69:             error("Illegal conditional");
  70:         t = t2;
  71: 
  72:     case COMMA:
  73:     case LOGAND:
  74:     case LOGOR:
  75:         *cp++ = block(2, op, t, 0, p1, p2);
  76:         return;
  77: 
  78:     case CALL:
  79:         if ((t1&XTYPE) != FUNC)
  80:             error("Call of non-function");
  81:         *cp++ = block(2,CALL,decref(t1),p1->dimp,p1,p2);
  82:         return;
  83: 
  84:     case STAR:
  85:         if (p1->op==AMPER ) {
  86:             *cp++ = p1->tr1;
  87:             return;
  88:         }
  89:         if ((t1&XTYPE) == FUNC)
  90:             error("Illegal indirection");
  91:         *cp++ = block(1,STAR,decref(t1),p1->dimp,p1);
  92:         return;
  93: 
  94:     case AMPER:
  95:         if (p1->op==STAR) {
  96:             p1->tr1->dimp = p1->dimp;
  97:             p1->tr1->type = incref(t1);
  98:             *cp++ = p1->tr1;
  99:             return;
 100:         }
 101:         if (p1->op==NAME) {
 102:             *cp++ = block(1,op,incref(t1),p1->dimp,p1);
 103:             return;
 104:         }
 105:         error("Illegal lvalue");
 106:         break;
 107: 
 108:     /*
 109: 	 * a->b goes to (*a).b
 110: 	 */
 111:     case ARROW:
 112:         *cp++ = p1;
 113:         chkw(p1, -1);
 114:         p1->type = PTR+STRUCT;
 115:         build(STAR);
 116:         p1 = *--cp;
 117: 
 118:     /*
 119: 	 * In a.b, a fairly complicated process has to
 120: 	 * be used to make the left operand look
 121: 	 * as if it had the type of the second.
 122: 	 * Also, the offset in the structure has to be
 123: 	 * given a special type to prevent conversion.
 124: 	 */
 125:     case DOT:
 126:         if (p2->op!=NAME || (p2->class!=MOS && p2->class!=FMOS))
 127:             error("Illegal structure ref");
 128:         *cp++ = p1;
 129:         t = t2;
 130:         if ((t&XTYPE) == ARRAY) {
 131:             t = decref(t);
 132:             p2->ssp++;
 133:         }
 134:         setype(p1, t, p2->dimp);
 135:         build(AMPER);
 136:         *cp++ = block(1,CON,NOTYPE,0,p2->nloc);
 137:         build(PLUS);
 138:         if ((t2&XTYPE) != ARRAY)
 139:             build(STAR);
 140:         if (p2->class == FMOS)
 141:             *cp++ = block(2, FSEL, t, 0, *--cp, p2->dimp);
 142:         return;
 143:     }
 144:     if ((dope&LVALUE)!=0)
 145:         chklval(p1);
 146:     if ((dope&LWORD)!=0)
 147:         chkw(p1, LONG);
 148:     if ((dope&RWORD)!=0)
 149:         chkw(p2, LONG);
 150:     if ((dope&BINARY)==0) {
 151:         if (op==ITOF)
 152:             t1 = DOUBLE;
 153:         else if (op==FTOI)
 154:             t1 = INT;
 155:         if (!fold(op, p1, 0))
 156:             *cp++ = block(1,op,t1,p1->dimp,p1);
 157:         return;
 158:     }
 159:     cvn = 0;
 160:     if (t1==STRUCT || t2==STRUCT) {
 161:         error("Unimplemented structure operation");
 162:         t1 = t2 = INT;
 163:     }
 164:     if (t2==NOTYPE) {
 165:         t = t1;
 166:         p2->type = INT; /* no int cv for struct */
 167:         t2 = INT;
 168:     } else
 169:         cvn = cvtab[lintyp(t1)][lintyp(t2)];
 170:     leftc = (cvn>>4)&017;
 171:     cvn =& 017;
 172:     t = leftc? t2:t1;
 173:     if (dope&ASSGOP) {
 174:         t = t1;
 175:         if (op==ASSIGN && (cvn==ITP||cvn==PTI))
 176:             cvn = leftc = 0;
 177:         if (leftc)
 178:             cvn = leftc;
 179:         leftc = 0;
 180:     } else if (op==COLON && t1>=PTR && t1==t2)
 181:         cvn = 0;
 182:     else if (dope&RELAT) {
 183:         if (op>=LESSEQ && (t1>=PTR || t2>=PTR))
 184:             op =+ LESSEQP-LESSEQ;
 185:         if (cvn==PTI)
 186:             cvn = 0;
 187:     }
 188:     if (cvn==PTI) {
 189:         cvn = 0;
 190:         if (op==MINUS) {
 191:             t = INT;
 192:             pcvn++;
 193:         } else {
 194:             if (t1!=t2 || t1!=(PTR+CHAR))
 195:                 cvn = XX;
 196:         }
 197:     }
 198:     if (cvn) {
 199:         t1 = plength(p1);
 200:         t2 = plength(p2);
 201:         if (cvn==XX || (cvn==PTI&&t1!=t2))
 202:             error("Illegal conversion");
 203:         else if (leftc)
 204:             p1 = convert(p1, t, cvn, t2);
 205:         else
 206:             p2 = convert(p2, t, cvn, t1);
 207:     }
 208:     if (dope&RELAT)
 209:         t = INT;
 210:     if (fold(op, p1, p2)==0)
 211:         *cp++ = block(2,op,t,(p1->dimp==0? p2:p1)->dimp,p1,p2);
 212:     if (pcvn && t1!=(PTR+CHAR)) {
 213:         p1 = *--cp;
 214:         *cp++ = convert(p1, 0, PTI, plength(p1->tr1));
 215:     }
 216: }
 217: 
 218: /*
 219:  * Generate the appropirate conversion operator.
 220:  * For pointer <=> integer this is a multiplication
 221:  * or division, otherwise a special operator.
 222:  */
 223: convert(p, t, cvn, len)
 224: struct tnode *p;
 225: {
 226:     register int n;
 227: 
 228:     switch(cvn) {
 229: 
 230:     case PTI:
 231:     case ITP:
 232:         if (len==1)
 233:             return(p);
 234:         return(block(2, (cvn==PTI?DIVIDE:TIMES), t, 0, p,
 235:             block(1, CON, 0, 0, len)));
 236: 
 237:     case ITF:
 238:         n = ITOF;
 239:         break;
 240:     case FTI:
 241:         n = FTOI;
 242:         break;
 243:     case ITL:
 244:         n = ITOL;
 245:         break;
 246:     case LTI:
 247:         n = LTOI;
 248:         break;
 249:     case FTL:
 250:         n = FTOL;
 251:         break;
 252:     case LTF:
 253:         n = LTOF;
 254:         break;
 255:     }
 256:     return(block(1, n, t, 0, p));
 257: }
 258: 
 259: /*
 260:  * Traverse an expression tree, adjust things
 261:  * so the types of things in it are consistent
 262:  * with the view that its top node has
 263:  * type at.
 264:  * Used with structure references.
 265:  */
 266: setype(ap, at, adimptr)
 267: struct tnode *ap;
 268: {
 269:     register struct tnode *p;
 270:     register t, dimptr;
 271: 
 272:     p = ap;
 273:     t = at;
 274:     dimptr = adimptr;
 275:     p->type = t;
 276:     if (dimptr != -1)
 277:         p->dimp = dimptr;
 278:     switch(p->op) {
 279: 
 280:     case AMPER:
 281:         setype(p->tr1, decref(t), dimptr);
 282:         return;
 283: 
 284:     case STAR:
 285:         setype(p->tr1, incref(t), dimptr);
 286:         return;
 287: 
 288:     case PLUS:
 289:     case MINUS:
 290:         setype(p->tr1, t, dimptr);
 291:     }
 292: }
 293: 
 294: /*
 295:  * A mention of a function name is turned into
 296:  * a pointer to that function.
 297:  */
 298: chkfun(ap)
 299: struct tnode *ap;
 300: {
 301:     register struct tnode *p;
 302:     register int t;
 303: 
 304:     p = ap;
 305:     if (((t = p->type)&XTYPE)==FUNC)
 306:         return(block(1,AMPER,incref(t),p->dimp,p));
 307:     return(p);
 308: }
 309: 
 310: /*
 311:  * A mention of an array is turned into
 312:  * a pointer to the base of the array.
 313:  */
 314: struct tnode *disarray(ap)
 315: struct tnode *ap;
 316: {
 317:     register int t;
 318:     register struct tnode *p;
 319: 
 320:     p = ap;
 321:     /* check array & not MOS */
 322:     if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->class==MOS)
 323:         return(p);
 324:     p->ssp++;
 325:     *cp++ = p;
 326:     setype(p, decref(t), -1);
 327:     build(AMPER);
 328:     return(*--cp);
 329: }
 330: 
 331: /*
 332:  * make sure that p is a ptr to a node
 333:  * with type int or char or 'okt.'
 334:  * okt might be nonexistent or 'long'
 335:  * (e.g. for <<).
 336:  */
 337: chkw(p, okt)
 338: struct tnode *p;
 339: {
 340:     register int t;
 341: 
 342:     if ((t=p->type)>CHAR && t<PTR && t!=okt)
 343:         error("Integer operand required");
 344:     return;
 345: }
 346: 
 347: /*
 348:  *'linearize' a type for looking up in the
 349:  * conversion table
 350:  */
 351: lintyp(t)
 352: {
 353:     switch(t) {
 354: 
 355:     case INT:
 356:     case CHAR:
 357:         return(0);
 358: 
 359:     case FLOAT:
 360:     case DOUBLE:
 361:         return(1);
 362: 
 363:     case LONG:
 364:         return(2);
 365: 
 366:     default:
 367:         return(3);
 368:     }
 369: }
 370: 
 371: /*
 372:  * Report an error.
 373:  */
 374: error(s, p1, p2, p3, p4, p5, p6)
 375: {
 376:     nerror++;
 377:     printf("%d: ", line);
 378:     printf(s, p1, p2, p3, p4, p5, p6);
 379:     printf("\n");
 380: }
 381: 
 382: /*
 383:  * Generate a node in an expression tree,
 384:  * setting the operator, type, degree (unused in this pass)
 385:  * and the operands.
 386:  */
 387: block(an, op, t, d, p1,p2,p3)
 388: int *p1, *p2, *p3;
 389: {
 390:     register int *ap, *p, n;
 391:     int *oldp;
 392: 
 393:     n = an+3;
 394:     p = gblock(n);
 395:     oldp = p;
 396:     ap = &op;
 397:     do {
 398:         *p++ = *ap++;
 399:     } while (--n);
 400:     return(oldp);
 401: }
 402: 
 403: /*
 404:  * Assign an unitialized block for use in the
 405:  * expression tree.
 406:  */
 407: gblock(n)
 408: {
 409:     register int *p;
 410: 
 411:     p = space;
 412:     if ((space =+ n) >= &osspace[OSSIZ]) {
 413:         error("Expression overflow");
 414:         exit(1);
 415:     }
 416:     return(p);
 417: }
 418: 
 419: /*
 420:  * Check that a tree can be used as an lvalue.
 421:  */
 422: chklval(ap)
 423: struct tnode *ap;
 424: {
 425:     register struct tnode *p;
 426: 
 427:     p = ap;
 428:     if (p->op!=NAME && p->op!=STAR)
 429:         error("Lvalue required");
 430: }
 431: 
 432: /*
 433:  * reduce some forms of `constant op constant'
 434:  * to a constant.  More of this is done in the next pass
 435:  * but this is used to allow constant expressions
 436:  * to be used in switches and array bounds.
 437:  */
 438: fold(op, ap1, ap2)
 439: struct tnode *ap1, *ap2;
 440: {
 441:     register struct tnode *p1;
 442:     register int v1, v2;
 443: 
 444:     p1 = ap1;
 445:     if (p1->op!=CON || (ap2!=0 && ap2->op!=CON))
 446:         return(0);
 447:     v1 = p1->value;
 448:     v2 = ap2->value;
 449:     switch (op) {
 450: 
 451:     case PLUS:
 452:         v1 =+ v2;
 453:         break;
 454: 
 455:     case MINUS:
 456:         v1 =- v2;
 457:         break;
 458: 
 459:     case TIMES:
 460:         v1 =* v2;
 461:         break;
 462: 
 463:     case DIVIDE:
 464:         v1 =/ v2;
 465:         break;
 466: 
 467:     case MOD:
 468:         v1 =% v2;
 469:         break;
 470: 
 471:     case AND:
 472:         v1 =& v2;
 473:         break;
 474: 
 475:     case OR:
 476:         v1 =| v2;
 477:         break;
 478: 
 479:     case EXOR:
 480:         v1 =^ v2;
 481:         break;
 482: 
 483:     case NEG:
 484:         v1 = - v1;
 485:         break;
 486: 
 487:     case COMPL:
 488:         v1 = ~ v1;
 489:         break;
 490: 
 491:     case LSHIFT:
 492:         v1 =<< v2;
 493:         break;
 494: 
 495:     case RSHIFT:
 496:         v1 =>> v2;
 497:         break;
 498: 
 499:     default:
 500:         return(0);
 501:     }
 502:     p1->value = v1;
 503:     *cp++ = p1;
 504:     return(1);
 505: }
 506: 
 507: /*
 508:  * Compile an expression expected to have constant value,
 509:  * for example an array bound or a case value.
 510:  */
 511: conexp()
 512: {
 513:     register struct tnode *t;
 514: 
 515:     initflg++;
 516:     if (t = tree())
 517:         if (t->op != CON)
 518:             error("Constant required");
 519:     initflg--;
 520:     return(t->value);
 521: }

Defined functions

block defined in line 387; used 31 times
build defined in line 17; used 13 times
chkfun defined in line 298; used 2 times
chklval defined in line 422; used 1 times
chkw defined in line 337; used 5 times
conexp defined in line 511; used 4 times
convert defined in line 223; used 3 times
disarray defined in line 314; used 3 times
error defined in line 374; used 72 times
fold defined in line 438; used 2 times
gblock defined in line 407; used 3 times
lintyp defined in line 351; used 2 times
  • in line 169(2)
setype defined in line 266; used 5 times
Last modified: 1975-07-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 992
Valid CSS Valid XHTML 1.0 Strict