|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.