1: /* Copyright (c) 1984 Regents of the University of California */ 2: 3: #ifndef lint 4: static char sccsid[] = "@(#)main.c 1.6 (Berkeley) 9/20/84"; 5: #endif not lint 6: 7: #include <stdio.h> 8: #include <ctype.h> 9: #include "inline.h" 10: 11: /* 12: * These are the pattern tables to be loaded 13: */ 14: struct pats *inittables[] = { 15: language_ptab, 16: libc_ptab, 17: machine_ptab, 18: 0 19: }; 20: 21: /* 22: * Statistics collection 23: */ 24: struct stats { 25: int attempted; /* number of expansion attempts */ 26: int finished; /* expansions done before end of basic block */ 27: int lostmodified; /* mergers inhibited by intervening mod */ 28: int savedpush; /* successful push/pop merger */ 29: int savedmove; /* move to tmp reg eliminated */ 30: } stats; 31: int dflag; 32: 33: main(argc, argv) 34: int argc; 35: char *argv[]; 36: { 37: register char *cp, *lp, *qp; 38: register char *bufp; 39: register struct pats *pp, **php; 40: struct pats **tablep; 41: register struct inststoptbl *itp, **ithp; 42: int size; 43: extern char *index(); 44: 45: if (argc > 1 && bcmp(argv[1], "-d", 3) == 0) 46: dflag++, argc--, argv++; 47: if (argc > 1) 48: freopen(argv[1], "r", stdin); 49: if (argc > 2) 50: freopen(argv[2], "w", stdout); 51: /* 52: * Set up the hash table for the patterns. 53: */ 54: for (tablep = inittables; *tablep; tablep++) { 55: for (pp = *tablep; pp->name[0] != '\0'; pp++) { 56: php = &patshdr[hash(pp->name, &size)]; 57: pp->size = size; 58: pp->next = *php; 59: *php = pp; 60: } 61: } 62: /* 63: * Set up the hash table for the instruction stop table. 64: */ 65: for (itp = inststoptable; itp->name[0] != '\0'; itp++) { 66: ithp = &inststoptblhdr[hash(itp->name, &size)]; 67: itp->size = size; 68: itp->next = *ithp; 69: *ithp = itp; 70: } 71: /* 72: * check each line and replace as appropriate 73: */ 74: buftail = bufhead = 0; 75: bufp = line[0]; 76: while (fgets(bufp, MAXLINELEN, stdin)) { 77: lp = index(bufp, LABELCHAR); 78: if (lp != NULL) { 79: qp = index(bufp, QUOTECHAR); 80: if (qp == NULL) { 81: bufp = newline(); 82: if (*++lp == '\n') { 83: emptyqueue(); 84: continue; 85: } 86: strcpy(bufp, lp); 87: *lp++ = '\n'; 88: *lp = '\0'; 89: emptyqueue(); 90: } 91: } 92: for (cp = bufp; isspace(*cp); cp++) 93: /* void */; 94: if ((cp = doreplaceon(cp)) == 0) { 95: bufp = newline(); 96: continue; 97: } 98: for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) { 99: if (pp->size == size && bcmp(pp->name, cp, size) == 0) { 100: expand(pp->replace); 101: bufp = line[bufhead]; 102: break; 103: } 104: } 105: if (!pp) { 106: emptyqueue(); 107: fputs(bufp, stdout); 108: } 109: } 110: emptyqueue(); 111: if (dflag) 112: fprintf(stderr, "inline: %s %d, %s %d, %s %d, %s %d\n", 113: "attempts", stats.attempted, 114: "finished", stats.finished, 115: "inhibited", stats.lostmodified, 116: "merged", stats.savedpush, 117: "nomoves", stats.savedmove); 118: exit(0); 119: } 120: 121: /* 122: * Integrate an expansion into the assembly stream 123: */ 124: expand(replace) 125: char *replace; 126: { 127: register int curptr; 128: char *nextreplace, *argv[MAXARGS]; 129: int argc, argreg, foundarg, mod = 0, args = 0; 130: char parsebuf[BUFSIZ]; 131: int argno = 0; 132: int flag; 133: struct oparg oparg[MAXARGS]; 134: 135: stats.attempted++; 136: for (curptr = bufhead; ; ) { 137: nextreplace = copyline(replace, line[bufhead]); 138: argc = parseline(line[bufhead], argv, parsebuf); 139: argreg = nextarg(argc, argv, &flag); 140: if (argreg == -1) 141: break; 142: args++; 143: for (foundarg = 0; curptr != buftail; ) { 144: curptr = PRED(curptr); 145: argc = parseline(line[curptr], argv, parsebuf); 146: if (isendofblock(argc, argv)) 147: break; 148: if (foundarg = ispusharg(argc, argv)) 149: break; 150: mod |= 1 << modifies(argc, argv); 151: } 152: if (!foundarg) 153: break; 154: replace = nextreplace; 155: if (mod & (1 << argreg)) { 156: stats.lostmodified++; 157: if (curptr == buftail) { 158: (void)newline(); 159: break; 160: } 161: (void)newline(); 162: } else { 163: if (checkvar(argc, argv, flag, oparg[argno].source, mod)) { 164: line[curptr][0] = '\0'; 165: oparg[argno].reg = argreg; 166: argno++; 167: stats.savedmove++; 168: } else { 169: rewrite(line[curptr], argc, argv, argreg); 170: stats.savedpush++; 171: mod |= 1 << argreg; 172: } 173: } 174: } 175: if (argreg == -1) 176: stats.finished++; 177: emptyqueue(); 178: output_replace(replace, oparg, argno, stdout); 179: cleanup(args); 180: } 181: 182: /* 183: * Parse a line of assembly language into opcode and arguments. 184: */ 185: parseline(linep, argv, linebuf) 186: char *linep; 187: char *argv[]; 188: char *linebuf; 189: { 190: register char *bufp = linebuf, *cp = linep; 191: register int argc = 0; 192: 193: for (;;) { 194: /* 195: * skip over white space 196: */ 197: while (isspace(*cp)) 198: cp++; 199: if (*cp == '\0') 200: return (argc); 201: /* 202: * copy argument 203: */ 204: if (argc == MAXARGS - 1) { 205: fprintf(stderr, "instruction too long->%s", linep); 206: return (argc); 207: } 208: argv[argc++] = bufp; 209: while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR) 210: *bufp++ = *cp++; 211: *bufp++ = '\0'; 212: if (*cp == COMMENTCHAR) 213: return (argc); 214: if (*cp == ARGSEPCHAR) 215: cp++; 216: } 217: } 218: 219: /* 220: * Check for instructions that end a basic block. 221: */ 222: isendofblock(argc, argv) 223: int argc; 224: char *argv[]; 225: { 226: register struct inststoptbl *itp; 227: int size; 228: 229: if (argc == 0) 230: return (0); 231: for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next) 232: if (itp->size == size && bcmp(argv[0], itp->name, size) == 0) 233: return (1); 234: return (0); 235: } 236: 237: /* 238: * Copy a newline terminated string. 239: * Return pointer to character following last character copied. 240: */ 241: char * 242: copyline(from, to) 243: register char *from, *to; 244: { 245: 246: while (*from != '\n') 247: *to++ = *from++; 248: *to++ = *from++; 249: *to = '\0'; 250: return (from); 251: } 252: 253: /* 254: * open space for next line in the queue 255: */ 256: char * 257: newline() 258: { 259: bufhead = SUCC(bufhead); 260: if (bufhead == buftail) { 261: fputs(line[buftail], stdout); 262: buftail = SUCC(buftail); 263: } 264: return (line[bufhead]); 265: } 266: 267: /* 268: * empty the queue by printing out all its lines. 269: */ 270: emptyqueue() 271: { 272: while (buftail != bufhead) { 273: fputs(line[buftail], stdout); 274: buftail = SUCC(buftail); 275: } 276: } 277: 278: /* 279: * Compute the hash of a string. 280: * Return the hash and the size of the item hashed 281: */ 282: hash(cp, size) 283: char *cp; 284: int *size; 285: { 286: register char *cp1 = cp; 287: register int hash = 0; 288: 289: while (*cp1 && *cp1 != '\n') 290: hash += (int)*cp1++; 291: *size = cp1 - cp + 1; 292: hash &= HSHSIZ - 1; 293: return (hash); 294: }