-------------------------------------------------------------------------*/
#include "common.h"
+#include "dbuf_string.h"
#define ISCHARDIGIT(c) isdigit((unsigned char)c)
#define ISCHARSPACE(c) isspace((unsigned char)c)
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 **);
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->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 */
- }
+ 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 */
+ }
+ 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 && 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 */
/* usage of it in the code depends on a value from this section */
/*-------------------------------------------------------------------*/
-/* operandsNotRelated - returns true of the condition's operands are */
+/* operandsNotRelated - returns true if the condition's operands are */
/* not related (taking into account register name aliases). N-way */
/* comparison performed between all operands. */
/*-------------------------------------------------------------------*/
{
"labelIsReturnOnly", labelIsReturnOnly
},
+ {
+ "labelIsUncondJump", labelIsUncondJump
+ },
{
"okToRemoveSLOC", okToRemoveSLOC
},
{
if (strcmp (ftab[i].fname, funcName) == 0)
{
- rc = (*ftab[i].func) (vars, currPl, endPl, head,
- funcArgs);
+ rc = (*ftab[i].func) (vars, currPl, endPl, head, funcArgs);
break;
}
}
/* printLine - prints a line chain into a given file */
/*-----------------------------------------------------------------*/
void
-printLine (lineNode * head, FILE * of)
+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 (head->ic!=last_ic)
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->isComment || head->isLabel)) {
- fprintf (of, "%s\n", head->line);
+ dbuf_printf (oBuf, "%s\n", head->line);
} else {
if (head->isInline && *head->line=='#') {
// comment out preprocessor directives in inline asm
- fprintf (of, ";");
+ dbuf_append_char (oBuf, ';');
}
- fprintf (of, "\t%s\n", head->line);
+ dbuf_printf (oBuf, "\t%s\n", head->line);
}
head = head->next;
}
/* newLineNode - creates a new peep line */
/*-----------------------------------------------------------------*/
lineNode *
-newLineNode (char *line)
+newLineNode (const char *line)
{
lineNode *pl;
return FALSE;
}
else
- /* variable not bound we need to
- bind it */
+ /* variable not bound we need to bind it */
bindVar (keyForVar (d + 1), &s, vars);
/* in either case go past the variable */
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" */
/* 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;
/* 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);