1 /*-------------------------------------------------------------------------
2 SDCCpeeph.c - The peep hole optimizer: for interpreting the
5 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 In other words, you are welcome to use, share and improve this program.
22 You are forbidden to forbid anyone else to use, share and improve
23 what you give them. Help stamp out software-hoarding!
24 -------------------------------------------------------------------------*/
28 static peepRule *rootRules = NULL;
29 static peepRule *currRule = NULL;
34 char name[SDCC_NAME_MAX + 1];
39 static hTab *labelHash = NULL;
47 static int hashSymbolName (const char *name);
48 static void buildLabelRefCountHash (lineNode * head);
50 static bool matchLine (char *, char *, hTab **);
52 #define FBYNAME(x) int x (hTab *vars, lineNode *currPl, lineNode *head, \
56 void peepRules2pCode(peepRule *);
59 /*-----------------------------------------------------------------*/
60 /* pcDistance - afinds a label back ward or forward */
61 /*-----------------------------------------------------------------*/
63 pcDistance (lineNode * cpos, char *lbl, bool back)
66 char buff[MAX_PATTERN_LEN];
69 SNPRINTF (buff, sizeof(buff), "%s:", lbl);
75 pl->line[strlen (pl->line) - 1] != ':' &&
80 if (strncmp (pl->line, buff, strlen (buff)) == 0)
92 /*-----------------------------------------------------------------*/
93 /* flat24bitModeAndPortDS390 - */
94 /*-----------------------------------------------------------------*/
95 FBYNAME (flat24bitModeAndPortDS390)
97 return ((strcmp(port->target,"ds390") == 0) &&
98 (options.model == MODEL_FLAT24));
101 /*-----------------------------------------------------------------*/
102 /* portIsDS390 - return true if port is DS390 */
103 /*-----------------------------------------------------------------*/
104 FBYNAME (portIsDS390)
106 return (strcmp(port->target,"ds390") == 0);
109 /*-----------------------------------------------------------------*/
110 /* flat24bitMode - will check to see if we are in flat24 mode */
111 /*-----------------------------------------------------------------*/
112 FBYNAME (flat24bitMode)
114 return (options.model == MODEL_FLAT24);
117 /*-----------------------------------------------------------------*/
118 /* xramMovcOption - check if using movc to read xram */
119 /*-----------------------------------------------------------------*/
120 FBYNAME (xramMovcOption)
122 return (options.xram_movc && (strcmp(port->target,"mcs51") == 0));
125 /*-----------------------------------------------------------------*/
126 /* labelInRange - will check to see if label %5 is within range */
127 /*-----------------------------------------------------------------*/
128 FBYNAME (labelInRange)
130 /* assumes that %5 pattern variable has the label name */
131 char *lbl = hTabItemWithKey (vars, 5);
137 /* if the previous two instructions are "ljmp"s then don't
138 do it since it can be part of a jump table */
139 if (currPl->prev && currPl->prev->prev &&
140 strstr (currPl->prev->line, "ljmp") &&
141 strstr (currPl->prev->prev->line, "ljmp"))
144 /* calculate the label distance : the jump for reladdr can be
145 +/- 127 bytes, here Iam assuming that an average 8051
146 instruction is 2 bytes long, so if the label is more than
147 63 intructions away, the label is considered out of range
148 for a relative jump. we could get more precise this will
149 suffice for now since it catches > 90% cases */
150 dist = (pcDistance (currPl, lbl, TRUE) +
151 pcDistance (currPl, lbl, FALSE));
153 /* if (!dist || dist > 45) has produced wrong sjmp */
154 /* 07-Sep-2000 Michael Schmitt */
155 /* FIX for Peephole 132 */
156 /* switch with lots of case can lead to a sjmp with a distance */
157 /* out of the range for sjmp */
158 if (!dist || dist > 43)
164 /*-----------------------------------------------------------------*/
165 /* operandsNotSame - check if %1 & %2 are the same */
166 /*-----------------------------------------------------------------*/
167 FBYNAME (operandsNotSame)
169 char *op1 = hTabItemWithKey (vars, 1);
170 char *op2 = hTabItemWithKey (vars, 2);
172 if (strcmp (op1, op2) == 0)
178 /*-----------------------------------------------------------------*/
179 /* operandsNotSame3- check if any pair of %1,%2,%3 are the same */
180 /*-----------------------------------------------------------------*/
181 FBYNAME (operandsNotSame3)
183 char *op1 = hTabItemWithKey (vars, 1);
184 char *op2 = hTabItemWithKey (vars, 2);
185 char *op3 = hTabItemWithKey (vars, 3);
187 if ( (strcmp (op1, op2) == 0) ||
188 (strcmp (op1, op3) == 0) ||
189 (strcmp (op2, op3) == 0) )
195 /*-----------------------------------------------------------------*/
196 /* operandsNotSame4- check if any pair of %1,%2,%3,.. are the same */
197 /*-----------------------------------------------------------------*/
198 FBYNAME (operandsNotSame4)
200 char *op1 = hTabItemWithKey (vars, 1);
201 char *op2 = hTabItemWithKey (vars, 2);
202 char *op3 = hTabItemWithKey (vars, 3);
203 char *op4 = hTabItemWithKey (vars, 4);
205 if ( (strcmp (op1, op2) == 0) ||
206 (strcmp (op1, op3) == 0) ||
207 (strcmp (op1, op4) == 0) ||
208 (strcmp (op2, op3) == 0) ||
209 (strcmp (op2, op4) == 0) ||
210 (strcmp (op3, op4) == 0) )
216 /*-----------------------------------------------------------------*/
217 /* operandsNotSame5- check if any pair of %1,%2,%3,.. are the same */
218 /*-----------------------------------------------------------------*/
219 FBYNAME (operandsNotSame5)
221 char *op1 = hTabItemWithKey (vars, 1);
222 char *op2 = hTabItemWithKey (vars, 2);
223 char *op3 = hTabItemWithKey (vars, 3);
224 char *op4 = hTabItemWithKey (vars, 4);
225 char *op5 = hTabItemWithKey (vars, 5);
227 if ( (strcmp (op1, op2) == 0) ||
228 (strcmp (op1, op3) == 0) ||
229 (strcmp (op1, op4) == 0) ||
230 (strcmp (op1, op5) == 0) ||
231 (strcmp (op2, op3) == 0) ||
232 (strcmp (op2, op4) == 0) ||
233 (strcmp (op2, op5) == 0) ||
234 (strcmp (op3, op4) == 0) ||
235 (strcmp (op3, op5) == 0) ||
236 (strcmp (op4, op5) == 0) )
242 /*-----------------------------------------------------------------*/
243 /* operandsNotSame6- check if any pair of %1,%2,%3,.. are the same */
244 /*-----------------------------------------------------------------*/
245 FBYNAME (operandsNotSame6)
247 char *op1 = hTabItemWithKey (vars, 1);
248 char *op2 = hTabItemWithKey (vars, 2);
249 char *op3 = hTabItemWithKey (vars, 3);
250 char *op4 = hTabItemWithKey (vars, 4);
251 char *op5 = hTabItemWithKey (vars, 5);
252 char *op6 = hTabItemWithKey (vars, 6);
254 if ( (strcmp (op1, op2) == 0) ||
255 (strcmp (op1, op3) == 0) ||
256 (strcmp (op1, op4) == 0) ||
257 (strcmp (op1, op5) == 0) ||
258 (strcmp (op1, op6) == 0) ||
259 (strcmp (op2, op3) == 0) ||
260 (strcmp (op2, op4) == 0) ||
261 (strcmp (op2, op5) == 0) ||
262 (strcmp (op2, op6) == 0) ||
263 (strcmp (op3, op4) == 0) ||
264 (strcmp (op3, op5) == 0) ||
265 (strcmp (op3, op6) == 0) ||
266 (strcmp (op4, op5) == 0) ||
267 (strcmp (op4, op6) == 0) ||
268 (strcmp (op5, op6) == 0) )
275 /*-----------------------------------------------------------------*/
276 /* operandsNotSame7- check if any pair of %1,%2,%3,.. are the same */
277 /*-----------------------------------------------------------------*/
278 FBYNAME (operandsNotSame7)
280 char *op1 = hTabItemWithKey (vars, 1);
281 char *op2 = hTabItemWithKey (vars, 2);
282 char *op3 = hTabItemWithKey (vars, 3);
283 char *op4 = hTabItemWithKey (vars, 4);
284 char *op5 = hTabItemWithKey (vars, 5);
285 char *op6 = hTabItemWithKey (vars, 6);
286 char *op7 = hTabItemWithKey (vars, 7);
288 if ( (strcmp (op1, op2) == 0) ||
289 (strcmp (op1, op3) == 0) ||
290 (strcmp (op1, op4) == 0) ||
291 (strcmp (op1, op5) == 0) ||
292 (strcmp (op1, op6) == 0) ||
293 (strcmp (op1, op7) == 0) ||
294 (strcmp (op2, op3) == 0) ||
295 (strcmp (op2, op4) == 0) ||
296 (strcmp (op2, op5) == 0) ||
297 (strcmp (op2, op6) == 0) ||
298 (strcmp (op2, op7) == 0) ||
299 (strcmp (op3, op4) == 0) ||
300 (strcmp (op3, op5) == 0) ||
301 (strcmp (op3, op6) == 0) ||
302 (strcmp (op3, op7) == 0) ||
303 (strcmp (op4, op5) == 0) ||
304 (strcmp (op4, op6) == 0) ||
305 (strcmp (op4, op7) == 0) ||
306 (strcmp (op5, op6) == 0) ||
307 (strcmp (op5, op7) == 0) ||
308 (strcmp (op6, op7) == 0) )
314 /*-----------------------------------------------------------------*/
315 /* operandsNotSame8- check if any pair of %1,%2,%3,.. are the same */
316 /*-----------------------------------------------------------------*/
317 FBYNAME (operandsNotSame8)
319 char *op1 = hTabItemWithKey (vars, 1);
320 char *op2 = hTabItemWithKey (vars, 2);
321 char *op3 = hTabItemWithKey (vars, 3);
322 char *op4 = hTabItemWithKey (vars, 4);
323 char *op5 = hTabItemWithKey (vars, 5);
324 char *op6 = hTabItemWithKey (vars, 6);
325 char *op7 = hTabItemWithKey (vars, 7);
326 char *op8 = hTabItemWithKey (vars, 8);
328 if ( (strcmp (op1, op2) == 0) ||
329 (strcmp (op1, op3) == 0) ||
330 (strcmp (op1, op4) == 0) ||
331 (strcmp (op1, op5) == 0) ||
332 (strcmp (op1, op6) == 0) ||
333 (strcmp (op1, op7) == 0) ||
334 (strcmp (op1, op8) == 0) ||
335 (strcmp (op2, op3) == 0) ||
336 (strcmp (op2, op4) == 0) ||
337 (strcmp (op2, op5) == 0) ||
338 (strcmp (op2, op6) == 0) ||
339 (strcmp (op2, op7) == 0) ||
340 (strcmp (op2, op8) == 0) ||
341 (strcmp (op3, op4) == 0) ||
342 (strcmp (op3, op5) == 0) ||
343 (strcmp (op3, op6) == 0) ||
344 (strcmp (op3, op7) == 0) ||
345 (strcmp (op3, op8) == 0) ||
346 (strcmp (op4, op5) == 0) ||
347 (strcmp (op4, op6) == 0) ||
348 (strcmp (op4, op7) == 0) ||
349 (strcmp (op4, op8) == 0) ||
350 (strcmp (op5, op6) == 0) ||
351 (strcmp (op5, op7) == 0) ||
352 (strcmp (op5, op8) == 0) ||
353 (strcmp (op6, op7) == 0) ||
354 (strcmp (op6, op8) == 0) ||
355 (strcmp (op7, op8) == 0) )
364 * takes two parameters: a variable (bound to a label name)
365 * and an expected reference count.
367 * Returns TRUE if that label is defined and referenced exactly
368 * the given number of times.
370 FBYNAME (labelRefCount)
372 int varNumber, expectedRefCount;
375 /* If we don't have the label hash table yet, build it. */
378 buildLabelRefCountHash (head);
381 if (sscanf (cmdLine, "%*[ \t%]%d %d", &varNumber, &expectedRefCount) == 2)
383 char *label = hTabItemWithKey (vars, varNumber);
387 labelHashEntry *entry;
389 entry = hTabFirstItemWK (labelHash, hashSymbolName (label));
393 if (!strcmp (label, entry->name))
397 entry = hTabNextItemWK (labelHash);
403 fprintf (stderr, "labelRefCount: %s has refCount %d, want %d\n",
404 label, entry->refCount, expectedRefCount);
407 rc = (expectedRefCount == entry->refCount);
411 fprintf (stderr, "*** internal error: no label has entry for"
412 " %s in labelRefCount peephole.\n",
418 fprintf (stderr, "*** internal error: var %d not bound"
419 " in peephole labelRefCount rule.\n",
427 "*** internal error: labelRefCount peephole restriction"
428 " malformed: %s\n", cmdLine);
433 /*-----------------------------------------------------------------*/
434 /* callFuncByName - calls a function as defined in the table */
435 /*-----------------------------------------------------------------*/
437 callFuncByName (char *fname,
445 int (*func) (hTab *, lineNode *, lineNode *, const char *);
450 "labelInRange", labelInRange
454 "operandsNotSame", operandsNotSame
458 "operandsNotSame3", operandsNotSame3
462 "operandsNotSame4", operandsNotSame4
466 "operandsNotSame5", operandsNotSame5
470 "operandsNotSame6", operandsNotSame6
474 "operandsNotSame7", operandsNotSame7
478 "operandsNotSame8", operandsNotSame8
482 "24bitMode", flat24bitMode
486 "xramMovcOption", xramMovcOption
490 "labelRefCount", labelRefCount
494 "portIsDS390", portIsDS390
497 "24bitModeAndPortDS390", flat24bitModeAndPortDS390
501 char *cmdCopy, *funcName, *funcArgs;
504 /* Isolate the function name part (we are passed the full condition
505 * string including arguments)
507 cmdCopy = Safe_strdup(fname);
508 funcName = strtok(cmdCopy, " \t");
509 funcArgs = strtok(NULL, "");
511 for (i = 0; i < ((sizeof (ftab)) / (sizeof (struct ftab))); i++)
513 if (strcmp (ftab[i].fname, funcName) == 0)
515 rc = (*ftab[i].func) (vars, currPl, head,
525 "could not find named function \"%s\" in "
526 "peephole function table\n",
528 // If the function couldn't be found, let's assume it's
529 // a bad rule and refuse it.
536 /*-----------------------------------------------------------------*/
537 /* printLine - prints a line chain into a given file */
538 /*-----------------------------------------------------------------*/
540 printLine (lineNode * head, FILE * of)
547 /* don't indent comments & labels */
549 (*head->line == ';' ||
550 head->line[strlen (head->line) - 1] == ':')) {
551 fprintf (of, "%s\n", head->line);
553 if (head->isInline && *head->line=='#') {
554 // comment out preprocessor directives in inline asm
557 fprintf (of, "\t%s\n", head->line);
563 /*-----------------------------------------------------------------*/
564 /* newPeepRule - creates a new peeprule and attach it to the root */
565 /*-----------------------------------------------------------------*/
567 newPeepRule (lineNode * match,
574 pr = Safe_alloc ( sizeof (peepRule));
576 pr->replace = replace;
577 pr->restart = restart;
581 pr->cond = Safe_strdup (cond);
586 pr->vars = newHashTable (100);
588 /* if root is empty */
590 rootRules = currRule = pr;
592 currRule = currRule->next = pr;
597 /*-----------------------------------------------------------------*/
598 /* newLineNode - creates a new peep line */
599 /*-----------------------------------------------------------------*/
601 newLineNode (char *line)
605 pl = Safe_alloc ( sizeof (lineNode));
606 pl->line = Safe_strdup (line);
610 /*-----------------------------------------------------------------*/
611 /* connectLine - connects two lines */
612 /*-----------------------------------------------------------------*/
614 connectLine (lineNode * pl1, lineNode * pl2)
618 fprintf (stderr, "trying to connect null line\n");
628 #define SKIP_SPACE(x,y) { while (*x && (isspace(*x) || *x == '\n')) x++; \
629 if (!*x) { fprintf(stderr,y); return ; } }
631 #define EXPECT_STR(x,y,z) { while (*x && strncmp(x,y,strlen(y))) x++ ; \
632 if (!*x) { fprintf(stderr,z); return ; } }
633 #define EXPECT_CHR(x,y,z) { while (*x && *x != y) x++ ; \
634 if (!*x) { fprintf(stderr,z); return ; } }
636 /*-----------------------------------------------------------------*/
637 /* getPeepLine - parses the peep lines */
638 /*-----------------------------------------------------------------*/
640 getPeepLine (lineNode ** head, char **bpp)
642 char lines[MAX_PATTERN_LEN];
645 lineNode *currL = NULL;
652 fprintf (stderr, "unexpected end of match pattern\n");
659 while (isspace (*bp) ||
670 /* read till end of line */
672 while ((*bp != '\n' && *bp != '}') && *bp)
677 *head = currL = newLineNode (lines);
679 currL = connectLine (currL, newLineNode (lines));
685 /*-----------------------------------------------------------------*/
686 /* readRules - reads the rules from a string buffer */
687 /*-----------------------------------------------------------------*/
692 char lines[MAX_PATTERN_LEN];
696 lineNode *currL = NULL;
702 /* look for the token "replace" that is the
704 while (*bp && strncmp (bp, "replace", 7))
711 /* then look for either "restart" or '{' */
712 while (strncmp (bp, "restart", 7) &&
719 fprintf (stderr, "expected 'restart' or '{'\n");
727 { /* must be restart */
729 bp += strlen ("restart");
731 EXPECT_CHR (bp, '{', "expected '{'\n");
735 /* skip thru all the blank space */
736 SKIP_SPACE (bp, "unexpected end of rule\n");
738 match = replace = currL = NULL;
739 /* we are the start of a rule */
740 getPeepLine (&match, &bp);
742 /* now look for by */
743 EXPECT_STR (bp, "by", "expected 'by'\n");
745 /* then look for a '{' */
746 EXPECT_CHR (bp, '{', "expected '{'\n");
749 SKIP_SPACE (bp, "unexpected end of rule\n");
750 getPeepLine (&replace, &bp);
752 /* look for a 'if' */
753 while ((isspace (*bp) || *bp == '\n') && *bp)
756 if (strncmp (bp, "if", 2) == 0)
759 while ((isspace (*bp) || *bp == '\n') && *bp)
763 fprintf (stderr, "expected condition name\n");
767 /* look for the condition */
769 while (*bp && (*bp != '\n'))
775 newPeepRule (match, replace, lines, restart);
778 newPeepRule (match, replace, NULL, restart);
783 /*-----------------------------------------------------------------*/
784 /* keyForVar - returns the numeric key for a var */
785 /*-----------------------------------------------------------------*/
800 /*-----------------------------------------------------------------*/
801 /* bindVar - binds a value to a variable in the given hashtable */
802 /*-----------------------------------------------------------------*/
804 bindVar (int key, char **s, hTab ** vtab)
806 char vval[MAX_PATTERN_LEN];
810 /* first get the value of the variable */
812 /* the value is ended by a ',' or space or newline or null or ) */
821 /* if we find a '(' then we need to balance it */
833 // include the trailing ')'
842 vvx = traceAlloc (&_G.values, Safe_strdup(vval));
844 hTabAddItem (vtab, key, vvx);
847 /*-----------------------------------------------------------------*/
848 /* matchLine - matches one line */
849 /*-----------------------------------------------------------------*/
851 matchLine (char *s, char *d, hTab ** vars)
860 /* skip white space in both */
866 /* if the destination is a var */
867 if (*d == '%' && isdigit (*(d + 1)))
869 char *v = hTabItemWithKey (*vars, keyForVar (d + 1));
870 /* if the variable is already bound
871 then it MUST match with dest */
879 /* variable not bound we need to
881 bindVar (keyForVar (d + 1), &s, vars);
883 /* in either case go past the variable */
889 /* they should be an exact match other wise */
902 /* get rid of the trailing spaces
903 in both source & destination */
912 /* after all this if only one of them
913 has something left over then no match */
920 /*-----------------------------------------------------------------*/
921 /* matchRule - matches a all the rule lines */
922 /*-----------------------------------------------------------------*/
924 matchRule (lineNode * pl,
929 lineNode *spl; /* source pl */
930 lineNode *rpl; /* rule peep line */
932 /* setToNull((void **) &pr->vars); */
933 /* pr->vars = newHashTable(100); */
935 /* for all the lines defined in the rule */
941 /* if the source line starts with a ';' then
942 comment line don't process or the source line
943 contains == . debugger information skip it */
945 (*spl->line == ';' || spl->isDebug))
951 if (!matchLine (spl->line, rpl->line, &pr->vars))
962 /* if this rule has additional conditions */
965 if (callFuncByName (pr->cond, pr->vars, pl, head))
983 /*-----------------------------------------------------------------*/
984 /* replaceRule - does replacement of a matching pattern */
985 /*-----------------------------------------------------------------*/
987 replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr)
990 lineNode *pl = NULL, *lhead = NULL;
991 /* a long function name and long variable name can evaluate to
992 4x max pattern length e.g. "mov dptr,((fie_var>>8)<<8)+fie_var" */
993 char lb[MAX_PATTERN_LEN*4];
995 lineNode *comment = NULL;
997 /* collect all the comment lines in the source */
998 for (cl = *shead; cl != stail; cl = cl->next)
1000 if (cl->line && (*cl->line == ';' || cl->isDebug))
1002 pl = (pl ? connectLine (pl, newLineNode (cl->line)) :
1003 (comment = newLineNode (cl->line)));
1004 pl->isDebug = cl->isDebug;
1009 /* for all the lines in the replacement pattern do */
1010 for (pl = pr->replace; pl; pl = pl->next)
1020 /* if the line contains a variable */
1021 if (*l == '%' && isdigit (*(l + 1)))
1023 v = hTabItemWithKey (pr->vars, keyForVar (l + 1));
1026 fprintf (stderr, "used unbound variable in replacement\n");
1034 while (isdigit (*l)) {
1044 cl = connectLine (cl, newLineNode (lb));
1046 lhead = cl = newLineNode (lb);
1049 /* add the comments if any to the head of list */
1052 lineNode *lc = comment;
1061 /* now we need to connect / replace the original chain */
1062 /* if there is a prev then change it */
1065 (*shead)->prev->next = lhead;
1066 lhead->prev = (*shead)->prev;
1069 /* now for the tail */
1070 if (stail && stail->next)
1072 stail->next->prev = cl;
1074 cl->next = stail->next;
1078 /* Returns TRUE if this line is a label definition.
1080 * If so, start will point to the start of the label name,
1081 * and len will be it's length.
1084 isLabelDefinition (const char *line, const char **start, int *len)
1086 const char *cp = line;
1088 /* This line is a label if if consists of:
1089 * [optional whitespace] followed by identifier chars
1090 * (alnum | $ | _ ) followed by a colon.
1093 while (*cp && isspace (*cp))
1105 while (isalnum (*cp) || (*cp == '$') || (*cp == '_'))
1110 if ((cp == *start) || (*cp != ':'))
1115 *len = (cp - (*start));
1119 /* Quick & dirty string hash function. */
1121 hashSymbolName (const char *name)
1127 hash = (hash << 6) ^ *name;
1136 return hash % HTAB_SIZE;
1139 /* Build a hash of all labels in the passed set of lines
1140 * and how many times they are referenced.
1143 buildLabelRefCountHash (lineNode * head)
1150 assert (labelHash == NULL);
1151 labelHash = newHashTable (HTAB_SIZE);
1153 /* First pass: locate all the labels. */
1158 if (isLabelDefinition (line->line, &label, &labelLen)
1159 && labelLen <= SDCC_NAME_MAX)
1161 labelHashEntry *entry;
1163 entry = traceAlloc (&_G.labels, Safe_alloc(sizeof (labelHashEntry)));
1165 memcpy (entry->name, label, labelLen);
1166 entry->name[labelLen] = 0;
1167 entry->refCount = -1;
1169 hTabAddItem (&labelHash, hashSymbolName (entry->name), entry);
1175 /* Second pass: for each line, note all the referenced labels. */
1176 /* This is ugly, O(N^2) stuff. Optimizations welcome... */
1180 for (i = 0; i < HTAB_SIZE; i++)
1182 labelHashEntry *thisEntry;
1184 thisEntry = hTabFirstItemWK (labelHash, i);
1188 if (strstr (line->line, thisEntry->name))
1190 thisEntry->refCount++;
1192 thisEntry = hTabNextItemWK (labelHash);
1199 /* Spew the contents of the table. Debugging fun only. */
1200 for (i = 0; i < HTAB_SIZE; i++)
1202 labelHashEntry *thisEntry;
1204 thisEntry = hTabFirstItemWK (labelHash, i);
1208 fprintf (stderr, "label: %s ref %d\n",
1209 thisEntry->name, thisEntry->refCount);
1210 thisEntry = hTabNextItemWK (labelHash);
1216 /* How does this work?
1222 replace and restart.
1227 Where is stuff allocated?
1231 /*-----------------------------------------------------------------*/
1232 /* peepHole - matches & substitutes rules */
1233 /*-----------------------------------------------------------------*/
1235 peepHole (lineNode ** pls)
1239 lineNode *mtail = NULL;
1242 #if !OPT_DISABLE_PIC
1243 /* The PIC port uses a different peep hole optimizer based on "pCode" */
1248 assert(labelHash == NULL);
1255 for (pr = rootRules; pr; pr = pr->next)
1257 for (spl = *pls; spl; spl = spl->next)
1259 /* if inline assembler then no peep hole */
1265 /* Tidy up any data stored in the hTab */
1268 if (matchRule (spl, &mtail, pr, *pls))
1273 replaceRule (pls, mtail, pr);
1275 replaceRule (&spl, mtail, pr);
1277 /* if restart rule type then
1278 start at the top again */
1287 hTabDeleteAll (pr->vars);
1288 Safe_free (pr->vars);
1292 freeTrace (&_G.values);
1295 } while (restart == TRUE);
1299 hTabDeleteAll (labelHash);
1300 freeTrace (&_G.labels);
1306 /*-----------------------------------------------------------------*/
1307 /* readFileIntoBuffer - reads a file into a string buffer */
1308 /*-----------------------------------------------------------------*/
1310 readFileIntoBuffer (char *fname)
1316 char lb[MAX_PATTERN_LEN];
1318 if (!(f = fopen (fname, "r")))
1320 fprintf (stderr, "cannot open peep rule file\n");
1324 while ((ch = fgetc (f)) != EOF)
1328 /* if we maxed out our local buffer */
1329 if (nch >= (MAX_PATTERN_LEN - 2))
1332 /* copy it into allocated buffer */
1335 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
1336 strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
1340 rs = Safe_strdup (lb);
1346 /* if some charaters left over */
1350 /* copy it into allocated buffer */
1353 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
1354 strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
1358 rs = Safe_strdup (lb);
1364 /*-----------------------------------------------------------------*/
1365 /* initPeepHole - initialises the peep hole optimizer stuff */
1366 /*-----------------------------------------------------------------*/
1372 /* read in the default rules */
1373 readRules (port->peep.default_rules);
1375 /* if we have any additional file read it too */
1376 if (options.peep_file)
1378 readRules (s = readFileIntoBuffer (options.peep_file));
1379 setToNull ((void **) &s);
1383 #if !OPT_DISABLE_PIC
1384 /* Convert the peep rules into pcode.
1385 NOTE: this is only support in the PIC port (at the moment)
1387 if (TARGET_IS_PIC) {
1388 peepRules2pCode(rootRules);