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_alloc ( strlen (cond) + 1);
558 strcpy (pr->cond, cond);
563 pr->vars = newHashTable (100);
565 /* if root is empty */
567 rootRules = currRule = pr;
569 currRule = currRule->next = pr;
574 /*-----------------------------------------------------------------*/
575 /* newLineNode - creates a new peep line */
576 /*-----------------------------------------------------------------*/
578 newLineNode (char *line)
582 pl = Safe_alloc ( sizeof (lineNode));
583 pl->line = Safe_alloc ( strlen (line) + 1);
584 strcpy (pl->line, line);
588 /*-----------------------------------------------------------------*/
589 /* connectLine - connects two lines */
590 /*-----------------------------------------------------------------*/
592 connectLine (lineNode * pl1, lineNode * pl2)
596 fprintf (stderr, "trying to connect null line\n");
606 #define SKIP_SPACE(x,y) { while (*x && (isspace(*x) || *x == '\n')) x++; \
607 if (!*x) { fprintf(stderr,y); return ; } }
609 #define EXPECT_STR(x,y,z) { while (*x && strncmp(x,y,strlen(y))) x++ ; \
610 if (!*x) { fprintf(stderr,z); return ; } }
611 #define EXPECT_CHR(x,y,z) { while (*x && *x != y) x++ ; \
612 if (!*x) { fprintf(stderr,z); return ; } }
614 /*-----------------------------------------------------------------*/
615 /* getPeepLine - parses the peep lines */
616 /*-----------------------------------------------------------------*/
618 getPeepLine (lineNode ** head, char **bpp)
620 char lines[MAX_PATTERN_LEN];
623 lineNode *currL = NULL;
630 fprintf (stderr, "unexpected end of match pattern\n");
637 while (isspace (*bp) ||
648 /* read till end of line */
650 while ((*bp != '\n' && *bp != '}') && *bp)
655 *head = currL = newLineNode (lines);
657 currL = connectLine (currL, newLineNode (lines));
663 /*-----------------------------------------------------------------*/
664 /* readRules - reads the rules from a string buffer */
665 /*-----------------------------------------------------------------*/
670 char lines[MAX_PATTERN_LEN];
674 lineNode *currL = NULL;
680 /* look for the token "replace" that is the
682 while (*bp && strncmp (bp, "replace", 7))
689 /* then look for either "restart" or '{' */
690 while (strncmp (bp, "restart", 7) &&
697 fprintf (stderr, "expected 'restart' or '{'\n");
705 { /* must be restart */
707 bp += strlen ("restart");
709 EXPECT_CHR (bp, '{', "expected '{'\n");
713 /* skip thru all the blank space */
714 SKIP_SPACE (bp, "unexpected end of rule\n");
716 match = replace = currL = NULL;
717 /* we are the start of a rule */
718 getPeepLine (&match, &bp);
720 /* now look for by */
721 EXPECT_STR (bp, "by", "expected 'by'\n");
723 /* then look for a '{' */
724 EXPECT_CHR (bp, '{', "expected '{'\n");
727 SKIP_SPACE (bp, "unexpected end of rule\n");
728 getPeepLine (&replace, &bp);
730 /* look for a 'if' */
731 while ((isspace (*bp) || *bp == '\n') && *bp)
734 if (strncmp (bp, "if", 2) == 0)
737 while ((isspace (*bp) || *bp == '\n') && *bp)
741 fprintf (stderr, "expected condition name\n");
745 /* look for the condition */
747 while (*bp && (*bp != '\n'))
753 newPeepRule (match, replace, lines, restart);
756 newPeepRule (match, replace, NULL, restart);
761 /*-----------------------------------------------------------------*/
762 /* keyForVar - returns the numeric key for a var */
763 /*-----------------------------------------------------------------*/
778 /*-----------------------------------------------------------------*/
779 /* bindVar - binds a value to a variable in the given hashtable */
780 /*-----------------------------------------------------------------*/
782 bindVar (int key, char **s, hTab ** vtab)
784 char vval[MAX_PATTERN_LEN];
788 /* first get the value of the variable */
790 /* the value is ended by a ',' or space or newline or null or ) */
799 /* if we find a '(' then we need to balance it */
811 // include the trailing ')'
820 vvx = traceAlloc (&_G.values, Safe_alloc(strlen (vval) + 1));
823 hTabAddItem (vtab, key, vvx);
826 /*-----------------------------------------------------------------*/
827 /* matchLine - matches one line */
828 /*-----------------------------------------------------------------*/
830 matchLine (char *s, char *d, hTab ** vars)
839 /* skip white space in both */
845 /* if the destination is a var */
846 if (*d == '%' && isdigit (*(d + 1)))
848 char *v = hTabItemWithKey (*vars, keyForVar (d + 1));
849 /* if the variable is already bound
850 then it MUST match with dest */
858 /* variable not bound we need to
860 bindVar (keyForVar (d + 1), &s, vars);
862 /* in either case go past the variable */
868 /* they should be an exact match other wise */
881 /* get rid of the trailing spaces
882 in both source & destination */
891 /* after all this if only one of them
892 has something left over then no match */
899 /*-----------------------------------------------------------------*/
900 /* matchRule - matches a all the rule lines */
901 /*-----------------------------------------------------------------*/
903 matchRule (lineNode * pl,
908 lineNode *spl; /* source pl */
909 lineNode *rpl; /* rule peep line */
911 /* setToNull((void **) &pr->vars); */
912 /* pr->vars = newHashTable(100); */
914 /* for all the lines defined in the rule */
920 /* if the source line starts with a ';' then
921 comment line don't process or the source line
922 contains == . debugger information skip it */
924 (*spl->line == ';' || spl->isDebug))
930 if (!matchLine (spl->line, rpl->line, &pr->vars))
941 /* if this rule has additional conditions */
944 if (callFuncByName (pr->cond, pr->vars, pl, head))
962 /*-----------------------------------------------------------------*/
963 /* replaceRule - does replacement of a matching pattern */
964 /*-----------------------------------------------------------------*/
966 replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr)
969 lineNode *pl = NULL, *lhead = NULL;
970 /* a long function name and long variable name can evaluate to
971 4x max pattern length e.g. "mov dptr,((fie_var>>8)<<8)+fie_var" */
972 char lb[MAX_PATTERN_LEN*4];
974 lineNode *comment = NULL;
976 /* collect all the comment lines in the source */
977 for (cl = *shead; cl != stail; cl = cl->next)
979 if (cl->line && (*cl->line == ';' || cl->isDebug))
981 pl = (pl ? connectLine (pl, newLineNode (cl->line)) :
982 (comment = newLineNode (cl->line)));
983 pl->isDebug = cl->isDebug;
988 /* for all the lines in the replacement pattern do */
989 for (pl = pr->replace; pl; pl = pl->next)
999 /* if the line contains a variable */
1000 if (*l == '%' && isdigit (*(l + 1)))
1002 v = hTabItemWithKey (pr->vars, keyForVar (l + 1));
1005 fprintf (stderr, "used unbound variable in replacement\n");
1013 while (isdigit (*l)) {
1023 cl = connectLine (cl, newLineNode (lb));
1025 lhead = cl = newLineNode (lb);
1028 /* add the comments if any to the head of list */
1031 lineNode *lc = comment;
1040 /* now we need to connect / replace the original chain */
1041 /* if there is a prev then change it */
1044 (*shead)->prev->next = lhead;
1045 lhead->prev = (*shead)->prev;
1048 /* now for the tail */
1049 if (stail && stail->next)
1051 stail->next->prev = cl;
1053 cl->next = stail->next;
1057 /* Returns TRUE if this line is a label definition.
1059 * If so, start will point to the start of the label name,
1060 * and len will be it's length.
1063 isLabelDefinition (const char *line, const char **start, int *len)
1065 const char *cp = line;
1067 /* This line is a label if if consists of:
1068 * [optional whitespace] followed by identifier chars
1069 * (alnum | $ | _ ) followed by a colon.
1072 while (*cp && isspace (*cp))
1084 while (isalnum (*cp) || (*cp == '$') || (*cp == '_'))
1089 if ((cp == *start) || (*cp != ':'))
1094 *len = (cp - (*start));
1098 /* Quick & dirty string hash function. */
1100 hashSymbolName (const char *name)
1106 hash = (hash << 6) ^ *name;
1115 return hash % HTAB_SIZE;
1118 /* Build a hash of all labels in the passed set of lines
1119 * and how many times they are referenced.
1122 buildLabelRefCountHash (lineNode * head)
1129 assert (labelHash == NULL);
1130 labelHash = newHashTable (HTAB_SIZE);
1132 /* First pass: locate all the labels. */
1137 if (isLabelDefinition (line->line, &label, &labelLen)
1138 && labelLen <= SDCC_NAME_MAX)
1140 labelHashEntry *entry;
1142 entry = traceAlloc (&_G.labels, Safe_alloc(sizeof (labelHashEntry)));
1144 memcpy (entry->name, label, labelLen);
1145 entry->name[labelLen] = 0;
1146 entry->refCount = -1;
1148 hTabAddItem (&labelHash, hashSymbolName (entry->name), entry);
1154 /* Second pass: for each line, note all the referenced labels. */
1155 /* This is ugly, O(N^2) stuff. Optimizations welcome... */
1159 for (i = 0; i < HTAB_SIZE; i++)
1161 labelHashEntry *thisEntry;
1163 thisEntry = hTabFirstItemWK (labelHash, i);
1167 if (strstr (line->line, thisEntry->name))
1169 thisEntry->refCount++;
1171 thisEntry = hTabNextItemWK (labelHash);
1178 /* Spew the contents of the table. Debugging fun only. */
1179 for (i = 0; i < HTAB_SIZE; i++)
1181 labelHashEntry *thisEntry;
1183 thisEntry = hTabFirstItemWK (labelHash, i);
1187 fprintf (stderr, "label: %s ref %d\n",
1188 thisEntry->name, thisEntry->refCount);
1189 thisEntry = hTabNextItemWK (labelHash);
1195 /* How does this work?
1201 replace and restart.
1206 Where is stuff allocated?
1210 /*-----------------------------------------------------------------*/
1211 /* peepHole - matches & substitutes rules */
1212 /*-----------------------------------------------------------------*/
1214 peepHole (lineNode ** pls)
1218 lineNode *mtail = NULL;
1221 #if !OPT_DISABLE_PIC
1222 /* The PIC port uses a different peep hole optimizer based on "pCode" */
1227 assert(labelHash == NULL);
1234 for (pr = rootRules; pr; pr = pr->next)
1236 for (spl = *pls; spl; spl = spl->next)
1238 /* if inline assembler then no peep hole */
1244 /* Tidy up any data stored in the hTab */
1247 if (matchRule (spl, &mtail, pr, *pls))
1252 replaceRule (pls, mtail, pr);
1254 replaceRule (&spl, mtail, pr);
1256 /* if restart rule type then
1257 start at the top again */
1266 hTabDeleteAll (pr->vars);
1267 Safe_free (pr->vars);
1271 freeTrace (&_G.values);
1274 } while (restart == TRUE);
1278 hTabDeleteAll (labelHash);
1279 freeTrace (&_G.labels);
1285 /*-----------------------------------------------------------------*/
1286 /* readFileIntoBuffer - reads a file into a string buffer */
1287 /*-----------------------------------------------------------------*/
1289 readFileIntoBuffer (char *fname)
1295 char lb[MAX_PATTERN_LEN];
1297 if (!(f = fopen (fname, "r")))
1299 fprintf (stderr, "cannot open peep rule file\n");
1303 while ((ch = fgetc (f)) != EOF)
1307 /* if we maxed out our local buffer */
1308 if (nch >= (MAX_PATTERN_LEN - 2))
1311 /* copy it into allocated buffer */
1314 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
1319 rs = Safe_alloc ( strlen (lb) + 1);
1326 /* if some charaters left over */
1330 /* copy it into allocated buffer */
1333 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
1338 rs = Safe_alloc ( strlen (lb) + 1);
1345 /*-----------------------------------------------------------------*/
1346 /* initPeepHole - initialises the peep hole optimizer stuff */
1347 /*-----------------------------------------------------------------*/
1353 /* read in the default rules */
1354 readRules (port->peep.default_rules);
1356 /* if we have any additional file read it too */
1357 if (options.peep_file)
1359 readRules (s = readFileIntoBuffer (options.peep_file));
1360 setToNull ((void **) &s);
1364 #if !OPT_DISABLE_PIC
1365 /* Convert the peep rules into pcode.
1366 NOTE: this is only support in the PIC port (at the moment)
1368 if (TARGET_IS_PIC) {
1369 peepRules2pCode(rootRules);