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 sprintf (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
502 for (i = 0; i < ((sizeof (ftab)) / (sizeof (struct ftab))); i++)
503 if (strncmp (ftab[i].fname, fname, strlen (ftab[i].fname)) == 0)
505 return (*ftab[i].func) (vars, currPl, head,
506 fname + strlen (ftab[i].fname));
508 fprintf (stderr, "could not find named function in function table\n");
512 /*-----------------------------------------------------------------*/
513 /* printLine - prints a line chain into a given file */
514 /*-----------------------------------------------------------------*/
516 printLine (lineNode * head, FILE * of)
523 /* don't indent comments & labels */
525 (*head->line == ';' ||
526 head->line[strlen (head->line) - 1] == ':')) {
527 fprintf (of, "%s\n", head->line);
529 if (head->isInline && *head->line=='#') {
530 // comment out preprocessor directives in inline asm
533 fprintf (of, "\t%s\n", head->line);
539 /*-----------------------------------------------------------------*/
540 /* newPeepRule - creates a new peeprule and attach it to the root */
541 /*-----------------------------------------------------------------*/
543 newPeepRule (lineNode * match,
550 pr = Safe_alloc ( sizeof (peepRule));
552 pr->replace = replace;
553 pr->restart = restart;
557 pr->cond = Safe_strdup (cond);
562 pr->vars = newHashTable (100);
564 /* if root is empty */
566 rootRules = currRule = pr;
568 currRule = currRule->next = pr;
573 /*-----------------------------------------------------------------*/
574 /* newLineNode - creates a new peep line */
575 /*-----------------------------------------------------------------*/
577 newLineNode (char *line)
581 pl = Safe_alloc ( sizeof (lineNode));
582 pl->line = Safe_strdup (line);
586 /*-----------------------------------------------------------------*/
587 /* connectLine - connects two lines */
588 /*-----------------------------------------------------------------*/
590 connectLine (lineNode * pl1, lineNode * pl2)
594 fprintf (stderr, "trying to connect null line\n");
604 #define SKIP_SPACE(x,y) { while (*x && (isspace(*x) || *x == '\n')) x++; \
605 if (!*x) { fprintf(stderr,y); return ; } }
607 #define EXPECT_STR(x,y,z) { while (*x && strncmp(x,y,strlen(y))) x++ ; \
608 if (!*x) { fprintf(stderr,z); return ; } }
609 #define EXPECT_CHR(x,y,z) { while (*x && *x != y) x++ ; \
610 if (!*x) { fprintf(stderr,z); return ; } }
612 /*-----------------------------------------------------------------*/
613 /* getPeepLine - parses the peep lines */
614 /*-----------------------------------------------------------------*/
616 getPeepLine (lineNode ** head, char **bpp)
618 char lines[MAX_PATTERN_LEN];
621 lineNode *currL = NULL;
628 fprintf (stderr, "unexpected end of match pattern\n");
635 while (isspace (*bp) ||
646 /* read till end of line */
648 while ((*bp != '\n' && *bp != '}') && *bp)
653 *head = currL = newLineNode (lines);
655 currL = connectLine (currL, newLineNode (lines));
661 /*-----------------------------------------------------------------*/
662 /* readRules - reads the rules from a string buffer */
663 /*-----------------------------------------------------------------*/
668 char lines[MAX_PATTERN_LEN];
672 lineNode *currL = NULL;
678 /* look for the token "replace" that is the
680 while (*bp && strncmp (bp, "replace", 7))
687 /* then look for either "restart" or '{' */
688 while (strncmp (bp, "restart", 7) &&
695 fprintf (stderr, "expected 'restart' or '{'\n");
703 { /* must be restart */
705 bp += strlen ("restart");
707 EXPECT_CHR (bp, '{', "expected '{'\n");
711 /* skip thru all the blank space */
712 SKIP_SPACE (bp, "unexpected end of rule\n");
714 match = replace = currL = NULL;
715 /* we are the start of a rule */
716 getPeepLine (&match, &bp);
718 /* now look for by */
719 EXPECT_STR (bp, "by", "expected 'by'\n");
721 /* then look for a '{' */
722 EXPECT_CHR (bp, '{', "expected '{'\n");
725 SKIP_SPACE (bp, "unexpected end of rule\n");
726 getPeepLine (&replace, &bp);
728 /* look for a 'if' */
729 while ((isspace (*bp) || *bp == '\n') && *bp)
732 if (strncmp (bp, "if", 2) == 0)
735 while ((isspace (*bp) || *bp == '\n') && *bp)
739 fprintf (stderr, "expected condition name\n");
743 /* look for the condition */
745 while (*bp && (*bp != '\n'))
751 newPeepRule (match, replace, lines, restart);
754 newPeepRule (match, replace, NULL, restart);
759 /*-----------------------------------------------------------------*/
760 /* keyForVar - returns the numeric key for a var */
761 /*-----------------------------------------------------------------*/
776 /*-----------------------------------------------------------------*/
777 /* bindVar - binds a value to a variable in the given hashtable */
778 /*-----------------------------------------------------------------*/
780 bindVar (int key, char **s, hTab ** vtab)
782 char vval[MAX_PATTERN_LEN];
786 /* first get the value of the variable */
788 /* the value is ended by a ',' or space or newline or null or ) */
797 /* if we find a '(' then we need to balance it */
809 // include the trailing ')'
818 vvx = traceAlloc (&_G.values, Safe_alloc(strlen (vval) + 1));
821 hTabAddItem (vtab, key, vvx);
824 /*-----------------------------------------------------------------*/
825 /* matchLine - matches one line */
826 /*-----------------------------------------------------------------*/
828 matchLine (char *s, char *d, hTab ** vars)
837 /* skip white space in both */
843 /* if the destination is a var */
844 if (*d == '%' && isdigit (*(d + 1)))
846 char *v = hTabItemWithKey (*vars, keyForVar (d + 1));
847 /* if the variable is already bound
848 then it MUST match with dest */
856 /* variable not bound we need to
858 bindVar (keyForVar (d + 1), &s, vars);
860 /* in either case go past the variable */
866 /* they should be an exact match other wise */
879 /* get rid of the trailing spaces
880 in both source & destination */
889 /* after all this if only one of them
890 has something left over then no match */
897 /*-----------------------------------------------------------------*/
898 /* matchRule - matches a all the rule lines */
899 /*-----------------------------------------------------------------*/
901 matchRule (lineNode * pl,
906 lineNode *spl; /* source pl */
907 lineNode *rpl; /* rule peep line */
909 /* setToNull((void **) &pr->vars); */
910 /* pr->vars = newHashTable(100); */
912 /* for all the lines defined in the rule */
918 /* if the source line starts with a ';' then
919 comment line don't process or the source line
920 contains == . debugger information skip it */
922 (*spl->line == ';' || spl->isDebug))
928 if (!matchLine (spl->line, rpl->line, &pr->vars))
939 /* if this rule has additional conditions */
942 if (callFuncByName (pr->cond, pr->vars, pl, head))
960 /*-----------------------------------------------------------------*/
961 /* replaceRule - does replacement of a matching pattern */
962 /*-----------------------------------------------------------------*/
964 replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr)
967 lineNode *pl = NULL, *lhead = NULL;
968 /* a long function name and long variable name can evaluate to
969 4x max pattern length e.g. "mov dptr,((fie_var>>8)<<8)+fie_var" */
970 char lb[MAX_PATTERN_LEN*4];
972 lineNode *comment = NULL;
974 /* collect all the comment lines in the source */
975 for (cl = *shead; cl != stail; cl = cl->next)
977 if (cl->line && (*cl->line == ';' || cl->isDebug))
979 pl = (pl ? connectLine (pl, newLineNode (cl->line)) :
980 (comment = newLineNode (cl->line)));
981 pl->isDebug = cl->isDebug;
986 /* for all the lines in the replacement pattern do */
987 for (pl = pr->replace; pl; pl = pl->next)
997 /* if the line contains a variable */
998 if (*l == '%' && isdigit (*(l + 1)))
1000 v = hTabItemWithKey (pr->vars, keyForVar (l + 1));
1003 fprintf (stderr, "used unbound variable in replacement\n");
1011 while (isdigit (*l)) {
1021 cl = connectLine (cl, newLineNode (lb));
1023 lhead = cl = newLineNode (lb);
1026 /* add the comments if any to the head of list */
1029 lineNode *lc = comment;
1038 /* now we need to connect / replace the original chain */
1039 /* if there is a prev then change it */
1042 (*shead)->prev->next = lhead;
1043 lhead->prev = (*shead)->prev;
1046 /* now for the tail */
1047 if (stail && stail->next)
1049 stail->next->prev = cl;
1051 cl->next = stail->next;
1055 /* Returns TRUE if this line is a label definition.
1057 * If so, start will point to the start of the label name,
1058 * and len will be it's length.
1061 isLabelDefinition (const char *line, const char **start, int *len)
1063 const char *cp = line;
1065 /* This line is a label if if consists of:
1066 * [optional whitespace] followed by identifier chars
1067 * (alnum | $ | _ ) followed by a colon.
1070 while (*cp && isspace (*cp))
1082 while (isalnum (*cp) || (*cp == '$') || (*cp == '_'))
1087 if ((cp == *start) || (*cp != ':'))
1092 *len = (cp - (*start));
1096 /* Quick & dirty string hash function. */
1098 hashSymbolName (const char *name)
1104 hash = (hash << 6) ^ *name;
1113 return hash % HTAB_SIZE;
1116 /* Build a hash of all labels in the passed set of lines
1117 * and how many times they are referenced.
1120 buildLabelRefCountHash (lineNode * head)
1127 assert (labelHash == NULL);
1128 labelHash = newHashTable (HTAB_SIZE);
1130 /* First pass: locate all the labels. */
1135 if (isLabelDefinition (line->line, &label, &labelLen)
1136 && labelLen <= SDCC_NAME_MAX)
1138 labelHashEntry *entry;
1140 entry = traceAlloc (&_G.labels, Safe_alloc(sizeof (labelHashEntry)));
1142 memcpy (entry->name, label, labelLen);
1143 entry->name[labelLen] = 0;
1144 entry->refCount = -1;
1146 hTabAddItem (&labelHash, hashSymbolName (entry->name), entry);
1152 /* Second pass: for each line, note all the referenced labels. */
1153 /* This is ugly, O(N^2) stuff. Optimizations welcome... */
1157 for (i = 0; i < HTAB_SIZE; i++)
1159 labelHashEntry *thisEntry;
1161 thisEntry = hTabFirstItemWK (labelHash, i);
1165 if (strstr (line->line, thisEntry->name))
1167 thisEntry->refCount++;
1169 thisEntry = hTabNextItemWK (labelHash);
1176 /* Spew the contents of the table. Debugging fun only. */
1177 for (i = 0; i < HTAB_SIZE; i++)
1179 labelHashEntry *thisEntry;
1181 thisEntry = hTabFirstItemWK (labelHash, i);
1185 fprintf (stderr, "label: %s ref %d\n",
1186 thisEntry->name, thisEntry->refCount);
1187 thisEntry = hTabNextItemWK (labelHash);
1193 /* How does this work?
1199 replace and restart.
1204 Where is stuff allocated?
1208 /*-----------------------------------------------------------------*/
1209 /* peepHole - matches & substitutes rules */
1210 /*-----------------------------------------------------------------*/
1212 peepHole (lineNode ** pls)
1216 lineNode *mtail = NULL;
1219 #if !OPT_DISABLE_PIC
1220 /* The PIC port uses a different peep hole optimizer based on "pCode" */
1225 assert(labelHash == NULL);
1232 for (pr = rootRules; pr; pr = pr->next)
1234 for (spl = *pls; spl; spl = spl->next)
1236 /* if inline assembler then no peep hole */
1242 /* Tidy up any data stored in the hTab */
1245 if (matchRule (spl, &mtail, pr, *pls))
1250 replaceRule (pls, mtail, pr);
1252 replaceRule (&spl, mtail, pr);
1254 /* if restart rule type then
1255 start at the top again */
1264 hTabDeleteAll (pr->vars);
1265 Safe_free (pr->vars);
1269 freeTrace (&_G.values);
1272 } while (restart == TRUE);
1276 hTabDeleteAll (labelHash);
1277 freeTrace (&_G.labels);
1283 /*-----------------------------------------------------------------*/
1284 /* readFileIntoBuffer - reads a file into a string buffer */
1285 /*-----------------------------------------------------------------*/
1287 readFileIntoBuffer (char *fname)
1293 char lb[MAX_PATTERN_LEN];
1295 if (!(f = fopen (fname, "r")))
1297 fprintf (stderr, "cannot open peep rule file\n");
1301 while ((ch = fgetc (f)) != EOF)
1305 /* if we maxed out our local buffer */
1306 if (nch >= (MAX_PATTERN_LEN - 2))
1309 /* copy it into allocated buffer */
1312 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
1317 rs = Safe_strdup (lb);
1323 /* if some charaters left over */
1327 /* copy it into allocated buffer */
1330 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
1335 rs = Safe_strdup (lb);
1341 /*-----------------------------------------------------------------*/
1342 /* initPeepHole - initialises the peep hole optimizer stuff */
1343 /*-----------------------------------------------------------------*/
1349 /* read in the default rules */
1350 readRules (port->peep.default_rules);
1352 /* if we have any additional file read it too */
1353 if (options.peep_file)
1355 readRules (s = readFileIntoBuffer (options.peep_file));
1356 setToNull ((void **) &s);
1360 #if !OPT_DISABLE_PIC
1361 /* Convert the peep rules into pcode.
1362 NOTE: this is only support in the PIC port (at the moment)
1364 if (TARGET_IS_PIC) {
1365 peepRules2pCode(rootRules);