116962Smckusick /* Copyright (c) 1984 Regents of the University of California */ 216962Smckusick 316962Smckusick #ifndef lint 4*16980Smckusick static char sccsid[] = "@(#)main.c 1.5 (Berkeley) 08/20/84"; 516962Smckusick #endif not lint 616962Smckusick 716962Smckusick #include <stdio.h> 816962Smckusick #include <ctype.h> 916963Smckusick #include "inline.h" 1016962Smckusick 1116975Smckusick /* 1216975Smckusick * These are the pattern tables to be loaded 1316975Smckusick */ 1416975Smckusick struct pats *inittables[] = { 1516975Smckusick language_ptab, 1616975Smckusick libc_ptab, 1716975Smckusick machine_ptab, 1816975Smckusick 0 1916975Smckusick }; 2016975Smckusick 21*16980Smckusick /* 22*16980Smckusick * Statistics collection 23*16980Smckusick */ 24*16980Smckusick struct stats { 25*16980Smckusick int attempted; /* number of expansion attempts */ 26*16980Smckusick int finished; /* expansions done before end of basic block */ 27*16980Smckusick int lostmodified; /* mergers inhibited by intervening mod */ 28*16980Smckusick int savedpush; /* successful push/pop merger */ 29*16980Smckusick } stats; 30*16980Smckusick int dflag; 31*16980Smckusick 3216962Smckusick main(argc, argv) 3316962Smckusick int argc; 3416962Smckusick char *argv[]; 3516962Smckusick { 3616962Smckusick register char *cp, *lp; 3716962Smckusick register char *bufp; 3816978Smckusick register struct pats *pp, **php; 3916978Smckusick struct pats **tablep; 4016978Smckusick register struct inststoptbl *itp, **ithp; 4116962Smckusick int size; 4216962Smckusick extern char *index(); 4316962Smckusick 44*16980Smckusick if (argc > 1 && bcmp(argv[1], "-d", 3) == 0) 45*16980Smckusick dflag++, argc--, argv++; 4616962Smckusick if (argc > 1) 4716962Smckusick freopen(argv[1], "r", stdin); 4816962Smckusick if (argc > 2) 4916962Smckusick freopen(argv[2], "w", stdout); 5016962Smckusick /* 5116978Smckusick * Set up the hash table for the patterns. 5216962Smckusick */ 5316975Smckusick for (tablep = inittables; *tablep; tablep++) { 5416975Smckusick for (pp = *tablep; pp->name[0] != '\0'; pp++) { 5516978Smckusick php = &patshdr[hash(pp->name, &size)]; 5616975Smckusick pp->size = size; 5716978Smckusick pp->next = *php; 5816978Smckusick *php = pp; 5916975Smckusick } 6016962Smckusick } 6116962Smckusick /* 6216978Smckusick * Set up the hash table for the instruction stop table. 6316978Smckusick */ 6416978Smckusick for (itp = inststoptable; itp->name[0] != '\0'; itp++) { 6516978Smckusick ithp = &inststoptblhdr[hash(itp->name, &size)]; 6616978Smckusick itp->size = size; 6716978Smckusick itp->next = *ithp; 6816978Smckusick *ithp = itp; 6916978Smckusick } 7016978Smckusick /* 7116962Smckusick * check each line and replace as appropriate 7216962Smckusick */ 7316962Smckusick buftail = bufhead = 0; 7416962Smckusick bufp = line[0]; 7516962Smckusick while (fgets(bufp, MAXLINELEN, stdin)) { 7616962Smckusick lp = index(bufp, LABELCHAR); 7716962Smckusick if (lp != NULL) { 7816962Smckusick bufp = newline(); 7916962Smckusick if (*++lp == '\n') { 8016962Smckusick emptyqueue(); 8116962Smckusick continue; 8216962Smckusick } 8316962Smckusick strcpy(bufp, lp); 8416962Smckusick *lp++ = '\n'; 8516962Smckusick *lp = '\0'; 8616962Smckusick emptyqueue(); 8716962Smckusick } 8816962Smckusick for (cp = bufp; isspace(*cp); cp++) 8916962Smckusick /* void */; 9016962Smckusick if ((cp = doreplaceon(cp)) == 0) { 9116962Smckusick bufp = newline(); 9216962Smckusick continue; 9316962Smckusick } 9416978Smckusick for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) { 9516962Smckusick if (pp->size == size && bcmp(pp->name, cp, size) == 0) { 9616962Smckusick expand(pp->replace); 9716962Smckusick bufp = line[bufhead]; 9816962Smckusick break; 9916962Smckusick } 10016962Smckusick } 10116962Smckusick if (!pp) { 10216962Smckusick emptyqueue(); 10316962Smckusick fputs(bufp, stdout); 10416962Smckusick } 10516962Smckusick } 10616962Smckusick emptyqueue(); 107*16980Smckusick if (dflag) 108*16980Smckusick fprintf(stderr, "inline: %s %d, %s %d, %s %d, %s %d\n", 109*16980Smckusick "attempts", stats.attempted, 110*16980Smckusick "finished", stats.finished, 111*16980Smckusick "inhibited", stats.lostmodified, 112*16980Smckusick "merged", stats.savedpush); 11316962Smckusick exit(0); 11416962Smckusick } 11516962Smckusick 11616962Smckusick /* 11716962Smckusick * Integrate an expansion into the assembly stream 11816962Smckusick */ 11916962Smckusick expand(replace) 12016962Smckusick char *replace; 12116962Smckusick { 12216962Smckusick register int curptr; 12316962Smckusick char *nextreplace, *argv[MAXARGS]; 12416978Smckusick int argc, argreg, foundarg, mod = 0; 12516962Smckusick char parsebuf[BUFSIZ]; 12616962Smckusick 127*16980Smckusick stats.attempted++; 128*16980Smckusick for (curptr = bufhead; ; ) { 12916962Smckusick nextreplace = copyline(replace, line[bufhead]); 13016962Smckusick argc = parseline(line[bufhead], argv, parsebuf); 13116962Smckusick argreg = nextarg(argc, argv); 13216962Smckusick if (argreg == -1) 13316962Smckusick break; 13416978Smckusick for (foundarg = 0; curptr != buftail; ) { 13516978Smckusick curptr = PRED(curptr); 13616962Smckusick argc = parseline(line[curptr], argv, parsebuf); 13716978Smckusick if (isendofblock(argc, argv)) 13816962Smckusick break; 13916978Smckusick if (foundarg = ispusharg(argc, argv)) 14016978Smckusick break; 14116962Smckusick mod |= 1 << modifies(argc, argv); 14216962Smckusick } 14316978Smckusick if (!foundarg) 14416962Smckusick break; 14516962Smckusick replace = nextreplace; 14616962Smckusick if (mod & (1 << argreg)) { 147*16980Smckusick stats.lostmodified++; 14816978Smckusick if (curptr == buftail) { 14916978Smckusick (void)newline(); 15016978Smckusick break; 15116978Smckusick } 15216962Smckusick (void)newline(); 15316962Smckusick } else { 154*16980Smckusick stats.savedpush++; 15516962Smckusick rewrite(line[curptr], argc, argv, argreg); 15616962Smckusick mod |= 1 << argreg; 15716962Smckusick } 15816962Smckusick } 159*16980Smckusick if (argreg == -1) 160*16980Smckusick stats.finished++; 16116962Smckusick emptyqueue(); 16216962Smckusick fputs(replace, stdout); 16316962Smckusick } 16416962Smckusick 16516962Smckusick /* 16616962Smckusick * Parse a line of assembly language into opcode and arguments. 16716962Smckusick */ 16816962Smckusick parseline(linep, argv, linebuf) 16916962Smckusick char *linep; 17016962Smckusick char *argv[]; 17116962Smckusick char *linebuf; 17216962Smckusick { 17316962Smckusick register char *bufp = linebuf, *cp = linep; 17416962Smckusick register int argc = 0; 17516962Smckusick 17616962Smckusick for (;;) { 17716962Smckusick /* 17816962Smckusick * skip over white space 17916962Smckusick */ 18016962Smckusick while (isspace(*cp)) 18116962Smckusick cp++; 18216962Smckusick if (*cp == '\0') 18316962Smckusick return (argc); 18416962Smckusick /* 18516962Smckusick * copy argument 18616962Smckusick */ 18716962Smckusick if (argc == MAXARGS - 1) { 18816962Smckusick fprintf(stderr, "instruction too long->%s", linep); 18916962Smckusick return (argc); 19016962Smckusick } 19116962Smckusick argv[argc++] = bufp; 19216978Smckusick while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR) 19316962Smckusick *bufp++ = *cp++; 19416962Smckusick *bufp++ = '\0'; 19516962Smckusick if (*cp == COMMENTCHAR) 19616962Smckusick return (argc); 19716978Smckusick if (*cp == ARGSEPCHAR) 19816962Smckusick cp++; 19916962Smckusick } 20016962Smckusick } 20116962Smckusick 20216962Smckusick /* 20316978Smckusick * Check for instructions that end a basic block. 20416978Smckusick */ 20516978Smckusick isendofblock(argc, argv) 20616978Smckusick int argc; 20716978Smckusick char *argv[]; 20816978Smckusick { 20916978Smckusick register struct inststoptbl *itp; 21016978Smckusick int size; 21116978Smckusick 21216978Smckusick if (argc == 0) 21316978Smckusick return (0); 21416978Smckusick for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next) 21516978Smckusick if (itp->size == size && bcmp(argv[0], itp->name, size) == 0) 21616978Smckusick return (1); 21716978Smckusick return (0); 21816978Smckusick } 21916978Smckusick 22016978Smckusick /* 22116962Smckusick * Copy a newline terminated string. 22216962Smckusick * Return pointer to character following last character copied. 22316962Smckusick */ 22416962Smckusick char * 22516962Smckusick copyline(from, to) 22616962Smckusick register char *from, *to; 22716962Smckusick { 22816962Smckusick 22916962Smckusick while (*from != '\n') 23016962Smckusick *to++ = *from++; 23116962Smckusick *to++ = *from++; 23216962Smckusick *to = '\0'; 23316962Smckusick return (from); 23416962Smckusick } 23516962Smckusick 23616962Smckusick /* 23716962Smckusick * open space for next line in the queue 23816962Smckusick */ 23916962Smckusick char * 24016962Smckusick newline() 24116962Smckusick { 24216962Smckusick bufhead = SUCC(bufhead); 24316962Smckusick if (bufhead == buftail) { 24416962Smckusick fputs(line[buftail], stdout); 24516962Smckusick buftail = SUCC(buftail); 24616962Smckusick } 24716962Smckusick return (line[bufhead]); 24816962Smckusick } 24916962Smckusick 25016962Smckusick /* 25116962Smckusick * empty the queue by printing out all its lines. 25216962Smckusick */ 25316962Smckusick emptyqueue() 25416962Smckusick { 25516962Smckusick while (buftail != bufhead) { 25616962Smckusick fputs(line[buftail], stdout); 25716962Smckusick buftail = SUCC(buftail); 25816962Smckusick } 25916962Smckusick } 26016962Smckusick 26116962Smckusick /* 26216962Smckusick * Compute the hash of a string. 26316962Smckusick * Return the hash and the size of the item hashed 26416962Smckusick */ 26516962Smckusick hash(cp, size) 26616962Smckusick char *cp; 26716962Smckusick int *size; 26816962Smckusick { 26916962Smckusick register char *cp1 = cp; 27016978Smckusick register int hash = 0; 27116962Smckusick 27216962Smckusick while (*cp1 && *cp1 != '\n') 27316962Smckusick hash += (int)*cp1++; 27416962Smckusick *size = cp1 - cp + 1; 27516962Smckusick hash &= HSHSIZ - 1; 27616978Smckusick return (hash); 27716962Smckusick } 278