X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCpeeph.c;h=b06c6f9e6e52f500754936bca8fbd13f89939c22;hb=460955131ad20d79c93ca045a52280eaa0d7d476;hp=2a0ed06950fb19c028b1c911812a4dd6b46fe656;hpb=6240f1651dbbc0a6392b5bc3db0709c78e4d4d42;p=fw%2Fsdcc diff --git a/src/SDCCpeeph.c b/src/SDCCpeeph.c index 2a0ed069..b06c6f9e 100644 --- a/src/SDCCpeeph.c +++ b/src/SDCCpeeph.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------- - SDCCpeeph.c - The peep hole optimizer: for interpreting the + SDCCpeeph.c - The peep hole optimizer: for interpreting the peep hole rules Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) @@ -8,19 +8,19 @@ under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! + what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ #include "common.h" @@ -29,9 +29,22 @@ peepRule *rootRules = NULL; peepRule *currRule = NULL; +#define HTAB_SIZE 53 +typedef struct +{ + char name[SDCC_NAME_MAX + 1]; + int refCount; +} labelHashEntry; + +hTab *labelHash = NULL; + +static int hashSymbolName(const char *name); +static void buildLabelRefCountHash(lineNode *head); + static bool matchLine (char *, char *, hTab **); -#define FBYNAME(x) int x (hTab *vars, lineNode *currPl, lineNode *head) +#define FBYNAME(x) int x (hTab *vars, lineNode *currPl, lineNode *head, \ + const char *cmdLine) /*-----------------------------------------------------------------*/ /* pcDistance - afinds a label back ward or forward */ @@ -45,27 +58,27 @@ int pcDistance (lineNode *cpos, char *lbl, bool back) sprintf(buff,"%s:",lbl); while (pl) { - if (pl->line && - *pl->line != ';' && - pl->line[strlen(pl->line)-1] != ':' && - !pl->isDebug) - - dist ++; + if (pl->line && + *pl->line != ';' && + pl->line[strlen(pl->line)-1] != ':' && + !pl->isDebug) - if (strncmp(pl->line,buff,strlen(buff)) == 0) - return dist; + dist ++; - if (back) - pl = pl->prev; - else - pl = pl->next; + if (strncmp(pl->line,buff,strlen(buff)) == 0) + return dist; + + if (back) + pl = pl->prev; + else + pl = pl->next; } return 0; } /*-----------------------------------------------------------------*/ -/* flat24bitMode - will check to see if we are in flat24 mode */ +/* flat24bitMode - will check to see if we are in flat24 mode */ /*-----------------------------------------------------------------*/ FBYNAME(flat24bitMode) { @@ -82,14 +95,14 @@ FBYNAME(labelInRange) int dist = 0 ; if (!lbl) - return FALSE; + return FALSE; /* if the previous teo instructions are "ljmp"s then don't do it since it can be part of a jump table */ if (currPl->prev && currPl->prev->prev && - strstr(currPl->prev->line,"ljmp") && - strstr(currPl->prev->prev->line,"ljmp")) - return FALSE ; + strstr(currPl->prev->line,"ljmp") && + strstr(currPl->prev->prev->line,"ljmp")) + return FALSE ; /* calculate the label distance : the jump for reladdr can be +/- 127 bytes, here Iam assuming that an average 8051 @@ -98,10 +111,15 @@ FBYNAME(labelInRange) for a relative jump. we could get more precise this will suffice for now since it catches > 90% cases */ dist = (pcDistance(currPl,lbl,TRUE) + - pcDistance(currPl,lbl,FALSE)) ; - - if (!dist || dist > 45) - return FALSE; + pcDistance(currPl,lbl,FALSE)) ; + +/* if (!dist || dist > 45) has produced wrong sjmp */ + /* 07-Sep-2000 Michael Schmitt */ + /* FIX for Peephole 132 */ + /* switch with lots of case can lead to a sjmp with a distance */ + /* out of the range for sjmp */ + if (!dist || dist > 43) + return FALSE; return TRUE; } @@ -115,34 +133,111 @@ FBYNAME(operandsNotSame) char *op2 = hTabItemWithKey(vars,2); if (strcmp(op1,op2) == 0) - return FALSE; + return FALSE; else - return TRUE; + return TRUE; +} + +/* labelRefCount: + * + * takes two parameters: a variable (bound to a label name) + * and an expected reference count. + * + * Returns TRUE if that label is defined and referenced exactly + * the given number of times. + */ +FBYNAME(labelRefCount) +{ + int varNumber, expectedRefCount; + bool rc = FALSE; + + /* If we don't have the label hash table yet, build it. */ + if (!labelHash) + { + buildLabelRefCountHash(head); + } + + if (sscanf(cmdLine, "%*[ \t%]%d %d", &varNumber, &expectedRefCount) == 2) + { + char *label = hTabItemWithKey(vars, varNumber); + + if (label) + { + labelHashEntry *entry; + + entry = hTabFirstItemWK(labelHash, hashSymbolName(label)); + + while (entry) + { + if (!strcmp(label, entry->name)) + { + break; + } + entry = hTabNextItemWK(labelHash); + } + if (entry) + { +#if 0 + /* debug spew. */ + fprintf(stderr, "labelRefCount: %s has refCount %d, want %d\n", + label, entry->refCount, expectedRefCount); +#endif + + rc = (expectedRefCount == entry->refCount); + } + else + { + fprintf(stderr, "*** internal error: no label has entry for" + " %s in labelRefCount peephole.\n", + label); + } + } + else + { + fprintf(stderr, "*** internal error: var %d not bound" + " in peephole labelRefCount rule.\n", + varNumber); + } + + } + else + { + fprintf(stderr, + "*** internal error: labelRefCount peephole restriction" + " malformed: %s\n", cmdLine); + } + return rc; } /*-----------------------------------------------------------------*/ /* callFuncByName - calls a function as defined in the table */ /*-----------------------------------------------------------------*/ -int callFuncByName ( char *fname, - hTab *vars, - lineNode *currPl, - lineNode *head) +int callFuncByName ( char *fname, + hTab *vars, + lineNode *currPl, + lineNode *head) { - struct ftab { - char *fname ; - int (*func)(hTab *,lineNode *,lineNode *) ; - } ftab[] = { - {"labelInRange", labelInRange }, - {"operandsNotSame", operandsNotSame }, - {"24bitMode", flat24bitMode }, + struct ftab + { + char *fname ; + int (*func)(hTab *,lineNode *,lineNode *,const char *) ; + } ftab[] = + { + {"labelInRange", labelInRange }, + {"operandsNotSame", operandsNotSame }, + {"24bitMode", flat24bitMode }, + {"labelRefCount", labelRefCount }, }; int i; - for ( i = 0 ; i < ((sizeof (ftab))/(sizeof(struct ftab))); i++) - if (strcmp(ftab[i].fname,fname) == 0) - return (*ftab[i].func)(vars,currPl,head); + for ( i = 0 ; i < ((sizeof (ftab))/(sizeof(struct ftab))); i++) + if (strncmp(ftab[i].fname,fname,strlen(ftab[i].fname)) == 0) + { + return (*ftab[i].func)(vars,currPl,head, + fname + strlen(ftab[i].fname)); + } fprintf(stderr,"could not find named function in function table\n"); - return TRUE; + return TRUE; } /*-----------------------------------------------------------------*/ @@ -151,48 +246,48 @@ int callFuncByName ( char *fname, void printLine (lineNode *head, FILE *of) { if (!of) - of = stdout ; + of = stdout ; while (head) { - /* don't indent comments & labels */ - if (head->line && - ( *head->line == ';' || - head->line[strlen(head->line)-1] == ':')) - fprintf(of,"%s\n",head->line); - else - fprintf(of,"\t%s\n",head->line); - head = head->next; + /* don't indent comments & labels */ + if (head->line && + ( *head->line == ';' || + head->line[strlen(head->line)-1] == ':')) + fprintf(of,"%s\n",head->line); + else + fprintf(of,"\t%s\n",head->line); + head = head->next; } } /*-----------------------------------------------------------------*/ /* newPeepRule - creates a new peeprule and attach it to the root */ /*-----------------------------------------------------------------*/ -peepRule *newPeepRule (lineNode *match , - lineNode *replace, - char *cond , - int restart) +peepRule *newPeepRule (lineNode *match , + lineNode *replace, + char *cond , + int restart) { peepRule *pr ; ALLOC(pr,sizeof(peepRule)); pr->match = match; pr->replace= replace; - pr->restart = restart; - + pr->restart = restart; + if (cond && *cond) { - ALLOC_ATOMIC(pr->cond,strlen(cond)+1); - strcpy(pr->cond,cond); + ALLOC_ATOMIC(pr->cond,strlen(cond)+1); + strcpy(pr->cond,cond); } else - pr->cond = NULL ; + pr->cond = NULL ; pr->vars = newHashTable(100); /* if root is empty */ - if (!rootRules) - rootRules = currRule = pr; + if (!rootRules) + rootRules = currRule = pr; else - currRule = currRule->next = pr; + currRule = currRule->next = pr; return pr; } @@ -206,7 +301,7 @@ lineNode *newLineNode (char *line) ALLOC(pl,sizeof(lineNode)); ALLOC_ATOMIC(pl->line,strlen(line)+1); - strcpy(pl->line,line); + strcpy(pl->line,line); return pl; } @@ -216,8 +311,8 @@ lineNode *newLineNode (char *line) lineNode *connectLine (lineNode *pl1, lineNode *pl2) { if (!pl1 || !pl2) { - fprintf (stderr,"trying to connect null line\n"); - return NULL ; + fprintf (stderr,"trying to connect null line\n"); + return NULL ; } pl2->prev = pl1; @@ -245,34 +340,34 @@ static void getPeepLine (lineNode **head, char **bpp) lineNode *currL = NULL ; char *bp = *bpp; while (1) { - - if (!*bp) { - fprintf(stderr,"unexpected end of match pattern\n"); - return ; - } - - if (*bp == '\n') { - bp++ ; - while (isspace(*bp) || - *bp == '\n') bp++; - } - - if (*bp == '}') { - bp++ ; - break; - } - - /* read till end of line */ - lp = lines ; - while ((*bp != '\n' && *bp != '}' ) && *bp) - *lp++ = *bp++ ; - - *lp = '\0'; - if (!currL) - *head = currL = newLineNode (lines); - else - currL = connectLine(currL,newLineNode(lines)); - } + + if (!*bp) { + fprintf(stderr,"unexpected end of match pattern\n"); + return ; + } + + if (*bp == '\n') { + bp++ ; + while (isspace(*bp) || + *bp == '\n') bp++; + } + + if (*bp == '}') { + bp++ ; + break; + } + + /* read till end of line */ + lp = lines ; + while ((*bp != '\n' && *bp != '}' ) && *bp) + *lp++ = *bp++ ; + + *lp = '\0'; + if (!currL) + *head = currL = newLineNode (lines); + else + currL = connectLine(currL,newLineNode(lines)); + } *bpp = bp; } @@ -288,38 +383,38 @@ static void readRules (char *bp) lineNode *match; lineNode *replace; lineNode *currL = NULL; - + if (!bp) - return; + return; top: restart = 0; /* look for the token "replace" that is the start of a rule */ while (*bp && strncmp(bp,"replace",7)) bp++; - + /* if not found */ - if (!*bp) - return ; + if (!*bp) + return ; /* then look for either "restart" or '{' */ while (strncmp(bp,"restart",7) && - *bp != '{' && bp ) bp++ ; + *bp != '{' && bp ) bp++ ; /* not found */ if (!*bp) { - fprintf(stderr,"expected 'restart' or '{'\n"); - return ; + fprintf(stderr,"expected 'restart' or '{'\n"); + return ; } /* if brace */ if (*bp == '{') - bp++ ; + bp++ ; else { /* must be restart */ - restart++; - bp += strlen("restart"); - /* look for '{' */ - EXPECT_CHR(bp,'{',"expected '{'\n"); - bp++; + restart++; + bp += strlen("restart"); + /* look for '{' */ + EXPECT_CHR(bp,'{',"expected '{'\n"); + bp++; } /* skip thru all the blank space */ @@ -335,31 +430,31 @@ static void readRules (char *bp) /* then look for a '{' */ EXPECT_CHR(bp,'{',"expected '{'\n"); bp++ ; - + SKIP_SPACE(bp,"unexpected end of rule\n"); getPeepLine (&replace, &bp); - - /* look for a 'if' */ + + /* look for a 'if' */ while ((isspace(*bp) || *bp == '\n') && *bp) bp++; - + if (strncmp(bp,"if",2) == 0) { - bp += 2; - while ((isspace(*bp) || *bp == '\n') && *bp) bp++; - if (!*bp) { - fprintf(stderr,"expected condition name\n"); - return; - } - - /* look for the condition */ - lp = lines; - while (isalnum(*bp)) { - *lp++ = *bp++; - } - *lp = '\0'; - - newPeepRule(match,replace,lines,restart); + bp += 2; + while ((isspace(*bp) || *bp == '\n') && *bp) bp++; + if (!*bp) { + fprintf(stderr,"expected condition name\n"); + return; + } + + /* look for the condition */ + lp = lines; + while (*bp && (*bp != '\n')) { + *lp++ = *bp++; + } + *lp = '\0'; + + newPeepRule(match,replace,lines,restart); } else - newPeepRule(match,replace,NULL,restart); + newPeepRule(match,replace,NULL,restart); goto top; } @@ -367,13 +462,13 @@ static void readRules (char *bp) /*-----------------------------------------------------------------*/ /* keyForVar - returns the numeric key for a var */ /*-----------------------------------------------------------------*/ -static int keyForVar (char *d) +static int keyForVar (char *d) { int i = 0; while (isdigit(*d)) { - i *= 10 ; - i += (*d++ - '0') ; + i *= 10 ; + i += (*d++ - '0') ; } return i; @@ -387,26 +482,26 @@ static void bindVar (int key, char **s, hTab **vtab) char vval[MAX_PATTERN_LEN]; char *vvx; char *vv = vval; - + /* first get the value of the variable */ vvx = *s; /* the value is ended by a ',' or space or newline or null */ - while (*vvx && - *vvx != ',' && - !isspace(*vvx) && - *vvx != '\n' && - *vvx != ':' ) { - char ubb = 0 ; - /* if we find a '(' then we need to balance it */ - if (*vvx == '(') { - ubb++ ; - while (ubb) { - *vv++ = *vvx++ ; - if (*vvx == '(') ubb++; - if (*vvx == ')') ubb--; - } - } else - *vv++ = *vvx++ ; + while (*vvx && + *vvx != ',' && + !isspace(*vvx) && + *vvx != '\n' && + *vvx != ':' ) { + char ubb = 0 ; + /* if we find a '(' then we need to balance it */ + if (*vvx == '(') { + ubb++ ; + while (ubb) { + *vv++ = *vvx++ ; + if (*vvx == '(') ubb++; + if (*vvx == ')') ubb--; + } + } else + *vv++ = *vvx++ ; } *s = vvx ; *vv = '\0'; @@ -414,121 +509,121 @@ static void bindVar (int key, char **s, hTab **vtab) ALLOC_ATOMIC(vvx,strlen(vval)+1); strcpy(vvx,vval); hTabAddItem(vtab,key,vvx); - + } /*-----------------------------------------------------------------*/ /* matchLine - matches one line */ /*-----------------------------------------------------------------*/ static bool matchLine (char *s, char *d, hTab **vars) -{ +{ if (!s || !(*s)) - return FALSE; + return FALSE; while (*s && *d) { - /* skip white space in both */ - while (isspace(*s)) s++; - while (isspace(*d)) d++; - - /* if the destination is a var */ - if (*d == '%' && isdigit(*(d+1))) { - char *v = hTabItemWithKey(*vars,keyForVar(d+1)); - /* if the variable is already bound - then it MUST match with dest */ - if (v) { - while (*v) - if (*v++ != *s++) return FALSE; - } else - /* variable not bound we need to - bind it */ - bindVar (keyForVar(d+1),&s,vars); - - /* in either case go past the variable */ - d++ ; - while (isdigit(*d)) d++; - } + /* skip white space in both */ + while (isspace(*s)) s++; + while (isspace(*d)) d++; + + /* if the destination is a var */ + if (*d == '%' && isdigit(*(d+1))) { + char *v = hTabItemWithKey(*vars,keyForVar(d+1)); + /* if the variable is already bound + then it MUST match with dest */ + if (v) { + while (*v) + if (*v++ != *s++) return FALSE; + } else + /* variable not bound we need to + bind it */ + bindVar (keyForVar(d+1),&s,vars); + + /* in either case go past the variable */ + d++ ; + while (isdigit(*d)) d++; + } - /* they should be an exact match other wise */ - if (*s && *d) { - while (isspace(*s))s++; - while (isspace(*d))d++; - if (*s++ != *d++) - return FALSE; - } + /* they should be an exact match other wise */ + if (*s && *d) { + while (isspace(*s))s++; + while (isspace(*d))d++; + if (*s++ != *d++) + return FALSE; + } } - /* get rid of the trailing spaces + /* get rid of the trailing spaces in both source & destination */ - if (*s) - while (isspace(*s)) s++; + if (*s) + while (isspace(*s)) s++; if (*d) - while (isspace(*d)) d++; + while (isspace(*d)) d++; /* after all this if only one of them has something left over then no match */ if (*s || *d) - return FALSE ; - + return FALSE ; + return TRUE ; } /*-----------------------------------------------------------------*/ /* matchRule - matches a all the rule lines */ /*-----------------------------------------------------------------*/ -static bool matchRule (lineNode *pl, - lineNode **mtail, - peepRule *pr, - lineNode *head) +static bool matchRule (lineNode *pl, + lineNode **mtail, + peepRule *pr, + lineNode *head) { lineNode *spl ; /* source pl */ lineNode *rpl ; /* rule peep line */ - - hTabClearAll(pr->vars); + + hTabClearAll(pr->vars); /* setToNull((void **) &pr->vars); */ /* pr->vars = newHashTable(100); */ /* for all the lines defined in the rule */ rpl = pr->match; - spl = pl ; + spl = pl ; while (spl && rpl) { - /* if the source line starts with a ';' then - comment line don't process or the source line - contains == . debugger information skip it */ - if (spl->line && - (*spl->line == ';' || spl->isDebug)) { - spl = spl->next; - continue; - } + /* if the source line starts with a ';' then + comment line don't process or the source line + contains == . debugger information skip it */ + if (spl->line && + (*spl->line == ';' || spl->isDebug)) { + spl = spl->next; + continue; + } + + if (!matchLine(spl->line,rpl->line,&pr->vars)) + return FALSE ; - if (!matchLine(spl->line,rpl->line,&pr->vars)) - return FALSE ; - - rpl = rpl->next ; - if (rpl) - spl = spl->next ; + rpl = rpl->next ; + if (rpl) + spl = spl->next ; } /* if rules ended */ if (!rpl) { - /* if this rule has additional conditions */ - if ( pr->cond) { - if (callFuncByName (pr->cond, pr->vars,pl,head) ) { - *mtail = spl; - return TRUE; - } else - return FALSE; - } else { - *mtail = spl; - return TRUE; - } + /* if this rule has additional conditions */ + if ( pr->cond) { + if (callFuncByName (pr->cond, pr->vars,pl,head) ) { + *mtail = spl; + return TRUE; + } else + return FALSE; + } else { + *mtail = spl; + return TRUE; + } } else - return FALSE; + return FALSE; } /*-----------------------------------------------------------------*/ @@ -537,76 +632,213 @@ static bool matchRule (lineNode *pl, static void replaceRule (lineNode **shead, lineNode *stail, peepRule *pr) { lineNode *cl = NULL; - lineNode *pl = NULL , *lhead = NULL; + lineNode *pl = NULL , *lhead = NULL; char lb[MAX_PATTERN_LEN]; char *lbp; lineNode *comment = NULL; /* collect all the comment lines in the source */ for (cl = *shead ; cl != stail ; cl = cl->next) { - if (cl->line && ( *cl->line == ';' || cl->isDebug)) { - pl = (pl ? connectLine (pl,newLineNode(cl->line)) : - (comment = newLineNode(cl->line))); - pl->isDebug = cl->isDebug; - } + if (cl->line && ( *cl->line == ';' || cl->isDebug)) { + pl = (pl ? connectLine (pl,newLineNode(cl->line)) : + (comment = newLineNode(cl->line))); + pl->isDebug = cl->isDebug; + } } cl = NULL; - + /* for all the lines in the replacement pattern do */ for ( pl = pr->replace ; pl ; pl = pl->next ) { - char *v; - char *l; - lbp = lb; - - l = pl->line; - while (*l) { - /* if the line contains a variable */ - if (*l == '%' && isdigit(*(l+1))) { - v = hTabItemWithKey(pr->vars,keyForVar(l+1)); - if (!v) { - fprintf(stderr,"used unbound variable in replacement\n"); - l++; - continue; - } - while (*v) - *lbp++ = *v++; - l++; - while (isdigit(*l)) l++; - continue ; - } - *lbp++ = *l++; - } + char *v; + char *l; + lbp = lb; + + l = pl->line; + while (*l) { + /* if the line contains a variable */ + if (*l == '%' && isdigit(*(l+1))) { + v = hTabItemWithKey(pr->vars,keyForVar(l+1)); + if (!v) { + fprintf(stderr,"used unbound variable in replacement\n"); + l++; + continue; + } + while (*v) + *lbp++ = *v++; + l++; + while (isdigit(*l)) l++; + continue ; + } + *lbp++ = *l++; + } - *lbp = '\0'; - if (cl) - cl = connectLine(cl,newLineNode(lb)); - else - lhead = cl = newLineNode(lb); + *lbp = '\0'; + if (cl) + cl = connectLine(cl,newLineNode(lb)); + else + lhead = cl = newLineNode(lb); } /* add the comments if any to the head of list */ if (comment) { - lineNode *lc = comment; - while (lc->next) lc = lc->next; - lc->next = lhead; - if (lhead) - lhead->prev = lc; - lhead = comment; + lineNode *lc = comment; + while (lc->next) lc = lc->next; + lc->next = lhead; + if (lhead) + lhead->prev = lc; + lhead = comment; } /* now we need to connect / replace the original chain */ /* if there is a prev then change it */ if ((*shead)->prev) { - (*shead)->prev->next = lhead; - lhead->prev = (*shead)->prev; - } else - *shead = lhead; + (*shead)->prev->next = lhead; + lhead->prev = (*shead)->prev; + } else + *shead = lhead; /* now for the tail */ if (stail && stail->next) { - stail->next->prev = cl; - if (cl) - cl->next = stail->next; - } + stail->next->prev = cl; + if (cl) + cl->next = stail->next; + } +} + +/* Returns TRUE if this line is a label definition. + * + * If so, start will point to the start of the label name, + * and len will be it's length. + */ +bool isLabelDefinition(const char *line, const char **start, int *len) +{ + const char *cp = line; + + /* This line is a label if if consists of: + * [optional whitespace] followed by identifier chars + * (alnum | $ | _ ) followed by a colon. + */ + + while (*cp && isspace(*cp)) + { + cp++; + } + + if (!*cp) + { + return FALSE; + } + + *start = cp; + + while (isalnum(*cp) || (*cp == '$') || (*cp == '_')) + { + cp++; + } + + if ((cp == *start) || (*cp != ':')) + { + return FALSE; + } + + *len = (cp - (*start)); + return TRUE; +} + +/* Quick & dirty string hash function. */ +static int hashSymbolName(const char *name) +{ + int hash = 0; + + while (*name) + { + hash = (hash << 6) ^ *name; + name++; + } + + if (hash < 0) + { + hash = -hash; + } + + return hash % HTAB_SIZE; +} + +/* Build a hash of all labels in the passed set of lines + * and how many times they are referenced. + */ +static void buildLabelRefCountHash(lineNode *head) +{ + lineNode *line; + const char *label; + int labelLen; + int i; + + assert(labelHash == NULL); + labelHash = newHashTable(HTAB_SIZE); + + /* First pass: locate all the labels. */ + line = head; + + while (line) + { + if (isLabelDefinition(line->line, &label, &labelLen) + && labelLen <= SDCC_NAME_MAX) + { + labelHashEntry *entry; + + ALLOC(entry, sizeof(labelHashEntry)); + + assert(entry != NULL); + + memcpy(entry->name, label, labelLen); + entry->name[labelLen] = 0; + entry->refCount = -1; + + hTabAddItem(&labelHash, hashSymbolName(entry->name), entry); + } + line = line->next; + } + + + /* Second pass: for each line, note all the referenced labels. */ + /* This is ugly, O(N^2) stuff. Optimizations welcome... */ + line = head; + while (line) + { + for (i = 0; i < HTAB_SIZE; i++) + { + labelHashEntry *thisEntry; + + thisEntry = hTabFirstItemWK(labelHash, i); + + while (thisEntry) + { + if (strstr(line->line, thisEntry->name)) + { + thisEntry->refCount++; + } + thisEntry = hTabNextItemWK(labelHash); + } + } + line = line->next; + } + +#if 0 + /* Spew the contents of the table. Debugging fun only. */ + for (i = 0; i < HTAB_SIZE; i++) + { + labelHashEntry *thisEntry; + + thisEntry = hTabFirstItemWK(labelHash, i); + + while (thisEntry) + { + fprintf(stderr, "label: %s ref %d\n", + thisEntry->name, thisEntry->refCount); + thisEntry = hTabNextItemWK(labelHash); + } + } +#endif } /*-----------------------------------------------------------------*/ @@ -614,37 +846,43 @@ static void replaceRule (lineNode **shead, lineNode *stail, peepRule *pr) /*-----------------------------------------------------------------*/ void peepHole (lineNode **pls ) { - lineNode *spl ; + lineNode *spl ; peepRule *pr ; lineNode *mtail = NULL; - top: + if (labelHash) + { + hTabDeleteAll(labelHash); + } + labelHash = NULL; + + top: /* for all rules */ for (pr = rootRules ; pr ; pr = pr->next ) { - - for (spl = *pls ; spl ; spl = spl->next ) { - - /* if inline assembler then no peep hole */ - if (spl->isInline) - continue ; - - mtail = NULL ; - - /* if it matches */ - if (matchRule (spl,&mtail,pr, *pls)) { - - /* then replace */ - if (spl == *pls) - replaceRule(pls, mtail, pr); - else - replaceRule (&spl, mtail,pr); - - /* if restart rule type then - start at the top again */ - if (pr->restart) - goto top; - } - } + + for (spl = *pls ; spl ; spl = spl->next ) { + + /* if inline assembler then no peep hole */ + if (spl->isInline) + continue ; + + mtail = NULL ; + + /* if it matches */ + if (matchRule (spl,&mtail,pr, *pls)) { + + /* then replace */ + if (spl == *pls) + replaceRule(pls, mtail, pr); + else + replaceRule (&spl, mtail,pr); + + /* if restart rule type then + start at the top again */ + if (pr->restart) + goto top; + } + } } } @@ -655,45 +893,45 @@ void peepHole (lineNode **pls ) static char *readFileIntoBuffer (char *fname) { FILE *f; - char *rs = NULL; + char *rs = NULL; int nch = 0 ; int ch; char lb[MAX_PATTERN_LEN]; if (!(f = fopen(fname,"r"))) { - fprintf(stderr,"cannot open peep rule file\n"); - return NULL; + fprintf(stderr,"cannot open peep rule file\n"); + return NULL; } while ((ch = fgetc(f)) != EOF) { - lb[nch++] = ch; - - /* if we maxed out our local buffer */ - if (nch >= (MAX_PATTERN_LEN - 2)) { - lb[nch] = '\0'; - /* copy it into allocated buffer */ - if (rs) { - rs = GC_realloc(rs,strlen(rs)+strlen(lb)+1); - strcat(rs,lb); - } else { - ALLOC_ATOMIC(rs,strlen(lb)+1); - strcpy(rs,lb); - } - nch = 0 ; - } + lb[nch++] = ch; + + /* if we maxed out our local buffer */ + if (nch >= (MAX_PATTERN_LEN - 2)) { + lb[nch] = '\0'; + /* copy it into allocated buffer */ + if (rs) { + rs = GC_realloc(rs,strlen(rs)+strlen(lb)+1); + strcat(rs,lb); + } else { + ALLOC_ATOMIC(rs,strlen(lb)+1); + strcpy(rs,lb); + } + nch = 0 ; + } } /* if some charaters left over */ if (nch) { - lb[nch] = '\0'; - /* copy it into allocated buffer */ - if (rs) { - rs = GC_realloc(rs,strlen(rs)+strlen(lb)+1); - strcat(rs,lb); - } else { - ALLOC_ATOMIC(rs,strlen(lb)+1); - strcpy(rs,lb); - } + lb[nch] = '\0'; + /* copy it into allocated buffer */ + if (rs) { + rs = GC_realloc(rs,strlen(rs)+strlen(lb)+1); + strcat(rs,lb); + } else { + ALLOC_ATOMIC(rs,strlen(lb)+1); + strcpy(rs,lb); + } } return rs; } @@ -710,7 +948,7 @@ void initPeepHole () /* if we have any additional file read it too */ if (options.peep_file) { - readRules(s=readFileIntoBuffer(options.peep_file)); - setToNull((void **) &s); + readRules(s=readFileIntoBuffer(options.peep_file)); + setToNull((void **) &s); } }