|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)bb.c 5.2 (Berkeley) 3/9/86"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * bb.c ! 13: * ! 14: * Basic block optimizations. ! 15: * ! 16: * University of Utah CS Dept modification history: ! 17: * ! 18: * $Log: bb.c,v $ ! 19: * Revision 5.2 86/03/09 18:13:56 donn ! 20: * In tempalloc(), don't forget to treat the vleng tree of a temp block ! 21: * before allocating it with altmpn. ! 22: * ! 23: * Revision 2.1 84/07/19 12:01:20 donn ! 24: * Changed comment headers for UofU. ! 25: * ! 26: * Revision 1.2 84/04/02 14:22:49 donn ! 27: * Bug in copy propagation missed places where temporaries are assigned to ! 28: * by OPSTAREQ or OPPLUSEQ, e.g. exponentiation with an integer constant ! 29: * power, expanded inline. ! 30: * ! 31: */ ! 32: ! 33: #include "defs.h" ! 34: #include "optim.h" ! 35: ! 36: /* ! 37: * This file contains code for determination of basic blocks, ! 38: * as well as some other optimization supporting routines ! 39: * [including the main routine 'optimize()']. ! 40: * ! 41: * The compiler's general debugging flag ['debugflag'] has been ! 42: * extended to provide the capability of having multiple flags ! 43: * which are contained in an array. If the option -d is used, ! 44: * then the flag debugflag[0] is set. If a sequence of one or more ! 45: * numbers are given (e.g, -d3,7,12), then the flags debugflag[3], ! 46: * debugflag[7], and debugflag[12] are set. The maximum number of ! 47: * flags available is specified in the defines.h file. ! 48: */ ! 49: ! 50: ! 51: Bblockp firstblock = NULL; /* first block in buffer */ ! 52: Bblockp lastblock = NULL; /* last block in buffer */ ! 53: ! 54: expptr tempalloc(); ! 55: ! 56: ! 57: optimize () ! 58: ! 59: { ! 60: Bblockp bb; ! 61: Slotp sl,nextsl; ! 62: ! 63: if (debugflag[2]) showbuffer (); ! 64: ! 65: optloops (); ! 66: ! 67: if (debugflag[3]) showbuffer (); ! 68: ! 69: formbblock (); ! 70: optcse (); ! 71: ! 72: if (debugflag[4]) showbuffer (); ! 73: ! 74: if (! debugflag[7]) ! 75: copyprop (); ! 76: ! 77: if (debugflag[9]) showbuffer (); ! 78: ! 79: for (sl = firstslot; sl; sl = nextsl) ! 80: { ! 81: nextsl = sl->next; ! 82: if (sl->type == SKFRTEMP) ! 83: { ! 84: templist = mkchain (sl->expr,templist); ! 85: sl->expr = NULL; ! 86: delslot (sl); ! 87: } ! 88: else ! 89: sl->expr = tempalloc (sl->expr); ! 90: } ! 91: ! 92: if (! debugflag[10]) ! 93: regalloc (); ! 94: ! 95: flushopt (); ! 96: } ! 97: ! 98: ! 99: ! 100: /* ! 101: * creates a new basic block record ! 102: */ ! 103: ! 104: LOCAL Bblockp newblock (sl) ! 105: Slotp sl; ! 106: ! 107: { ! 108: register Bblockp bb; ! 109: ! 110: bb = ALLOC( bblock ); ! 111: bb->next = NULL ; ! 112: if (lastblock) ! 113: { ! 114: bb->prev = lastblock; ! 115: lastblock->next = bb; ! 116: lastblock = bb; ! 117: } ! 118: else ! 119: { ! 120: firstblock = lastblock = bb; ! 121: bb->prev = NULL; ! 122: } ! 123: ! 124: bb->first = sl; ! 125: return (bb); ! 126: } ! 127: ! 128: ! 129: ! 130: /* ! 131: * scans slot buffer, creating basic block records ! 132: */ ! 133: ! 134: formbblock () ! 135: ! 136: { ! 137: Slotp sl; ! 138: field type; ! 139: Bblockp newbb; ! 140: ! 141: newbb = NULL; ! 142: for (sl = firstslot; sl; sl = sl->next) ! 143: { ! 144: type = sl->type; ! 145: switch (type) ! 146: { ! 147: case SKEQ: ! 148: if (!newbb) ! 149: newbb = newblock(sl); ! 150: if (containscall(sl->expr)) ! 151: { ! 152: newbb->last = sl; ! 153: newbb = NULL; ! 154: } ! 155: break; ! 156: case SKNULL: ! 157: case SKASSIGN: ! 158: case SKFRTEMP: ! 159: if (!newbb) ! 160: newbb = newblock(sl); ! 161: break; ! 162: case SKPAUSE: ! 163: case SKSTOP: ! 164: case SKIFN: ! 165: case SKGOTO: ! 166: case SKCMGOTO: ! 167: case SKARIF: ! 168: case SKASGOTO: ! 169: case SKIOIFN: ! 170: case SKCALL: ! 171: case SKRETURN: ! 172: if (!newbb) ! 173: newbb = newblock(sl); ! 174: newbb->last = sl; ! 175: newbb = NULL; ! 176: break; ! 177: case SKLABEL: ! 178: if (newbb) ! 179: newbb->last = sl->prev; ! 180: newbb = newblock(sl); ! 181: break; ! 182: case SKDOHEAD: ! 183: case SKENDDO: ! 184: if (!newbb) ! 185: newbb = newblock(sl); ! 186: break; ! 187: default: ! 188: badthing("SKtype", "formbblock", type); ! 189: break; ! 190: } ! 191: } ! 192: if (newbb) ! 193: newbb->last = lastslot; ! 194: } ! 195: ! 196: ! 197: ! 198: /* ! 199: * frees all basic block records ! 200: * as well as the id and value node chains hanging off the bb and their ! 201: * respective cross link chains (IDlist, DUPlist and NODElist structs) ! 202: */ ! 203: ! 204: clearbb () ! 205: { ! 206: Bblockp bb,next; ! 207: ! 208: for (bb = firstblock; bb; bb = next) ! 209: { ! 210: next = bb->next; ! 211: { ! 212: idptr idp,next; ! 213: for(idp = bb->headid; idp; idp = next) ! 214: { ! 215: next = idp->next; ! 216: { ! 217: nodelptr nodelp, next; ! 218: for(nodelp = idp->headnodelist; nodelp; nodelp = next) ! 219: { ! 220: next = nodelp->next; ! 221: free( (charptr) nodelp); ! 222: } ! 223: } ! 224: free( (charptr) idp); ! 225: } ! 226: } ! 227: { ! 228: valuen vp,next; ! 229: for(vp = bb->headnode; vp; vp = next) ! 230: { ! 231: next = vp->next; ! 232: { ! 233: idlptr idlp, next; ! 234: for(idlp = vp->headdeplist; idlp; idlp = next) ! 235: { ! 236: next = idlp->next; ! 237: free( (charptr) idlp); ! 238: } ! 239: } ! 240: { ! 241: duplptr duplp, next; ! 242: for(duplp = vp->headduplist; duplp; duplp = next) ! 243: { ! 244: next = duplp->next; ! 245: free( (charptr) duplp); ! 246: } ! 247: } ! 248: free( (charptr) vp); ! 249: } ! 250: } ! 251: free ( (charptr) bb); ! 252: } ! 253: firstblock = lastblock = NULL; ! 254: } ! 255: ! 256: ! 257: /* structure for maintaining records on copy statements */ ! 258: ! 259: typedef struct Subrec { ! 260: Addrp lmem; ! 261: Addrp rmem; ! 262: int sets; ! 263: } *Subrecp; ! 264: ! 265: ! 266: LOCAL chainp sublist; /* list of copy statements */ ! 267: LOCAL int prop1count; /* count of number of temporaries eliminated */ ! 268: LOCAL int prop2count; /* count of number of uses of temporaries replaced */ ! 269: ! 270: expptr rmcommaop(); ! 271: Addrp subfor(); ! 272: ! 273: ! 274: ! 275: /* ! 276: * eliminates copy statements of the form T1 = T2 from the intermediate ! 277: * code, where T1 and T2 are temporary variables which are each ! 278: * set only once; eliminates the copy statement and replaces each ! 279: * use of T1 by T2 (T1 is therefore totally eliminated). ! 280: */ ! 281: ! 282: LOCAL copyprop () ! 283: ! 284: { ! 285: Slotp sl,nextsl; ! 286: expptr expr; ! 287: Tempp lp,rp; ! 288: ! 289: for (sl = firstslot; sl; sl = sl->next) ! 290: sl->expr = rmcommaop (sl->expr,sl); ! 291: ! 292: prop1count = prop2count = 0; ! 293: findcopies (); ! 294: ! 295: for (sl = firstslot; sl; sl = nextsl) ! 296: { ! 297: nextsl = sl->next; ! 298: expr = sl->expr; ! 299: ! 300: if ((sl->type == SKFRTEMP) && subfor (expr)) ! 301: { ! 302: delslot (sl); ! 303: expr = ENULL; ! 304: } ! 305: else if (expr && expr->tag == TEXPR && ! 306: expr->exprblock.opcode == OPASSIGN) ! 307: { ! 308: lp = (Tempp) expr->exprblock.leftp; ! 309: rp = (Tempp) expr->exprblock.rightp; ! 310: if (lp->tag == TTEMP && rp->tag == TTEMP) ! 311: if (subfor(lp->memalloc) == rp->memalloc ! 312: && !subfor (rp->memalloc)) ! 313: { ! 314: frexpr (expr); ! 315: expr = sl->expr = ENULL; ! 316: prop1count++; ! 317: } ! 318: } ! 319: ! 320: propagate (expr); ! 321: } ! 322: ! 323: if (debugflag[0]) ! 324: fprintf (diagfile, ! 325: "%d temporarie%s replaced by copy propagation (%d use%s)\n", ! 326: prop1count,(prop1count==1 ? "" : "s"), ! 327: prop2count,(prop2count==1 ? "" : "s") ); ! 328: } ! 329: ! 330: ! 331: ! 332: /* ! 333: * finds copy statements and enters information in table ! 334: */ ! 335: ! 336: LOCAL findcopies () ! 337: ! 338: { ! 339: Slotp sl; ! 340: expptr expr; ! 341: chainp cp; ! 342: ! 343: for (sl = firstslot; sl; sl = sl->next) ! 344: { ! 345: expr = sl->expr; ! 346: if (expr) switch (expr->tag) ! 347: { ! 348: case TEXPR: ! 349: ckexpr (expr); ! 350: break; ! 351: ! 352: case TLIST: ! 353: for (cp = expr->listblock.listp; cp; cp = cp->nextp) ! 354: { ! 355: expr = (expptr) cp->datap; ! 356: ckexpr (expr); ! 357: } ! 358: break; ! 359: ! 360: default: ! 361: break; ! 362: } ! 363: } ! 364: } ! 365: ! 366: ! 367: ! 368: /* ! 369: * checks an individual expression ! 370: */ ! 371: ! 372: ckexpr (expr) ! 373: expptr expr; ! 374: ! 375: { ! 376: Tempp lp,rp; ! 377: int oc = expr->exprblock.opcode; ! 378: ! 379: if (oc == OPASSIGN || oc == OPPLUSEQ || oc == OPSTAREQ) ! 380: { ! 381: lp = (Tempp) expr->exprblock.leftp; ! 382: rp = (Tempp) expr->exprblock.rightp; ! 383: if (lp->tag == TTEMP) ! 384: if (rp->tag == TTEMP && oc == OPASSIGN) ! 385: enter (lp->memalloc, rp->memalloc); ! 386: else ! 387: enter (lp->memalloc, ENULL); ! 388: } ! 389: } ! 390: ! 391: ! 392: ! 393: /* ! 394: * Enters the given memalloc values in the table (or update if they ! 395: * are already there), for the assignment statement m1 = m2. ! 396: * If m2 is NULL, this indicates that the assignment is not a copy ! 397: * statement. ! 398: */ ! 399: ! 400: LOCAL enter (m1,m2) ! 401: Addrp m1,m2; ! 402: ! 403: { ! 404: chainp cp; ! 405: Subrecp old,new; ! 406: ! 407: for (cp = sublist; cp; cp = cp->nextp) ! 408: { ! 409: old = (Subrecp) cp->datap; ! 410: if (old->lmem == m1) ! 411: { ! 412: old->sets++; ! 413: return; ! 414: } ! 415: } ! 416: ! 417: new = ALLOC (Subrec); ! 418: new->lmem = m1; ! 419: new->rmem = m2; ! 420: new->sets = 1; ! 421: sublist = mkchain (new, sublist); ! 422: } ! 423: ! 424: ! 425: ! 426: /* ! 427: * looks for record for the given memalloc value ! 428: */ ! 429: ! 430: LOCAL Subrecp lookup (mem) ! 431: Addrp mem; ! 432: ! 433: { ! 434: chainp cp; ! 435: Subrecp rec; ! 436: ! 437: for (cp = sublist; cp; cp = cp->nextp) ! 438: { ! 439: rec = (Subrecp) cp->datap; ! 440: if (rec->lmem == mem) ! 441: return rec; ! 442: } ! 443: ! 444: return NULL; ! 445: } ! 446: ! 447: ! 448: ! 449: /* ! 450: * checks to see if there is a substitute for given memalloc value ! 451: */ ! 452: ! 453: LOCAL Addrp subfor (mem) ! 454: Addrp mem; ! 455: ! 456: { ! 457: Subrecp rec,rec2; ! 458: Addrp sub; ! 459: ! 460: rec = lookup (mem); ! 461: if (rec && rec->sets == 1) ! 462: { ! 463: sub = rec->rmem; ! 464: rec2 = lookup(sub); ! 465: if (rec2 && rec2->sets == 1) ! 466: return sub; ! 467: } ! 468: ! 469: return NULL; ! 470: } ! 471: ! 472: ! 473: ! 474: /* ! 475: * actually propagates the information ! 476: */ ! 477: ! 478: LOCAL propagate (expr) ! 479: expptr expr; ! 480: ! 481: { ! 482: chainp t; ! 483: Addrp new; ! 484: ! 485: if (! expr) return; ! 486: ! 487: switch (expr->tag) ! 488: { ! 489: case TEXPR: ! 490: propagate (expr->exprblock.leftp); ! 491: propagate (expr->exprblock.rightp); ! 492: break; ! 493: ! 494: case TADDR: ! 495: propagate (expr->addrblock.vleng); ! 496: propagate (expr->addrblock.memoffset); ! 497: break; ! 498: ! 499: case TLIST: ! 500: for (t = expr->listblock.listp; t; t = t->nextp) ! 501: propagate (t->datap); ! 502: break; ! 503: ! 504: case TTEMP: ! 505: new = subfor (expr->tempblock.memalloc); ! 506: if (new) ! 507: { ! 508: expr->tempblock.memalloc = new; ! 509: prop2count++; ! 510: } ! 511: break; ! 512: ! 513: default: ! 514: break; ! 515: } ! 516: } ! 517: ! 518: ! 519: ! 520: /* ! 521: * allocates ADDR blocks for each TEMP in the expression ! 522: */ ! 523: ! 524: LOCAL expptr tempalloc (expr) ! 525: expptr expr; ! 526: ! 527: { ! 528: chainp t; ! 529: ! 530: if (! expr) ! 531: return NULL; ! 532: ! 533: switch (expr->tag) ! 534: { ! 535: case TEXPR: ! 536: expr->exprblock.leftp = tempalloc (expr->exprblock.leftp); ! 537: expr->exprblock.rightp = tempalloc (expr->exprblock.rightp); ! 538: break; ! 539: ! 540: case TADDR: ! 541: expr->addrblock.vleng = tempalloc (expr->addrblock.vleng); ! 542: expr->addrblock.memoffset = tempalloc (expr->addrblock.memoffset); ! 543: break; ! 544: ! 545: case TLIST: ! 546: for (t = expr->listblock.listp; t; t = t->nextp) ! 547: t->datap = (tagptr) tempalloc (t->datap); ! 548: break; ! 549: ! 550: case TTEMP: ! 551: expr->tempblock.vleng = tempalloc (expr->tempblock.vleng); ! 552: return (expptr) cpexpr (altmpn (expr)); ! 553: break; ! 554: ! 555: default: ! 556: break; ! 557: } ! 558: return expr; ! 559: } ! 560: ! 561: ! 562: /********************* debugging routines *********************/ ! 563: ! 564: ! 565: ! 566: Announce (s,q) ! 567: char *s; ! 568: expptr q; ! 569: ! 570: { ! 571: fprintf (diagfile,"\nAn expression [%s]----->\n",s); ! 572: showexpr(q,0); ! 573: fprintf (diagfile,"\n-------------end of expr--------------\n"); ! 574: } ! 575: ! 576: ! 577: ! 578: /* ! 579: * dump the basic block buffer, including expressions, mnemonically ! 580: */ ! 581: ! 582: showbuffer () ! 583: ! 584: { ! 585: Slotp sl; ! 586: Bblockp bb; ! 587: int i; ! 588: ! 589: fprintf (diagfile,"Basic blocks with first and last slots ----------\n"); ! 590: for (i=1, bb = firstblock; bb; i++, bb = bb->next) ! 591: fprintf (diagfile,"%2d. %d %d\n",i,bb->first,bb->last); ! 592: fprintf (diagfile,"\n"); ! 593: ! 594: fprintf (diagfile,"Slots and expressions ----------\n"); ! 595: ! 596: fprintf (diagfile,"tag pointer vtype vclass vstg vleng\n"); ! 597: fprintf (diagfile," ADDR memno memoffset istemp ntempelt varleng\n"); ! 598: fprintf (diagfile," TEMP memalloc istemp ntempelt varleng\n"); ! 599: fprintf (diagfile," EXPR opcode leftp rightp\n"); ! 600: fprintf (diagfile," LIST type listp\n"); ! 601: fprintf (diagfile,"\n"); ! 602: ! 603: for (i=1, sl = firstslot; sl; i++, sl = sl->next) ! 604: { ! 605: fprintf (diagfile,"%2d. ",i); ! 606: showslt (sl); ! 607: } ! 608: fprintf (diagfile,"---------- End of showbuffer ----------\n"); ! 609: } ! 610: ! 611: ! 612: ! 613: /* ! 614: * dumps a single slot in the code buffer ! 615: */ ! 616: ! 617: LOCAL charptr Zslot[] = {"NULL", ! 618: "IFN","GOTO","LABEL","EQ","CALL","CMGOTO","STOP","DOHEAD", ! 619: "ENDDO","ARIF","RETURN","ASGOTO","PAUSE","ASSIGN","IOIFN","FRTEMP"}; ! 620: ! 621: ! 622: ! 623: showslt (sl) ! 624: Slotp sl; ! 625: ! 626: { ! 627: fprintf (diagfile,"(%2d) %d %s %d\n", ! 628: sl->lineno,sl,Zslot[sl->type],sl->label); ! 629: showexpr (sl->expr,0); ! 630: fprintf (diagfile,"\n"); ! 631: } ! 632: ! 633: ! 634: ! 635: showslottype (type) ! 636: int type; ! 637: ! 638: { ! 639: fprintf (diagfile,"%s\n",Zslot[type]); ! 640: } ! 641: ! 642: ! 643: ! 644: /* ! 645: * displays the given expression at the given indentation, showing ! 646: * its subexpressions at further indentations ! 647: */ ! 648: ! 649: LOCAL charptr Ztag[] = {"----", ! 650: "NAME","CONST","EXPR","ADDR","TEMP","PRIM","LIST","IMPLDO","ERROR"}; ! 651: LOCAL charptr Zstg[] = {"unk", ! 652: "ARG","AUTO","BSS","INIT","CONST","EXT","INTR","STFUNCT", ! 653: "COMMON","EQUIV","REG","LENG","NULL","PREG"}; ! 654: LOCAL charptr Zclass[] = {"unk", ! 655: "PARAM","VAR","ENTRY","MAIN","BLOCK","PROC","NAMELIST"}; ! 656: LOCAL charptr Zop[] = {"----", ! 657: "PLUS","MINUS","STAR","SLASH","POWER","NEG","OR","AND","EQV", ! 658: "NEQV","NOT","CONCAT","LT","EQ","GT","LE","NE","GE","CALL", ! 659: "CCALL","ASSIGN","PLUSEQ","STAREQ","CONV","LSHIFT","MOD", ! 660: "COMMA","QUEST","COLON","ABS","MIN","MAX","ADDR","INDIRECT", ! 661: "BITOR","BITAND","BITXOR","BITNOT","RSHIFT","PAREN"}; ! 662: LOCAL charptr Ztype[] = {"unk", ! 663: "ADDR","SHORT","LONG","REAL","DREAL","COMPLEX","DCOMPLEX", ! 664: "LOGICAL","CHAR","SUBR","ERROR"}; ! 665: ! 666: ! 667: showexpr(p,indent) ! 668: tagptr p; ! 669: int indent; ! 670: ! 671: { ! 672: int i; ! 673: int type; ! 674: chainp q; ! 675: ! 676: #define PRHEAD(q) fprintf(diagfile,"%s %d %s %s %s %d", \ ! 677: Ztag[q->tag], q, Ztype[q->headblock.vtype], \ ! 678: Zclass[q->headblock.vclass], Zstg[q->headblock.vstg], \ ! 679: q->headblock.vleng); ! 680: #define SHOWEXPR(p) showexpr(p,indent+2) ! 681: ! 682: ! 683: ! 684: if(p == NULL) ! 685: return; ! 686: ! 687: for (i=0; i<indent; i++) ! 688: putc(' ',diagfile); ! 689: ! 690: switch(p->tag) ! 691: { ! 692: case TCONST: ! 693: PRHEAD(p); ! 694: ! 695: type=p->constblock.vtype; ! 696: if (ISCHAR(p)) ! 697: { ! 698: fprintf(diagfile," ISCHAR ccp= %d\n", ! 699: p->constblock.const.ccp); ! 700: SHOWEXPR(p->constblock.vleng); ! 701: } ! 702: else if( ISINT(type) ) ! 703: fprintf(diagfile," ci= %d\n",p->constblock.const.ci); ! 704: else if( ISREAL(type) ) ! 705: fprintf(diagfile," cd[0]= %e\n",p->constblock.const.cd[0]); ! 706: else fprintf(diagfile," cd[0]= %e cd[1]= %e\n", ! 707: p->constblock.const.cd[0], ! 708: p->constblock.const.cd[1] ); ! 709: break; ! 710: ! 711: case TADDR: ! 712: PRHEAD(p); ! 713: fprintf(diagfile, ! 714: " memno= %d %d %d %d %d\n", ! 715: p->addrblock.memno,p->addrblock.memoffset,p->addrblock.istemp, ! 716: p->addrblock.ntempelt,p->addrblock.varleng); ! 717: SHOWEXPR(p->addrblock.vleng); ! 718: SHOWEXPR(p->addrblock.memoffset); ! 719: break; ! 720: ! 721: case TTEMP: ! 722: fprintf(diagfile,"%s %d %s %s %d", ! 723: Ztag[p->tag], p, Ztype[p->headblock.vtype], ! 724: Zclass[p->headblock.vclass], ! 725: p->headblock.vleng); ! 726: fprintf(diagfile, ! 727: " memalloc= %d %d %d %d\n", ! 728: p->tempblock.memalloc,p->tempblock.istemp, ! 729: p->tempblock.ntempelt,p->tempblock.varleng); ! 730: SHOWEXPR(p->tempblock.vleng); ! 731: SHOWEXPR(p->tempblock.memalloc); ! 732: break; ! 733: ! 734: case TERROR: ! 735: fprintf(diagfile,"ERROR %d\n",p); ! 736: break; ! 737: ! 738: case TNAME: ! 739: fprintf(diagfile,"NAME %d\n",p); ! 740: return; ! 741: ! 742: case TPRIM: ! 743: fprintf(diagfile,"PRIM %d --- not implemented\n",p); ! 744: break; ! 745: ! 746: case TEXPR: ! 747: PRHEAD(p); ! 748: fprintf(diagfile," opcode= %s %d %d\n", ! 749: Zop[p->exprblock.opcode],p->exprblock.leftp, ! 750: p->exprblock.rightp); ! 751: SHOWEXPR(p->exprblock.leftp); ! 752: if(p->exprblock.rightp) ! 753: SHOWEXPR(p->exprblock.rightp); ! 754: break; ! 755: ! 756: case TLIST: ! 757: fprintf(diagfile,"LIST %d %s %d\n",p, ! 758: Ztype[p->listblock.vtype],p->listblock.listp); ! 759: for(q= p->listblock.listp ; q ; q = q->nextp) ! 760: SHOWEXPR(q->datap); ! 761: for (i=0; i<indent; i++) ! 762: putc (' ',diagfile); ! 763: fprintf(diagfile,"END LIST %d\n",p); ! 764: break; ! 765: ! 766: default: ! 767: fprintf(diagfile,"showexpr BAD TAG= %d at %d \n",p->tag,p); ! 768: } ! 769: } ! 770: ! 771: ! 772: ! 773: selective()/************************************/ ! 774: { ! 775: int i; ! 776: Slotp sl; ! 777: ! 778: i=0; ! 779: fprintf (stderr,"SELECTIVE OUTPUT\n"); ! 780: for (sl=firstslot;sl;sl=sl->next) ! 781: { ! 782: i++; ! 783: if (i>=176 && i<184) ! 784: { ! 785: fprintf (stderr,"%d. ",i); ! 786: showslt(sl); ! 787: } ! 788: } ! 789: } ! 790: ! 791: ! 792: ! 793: ! 794: LOCAL containscall(p) ! 795: expptr p; ! 796: { ! 797: chainp cp; ! 798: ! 799: if (p == NULL) ! 800: return NO; ! 801: ! 802: switch (p->tag) ! 803: { ! 804: case TADDR: ! 805: if (containscall(p->addrblock.vleng) ! 806: || containscall(p->addrblock.memoffset)) ! 807: return YES; ! 808: else ! 809: return NO; ! 810: ! 811: case TCONST: ! 812: return NO; ! 813: ! 814: case TERROR: ! 815: return NO; ! 816: ! 817: case TEXPR: ! 818: if (p->exprblock.opcode == OPCALL || ! 819: p->exprblock.opcode == OPCCALL) ! 820: return YES; ! 821: if (containscall(p->exprblock.vleng) || ! 822: containscall(p->exprblock.leftp) || ! 823: containscall(p->exprblock.rightp)) ! 824: return YES; ! 825: else ! 826: return NO; ! 827: ! 828: case TLIST: ! 829: cp = p->listblock.listp; ! 830: while (cp) ! 831: { ! 832: if (containscall(cp->datap)) ! 833: return YES; ! 834: cp = cp->nextp; ! 835: } ! 836: return NO; ! 837: ! 838: default: ! 839: return YES; ! 840: } ! 841: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.