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
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_strdup(vval));
820 hTabAddItem (vtab, key, vvx);
823 /*-----------------------------------------------------------------*/
824 /* matchLine - matches one line */
825 /*-----------------------------------------------------------------*/
827 matchLine (char *s, char *d, hTab ** vars)
836 /* skip white space in both */
842 /* if the destination is a var */
843 if (*d == '%' && isdigit (*(d + 1)))
845 char *v = hTabItemWithKey (*vars, keyForVar (d + 1));
846 /* if the variable is already bound
847 then it MUST match with dest */
855 /* variable not bound we need to
857 bindVar (keyForVar (d + 1), &s, vars);
859 /* in either case go past the variable */
865 /* they should be an exact match other wise */
878 /* get rid of the trailing spaces
879 in both source & destination */
888 /* after all this if only one of them
889 has something left over then no match */
896 /*-----------------------------------------------------------------*/
897 /* matchRule - matches a all the rule lines */
898 /*-----------------------------------------------------------------*/
900 matchRule (lineNode * pl,
905 lineNode *spl; /* source pl */
906 lineNode *rpl; /* rule peep line */
908 /* setToNull((void **) &pr->vars); */
909 /* pr->vars = newHashTable(100); */
911 /* for all the lines defined in the rule */
917 /* if the source line starts with a ';' then
918 comment line don't process or the source line
919 contains == . debugger information skip it */
921 (*spl->line == ';' || spl->isDebug))
927 if (!matchLine (spl->line, rpl->line, &pr->vars))
938 /* if this rule has additional conditions */
941 if (callFuncByName (pr->cond, pr->vars, pl, head))
959 /*-----------------------------------------------------------------*/
960 /* replaceRule - does replacement of a matching pattern */
961 /*-----------------------------------------------------------------*/
963 replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr)
966 lineNode *pl = NULL, *lhead = NULL;
967 /* a long function name and long variable name can evaluate to
968 4x max pattern length e.g. "mov dptr,((fie_var>>8)<<8)+fie_var" */
969 char lb[MAX_PATTERN_LEN*4];
971 lineNode *comment = NULL;
973 /* collect all the comment lines in the source */
974 for (cl = *shead; cl != stail; cl = cl->next)
976 if (cl->line && (*cl->line == ';' || cl->isDebug))
978 pl = (pl ? connectLine (pl, newLineNode (cl->line)) :
979 (comment = newLineNode (cl->line)));
980 pl->isDebug = cl->isDebug;
985 /* for all the lines in the replacement pattern do */
986 for (pl = pr->replace; pl; pl = pl->next)
996 /* if the line contains a variable */
997 if (*l == '%' && isdigit (*(l + 1)))
999 v = hTabItemWithKey (pr->vars, keyForVar (l + 1));
1002 fprintf (stderr, "used unbound variable in replacement\n");
1010 while (isdigit (*l)) {
1020 cl = connectLine (cl, newLineNode (lb));
1022 lhead = cl = newLineNode (lb);
1025 /* add the comments if any to the head of list */
1028 lineNode *lc = comment;
1037 /* now we need to connect / replace the original chain */
1038 /* if there is a prev then change it */
1041 (*shead)->prev->next = lhead;
1042 lhead->prev = (*shead)->prev;
1045 /* now for the tail */
1046 if (stail && stail->next)
1048 stail->next->prev = cl;
1050 cl->next = stail->next;
1054 /* Returns TRUE if this line is a label definition.
1056 * If so, start will point to the start of the label name,
1057 * and len will be it's length.
1060 isLabelDefinition (const char *line, const char **start, int *len)
1062 const char *cp = line;
1064 /* This line is a label if if consists of:
1065 * [optional whitespace] followed by identifier chars
1066 * (alnum | $ | _ ) followed by a colon.
1069 while (*cp && isspace (*cp))
1081 while (isalnum (*cp) || (*cp == '$') || (*cp == '_'))
1086 if ((cp == *start) || (*cp != ':'))
1091 *len = (cp - (*start));
1095 /* Quick & dirty string hash function. */
1097 hashSymbolName (const char *name)
1103 hash = (hash << 6) ^ *name;
1112 return hash % HTAB_SIZE;
1115 /* Build a hash of all labels in the passed set of lines
1116 * and how many times they are referenced.
1119 buildLabelRefCountHash (lineNode * head)
1126 assert (labelHash == NULL);
1127 labelHash = newHashTable (HTAB_SIZE);
1129 /* First pass: locate all the labels. */
1134 if (isLabelDefinition (line->line, &label, &labelLen)
1135 && labelLen <= SDCC_NAME_MAX)
1137 labelHashEntry *entry;
1139 entry = traceAlloc (&_G.labels, Safe_alloc(sizeof (labelHashEntry)));
1141 memcpy (entry->name, label, labelLen);
1142 entry->name[labelLen] = 0;
1143 entry->refCount = -1;
1145 hTabAddItem (&labelHash, hashSymbolName (entry->name), entry);
1151 /* Second pass: for each line, note all the referenced labels. */
1152 /* This is ugly, O(N^2) stuff. Optimizations welcome... */
1156 for (i = 0; i < HTAB_SIZE; i++)
1158 labelHashEntry *thisEntry;
1160 thisEntry = hTabFirstItemWK (labelHash, i);
1164 if (strstr (line->line, thisEntry->name))
1166 thisEntry->refCount++;
1168 thisEntry = hTabNextItemWK (labelHash);
1175 /* Spew the contents of the table. Debugging fun only. */
1176 for (i = 0; i < HTAB_SIZE; i++)
1178 labelHashEntry *thisEntry;
1180 thisEntry = hTabFirstItemWK (labelHash, i);
1184 fprintf (stderr, "label: %s ref %d\n",
1185 thisEntry->name, thisEntry->refCount);
1186 thisEntry = hTabNextItemWK (labelHash);
1192 /* How does this work?
1198 replace and restart.
1203 Where is stuff allocated?
1207 /*-----------------------------------------------------------------*/
1208 /* peepHole - matches & substitutes rules */
1209 /*-----------------------------------------------------------------*/
1211 peepHole (lineNode ** pls)
1215 lineNode *mtail = NULL;
1218 #if !OPT_DISABLE_PIC
1219 /* The PIC port uses a different peep hole optimizer based on "pCode" */
1224 assert(labelHash == NULL);
1231 for (pr = rootRules; pr; pr = pr->next)
1233 for (spl = *pls; spl; spl = spl->next)
1235 /* if inline assembler then no peep hole */
1241 /* Tidy up any data stored in the hTab */
1244 if (matchRule (spl, &mtail, pr, *pls))
1249 replaceRule (pls, mtail, pr);
1251 replaceRule (&spl, mtail, pr);
1253 /* if restart rule type then
1254 start at the top again */
1263 hTabDeleteAll (pr->vars);
1264 Safe_free (pr->vars);
1268 freeTrace (&_G.values);
1271 } while (restart == TRUE);
1275 hTabDeleteAll (labelHash);
1276 freeTrace (&_G.labels);
1282 /*-----------------------------------------------------------------*/
1283 /* readFileIntoBuffer - reads a file into a string buffer */
1284 /*-----------------------------------------------------------------*/
1286 readFileIntoBuffer (char *fname)
1292 char lb[MAX_PATTERN_LEN];
1294 if (!(f = fopen (fname, "r")))
1296 fprintf (stderr, "cannot open peep rule file\n");
1300 while ((ch = fgetc (f)) != EOF)
1304 /* if we maxed out our local buffer */
1305 if (nch >= (MAX_PATTERN_LEN - 2))
1308 /* copy it into allocated buffer */
1311 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
1312 strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
1316 rs = Safe_strdup (lb);
1322 /* if some charaters left over */
1326 /* copy it into allocated buffer */
1329 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
1330 strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
1334 rs = Safe_strdup (lb);
1340 /*-----------------------------------------------------------------*/
1341 /* initPeepHole - initialises the peep hole optimizer stuff */
1342 /*-----------------------------------------------------------------*/
1348 /* read in the default rules */
1349 readRules (port->peep.default_rules);
1351 /* if we have any additional file read it too */
1352 if (options.peep_file)
1354 readRules (s = readFileIntoBuffer (options.peep_file));
1355 setToNull ((void **) &s);
1359 #if !OPT_DISABLE_PIC
1360 /* Convert the peep rules into pcode.
1361 NOTE: this is only support in the PIC port (at the moment)
1363 if (TARGET_IS_PIC) {
1364 peepRules2pCode(rootRules);