-------------------------------------------------------------------------*/
#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
{
static void buildLabelRefCountHash (lineNode * head);
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 *);
/*-----------------------------------------------------------------*/
/* pcDistance - afinds a label back ward or forward */
/*-----------------------------------------------------------------*/
-int
-mcs51_instruction_size(const char *inst)
-{
- char *op, op1[256], op2[256];
- int opsize;
- const char *p;
-
- while (*inst && isspace(*inst)) inst++;
-
- #define ISINST(s) (strncmp(inst, (s), sizeof(s)-1) == 0)
-
- /* Based on the current (2003-08-22) code generation for the
- small library, the top instruction probability is:
-
- 57% mov/movx/movc
- 6% push
- 6% pop
- 4% inc
- 4% lcall
- 4% add
- 3% clr
- 2% subb
- */
- /* mov, push, & pop are the 69% of the cases. Check them first! */
- if (ISINST("mov"))
- {
- if (*(inst+3)=='x') return 1; /* movx */
- if (*(inst+3)=='c') return 1; /* movc */
- goto checkoperands; /* mov */
- }
- if (ISINST("push")) return 2;
- if (ISINST("pop")) return 2;
-
- if (ISINST("lcall")) return 3;
- if (ISINST("ret")) return 1;
- if (ISINST("ljmp")) return 3;
- if (ISINST("sjmp")) return 2;
- if (ISINST("rlc")) return 1;
- if (ISINST("rrc")) return 1;
- if (ISINST("rl")) return 1;
- if (ISINST("rr")) return 1;
- if (ISINST("swap")) return 1;
- if (ISINST("jc")) return 2;
- if (ISINST("jnc")) return 2;
- if (ISINST("jb")) return 3;
- if (ISINST("jnb")) return 3;
- if (ISINST("jbc")) return 3;
- if (ISINST("jmp")) return 1; // always jmp @a+dptr
- if (ISINST("jz")) return 2;
- if (ISINST("jnz")) return 2;
- if (ISINST("cjne")) return 3;
- if (ISINST("mul")) return 1;
- if (ISINST("div")) return 1;
- if (ISINST("da")) return 1;
- if (ISINST("xchd")) return 1;
- if (ISINST("reti")) return 1;
- if (ISINST("nop")) return 1;
- if (ISINST("acall")) return 1;
- if (ISINST("ajmp")) return 2;
-
-checkoperands:
- p = inst;
- while (*p && isalnum(*p)) p++;
- for (op = op1, opsize=0; *p && *p != ',' && opsize < sizeof(op1); p++) {
- if (!isspace(*p)) *op++ = *p, opsize++;
- }
- *op = '\0';
- if (*p == ',') p++;
- for (op = op2, opsize=0; *p && *p != ',' && opsize < sizeof(op2); p++) {
- if (!isspace(*p)) *op++ = *p, opsize++;
- }
- *op = '\0';
-
- #define IS_A(s) (*(s) == 'a' && *(s+1) == '\0')
- #define IS_C(s) (*(s) == 'c' && *(s+1) == '\0')
- #define IS_Rn(s) (*(s) == 'r' && *(s+1) >= '0' && *(s+1) <= '7')
- #define IS_atRi(s) (*(s) == '@' && *(s+1) == 'r')
-
- if (ISINST("mov")) {
- if (IS_C(op1) || IS_C(op2)) return 2;
- if (IS_A(op1)) {
- if (IS_Rn(op2) || IS_atRi(op2)) return 1;
- return 2;
- }
- if (IS_Rn(op1) || IS_atRi(op1)) {
- if (IS_A(op2)) return 1;
- return 2;
- }
- if (strcmp(op1, "dptr") == 0) return 3;
- if (IS_A(op2) || IS_Rn(op2) || IS_atRi(op2)) return 2;
- return 3;
- }
- if (ISINST("add") || ISINST("addc") || ISINST("subb") || ISINST("xch")) {
- if (IS_Rn(op2) || IS_atRi(op2)) return 1;
- return 2;
- }
- if (ISINST("inc") || ISINST("dec")) {
- if (IS_A(op1) || IS_Rn(op1) || IS_atRi(op1)) return 1;
- if (strcmp(op1, "dptr") == 0) return 1;
- return 2;
- }
- if (ISINST("anl") || ISINST("orl") || ISINST("xrl")) {
- if (IS_C(op1)) return 2;
- if (IS_A(op1)) {
- if (IS_Rn(op2) || IS_atRi(op2)) return 1;
- return 2;
- } else {
- if (IS_A(op2)) return 2;
- return 3;
- }
- }
- if (ISINST("clr") || ISINST("setb") || ISINST("cpl")) {
- if (IS_A(op1) || IS_C(op1)) return 1;
- return 2;
- }
- if (ISINST("djnz")) {
- if (IS_Rn(op1)) return 2;
- return 3;
- }
-
- if (*inst == 'a' && *(inst+1) == 'r' && *(inst+2) >= '0' && *(inst+2) <= '7' && op1[0] == '=') {
- /* ignore ar0 = 0x00 type definitions */
- return 0;
- }
-
- fprintf(stderr, "Warning, peephole unrecognized instruction: %s\n", inst);
- return 3;
-}
-int
+static int
pcDistance (lineNode * cpos, char *lbl, bool back)
{
lineNode *pl = cpos;
{
if (pl->line &&
- *pl->line != ';' &&
- pl->line[strlen (pl->line) - 1] != ':' &&
- !pl->isDebug) {
- if (TARGET_IS_MCS51) {
- dist += mcs51_instruction_size(pl->line);
- } 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 - */
+/* flat24bitModeAndPortDS390 - */
/*-----------------------------------------------------------------*/
FBYNAME (flat24bitModeAndPortDS390)
{
return (((strcmp(port->target,"ds390") == 0) ||
- (strcmp(port->target,"ds400") == 0)) &&
- (options.model == MODEL_FLAT24));
+ (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));
}
/*-----------------------------------------------------------------*/
/* 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 &&
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));
+ pcDistance (currPl, lbl, FALSE));
/* changed to 127, now that pcDistance return actual number of bytes */
if (!dist || dist > 127)
return TRUE;
}
+
+/*-----------------------------------------------------------------*/
+/* labelJTInRange - will check to see if label %5 and up are */
+/* within range. */
+/* Specifically meant to optimize long (3-byte) jumps to short */
+/* (2-byte) jumps in jumptables */
+/*-----------------------------------------------------------------*/
+FBYNAME (labelJTInRange)
+{
+ char *lbl;
+ int dist, count, i;
+
+ 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<count; i++)
+ {
+ /* assumes that the %5 pattern variable has the first ljmp label */
+ lbl = hTabItemWithKey (vars, 5+i);
+ if (!lbl)
+ return FALSE;
+
+ dist = pcDistance (currPl, lbl, FALSE);
+
+ /* three terms used to calculate allowable distance */
+// printf("\nlabel %s %i dist %i cdist 0x%02x 0x%02x\n", lbl, i, dist, dist -(count-i-1)-(7+3*i), 127+(count-i-1)+(7+3*i) - dist);
+ if (!dist ||
+ dist > 127+ /* range of sjmp */
+ (7+3*i)+ /* offset between this jump and currPl,
+ should use pcDistance instead? */
+ (count-i-1) /* if peephole applies distance is shortened */
+ )
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
/*-----------------------------------------------------------------*/
/* labelIsReturnOnly - Check if label %5 is followed by RET */
/*-----------------------------------------------------------------*/
const char *label, *p;
const lineNode *pl;
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;
len = strlen(label);
for(pl = currPl; pl; pl = pl->next) {
- if (pl->line && !pl->isDebug &&
- 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->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 */
p = pl->line;
- for (p = pl->line; *p && isspace(*p); p++)
- ;
- if (strcmp(p, "ret") == 0) return TRUE;
+ for (p = pl->line; *p && ISCHARSPACE(*p); p++)
+ ;
+
+ retInst = "ret";
+ if (TARGET_IS_HC08)
+ retInst = "rts";
+ if (strcmp(p, retInst) == 0) return TRUE;
return FALSE;
}
/* 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;
+}
/*-----------------------------------------------------------------*/
/* operandsNotSame - check if %1 & %2 are the same */
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:
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;
}
+
/* Within the context of the lines currPl through endPl, determine
** if the variable var contains a symbol that is volatile. Returns
** TRUE only if it is certain that this was not volatile (the symbol
/* 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';
}
}
}
-
+
/* Couldn't find the symbol for some reason. Assume volatile. */
return FALSE;
}
}
/* 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);
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;
}
-
+
+
+/*------------------------------------------------------------------*/
+/* 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)
+{
+ int varNumber;
+ char *var;
+ char *digitend;
+ set *operands = NULL;
+
+ if (!cmdLine)
+ return NULL;
+
+ while (*cmdLine && ISCHARSPACE(*cmdLine))
+ cmdLine++;
+
+ while (*cmdLine)
+ {
+ 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)
+ {
+ if (!strcmp (op, "acc") || !strncmp (op, "acc.", 4))
+ return "a";
+ if (!strncmp (op, "ar", 2) && ISCHARDIGIT(*(op+2)) && !*(op+3))
+ return op+1;
+ }
+
+ return op;
+}
+
+
+/*-------------------------------------------------------------------*/
+/* operandsNotRelated - returns true of 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)
+ {
+ fprintf (stderr,
+ "*** internal error: operandsNotRelated peephole restriction"
+ " malformed: %s\n", cmdLine);
+ return FALSE;
+ }
+
+ while ((op1 = setFirstItem (operands)))
+ {
+ 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)
+ {
+ fprintf (stderr,
+ "*** internal error: operandsLiteral peephole restriction"
+ " malformed: %s\n", cmdLine);
+ return FALSE;
+ }
+
+ for (op = setFirstItem (operands); op; op = setNextItem (operands))
+ {
+ if (!isdigit(*op))
+ {
+ deleteSet (&operands);
+ return FALSE;
+ }
+ }
+
+ deleteSet (&operands);
+ return TRUE;
+}
+
/*-----------------------------------------------------------------*/
/* callFuncByName - calls a function as defined in the table */
/*-----------------------------------------------------------------*/
-int
+static int
callFuncByName (char *fname,
- hTab * vars,
- lineNode * currPl,
- lineNode * endPl,
- lineNode * head)
+ hTab * vars,
+ lineNode * currPl,
+ lineNode * endPl,
+ lineNode * head)
{
struct ftab
{
char *fname;
- int (*func) (hTab *, lineNode *, lineNode *, lineNode *, const char *);
+ int (*func) (hTab *, lineNode *, lineNode *, lineNode *, char *);
}
ftab[] =
{
"labelInRange", labelInRange
}
,
+ {
+ "labelJTInRange", labelJTInRange
+ }
+ ,
{
"operandsNotSame", operandsNotSame
}
{
"operandsNotSame8", operandsNotSame8
}
- ,
+ ,
{
"24bitMode", flat24bitMode
}
{
"okToRemoveSLOC", okToRemoveSLOC
},
+ {
+ "deadMove", deadMove
+ },
{
"24bitModeAndPortDS390", flat24bitModeAndPortDS390
},
{
"notVolatile", notVolatile
+ },
+ {
+ "operandsNotRelated", operandsNotRelated
+ },
+ {
+ "operandsLiteral", operandsLiteral
+ },
+ {
+ "labelRefCountChange", labelRefCountChange
}
};
- int i;
- char *cmdCopy, *funcName, *funcArgs;
- int rc = -1;
-
- /* Isolate the function name part (we are passed the full condition
- * string including arguments)
+ 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 == '(')
+ {
+ cmdTerm = funcArgs;
+ while ((c = *cmdTerm) && c != ')')
+ 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)
{
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;
}
/*-----------------------------------------------------------------*/
/* 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;
/* newLineNode - creates a new peep line */
/*-----------------------------------------------------------------*/
lineNode *
-newLineNode (char *line)
+newLineNode (const char *line)
{
lineNode *pl;
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++ ; \
/*-----------------------------------------------------------------*/
/* getPeepLine - parses the peep lines */
/*-----------------------------------------------------------------*/
-static void
+static void
getPeepLine (lineNode ** head, char **bpp)
{
char lines[MAX_PATTERN_LEN];
char *lp;
+ int isComment;
lineNode *currL = NULL;
char *bp = *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';
- if (!currL)
- *head = currL = newLineNode (lines);
- else
- currL = connectLine (currL, newLineNode (lines));
lp = lines;
- while (*lp && isspace(*lp))
+ while (*lp && ISCHARSPACE(*lp))
lp++;
- if (*lp==';')
- currL->isComment = 1;
+ isComment = (*lp == ';');
+
+ if (!isComment || (isComment && !options.noPeepComments))
+ {
+ 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);
+ }
+
}
*bpp = bp;
/*-----------------------------------------------------------------*/
/* 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;
/* then look for either "restart" or '{' */
while (strncmp (bp, "restart", 7) &&
- *bp != '{' && bp)
+ *bp != '{' && bp)
bp++;
/* not found */
if (*bp == '{')
bp++;
else
- { /* must be restart */
+ { /* must be restart */
restart++;
bp += strlen ("restart");
/* look for '{' */
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;
}
/*-----------------------------------------------------------------*/
/* 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');
/*-----------------------------------------------------------------*/
/* 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];
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';
/*-----------------------------------------------------------------*/
/* matchLine - matches one line */
/*-----------------------------------------------------------------*/
-static bool
+static bool
matchLine (char *s, char *d, hTab ** vars)
{
{
/* 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
/*-----------------------------------------------------------------*/
/* 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); */
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 */
{
/* 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;
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;
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;
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
*/
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.
*/
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:
/* 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);
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;
}
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.
}
}
-
+
/*-----------------------------------------------------------------*/
/* replaceRule - does replacement of a matching pattern */
/*-----------------------------------------------------------------*/
-static void
+static void
replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr)
{
lineNode *cl = NULL;
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;
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 */
{
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;
}
- /* determine which iCodes the replacment lines relate to */
- reassociate_ic(*shead,stail,lhead,cl);
-
- /* now we need to connect / replace the original chain */
- /* if there is a prev then change it */
- if ((*shead)->prev)
+ if (lhead)
{
- (*shead)->prev->next = lhead;
- lhead->prev = (*shead)->prev;
+ /* determine which iCodes the replacment lines relate to */
+ reassociate_ic(*shead,stail,lhead,cl);
+
+ /* 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 = lhead;
+ /* now for the tail */
+ if (stail && stail->next)
+ {
+ stail->next->prev = cl;
+ if (cl)
+ cl->next = stail->next;
+ }
}
- *shead = lhead;
- /* now for the tail */
- if (stail && stail->next)
+ else
{
- stail->next->prev = cl;
- if (cl)
- cl->next = stail->next;
+ /* the replacement is empty - delete the source lines */
+ if ((*shead)->prev)
+ (*shead)->prev->next = stail->next;
+ if (stail->next)
+ stail->next->prev = (*shead)->prev;
+ *shead = stail->next;
}
}
* 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;
* (alnum | $ | _ ) followed by a colon.
*/
- while (*cp && isspace (*cp))
+ while (*cp && ISCHARSPACE (*cp))
{
cp++;
}
*start = cp;
- while (isalnum (*cp) || (*cp == '$') || (*cp == '_'))
+ while (ISCHARALNUM (*cp) || (*cp == '$') || (*cp == '_') ||
+ (isPeepRule && (*cp == '%')))
{
cp++;
}
}
/* Quick & dirty string hash function. */
-static int
+static int
hashSymbolName (const char *name)
{
int hash = 0;
/* 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;
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;
+ 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)));
+ entry = traceAlloc (&_G.labels, Safe_alloc(sizeof (labelHashEntry)));
- memcpy (entry->name, label, labelLen);
- entry->name[labelLen] = 0;
- entry->refCount = -1;
+ memcpy (entry->name, label, labelLen);
+ entry->name[labelLen] = 0;
+ entry->refCount = -1;
- hTabAddItem (&labelHash, hashSymbolName (entry->name), entry);
- }
- line = line->next;
+ /* 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);
+ }
+ }
}
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;
}
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
}
matchLine
Where is stuff allocated?
-
+
*/
/*-----------------------------------------------------------------*/
/* peepHole - matches & substitutes rules */
/*-----------------------------------------------------------------*/
-void
+void
peepHole (lineNode ** pls)
{
lineNode *spl;
** 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))
{
-
+
/* 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)
restart = TRUE;
}
}
-
+
if (pr->vars)
{
hTabDeleteAll (pr->vars);
Safe_free (pr->vars);
pr->vars = NULL;
}
-
+
freeTrace (&_G.values);
}
}
/* 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;
- }
+ {
+ 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);
- }
+ {
+ 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;
}
/*-----------------------------------------------------------------*/
/* 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;
}
/* 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
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