X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCpeeph.c;h=5a7447fff503ce66a2099c3a4ccd4d7da8c5a905;hb=5a1d5e778e85664f4e6657019348b4756b16eacb;hp=c5534bc2ed69466b94901c1971551695d90bb7bd;hpb=718b60e3887d0e69341bd1e9d335ce9d09441e5f;p=fw%2Fsdcc diff --git a/src/SDCCpeeph.c b/src/SDCCpeeph.c index c5534bc2..5a7447ff 100644 --- a/src/SDCCpeeph.c +++ b/src/SDCCpeeph.c @@ -24,19 +24,18 @@ -------------------------------------------------------------------------*/ #include "common.h" +#include "dbuf_string.h" + +#define ISCHARDIGIT(c) isdigit((unsigned char)c) +#define ISCHARSPACE(c) isspace((unsigned char)c) +#define ISCHARALNUM(c) isalnum((unsigned char)c) static peepRule *rootRules = NULL; static peepRule *currRule = NULL; #define HTAB_SIZE 53 -typedef struct - { - char name[SDCC_NAME_MAX + 1]; - int refCount; - } -labelHashEntry; -static hTab *labelHash = NULL; +hTab *labelHash = NULL; static struct { @@ -46,12 +45,12 @@ static struct static int hashSymbolName (const char *name); static void buildLabelRefCountHash (lineNode * head); +static void bindVar (int key, char **s, hTab ** vtab); static bool matchLine (char *, char *, hTab **); -bool isLabelDefinition (const char *line, const char **start, int *len); -#define FBYNAME(x) int x (hTab *vars, lineNode *currPl, lineNode *endPl, \ - lineNode *head, const char *cmdLine) +#define FBYNAME(x) static int x (hTab *vars, lineNode *currPl, lineNode *endPl, \ + lineNode *head, char *cmdLine) #if !OPT_DISABLE_PIC void peepRules2pCode(peepRule *); @@ -62,10 +61,41 @@ void pic16_peepRules2pCode(peepRule *); #endif /*-----------------------------------------------------------------*/ -/* pcDistance - afinds a label back ward or forward */ +/* getPatternVar - finds a pattern variable */ +/*-----------------------------------------------------------------*/ + +static char* +getPatternVar (hTab *vars, char **cmdLine) +{ + int varNumber; + char *digitend; + + if (!cmdLine || !*cmdLine || !**cmdLine) + return NULL; /* no parameters given */ + + while (**cmdLine && ISCHARSPACE(**cmdLine)) + (*cmdLine)++; /* skip whitespace */ + + if (**cmdLine != '%') + goto error; + (*cmdLine)++; + if (!ISCHARDIGIT (**cmdLine)) + goto error; + varNumber = strtol (*cmdLine, &digitend, 10); + *cmdLine = digitend; + return hTabItemWithKey (vars, varNumber); + +error: + fprintf (stderr, + "*** internal error: peephole restriction malformed: %s\n", *cmdLine); + return NULL; +} + +/*-----------------------------------------------------------------*/ +/* pcDistance - finds a label backward or forward */ /*-----------------------------------------------------------------*/ -int +static int pcDistance (lineNode * cpos, char *lbl, bool back) { lineNode *pl = cpos; @@ -75,47 +105,40 @@ pcDistance (lineNode * cpos, char *lbl, bool back) SNPRINTF (buff, sizeof(buff), "%s:", lbl); while (pl) { - if (pl->line && - *pl->line != ';' && - pl->line[strlen (pl->line) - 1] != ':' && - !pl->isDebug) { - if (port->peep.getSize) { - dist += port->peep.getSize(pl); - } else { - dist += 3; - } - } + !pl->isComment && + !pl->isLabel && + !pl->isDebug) + { + if (port->peep.getSize) + { + dist += port->peep.getSize(pl); + } + else + { + dist += 3; + } + } if (strncmp (pl->line, buff, strlen (buff)) == 0) - return dist; + return dist; if (back) - pl = pl->prev; + pl = pl->prev; else - pl = pl->next; + pl = pl->next; } return 0; } /*-----------------------------------------------------------------*/ -/* flat24bitModeAndPortDS390 - */ -/*-----------------------------------------------------------------*/ -FBYNAME (flat24bitModeAndPortDS390) -{ - return (((strcmp(port->target,"ds390") == 0) || - (strcmp(port->target,"ds400") == 0)) && - (options.model == MODEL_FLAT24)); -} - -/*-----------------------------------------------------------------*/ -/* portIsDS390 - return true if port is DS390 */ +/* portIsDS390 - return true if port is DS390 */ /*-----------------------------------------------------------------*/ FBYNAME (portIsDS390) { return ((strcmp(port->target,"ds390") == 0) || - (strcmp(port->target,"ds400") == 0)); + (strcmp(port->target,"ds400") == 0)); } /*-----------------------------------------------------------------*/ @@ -134,51 +157,65 @@ FBYNAME (xramMovcOption) return (options.xram_movc && (strcmp(port->target,"mcs51") == 0)); } - - - - +/*-----------------------------------------------------------------*/ +/* useAcallAjmp - Enable replacement of lcall/ljmp with acall/ajmp */ +/*-----------------------------------------------------------------*/ +FBYNAME (useAcallAjmp) +{ + return (options.acall_ajmp && (strcmp(port->target,"mcs51") == 0)); +} /*-----------------------------------------------------------------*/ -/* labelInRange - will check to see if label %5 is within range */ +/* labelInRange - will check to see if label is within range */ /*-----------------------------------------------------------------*/ FBYNAME (labelInRange) { - /* assumes that %5 pattern variable has the label name */ - char *lbl = hTabItemWithKey (vars, 5); int dist = 0; + char *lbl = getPatternVar (vars, &cmdLine); if (!lbl) - return FALSE; + { + /* If no parameters given, assume that %5 pattern variable + has the label name for backward compatibility */ + lbl = hTabItemWithKey (vars, 5); + } - /* Don't optimize jumps in a jump table; a more generic test */ - if (currPl->ic && currPl->ic->op == JUMPTABLE) - return FALSE; - - /* if the previous two 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")) + if (!lbl) return FALSE; - /* calculate the label distance : the jump for reladdr can be - +/- 127 bytes, here Iam assuming that an average 8051 - instruction is 2 bytes long, so if the label is more than - 63 intructions away, the label is considered out of range - 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)); - -/* changed to 127, now that pcDistance return actual number of bytes */ - if (!dist || dist > 127) - return FALSE; + do + { + /* Don't optimize jumps in a jump table; a more generic test */ + if (currPl->ic && currPl->ic->op == JUMPTABLE) + return FALSE; + + /* if the previous two 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; + + /* calculate the label distance : the jump for reladdr can be + +/- 127 bytes, here I am assuming that an average 8051 + instruction is 2 bytes long, so if the label is more than + 63 intructions away, the label is considered out of range + 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)); + + /* changed to 127, now that pcDistance return actual number of bytes */ + if (!dist || dist > 127) + return FALSE; + + lbl = getPatternVar (vars, &cmdLine); + } + while (lbl); return TRUE; } - /*-----------------------------------------------------------------*/ /* labelJTInRange - will check to see if label %5 and up are */ /* within range. */ @@ -192,13 +229,13 @@ FBYNAME (labelJTInRange) if (!getenv("SDCC_SJMP_JUMPTABLE")) return FALSE; - + /* Only optimize within a jump table */ if (currPl->ic && currPl->ic->op != JUMPTABLE) return FALSE; - + count = elementsInSet( IC_JTLABELS (currPl->ic) ); - + /* check all labels (this is needed if the case statements are unsorted) */ for (i=0; i 127+ /* range of sjmp */ - (7+3*i)+ /* offset between this jump and currPl, + (7+3*i)+ /* offset between this jump and currPl, should use pcDistance instead? */ (count-i-1) /* if peephole applies distance is shortened */ ) @@ -222,7 +259,6 @@ FBYNAME (labelJTInRange) return TRUE; } - /*-----------------------------------------------------------------*/ /* labelIsReturnOnly - Check if label %5 is followed by RET */ /*-----------------------------------------------------------------*/ @@ -234,38 +270,131 @@ FBYNAME (labelIsReturnOnly) int len; char * retInst; + /* Don't optimize jumps in a jump table; a more generic test */ + if (currPl->ic && currPl->ic->op == JUMPTABLE) + return FALSE; + label = hTabItemWithKey (vars, 5); - if (!label) return FALSE; + if (!label) + return FALSE; len = strlen(label); - for(pl = currPl; pl; pl = pl->next) { - if (pl->line && !pl->isDebug && !pl->isComment && - pl->line[strlen(pl->line)-1] == ':') { - if (strncmp(pl->line, label, len) == 0) break; /* Found Label */ - if (strlen(pl->line) != 7 || !isdigit(*(pl->line)) || - !isdigit(*(pl->line+1)) || !isdigit(*(pl->line+2)) || - !isdigit(*(pl->line+3)) || !isdigit(*(pl->line+4)) || - *(pl->line+5) != '$') { - return FALSE; /* non-local label encountered */ - } - } - } - if (!pl) return FALSE; /* did not find the label */ + for(pl = currPl; pl; pl = pl->next) + { + if (pl->line && !pl->isDebug && !pl->isComment && pl->isLabel) + { + if (strncmp(pl->line, label, len) == 0) + break; /* Found Label */ + if (strlen(pl->line) != 7 || !ISCHARDIGIT(*(pl->line)) || + !ISCHARDIGIT(*(pl->line+1)) || !ISCHARDIGIT(*(pl->line+2)) || + !ISCHARDIGIT(*(pl->line+3)) || !ISCHARDIGIT(*(pl->line+4)) || + *(pl->line+5) != '$') + { + return FALSE; /* non-local label encountered */ + } + } + } + if (!pl) + return FALSE; /* did not find the label */ pl = pl->next; while (pl && (pl->isDebug || pl->isComment)) pl = pl->next; - if (!pl || !pl->line || pl->isDebug) return FALSE; /* next line not valid */ + if (!pl || !pl->line || pl->isDebug) + return FALSE; /* next line not valid */ p = pl->line; - for (p = pl->line; *p && isspace(*p); p++) - ; - + for (p = pl->line; *p && ISCHARSPACE(*p); p++) + ; + retInst = "ret"; if (TARGET_IS_HC08) retInst = "rts"; - if (strcmp(p, retInst) == 0) return TRUE; + if (strcmp(p, retInst) == 0) + return TRUE; return FALSE; } +/*-----------------------------------------------------------------*/ +/* labelIsUncondJump - Check if label %5 is followed by an */ +/* unconditional jump and put the destination of that jump in %6 */ +/*-----------------------------------------------------------------*/ +FBYNAME (labelIsUncondJump) +{ + /* assumes that %5 pattern variable has the label name */ + const char *label; + char *p, *q; + const lineNode *pl; + int len; + char * jpInst = NULL; + + /* Don't optimize jumps in a jump table; a more generic test */ + if (currPl->ic && currPl->ic->op == JUMPTABLE) + return FALSE; + + label = hTabItemWithKey (vars, 5); + if (!label) + return FALSE; + len = strlen(label); + + for (pl = currPl; pl; pl = pl->next) + { + if (pl->line && !pl->isDebug && !pl->isComment && pl->isLabel) + { + if (strncmp(pl->line, label, len) == 0) + break; /* Found Label */ + if (strlen(pl->line) != 7 || !ISCHARDIGIT(*(pl->line)) || + !ISCHARDIGIT(*(pl->line+1)) || !ISCHARDIGIT(*(pl->line+2)) || + !ISCHARDIGIT(*(pl->line+3)) || !ISCHARDIGIT(*(pl->line+4)) || + *(pl->line+5) != '$') + { + return FALSE; /* non-local label encountered */ + } + } + } + if (!pl) + return FALSE; /* did not find the label */ + pl = pl->next; + while (pl && (pl->isDebug || pl->isComment)) + pl = pl->next; + if (!pl || !pl->line) + return FALSE; /* next line not valid */ + p = pl->line; + while (*p && ISCHARSPACE(*p)) + p++; + + if (TARGET_MCS51_LIKE) + jpInst = "ljmp"; + if (TARGET_IS_HC08) + jpInst = "jmp"; + if (TARGET_Z80_LIKE) + jpInst = "jp"; + len = strlen(jpInst); + if (strncmp(p, jpInst, len) != 0) + return FALSE; /* next line is no jump */ + p += len; + while (*p && ISCHARSPACE(*p)) + p++; + + q = p; + while (*q && *q!=';') + q++; + while (q>p && ISCHARSPACE(*q)) + q--; + len = q-p; + if (len == 0) + return FALSE; /* no destination? */ + if (TARGET_Z80_LIKE) + { + while (q>p && *q!=',') + q--; + if (*q==',') + return FALSE; /* conditional jump */ + } + if (strcmp(p, q) == 0) + return FALSE; /* labels are equal */ + /* now put the destination in %6 */ + bindVar (6, &p, &vars); + return TRUE; +} /*-----------------------------------------------------------------*/ /* okToRemoveSLOC - Check if label %1 is a SLOC and not other */ @@ -289,19 +418,54 @@ FBYNAME (okToRemoveSLOC) /* Look for any occurance of this SLOC before the peephole match */ for (pl = currPl->prev; pl; pl = pl->prev) { - if (pl->line && !pl->isDebug && !pl->isComment - && *pl->line != ';' && strstr(pl->line, sloc)) - return FALSE; + if (pl->line && !pl->isDebug && !pl->isComment + && *pl->line != ';' && strstr(pl->line, sloc)) + return FALSE; } /* Look for any occurance of this SLOC after the peephole match */ for (pl = endPl->next; pl; pl = pl->next) { - if (pl->line && !pl->isDebug && !pl->isComment - && *pl->line != ';' && strstr(pl->line, sloc)) - return FALSE; + if (pl->line && !pl->isDebug && !pl->isComment + && *pl->line != ';' && strstr(pl->line, sloc)) + return FALSE; } return TRUE; /* safe for a peephole to remove it :) */ } +/*-----------------------------------------------------------------*/ +/* deadMove - Check, if a pop/push pair can be removed */ +/*-----------------------------------------------------------------*/ +FBYNAME (deadMove) +{ + const char *reg = hTabItemWithKey (vars, 1); + + if (port->peep.deadMove) + return port->peep.deadMove (reg, currPl, head); + + fprintf (stderr, "Function deadMove not initialized in port structure\n"); + return FALSE; +} + +/*-----------------------------------------------------------------*/ +/* notUsed - Check, if value in register is not read again */ +/*-----------------------------------------------------------------*/ +FBYNAME (notUsed) +{ + const char *what; + + if(cmdLine[0] != '\'') + what = hTabItemWithKey (vars, 1); + else + { + cmdLine[strlen(cmdLine) - 1] = 0; + what = cmdLine + 1; + } + + if (port->peep.notUsed) + return port->peep.notUsed (what, endPl, head); + + fprintf (stderr, "Function notUsed not initialized in port structure\n"); + return FALSE; +} /*-----------------------------------------------------------------*/ /* operandsNotSame - check if %1 & %2 are the same */ @@ -413,7 +577,6 @@ FBYNAME (operandsNotSame6) return TRUE; } - /*-----------------------------------------------------------------*/ /* operandsNotSame7- check if any pair of %1,%2,%3,.. are the same */ /*-----------------------------------------------------------------*/ @@ -500,6 +663,34 @@ FBYNAME (operandsNotSame8) return TRUE; } +/*-----------------------------------------------------------------*/ +/* labelHashEntry- searches for a label in the list labelHash */ +/* Builds labelHash, if it does not yet exist. */ +/* Returns the labelHashEntry or NULL */ +/*-----------------------------------------------------------------*/ +labelHashEntry * +getLabelRef (const char *label, lineNode *head) +{ + labelHashEntry *entry; + + /* If we don't have the label hash table yet, build it. */ + if (!labelHash) + { + buildLabelRefCountHash (head); + } + + entry = hTabFirstItemWK (labelHash, hashSymbolName (label)); + + while (entry) + { + if (!strcmp (label, entry->name)) + { + break; + } + entry = hTabNextItemWK (labelHash); + } + return entry; +} /* labelRefCount: @@ -514,60 +705,120 @@ FBYNAME (labelRefCount) int varNumber, expectedRefCount; bool rc = FALSE; + if (sscanf (cmdLine, "%*[ \t%]%d %d", &varNumber, &expectedRefCount) == 2) + { + char *label = hTabItemWithKey (vars, varNumber); + + if (label) + { + labelHashEntry *entry = getLabelRef (label, head); + + 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; +} + +/* labelRefCountChange: + * takes two parameters: a variable (bound to a label name) + * and a signed int for changing the reference count. + * + * Please note, this function is not a conditional. It unconditionally + * changes the label. It should be passed as the 'last' function + * so it only is applied if all other conditions have been met. + * + * should always return TRUE + */ +FBYNAME (labelRefCountChange) +{ + int varNumber, RefCountDelta; + 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) + if (sscanf (cmdLine, "%*[ \t%]%d %i", &varNumber, &RefCountDelta) == 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 + { + labelHashEntry *entry; - 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); - } + entry = hTabFirstItemWK (labelHash, hashSymbolName (label)); + while (entry) + { + if (!strcmp (label, entry->name)) + { + break; + } + entry = hTabNextItemWK (labelHash); + } + if (entry) + { + if (0 <= entry->refCount + RefCountDelta) + { + entry->refCount += RefCountDelta; + rc = TRUE; + } + else + { + fprintf (stderr, "*** internal error: label %s may not get" + " negative refCount in %s peephole.\n", + label, __FUNCTION__); + } + } + else + { + fprintf (stderr, "*** internal error: no label has entry for" + " %s in %s peephole.\n", + label, __FUNCTION__); + } + } + else + { + fprintf (stderr, "*** internal error: var %d not bound" + " in peephole %s rule.\n", + varNumber, __FUNCTION__); + } } else { fprintf (stderr, - "*** internal error: labelRefCount peephole restriction" - " malformed: %s\n", cmdLine); + "*** internal error: labelRefCount peephole restriction" + " malformed: %s\n", cmdLine); } return rc; } @@ -614,7 +865,7 @@ notVolatileVariable(char *var, lineNode *currPl, lineNode *endPl) /* Extract a symbol name from the variable */ while (*vp && (*vp!='_')) vp++; - while (*vp && (isalnum(*vp) || *vp=='_')) + while (*vp && (ISCHARALNUM(*vp) || *vp=='_')) *p++ = *vp++; *p='\0'; @@ -636,26 +887,56 @@ notVolatileVariable(char *var, lineNode *currPl, lineNode *endPl) { case IFX: op = IC_COND (cl->ic); - if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) ) - return !op->isvolatile; + if (IS_SYMOP (op) && + ( !strcmp(OP_SYMBOL (op)->rname, symname) || + (OP_SYMBOL (op)->isspilt && + SPIL_LOC (op) && + !strcmp(SPIL_LOC (op)->rname, symname)) )) + { + return !op->isvolatile; + } case JUMPTABLE: op = IC_JTCOND (cl->ic); - if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) ) - return !op->isvolatile; + if (IS_SYMOP (op) && + ( !strcmp(OP_SYMBOL (op)->rname, symname) || + (OP_SYMBOL (op)->isspilt && + SPIL_LOC (op) && + !strcmp(SPIL_LOC (op)->rname, symname)) )) + { + return !op->isvolatile; + } default: op = IC_LEFT (cl->ic); - if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) ) - return !op->isvolatile; + if (IS_SYMOP (op) && + ( !strcmp(OP_SYMBOL (op)->rname, symname) || + (OP_SYMBOL (op)->isspilt && + SPIL_LOC (op) && + !strcmp(SPIL_LOC (op)->rname, symname)) )) + { + return !op->isvolatile; + } op = IC_RIGHT (cl->ic); - if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) ) - return !op->isvolatile; + if (IS_SYMOP (op) && + ( !strcmp(OP_SYMBOL (op)->rname, symname) || + (OP_SYMBOL (op)->isspilt && + SPIL_LOC (op) && + !strcmp(SPIL_LOC (op)->rname, symname)) )) + { + return !op->isvolatile; + } op = IC_RESULT (cl->ic); - if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) ) - return !op->isvolatile; + if (IS_SYMOP (op) && + ( !strcmp(OP_SYMBOL (op)->rname, symname) || + (OP_SYMBOL (op)->isspilt && + SPIL_LOC (op) && + !strcmp(SPIL_LOC (op)->rname, symname)) )) + { + return !op->isvolatile; + } } } } - + /* Couldn't find the symbol for some reason. Assume volatile. */ return FALSE; } @@ -717,18 +998,18 @@ FBYNAME (notVolatile) } /* There were parameters; check the volatility of each */ - while (*cmdLine && isspace(*cmdLine)) + while (*cmdLine && ISCHARSPACE(*cmdLine)) cmdLine++; while (*cmdLine) { if (*cmdLine!='%') goto error; cmdLine++; - if (!isdigit(*cmdLine)) + if (!ISCHARDIGIT(*cmdLine)) goto error; varNumber = strtol(cmdLine, &digitend, 10); cmdLine = digitend; - while (*cmdLine && isspace(*cmdLine)) + while (*cmdLine && ISCHARSPACE(*cmdLine)) cmdLine++; var = hTabItemWithKey (vars, varNumber); @@ -740,153 +1021,364 @@ FBYNAME (notVolatile) return FALSE; } else - { - fprintf (stderr, "*** internal error: var %d not bound" - " in peephole notVolatile rule.\n", - varNumber); - return FALSE; - } + { + fprintf (stderr, "*** internal error: var %d not bound" + " in peephole notVolatile rule.\n", + varNumber); + return FALSE; + } } return TRUE; - - + error: fprintf (stderr, "*** internal error: notVolatile peephole restriction" " malformed: %s\n", cmdLine); return FALSE; } - -/*-----------------------------------------------------------------*/ -/* callFuncByName - calls a function as defined in the table */ -/*-----------------------------------------------------------------*/ -int -callFuncByName (char *fname, - hTab * vars, - lineNode * currPl, - lineNode * endPl, - lineNode * head) +/*------------------------------------------------------------------*/ +/* setFromConditionArgs - parse a peephole condition's arguments */ +/* to produce a set of strings, one per argument. Variables %x will */ +/* be replaced with their values. String literals (in single quotes)*/ +/* are accepted and return in unquoted form. */ +/*------------------------------------------------------------------*/ +static set * +setFromConditionArgs (char *cmdLine, hTab * vars) { - struct ftab - { - char *fname; - int (*func) (hTab *, lineNode *, lineNode *, lineNode *, const char *); - } - ftab[] = - { - { - "labelInRange", labelInRange - } - , - { - "labelJTInRange", labelJTInRange - } - , - { - "operandsNotSame", operandsNotSame - } - , - { - "operandsNotSame3", operandsNotSame3 - } - , - { - "operandsNotSame4", operandsNotSame4 - } - , - { - "operandsNotSame5", operandsNotSame5 - } - , - { - "operandsNotSame6", operandsNotSame6 - } - , + int varNumber; + char *var; + char *digitend; + set *operands = NULL; + + if (!cmdLine) + return NULL; + + while (*cmdLine && ISCHARSPACE(*cmdLine)) + cmdLine++; + + while (*cmdLine) { - "operandsNotSame7", operandsNotSame7 + if (*cmdLine == '%') + { + cmdLine++; + if (!ISCHARDIGIT(*cmdLine)) + goto error; + varNumber = strtol(cmdLine, &digitend, 10); + cmdLine = digitend; + + var = hTabItemWithKey (vars, varNumber); + + if (var) + { + addSetHead (&operands, var); + } + else + goto error; + } + else if (*cmdLine == '\'' ) + { + char quote = *cmdLine; + + var = ++cmdLine; + while (*cmdLine && *cmdLine != quote) + cmdLine++; + if (*cmdLine == quote) + *cmdLine++ = '\0'; + else + goto error; + addSetHead (&operands, var); + } + else + goto error; + + while (*cmdLine && ISCHARSPACE(*cmdLine)) + cmdLine++; } - , + + return operands; + +error: + deleteSet (&operands); + return NULL; +} + +static const char * +operandBaseName (const char *op) +{ + if (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_DS400) { - "operandsNotSame8", operandsNotSame8 + if (!strcmp (op, "acc") || !strncmp (op, "acc.", 4)) + return "a"; + if (!strncmp (op, "ar", 2) && ISCHARDIGIT(*(op+2)) && !*(op+3)) + return op+1; + // bug 1739475, temp fix + if (op[0] == '@') + return operandBaseName(op+1); } - , + + return op; +} + +/*-------------------------------------------------------------------*/ +/* operandsNotRelated - returns true if the condition's operands are */ +/* not related (taking into account register name aliases). N-way */ +/* comparison performed between all operands. */ +/*-------------------------------------------------------------------*/ +FBYNAME (operandsNotRelated) +{ + set *operands; + const char *op1, *op2; + + operands = setFromConditionArgs (cmdLine, vars); + + if (!operands) { - "24bitMode", flat24bitMode + fprintf (stderr, + "*** internal error: operandsNotRelated peephole restriction" + " malformed: %s\n", cmdLine); + return FALSE; } - , + + while ((op1 = setFirstItem (operands))) { - "xramMovcOption", xramMovcOption + deleteSetItem (&operands, (void*)op1); + op1 = operandBaseName (op1); + + for (op2 = setFirstItem (operands); op2; op2 = setNextItem (operands)) + { + op2 = operandBaseName (op2); + if (strcmp (op1, op2) == 0) + { + deleteSet (&operands); + return FALSE; + } + } } - , + + deleteSet (&operands); + return TRUE; +} + +/*-------------------------------------------------------------------*/ +/* operandsLiteral - returns true of the condition's operands are */ +/* literals. */ +/*-------------------------------------------------------------------*/ +FBYNAME (operandsLiteral) +{ + set *operands; + const char *op; + + operands = setFromConditionArgs (cmdLine, vars); + + if (!operands) { - "labelRefCount", labelRefCount + fprintf (stderr, + "*** internal error: operandsLiteral peephole restriction" + " malformed: %s\n", cmdLine); + return FALSE; } - , - { - "portIsDS390", portIsDS390 - }, - { - "labelIsReturnOnly", labelIsReturnOnly - }, - { - "okToRemoveSLOC", okToRemoveSLOC - }, - { - "24bitModeAndPortDS390", flat24bitModeAndPortDS390 - }, + + for (op = setFirstItem (operands); op; op = setNextItem (operands)) { - "notVolatile", notVolatile + if (!isdigit(*op)) + { + deleteSet (&operands); + return FALSE; + } } - }; - int i; - char *cmdCopy, *funcName, *funcArgs; - int rc = -1; - - /* Isolate the function name part (we are passed the full condition - * string including arguments) + + deleteSet (&operands); + return TRUE; +} + +static const struct ftab +{ + char *fname; + int (*func) (hTab *, lineNode *, lineNode *, lineNode *, char *); +} +ftab[] = // sorted on the number of times used +{ // in the peephole rules on 2007-10-29 + { + "labelRefCount", labelRefCount //105 + }, + { + "notVolatile", notVolatile //85 + }, + { + "labelRefCountChange", labelRefCountChange //74 + }, + { + "labelInRange", labelInRange //37 + }, + { + "labelJTInRange", labelJTInRange //13 + }, + { + "operandsNotRelated", operandsNotRelated //9 + }, + { + "24bitMode", flat24bitMode //9 + }, + { + "operandsNotSame", operandsNotSame //8 + }, + { + "operandsNotSame3", operandsNotSame3 + }, + { + "operandsNotSame4", operandsNotSame4 + }, + { + "operandsNotSame5", operandsNotSame5 + }, + { + "operandsNotSame6", operandsNotSame6 + }, + { + "operandsNotSame7", operandsNotSame7 + }, + { + "operandsNotSame8", operandsNotSame8 + }, + { + "xramMovcOption", xramMovcOption + }, + { + "portIsDS390", portIsDS390 + }, + { + "labelIsReturnOnly", labelIsReturnOnly + }, + { + "labelIsUncondJump", labelIsUncondJump + }, + { + "okToRemoveSLOC", okToRemoveSLOC + }, + { + "deadMove", deadMove + }, + { + "operandsLiteral", operandsLiteral + }, + { + "useAcallAjmp", useAcallAjmp + }, + { + "notUsed", notUsed + } +}; +/*-----------------------------------------------------------------*/ +/* callFuncByName - calls a function as defined in the table */ +/*-----------------------------------------------------------------*/ +static int +callFuncByName (char *fname, + hTab * vars, + lineNode * currPl, /* first source line matched */ + lineNode * endPl, /* last source line matched */ + lineNode * head) +{ + int i; + char *cmdCopy, *funcName, *funcArgs, *cmdTerm; + char c; + int rc; + + /* Isolate the function name part (we are passed the full condition + * string including arguments) */ - cmdCopy = Safe_strdup(fname); - funcName = strtok(cmdCopy, " \t"); - funcArgs = strtok(NULL, ""); + cmdTerm = cmdCopy = Safe_strdup(fname); - for (i = 0; i < ((sizeof (ftab)) / (sizeof (struct ftab))); i++) - { - if (strcmp (ftab[i].fname, funcName) == 0) - { - rc = (*ftab[i].func) (vars, currPl, endPl, head, - funcArgs); - } - } - - if (rc == -1) + do { - fprintf (stderr, - "could not find named function \"%s\" in " - "peephole function table\n", - funcName); - // If the function couldn't be found, let's assume it's - // a bad rule and refuse it. - rc = FALSE; + funcArgs = funcName = cmdTerm; + while ((c = *funcArgs) && c != ' ' && c != '\t' && c != '(') + funcArgs++; + *funcArgs = '\0'; /* terminate the function name */ + if (c) + funcArgs++; + + /* Find the start of the arguments */ + if (c == ' ' || c == '\t') + while ((c = *funcArgs) && (c == ' ' || c == '\t')) + funcArgs++; + + /* If the arguments started with an opening parenthesis, */ + /* use the closing parenthesis for the end of the */ + /* arguments and look for the start of another condition */ + /* that can optionally follow. If there was no opening */ + /* parethesis, then everything that follows are arguments */ + /* and there can be no additional conditions. */ + if (c == '(') + { + + int num_parenthesis = 0; + cmdTerm = funcArgs; + + while ((c = *cmdTerm) && (c != ')' || num_parenthesis)) + { + if (c == '(') + num_parenthesis++; + else if (c == ')') + num_parenthesis--; + cmdTerm++; + } + *cmdTerm = '\0'; /* terminate the arguments */ + if (c == ')') + { + cmdTerm++; + while ((c = *cmdTerm) && (c == ' ' || c == '\t' || c == ',')) + cmdTerm++; + if (!*cmdTerm) + cmdTerm = NULL; + } + else + cmdTerm = NULL; /* closing parenthesis missing */ + } + else + cmdTerm = NULL; + + if (!*funcArgs) + funcArgs = NULL; + + rc = -1; + for (i = 0; i < ((sizeof (ftab)) / (sizeof (struct ftab))); i++) + { + if (strcmp (ftab[i].fname, funcName) == 0) + { + rc = (*ftab[i].func) (vars, currPl, endPl, head, funcArgs); + break; + } + } + + if (rc == -1) + { + fprintf (stderr, + "could not find named function \"%s\" in " + "peephole function table\n", + funcName); + // If the function couldn't be found, let's assume it's + // a bad rule and refuse it. + rc = FALSE; + break; + } } + while (rc && cmdTerm); + + Safe_free(cmdCopy); - Safe_free(cmdCopy); - return rc; } /*-----------------------------------------------------------------*/ /* printLine - prints a line chain into a given file */ /*-----------------------------------------------------------------*/ -void -printLine (lineNode * head, FILE * of) +void +printLine (lineNode * head, struct dbuf_s * oBuf) { iCode *last_ic = NULL; bool debug_iCode_tracking = (getenv("DEBUG_ICODE_TRACKING")!=NULL); - - if (!of) - of = stdout; while (head) { @@ -896,24 +1388,23 @@ printLine (lineNode * head, FILE * of) if (debug_iCode_tracking) { if (head->ic) - fprintf (of, "; block = %d, seq = %d\n", + dbuf_printf (oBuf, "; block = %d, seq = %d\n", head->ic->block, head->ic->seq); else - fprintf (of, "; iCode lost\n"); + dbuf_append_str (oBuf, "; iCode lost\n"); } } - + /* don't indent comments & labels */ if (head->line && - (*head->line == ';' || - head->line[strlen (head->line) - 1] == ':')) { - fprintf (of, "%s\n", head->line); + (head->isComment || head->isLabel)) { + dbuf_printf (oBuf, "%s\n", head->line); } else { - if (head->isInline && *head->line=='#') { - // comment out preprocessor directives in inline asm - fprintf (of, ";"); - } - fprintf (of, "\t%s\n", head->line); + if (head->isInline && *head->line=='#') { + // comment out preprocessor directives in inline asm + dbuf_append_char (oBuf, ';'); + } + dbuf_printf (oBuf, "\t%s\n", head->line); } head = head->next; } @@ -922,11 +1413,11 @@ printLine (lineNode * head, FILE * of) /*-----------------------------------------------------------------*/ /* newPeepRule - creates a new peeprule and attach it to the root */ /*-----------------------------------------------------------------*/ -peepRule * +static peepRule * newPeepRule (lineNode * match, - lineNode * replace, - char *cond, - int restart) + lineNode * replace, + char *cond, + int restart) { peepRule *pr; @@ -957,7 +1448,7 @@ newPeepRule (lineNode * match, /* newLineNode - creates a new peep line */ /*-----------------------------------------------------------------*/ lineNode * -newLineNode (char *line) +newLineNode (const char *line) { lineNode *pl; @@ -985,7 +1476,7 @@ connectLine (lineNode * pl1, lineNode * pl2) return pl2; } -#define SKIP_SPACE(x,y) { while (*x && (isspace(*x) || *x == '\n')) x++; \ +#define SKIP_SPACE(x,y) { while (*x && (ISCHARSPACE(*x) || *x == '\n')) x++; \ if (!*x) { fprintf(stderr,y); return ; } } #define EXPECT_STR(x,y,z) { while (*x && strncmp(x,y,strlen(y))) x++ ; \ @@ -996,7 +1487,7 @@ connectLine (lineNode * pl1, lineNode * pl2) /*-----------------------------------------------------------------*/ /* getPeepLine - parses the peep lines */ /*-----------------------------------------------------------------*/ -static void +static void getPeepLine (lineNode ** head, char **bpp) { char lines[MAX_PATTERN_LEN]; @@ -1009,44 +1500,49 @@ getPeepLine (lineNode ** head, char **bpp) { if (!*bp) - { - fprintf (stderr, "unexpected end of match pattern\n"); - return; - } + { + fprintf (stderr, "unexpected end of match pattern\n"); + return; + } if (*bp == '\n') - { - bp++; - while (isspace (*bp) || - *bp == '\n') - bp++; - } + { + bp++; + while (ISCHARSPACE (*bp) || + *bp == '\n') + bp++; + } if (*bp == '}') - { - bp++; - break; - } + { + bp++; + break; + } /* read till end of line */ lp = lines; while ((*bp != '\n' && *bp != '}') && *bp) - *lp++ = *bp++; + *lp++ = *bp++; *lp = '\0'; - + lp = lines; - while (*lp && isspace(*lp)) + while (*lp && ISCHARSPACE(*lp)) lp++; isComment = (*lp == ';'); - + if (!isComment || (isComment && !options.noPeepComments)) - { - if (!currL) - *head = currL = newLineNode (lines); - else - currL = connectLine (currL, newLineNode (lines)); - currL->isComment = isComment; - } + { + const char *dummy1; + int dummy2; + + if (!currL) + *head = currL = newLineNode (lines); + else + currL = connectLine (currL, newLineNode (lines)); + currL->isComment = isComment; + currL->isLabel = isLabelDefinition (currL->line, &dummy1, &dummy2, + TRUE); + } } @@ -1056,12 +1552,12 @@ getPeepLine (lineNode ** head, char **bpp) /*-----------------------------------------------------------------*/ /* readRules - reads the rules from a string buffer */ /*-----------------------------------------------------------------*/ -static void +static void readRules (char *bp) { char restart = 0; char lines[MAX_PATTERN_LEN]; - char *lp; + char *lp, *rp; lineNode *match; lineNode *replace; lineNode *currL = NULL; @@ -1081,7 +1577,7 @@ top: /* then look for either "restart" or '{' */ while (strncmp (bp, "restart", 7) && - *bp != '{' && bp) + *bp != '{' && bp) bp++; /* not found */ @@ -1095,7 +1591,7 @@ top: if (*bp == '{') bp++; else - { /* must be restart */ + { /* must be restart */ restart++; bp += strlen ("restart"); /* look for '{' */ @@ -1117,36 +1613,65 @@ top: EXPECT_CHR (bp, '{', "expected '{'\n"); bp++; + /* save char position (needed for generating error msg) */ + rp = bp; + SKIP_SPACE (bp, "unexpected end of rule\n"); getPeepLine (&replace, &bp); /* look for a 'if' */ - while ((isspace (*bp) || *bp == '\n') && *bp) + while ((ISCHARSPACE (*bp) || *bp == '\n') && *bp) bp++; if (strncmp (bp, "if", 2) == 0) { bp += 2; - while ((isspace (*bp) || *bp == '\n') && *bp) - bp++; + while ((ISCHARSPACE (*bp) || *bp == '\n') && *bp) + bp++; if (!*bp) - { - fprintf (stderr, "expected condition name\n"); - return; - } + { + fprintf (stderr, "expected condition name\n"); + return; + } /* look for the condition */ lp = lines; while (*bp && (*bp != '\n')) - { - *lp++ = *bp++; - } + { + *lp++ = *bp++; + } *lp = '\0'; newPeepRule (match, replace, lines, restart); } else - newPeepRule (match, replace, NULL, restart); + { + if (*bp && strncmp (bp, "replace", 7)) + { + /* not the start of a new peeprule, so "if" should be here */ + + char strbuff[1000]; + char *cp; + + /* go to the start of the line following "{" of the "by" token */ + while (*rp && (*rp == '\n')) + rp++; + + /* copy text of rule starting with line after "by {" */ + cp = strbuff; + while (*rp && (rp < bp) && ((cp - strbuff) < sizeof(strbuff))) + *cp++ = *rp++; + + /* and now the rest of the line */ + while (*rp && (*rp != '\n') && ((cp - strbuff) < sizeof(strbuff))) + *cp++ = *rp++; + + *cp = '\0'; + fprintf (stderr, "%s\nexpected '} if ...'\n", strbuff); + return; + } + newPeepRule (match, replace, NULL, restart); + } goto top; } @@ -1154,12 +1679,12 @@ top: /*-----------------------------------------------------------------*/ /* keyForVar - returns the numeric key for a var */ /*-----------------------------------------------------------------*/ -static int +static int keyForVar (char *d) { int i = 0; - while (isdigit (*d)) + while (ISCHARDIGIT (*d)) { i *= 10; i += (*d++ - '0'); @@ -1171,7 +1696,7 @@ keyForVar (char *d) /*-----------------------------------------------------------------*/ /* bindVar - binds a value to a variable in the given hashtable */ /*-----------------------------------------------------------------*/ -static void +static void bindVar (int key, char **s, hTab ** vtab) { char vval[MAX_PATTERN_LEN]; @@ -1182,30 +1707,30 @@ bindVar (int key, char **s, hTab ** vtab) vvx = *s; /* the value is ended by a ',' or space or newline or null or ) */ while (*vvx && - *vvx != ',' && - !isspace (*vvx) && - *vvx != '\n' && - *vvx != ':' && - *vvx != ')') + *vvx != ',' && + !ISCHARSPACE (*vvx) && + *vvx != '\n' && + *vvx != ':' && + *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--; - } - // include the trailing ')' - *vv++ = *vvx++; - } + { + ubb++; + while (ubb) + { + *vv++ = *vvx++; + if (*vvx == '(') + ubb++; + if (*vvx == ')') + ubb--; + } + // include the trailing ')' + *vv++ = *vvx++; + } else - *vv++ = *vvx++; + *vv++ = *vvx++; } *s = vvx; *vv = '\0'; @@ -1218,67 +1743,64 @@ bindVar (int key, char **s, hTab ** vtab) /*-----------------------------------------------------------------*/ /* matchLine - matches one line */ /*-----------------------------------------------------------------*/ -static bool +static bool matchLine (char *s, char *d, hTab ** vars) { - if (!s || !(*s)) return FALSE; while (*s && *d) { - /* skip white space in both */ - while (isspace (*s)) - s++; - while (isspace (*d)) - d++; + while (ISCHARSPACE (*s)) + s++; + while (ISCHARSPACE (*d)) + d++; /* if the destination is a var */ - if (*d == '%' && isdigit (*(d + 1)) && vars) - { - 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++; - - while (isspace (*s)) - s++; - while (isspace (*d)) - d++; - } + if (*d == '%' && ISCHARDIGIT (*(d + 1)) && vars) + { + 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 (ISCHARDIGIT (*d)) + d++; + + while (ISCHARSPACE (*s)) + s++; + while (ISCHARSPACE (*d)) + d++; + } /* they should be an exact match other wise */ if (*s && *d) - { - if (*s++ != *d++) - return FALSE; - } + { + if (*s++ != *d++) + return FALSE; + } } /* get rid of the trailing spaces in both source & destination */ if (*s) - while (isspace (*s)) + while (ISCHARSPACE (*s)) s++; if (*d) - while (isspace (*d)) + while (ISCHARSPACE (*d)) d++; /* after all this if only one of them @@ -1292,14 +1814,14 @@ matchLine (char *s, char *d, hTab ** vars) /*-----------------------------------------------------------------*/ /* matchRule - matches a all the rule lines */ /*-----------------------------------------------------------------*/ -static bool +static bool matchRule (lineNode * pl, - lineNode ** mtail, - peepRule * pr, - lineNode * head) + lineNode ** mtail, + peepRule * pr, + lineNode * head) { - lineNode *spl; /* source pl */ - lineNode *rpl; /* rule peep line */ + lineNode *spl; /* source pl */ + lineNode *rpl; /* rule peep line */ /* setToNull((void *) &pr->vars); */ /* pr->vars = newHashTable(100); */ @@ -1314,18 +1836,18 @@ matchRule (lineNode * pl, 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; - } + (*spl->line == ';' || spl->isDebug)) + { + spl = spl->next; + continue; + } if (!matchLine (spl->line, rpl->line, &pr->vars)) - return FALSE; + return FALSE; rpl = rpl->next; if (rpl) - spl = spl->next; + spl = spl->next; } /* if rules ended */ @@ -1333,20 +1855,20 @@ matchRule (lineNode * pl, { /* if this rule has additional conditions */ if (pr->cond) - { - if (callFuncByName (pr->cond, pr->vars, pl, spl, head)) - { - *mtail = spl; - return TRUE; - } - else - return FALSE; - } + { + if (callFuncByName (pr->cond, pr->vars, pl, spl, head)) + { + *mtail = spl; + return TRUE; + } + else + return FALSE; + } else - { - *mtail = spl; - return TRUE; - } + { + *mtail = spl; + return TRUE; + } } else return FALSE; @@ -1356,8 +1878,8 @@ static void reassociate_ic_down (lineNode *shead, lineNode *stail, lineNode *rhead, lineNode *rtail) { - lineNode *csl; /* current source line */ - lineNode *crl; /* current replacement line */ + lineNode *csl; /* current source line */ + lineNode *crl; /* current replacement line */ csl = shead; crl = rhead; @@ -1388,8 +1910,8 @@ static void reassociate_ic_up (lineNode *shead, lineNode *stail, lineNode *rhead, lineNode *rtail) { - lineNode *csl; /* current source line */ - lineNode *crl; /* current replacement line */ + lineNode *csl; /* current source line */ + lineNode *crl; /* current replacement line */ csl = stail; crl = rtail; @@ -1423,11 +1945,11 @@ static void reassociate_ic (lineNode *shead, lineNode *stail, lineNode *rhead, lineNode *rtail) { - lineNode *csl; /* current source line */ - lineNode *crl; /* current replacement line */ + lineNode *csl; /* current source line */ + lineNode *crl; /* current replacement line */ bool single_iCode; iCode *ic; - + /* Check to see if all the source lines (excluding comments) came ** for the same iCode */ @@ -1453,11 +1975,11 @@ reassociate_ic (lineNode *shead, lineNode *stail, crl->ic = ic; return; } - + single_iCode = FALSE; break; } - + /* If all of the source lines came from the same iCode, then so have ** all of the replacement lines too. */ @@ -1467,7 +1989,7 @@ reassociate_ic (lineNode *shead, lineNode *stail, crl->ic = ic; return; } - + /* The source lines span iCodes, so we may end up with replacement ** lines that we don't know which iCode(s) to associate with. Do the ** best we can by using the following strategies: @@ -1484,7 +2006,7 @@ reassociate_ic (lineNode *shead, lineNode *stail, /* Strategy #1: Start at the top and scan down for matches */ reassociate_ic_down(shead,stail,rhead,rtail); - + /* Strategy #2: Start at the bottom and scan up for matches */ reassociate_ic_up(shead,stail,rhead,rtail); @@ -1494,16 +2016,13 @@ reassociate_ic (lineNode *shead, lineNode *stail, csl = shead; while (1) { - const char *labelStart; - int labelLength; - /* skip over any comments */ while (csl!=stail->next && csl->isComment) csl = csl->next; if (csl==stail->next) break; - if (isLabelDefinition(csl->line, &labelStart, &labelLength)) + if (csl->isLabel) { /* found a source line label; look for it in the replacment lines */ crl = rhead; @@ -1524,7 +2043,7 @@ reassociate_ic (lineNode *shead, lineNode *stail, } csl = csl->next; } - + /* Try to assign a meaningful iCode to any comment that is missing one. Since they are comments, it's ok to make mistakes; we are just trying to improve continuity to simplify other tests. @@ -1538,11 +2057,11 @@ reassociate_ic (lineNode *shead, lineNode *stail, } } - + /*-----------------------------------------------------------------*/ /* replaceRule - does replacement of a matching pattern */ /*-----------------------------------------------------------------*/ -static void +static void replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr) { lineNode *cl = NULL; @@ -1557,12 +2076,12 @@ replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr) 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; - pl->isComment = cl->isComment || (*cl->line == ';'); - } + { + pl = (pl ? connectLine (pl, newLineNode (cl->line)) : + (comment = newLineNode (cl->line))); + pl->isDebug = cl->isDebug; + pl->isComment = cl->isComment || (*cl->line == ';'); + } } cl = NULL; @@ -1576,35 +2095,36 @@ replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr) 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++; - } + { + /* if the line contains a variable */ + if (*l == '%' && ISCHARDIGIT (*(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 (ISCHARDIGIT (*l)) { + l++; + } + continue; + } + *lbp++ = *l++; + } *lbp = '\0'; if (cl) - cl = connectLine (cl, newLineNode (lb)); + cl = connectLine (cl, newLineNode (lb)); else - lhead = cl = newLineNode (lb); + lhead = cl = newLineNode (lb); cl->isComment = pl->isComment; + cl->isLabel = pl->isLabel; } /* add the comments if any to the head of list */ @@ -1612,10 +2132,10 @@ replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr) { lineNode *lc = comment; while (lc->next) - lc = lc->next; + lc = lc->next; lc->next = lhead; if (lhead) - lhead->prev = lc; + lhead->prev = lc; lhead = comment; } @@ -1627,18 +2147,18 @@ replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr) /* 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; - } + { + (*shead)->prev->next = lhead; + lhead->prev = (*shead)->prev; + } *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; + } } else { @@ -1656,8 +2176,9 @@ replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr) * 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) +bool +isLabelDefinition (const char *line, const char **start, int *len, + bool isPeepRule) { const char *cp = line; @@ -1666,7 +2187,7 @@ isLabelDefinition (const char *line, const char **start, int *len) * (alnum | $ | _ ) followed by a colon. */ - while (*cp && isspace (*cp)) + while (*cp && ISCHARSPACE (*cp)) { cp++; } @@ -1678,7 +2199,8 @@ isLabelDefinition (const char *line, const char **start, int *len) *start = cp; - while (isalnum (*cp) || (*cp == '$') || (*cp == '_')) + while (ISCHARALNUM (*cp) || (*cp == '$') || (*cp == '_') || + (isPeepRule && (*cp == '%'))) { cp++; } @@ -1693,7 +2215,7 @@ isLabelDefinition (const char *line, const char **start, int *len) } /* Quick & dirty string hash function. */ -static int +static int hashSymbolName (const char *name) { int hash = 0; @@ -1715,7 +2237,7 @@ hashSymbolName (const char *name) /* Build a hash of all labels in the passed set of lines * and how many times they are referenced. */ -static void +static void buildLabelRefCountHash (lineNode * head) { lineNode *line; @@ -1727,30 +2249,35 @@ buildLabelRefCountHash (lineNode * head) labelHash = newHashTable (HTAB_SIZE); /* First pass: locate all the labels. */ - line = head; - - while (line) + for (line = head; line; line = line->next) { - if (isLabelDefinition (line->line, &label, &labelLen) - && labelLen <= SDCC_NAME_MAX) - { - labelHashEntry *entry; - - entry = traceAlloc (&_G.labels, Safe_alloc(sizeof (labelHashEntry))); - - memcpy (entry->name, label, labelLen); - entry->name[labelLen] = 0; - entry->refCount = -1; - - /* Assume function entry points are referenced somewhere, */ - /* even if we can't find a reference (might be from outside */ - /* the function) */ - if (line->ic && (line->ic->op == FUNCTION)) - entry->refCount++; - - hTabAddItem (&labelHash, hashSymbolName (entry->name), entry); - } - line = line->next; + if (line->isLabel || + line->isInline) + { + /* run isLabelDefinition to: + - look for labels in inline assembler + - calculate labelLen + */ + if (isLabelDefinition (line->line, &label, &labelLen, FALSE) && + labelLen <= SDCC_NAME_MAX) + { + labelHashEntry *entry; + + entry = traceAlloc (&_G.labels, Safe_alloc(sizeof (labelHashEntry))); + + memcpy (entry->name, label, labelLen); + entry->name[labelLen] = 0; + entry->refCount = -1; + + /* Assume function entry points are referenced somewhere, */ + /* even if we can't find a reference (might be from outside */ + /* the function) */ + if (line->ic && (line->ic->op == FUNCTION)) + entry->refCount++; + + hTabAddItem (&labelHash, hashSymbolName (entry->name), entry); + } + } } @@ -1760,20 +2287,20 @@ buildLabelRefCountHash (lineNode * 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); - } - } + { + labelHashEntry *thisEntry; + + thisEntry = hTabFirstItemWK (labelHash, i); + + while (thisEntry) + { + if (strstr (line->line, thisEntry->name)) + { + thisEntry->refCount++; + } + thisEntry = hTabNextItemWK (labelHash); + } + } line = line->next; } @@ -1786,11 +2313,11 @@ buildLabelRefCountHash (lineNode * head) thisEntry = hTabFirstItemWK (labelHash, i); while (thisEntry) - { - fprintf (stderr, "label: %s ref %d\n", - thisEntry->name, thisEntry->refCount); - thisEntry = hTabNextItemWK (labelHash); - } + { + fprintf (stderr, "label: %s ref %d\n", + thisEntry->name, thisEntry->refCount); + thisEntry = hTabNextItemWK (labelHash); + } } #endif } @@ -1807,19 +2334,19 @@ buildLabelRefCountHash (lineNode * head) matchLine Where is stuff allocated? - + */ /*-----------------------------------------------------------------*/ /* peepHole - matches & substitutes rules */ /*-----------------------------------------------------------------*/ -void +void peepHole (lineNode ** pls) { lineNode *spl; peepRule *pr; lineNode *mtail = NULL; - bool restart; + bool restart, replaced; #if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16 /* The PIC port uses a different peep hole optimizer based on "pCode" */ @@ -1836,8 +2363,10 @@ peepHole (lineNode ** pls) /* for all rules */ for (pr = rootRules; pr; pr = pr->next) { - for (spl = *pls; spl; spl = spl->next) + for (spl = *pls; spl; spl = replaced ? spl : spl->next) { + replaced = FALSE; + /* if inline assembler then no peep hole */ if (spl->isInline) continue; @@ -1846,21 +2375,26 @@ peepHole (lineNode ** pls) ** or comment */ if (spl->isDebug || spl->isComment || *(spl->line)==';') continue; - + mtail = NULL; /* Tidy up any data stored in the hTab */ - + /* if it matches */ if (matchRule (spl, &mtail, pr, *pls)) { - + /* restart at the replaced line */ + replaced = TRUE; + /* then replace */ if (spl == *pls) - replaceRule (pls, mtail, pr); + { + replaceRule (pls, mtail, pr); + spl = *pls; + } else replaceRule (&spl, mtail, pr); - + /* if restart rule type then start at the top again */ if (pr->restart) @@ -1868,14 +2402,14 @@ peepHole (lineNode ** pls) restart = TRUE; } } - + if (pr->vars) { hTabDeleteAll (pr->vars); Safe_free (pr->vars); pr->vars = NULL; } - + freeTrace (&_G.values); } } @@ -1914,36 +2448,36 @@ readFileIntoBuffer (char *fname) /* if we maxed out our local buffer */ if (nch >= (MAX_PATTERN_LEN - 2)) - { - lb[nch] = '\0'; - /* copy it into allocated buffer */ - if (rs) - { - rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1); - strncatz (rs, lb, strlen (rs) + strlen (lb) + 1); - } - else - { - rs = Safe_strdup (lb); - } - nch = 0; - } - } - - /* if some charaters left over */ + { + lb[nch] = '\0'; + /* copy it into allocated buffer */ + if (rs) + { + rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1); + strncatz (rs, lb, strlen (rs) + strlen (lb) + 1); + } + else + { + rs = Safe_strdup (lb); + } + nch = 0; + } + } + + /* if some characters left over */ if (nch) { lb[nch] = '\0'; /* copy it into allocated buffer */ if (rs) - { - rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1); - strncatz (rs, lb, strlen (rs) + strlen (lb) + 1); - } + { + rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1); + strncatz (rs, lb, strlen (rs) + strlen (lb) + 1); + } else - { - rs = Safe_strdup (lb); - } + { + rs = Safe_strdup (lb); + } } return rs; } @@ -1951,19 +2485,24 @@ readFileIntoBuffer (char *fname) /*-----------------------------------------------------------------*/ /* initPeepHole - initialises the peep hole optimizer stuff */ /*-----------------------------------------------------------------*/ -void +void initPeepHole () { char *s; /* read in the default rules */ - readRules (port->peep.default_rules); + if (!options.nopeep) + { + readRules (port->peep.default_rules); + } /* if we have any additional file read it too */ if (options.peep_file) { readRules (s = readFileIntoBuffer (options.peep_file)); setToNull ((void *) &s); + /* override nopeep setting, default rules have not been read */ + options.nopeep = 0; } @@ -1971,8 +2510,8 @@ initPeepHole () /* Convert the peep rules into pcode. NOTE: this is only support in the PIC port (at the moment) */ - if (TARGET_IS_PIC) - peepRules2pCode(rootRules); + if (TARGET_IS_PIC) + peepRules2pCode(rootRules); #endif #if !OPT_DISABLE_PIC16 @@ -1980,8 +2519,8 @@ initPeepHole () NOTE: this is only support in the PIC port (at the moment) and the PIC16 port (VR 030601) */ - if (TARGET_IS_PIC16) - pic16_peepRules2pCode(rootRules); + if (TARGET_IS_PIC16) + pic16_peepRules2pCode(rootRules); #endif