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