|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)stat.c 1.12 9/5/83"; ! 4: ! 5: #include "whoami.h" ! 6: #include "0.h" ! 7: #include "tree.h" ! 8: #include "objfmt.h" ! 9: #ifdef PC ! 10: # include "pcops.h" ! 11: # include "pc.h" ! 12: #endif PC ! 13: #include "tmps.h" ! 14: ! 15: int cntstat; ! 16: short cnts = 3; ! 17: #include "opcode.h" ! 18: ! 19: /* ! 20: * Statement list ! 21: */ ! 22: statlist(r) ! 23: int *r; ! 24: { ! 25: register *sl; ! 26: ! 27: for (sl=r; sl != NIL; sl=sl[2]) ! 28: statement(sl[1]); ! 29: } ! 30: ! 31: /* ! 32: * Statement ! 33: */ ! 34: statement(r) ! 35: int *r; ! 36: { ! 37: register *s; ! 38: register struct nl *snlp; ! 39: struct tmps soffset; ! 40: ! 41: s = r; ! 42: snlp = nlp; ! 43: soffset = sizes[cbn].curtmps; ! 44: top: ! 45: if (cntstat) { ! 46: cntstat = 0; ! 47: putcnt(); ! 48: } ! 49: if (s == NIL) ! 50: return; ! 51: line = s[1]; ! 52: if (s[0] == T_LABEL) { ! 53: labeled(s[2]); ! 54: s = s[3]; ! 55: noreach = 0; ! 56: cntstat = 1; ! 57: goto top; ! 58: } ! 59: if (noreach) { ! 60: noreach = 0; ! 61: warning(); ! 62: error("Unreachable statement"); ! 63: } ! 64: switch (s[0]) { ! 65: case T_PCALL: ! 66: putline(); ! 67: # ifdef OBJ ! 68: proc(s); ! 69: # endif OBJ ! 70: # ifdef PC ! 71: pcproc( s ); ! 72: # endif PC ! 73: break; ! 74: case T_ASGN: ! 75: putline(); ! 76: asgnop(s); ! 77: break; ! 78: case T_GOTO: ! 79: putline(); ! 80: gotoop(s[2]); ! 81: noreach = 1; ! 82: cntstat = 1; ! 83: break; ! 84: default: ! 85: level++; ! 86: switch (s[0]) { ! 87: default: ! 88: panic("stat"); ! 89: case T_IF: ! 90: case T_IFEL: ! 91: ifop(s); ! 92: break; ! 93: case T_WHILE: ! 94: whilop(s); ! 95: noreach = 0; ! 96: break; ! 97: case T_REPEAT: ! 98: repop(s); ! 99: break; ! 100: case T_FORU: ! 101: case T_FORD: ! 102: forop(s); ! 103: noreach = 0; ! 104: break; ! 105: case T_BLOCK: ! 106: statlist(s[2]); ! 107: break; ! 108: case T_CASE: ! 109: putline(); ! 110: # ifdef OBJ ! 111: caseop(s); ! 112: # endif OBJ ! 113: # ifdef PC ! 114: pccaseop( s ); ! 115: # endif PC ! 116: break; ! 117: case T_WITH: ! 118: withop(s); ! 119: break; ! 120: } ! 121: --level; ! 122: if (gotos[cbn]) ! 123: ungoto(); ! 124: break; ! 125: } ! 126: /* ! 127: * Free the temporary name list entries defined in ! 128: * expressions, e.g. STRs, and WITHPTRs from withs. ! 129: */ ! 130: nlfree(snlp); ! 131: /* ! 132: * free any temporaries allocated for this statement ! 133: * these come from strings and sets. ! 134: */ ! 135: tmpfree(&soffset); ! 136: } ! 137: ! 138: ungoto() ! 139: { ! 140: register struct nl *p; ! 141: ! 142: for (p = gotos[cbn]; p != NIL; p = p->chain) ! 143: if ((p->nl_flags & NFORWD) != 0) { ! 144: if (p->value[NL_GOLEV] != NOTYET) ! 145: if (p->value[NL_GOLEV] > level) ! 146: p->value[NL_GOLEV] = level; ! 147: } else ! 148: if (p->value[NL_GOLEV] != DEAD) ! 149: if (p->value[NL_GOLEV] > level) ! 150: p->value[NL_GOLEV] = DEAD; ! 151: } ! 152: ! 153: putcnt() ! 154: { ! 155: ! 156: if (monflg == 0) { ! 157: return; ! 158: } ! 159: inccnt( getcnt() ); ! 160: } ! 161: ! 162: int ! 163: getcnt() ! 164: { ! 165: ! 166: return ++cnts; ! 167: } ! 168: ! 169: inccnt( counter ) ! 170: int counter; ! 171: { ! 172: ! 173: # ifdef OBJ ! 174: put(2, O_COUNT, counter ); ! 175: # endif OBJ ! 176: # ifdef PC ! 177: putRV( PCPCOUNT , 0 , counter * sizeof (long) , NGLOBAL , P2INT ); ! 178: putleaf( P2ICON , 1 , 0 , P2INT , 0 ); ! 179: putop( P2ASG P2PLUS , P2INT ); ! 180: putdot( filename , line ); ! 181: # endif PC ! 182: } ! 183: ! 184: putline() ! 185: { ! 186: ! 187: # ifdef OBJ ! 188: if (opt('p') != 0) ! 189: put(2, O_LINO, line); ! 190: ! 191: /* ! 192: * put out line number information for pdx ! 193: */ ! 194: lineno(line); ! 195: ! 196: # endif OBJ ! 197: # ifdef PC ! 198: static lastline; ! 199: ! 200: if ( line != lastline ) { ! 201: stabline( line ); ! 202: lastline = line; ! 203: } ! 204: if ( opt( 'p' ) ) { ! 205: if ( opt('t') ) { ! 206: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 207: , "_LINO" ); ! 208: putop( P2UNARY P2CALL , P2INT ); ! 209: putdot( filename , line ); ! 210: } else { ! 211: putRV( STMTCOUNT , 0 , 0 , NGLOBAL , P2INT ); ! 212: putleaf( P2ICON , 1 , 0 , P2INT , 0 ); ! 213: putop( P2ASG P2PLUS , P2INT ); ! 214: putdot( filename , line ); ! 215: } ! 216: } ! 217: # endif PC ! 218: } ! 219: ! 220: /* ! 221: * With varlist do stat ! 222: * ! 223: * With statement requires an extra word ! 224: * in automatic storage for each level of withing. ! 225: * These indirect pointers are initialized here, and ! 226: * the scoping effect of the with statement occurs ! 227: * because lookup examines the field names of the records ! 228: * associated with the WITHPTRs on the withlist. ! 229: */ ! 230: withop(s) ! 231: int *s; ! 232: { ! 233: register *p; ! 234: register struct nl *r; ! 235: struct nl *tempnlp; ! 236: int *swl; ! 237: ! 238: putline(); ! 239: swl = withlist; ! 240: for (p = s[2]; p != NIL; p = p[2]) { ! 241: /* ! 242: * no one uses the allocated temporary namelist entry, ! 243: * since we have to use it before we know its type; ! 244: * but we use its runtime location for the with pointer. ! 245: */ ! 246: tempnlp = tmpalloc(sizeof(int *), nl + TPTR, REGOK); ! 247: # ifdef OBJ ! 248: put(2, O_LV | cbn <<8+INDX, tempnlp -> value[ NL_OFFS ] ); ! 249: # endif OBJ ! 250: # ifdef PC ! 251: putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , ! 252: tempnlp -> extra_flags , P2PTR|P2STRTY ); ! 253: # endif PC ! 254: r = lvalue(p[1], MOD , LREQ ); ! 255: if (r == NIL) ! 256: continue; ! 257: if (r->class != RECORD) { ! 258: error("Variable in with statement refers to %s, not to a record", nameof(r)); ! 259: continue; ! 260: } ! 261: r = defnl(0, WITHPTR, r, tempnlp -> value[ NL_OFFS ] ); ! 262: # ifdef PC ! 263: r -> extra_flags |= tempnlp -> extra_flags; ! 264: # endif PC ! 265: r->nl_next = withlist; ! 266: withlist = r; ! 267: # ifdef OBJ ! 268: put(1, PTR_AS); ! 269: # endif OBJ ! 270: # ifdef PC ! 271: putop( P2ASSIGN , P2PTR|P2STRTY ); ! 272: putdot( filename , line ); ! 273: # endif PC ! 274: } ! 275: statement(s[3]); ! 276: withlist = swl; ! 277: } ! 278: ! 279: extern flagwas; ! 280: /* ! 281: * var := expr ! 282: */ ! 283: asgnop(r) ! 284: int *r; ! 285: { ! 286: register struct nl *p; ! 287: register *av; ! 288: ! 289: if (r == NIL) ! 290: return (NIL); ! 291: /* ! 292: * Asgnop's only function is ! 293: * to handle function variable ! 294: * assignments. All other assignment ! 295: * stuff is handled by asgnop1. ! 296: * the if below checks for unqualified lefthandside: ! 297: * necessary for fvars. ! 298: */ ! 299: av = r[2]; ! 300: if (av != NIL && av[0] == T_VAR && av[3] == NIL) { ! 301: p = lookup1(av[2]); ! 302: if (p != NIL) ! 303: p->nl_flags = flagwas; ! 304: if (p != NIL && p->class == FVAR) { ! 305: /* ! 306: * Give asgnop1 the func ! 307: * which is the chain of ! 308: * the FVAR. ! 309: */ ! 310: p->nl_flags |= NUSED|NMOD; ! 311: p = p->chain; ! 312: if (p == NIL) { ! 313: rvalue(r[3], NIL , RREQ ); ! 314: return; ! 315: } ! 316: # ifdef OBJ ! 317: put(2, O_LV | bn << 8+INDX, (int)p->value[NL_OFFS]); ! 318: if (isa(p->type, "i") && width(p->type) == 1) ! 319: asgnop1(r, nl+T2INT); ! 320: else ! 321: asgnop1(r, p->type); ! 322: # endif OBJ ! 323: # ifdef PC ! 324: /* ! 325: * this should be the lvalue of the fvar, ! 326: * but since the second pass knows to use ! 327: * the address of the left operand of an ! 328: * assignment, what i want here is an rvalue. ! 329: * see note in funchdr about fvar allocation. ! 330: */ ! 331: p = p -> ptr[ NL_FVAR ]; ! 332: putRV( p -> symbol , bn , p -> value[ NL_OFFS ] , ! 333: p -> extra_flags , p2type( p -> type ) ); ! 334: asgnop1( r , p -> type ); ! 335: # endif PC ! 336: return; ! 337: } ! 338: } ! 339: asgnop1(r, NIL); ! 340: } ! 341: ! 342: /* ! 343: * Asgnop1 handles all assignments. ! 344: * If p is not nil then we are assigning ! 345: * to a function variable, otherwise ! 346: * we look the variable up ourselves. ! 347: */ ! 348: struct nl * ! 349: asgnop1(r, p) ! 350: int *r; ! 351: register struct nl *p; ! 352: { ! 353: register struct nl *p1; ! 354: int w; ! 355: ! 356: if (r == NIL) ! 357: return (NIL); ! 358: if (p == NIL) { ! 359: # ifdef OBJ ! 360: p = lvalue(r[2], MOD|ASGN|NOUSE , LREQ ); ! 361: w = width(p); ! 362: # endif OBJ ! 363: # ifdef PC ! 364: /* ! 365: * since the second pass knows that it should reference ! 366: * the lefthandside of asignments, what i need here is ! 367: * an rvalue. ! 368: */ ! 369: p = lvalue( r[2] , MOD|ASGN|NOUSE , RREQ ); ! 370: # endif PC ! 371: if ( p == NIL ) { ! 372: rvalue( r[3] , NIL , RREQ ); ! 373: return NIL; ! 374: } ! 375: } ! 376: # ifdef OBJ ! 377: /* ! 378: * assigning to the return value, which is at least ! 379: * of width two since it resides on the stack ! 380: */ ! 381: else { ! 382: w = width(p); ! 383: if (w < 2) ! 384: w = 2; ! 385: } ! 386: p1 = rvalue(r[3], p , RREQ ); ! 387: # endif OBJ ! 388: # ifdef PC ! 389: /* ! 390: * if this is a scalar assignment, ! 391: * then i want to rvalue the righthandside. ! 392: * if this is a structure assignment, ! 393: * then i want an lvalue to the righthandside. ! 394: * that's what the intermediate form sez. ! 395: */ ! 396: switch ( classify( p ) ) { ! 397: case TINT: ! 398: case TCHAR: ! 399: case TBOOL: ! 400: case TSCAL: ! 401: precheck( p , "_RANG4" , "_RSNG4" ); ! 402: case TDOUBLE: ! 403: case TPTR: ! 404: p1 = rvalue( r[3] , p , RREQ ); ! 405: break; ! 406: default: ! 407: p1 = rvalue( r[3] , p , LREQ ); ! 408: break; ! 409: } ! 410: # endif PC ! 411: if (p1 == NIL) ! 412: return (NIL); ! 413: if (incompat(p1, p, r[3])) { ! 414: cerror("Type of expression clashed with type of variable in assignment"); ! 415: return (NIL); ! 416: } ! 417: # ifdef OBJ ! 418: switch (classify(p)) { ! 419: case TINT: ! 420: case TBOOL: ! 421: case TCHAR: ! 422: case TSCAL: ! 423: rangechk(p, p1); ! 424: gen(O_AS2, O_AS2, w, width(p1)); ! 425: break; ! 426: case TDOUBLE: ! 427: case TPTR: ! 428: gen(O_AS2, O_AS2, w, width(p1)); ! 429: break; ! 430: default: ! 431: put(2, O_AS, w); ! 432: break; ! 433: } ! 434: # endif OBJ ! 435: # ifdef PC ! 436: switch (classify(p)) { ! 437: case TINT: ! 438: case TBOOL: ! 439: case TCHAR: ! 440: case TSCAL: ! 441: postcheck(p, p1); ! 442: sconv(p2type(p1), p2type(p)); ! 443: putop( P2ASSIGN , p2type( p ) ); ! 444: putdot( filename , line ); ! 445: break; ! 446: case TPTR: ! 447: putop( P2ASSIGN , p2type( p ) ); ! 448: putdot( filename , line ); ! 449: break; ! 450: case TDOUBLE: ! 451: sconv(p2type(p1), p2type(p)); ! 452: putop( P2ASSIGN , p2type( p ) ); ! 453: putdot( filename , line ); ! 454: break; ! 455: default: ! 456: putstrop(P2STASG, ADDTYPE(p2type(p), P2PTR), ! 457: lwidth(p), align(p)); ! 458: putdot( filename , line ); ! 459: break; ! 460: } ! 461: # endif PC ! 462: return (p); /* Used by for statement */ ! 463: } ! 464: ! 465: /* ! 466: * if expr then stat [ else stat ] ! 467: */ ! 468: ifop(r) ! 469: int *r; ! 470: { ! 471: register struct nl *p; ! 472: register l1, l2; /* l1 is start of else, l2 is end of else */ ! 473: int goc; ! 474: bool nr; ! 475: ! 476: goc = gocnt; ! 477: if (r == NIL) ! 478: return; ! 479: putline(); ! 480: p = rvalue(r[2], NIL , RREQ ); ! 481: if (p == NIL) { ! 482: statement(r[3]); ! 483: noreach = 0; ! 484: statement(r[4]); ! 485: noreach = 0; ! 486: return; ! 487: } ! 488: if (isnta(p, "b")) { ! 489: error("Type of expression in if statement must be Boolean, not %s", nameof(p)); ! 490: statement(r[3]); ! 491: noreach = 0; ! 492: statement(r[4]); ! 493: noreach = 0; ! 494: return; ! 495: } ! 496: # ifdef OBJ ! 497: l1 = put(2, O_IF, getlab()); ! 498: # endif OBJ ! 499: # ifdef PC ! 500: l1 = getlab(); ! 501: putleaf( P2ICON , l1 , 0 , P2INT , 0 ); ! 502: putop( P2CBRANCH , P2INT ); ! 503: putdot( filename , line ); ! 504: # endif PC ! 505: putcnt(); ! 506: statement(r[3]); ! 507: nr = noreach; ! 508: if (r[4] != NIL) { ! 509: /* ! 510: * else stat ! 511: */ ! 512: --level; ! 513: ungoto(); ! 514: ++level; ! 515: # ifdef OBJ ! 516: l2 = put(2, O_TRA, getlab()); ! 517: # endif OBJ ! 518: # ifdef PC ! 519: l2 = getlab(); ! 520: putjbr( l2 ); ! 521: # endif PC ! 522: patch(l1); ! 523: noreach = 0; ! 524: statement(r[4]); ! 525: noreach = (noreach && nr); ! 526: l1 = l2; ! 527: } else ! 528: noreach = 0; ! 529: patch(l1); ! 530: if (goc != gocnt) ! 531: putcnt(); ! 532: } ! 533: ! 534: /* ! 535: * while expr do stat ! 536: */ ! 537: whilop(r) ! 538: int *r; ! 539: { ! 540: register struct nl *p; ! 541: register l1, l2; ! 542: int goc; ! 543: ! 544: goc = gocnt; ! 545: if (r == NIL) ! 546: return; ! 547: putlab(l1 = getlab()); ! 548: putline(); ! 549: p = rvalue(r[2], NIL , RREQ ); ! 550: if (p == NIL) { ! 551: statement(r[3]); ! 552: noreach = 0; ! 553: return; ! 554: } ! 555: if (isnta(p, "b")) { ! 556: error("Type of expression in while statement must be Boolean, not %s", nameof(p)); ! 557: statement(r[3]); ! 558: noreach = 0; ! 559: return; ! 560: } ! 561: l2 = getlab(); ! 562: # ifdef OBJ ! 563: put(2, O_IF, l2); ! 564: # endif OBJ ! 565: # ifdef PC ! 566: putleaf( P2ICON , l2 , 0 , P2INT , 0 ); ! 567: putop( P2CBRANCH , P2INT ); ! 568: putdot( filename , line ); ! 569: # endif PC ! 570: putcnt(); ! 571: statement(r[3]); ! 572: # ifdef OBJ ! 573: put(2, O_TRA, l1); ! 574: # endif OBJ ! 575: # ifdef PC ! 576: putjbr( l1 ); ! 577: # endif PC ! 578: patch(l2); ! 579: if (goc != gocnt) ! 580: putcnt(); ! 581: } ! 582: ! 583: /* ! 584: * repeat stat* until expr ! 585: */ ! 586: repop(r) ! 587: int *r; ! 588: { ! 589: register struct nl *p; ! 590: register l; ! 591: int goc; ! 592: ! 593: goc = gocnt; ! 594: if (r == NIL) ! 595: return; ! 596: l = putlab(getlab()); ! 597: putcnt(); ! 598: statlist(r[2]); ! 599: line = r[1]; ! 600: p = rvalue(r[3], NIL , RREQ ); ! 601: if (p == NIL) ! 602: return; ! 603: if (isnta(p,"b")) { ! 604: error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p)); ! 605: return; ! 606: } ! 607: # ifdef OBJ ! 608: put(2, O_IF, l); ! 609: # endif OBJ ! 610: # ifdef PC ! 611: putleaf( P2ICON , l , 0 , P2INT , 0 ); ! 612: putop( P2CBRANCH , P2INT ); ! 613: putdot( filename , line ); ! 614: # endif PC ! 615: if (goc != gocnt) ! 616: putcnt(); ! 617: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.