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 #define ISCHARDIGIT(c) isdigit((unsigned char)c)
29 #define ISCHARSPACE(c) isspace((unsigned char)c)
30 #define ISCHARALNUM(c) isalnum((unsigned char)c)
32 static peepRule *rootRules = NULL;
33 static peepRule *currRule = NULL;
38 char name[SDCC_NAME_MAX + 1];
43 static hTab *labelHash = NULL;
51 static int hashSymbolName (const char *name);
52 static void buildLabelRefCountHash (lineNode * head);
54 static bool matchLine (char *, char *, hTab **);
55 bool isLabelDefinition (const char *line, const char **start, int *len);
57 #define FBYNAME(x) int x (hTab *vars, lineNode *currPl, lineNode *endPl, \
58 lineNode *head, char *cmdLine)
61 void peepRules2pCode(peepRule *);
64 #if !OPT_DISABLE_PIC16
65 void pic16_peepRules2pCode(peepRule *);
68 /*-----------------------------------------------------------------*/
69 /* pcDistance - afinds a label back ward or forward */
70 /*-----------------------------------------------------------------*/
73 pcDistance (lineNode * cpos, char *lbl, bool back)
76 char buff[MAX_PATTERN_LEN];
79 SNPRINTF (buff, sizeof(buff), "%s:", lbl);
85 pl->line[strlen (pl->line) - 1] != ':' &&
87 if (port->peep.getSize) {
88 dist += port->peep.getSize(pl);
94 if (strncmp (pl->line, buff, strlen (buff)) == 0)
106 /*-----------------------------------------------------------------*/
107 /* flat24bitModeAndPortDS390 - */
108 /*-----------------------------------------------------------------*/
109 FBYNAME (flat24bitModeAndPortDS390)
111 return (((strcmp(port->target,"ds390") == 0) ||
112 (strcmp(port->target,"ds400") == 0)) &&
113 (options.model == MODEL_FLAT24));
116 /*-----------------------------------------------------------------*/
117 /* portIsDS390 - return true if port is DS390 */
118 /*-----------------------------------------------------------------*/
119 FBYNAME (portIsDS390)
121 return ((strcmp(port->target,"ds390") == 0) ||
122 (strcmp(port->target,"ds400") == 0));
125 /*-----------------------------------------------------------------*/
126 /* flat24bitMode - will check to see if we are in flat24 mode */
127 /*-----------------------------------------------------------------*/
128 FBYNAME (flat24bitMode)
130 return (options.model == MODEL_FLAT24);
133 /*-----------------------------------------------------------------*/
134 /* xramMovcOption - check if using movc to read xram */
135 /*-----------------------------------------------------------------*/
136 FBYNAME (xramMovcOption)
138 return (options.xram_movc && (strcmp(port->target,"mcs51") == 0));
146 /*-----------------------------------------------------------------*/
147 /* labelInRange - will check to see if label %5 is within range */
148 /*-----------------------------------------------------------------*/
149 FBYNAME (labelInRange)
151 /* assumes that %5 pattern variable has the label name */
152 char *lbl = hTabItemWithKey (vars, 5);
158 /* Don't optimize jumps in a jump table; a more generic test */
159 if (currPl->ic && currPl->ic->op == JUMPTABLE)
162 /* if the previous two instructions are "ljmp"s then don't
163 do it since it can be part of a jump table */
164 if (currPl->prev && currPl->prev->prev &&
165 strstr (currPl->prev->line, "ljmp") &&
166 strstr (currPl->prev->prev->line, "ljmp"))
169 /* calculate the label distance : the jump for reladdr can be
170 +/- 127 bytes, here Iam assuming that an average 8051
171 instruction is 2 bytes long, so if the label is more than
172 63 intructions away, the label is considered out of range
173 for a relative jump. we could get more precise this will
174 suffice for now since it catches > 90% cases */
175 dist = (pcDistance (currPl, lbl, TRUE) +
176 pcDistance (currPl, lbl, FALSE));
178 /* changed to 127, now that pcDistance return actual number of bytes */
179 if (!dist || dist > 127)
186 /*-----------------------------------------------------------------*/
187 /* labelJTInRange - will check to see if label %5 and up are */
189 /* Specifically meant to optimize long (3-byte) jumps to short */
190 /* (2-byte) jumps in jumptables */
191 /*-----------------------------------------------------------------*/
192 FBYNAME (labelJTInRange)
197 if (!getenv("SDCC_SJMP_JUMPTABLE"))
200 /* Only optimize within a jump table */
201 if (currPl->ic && currPl->ic->op != JUMPTABLE)
204 count = elementsInSet( IC_JTLABELS (currPl->ic) );
206 /* check all labels (this is needed if the case statements are unsorted) */
207 for (i=0; i<count; i++)
209 /* assumes that the %5 pattern variable has the first ljmp label */
210 lbl = hTabItemWithKey (vars, 5+i);
214 dist = pcDistance (currPl, lbl, FALSE);
216 /* three terms used to calculate allowable distance */
217 // printf("\nlabel %s %i dist %i cdist 0x%02x 0x%02x\n", lbl, i, dist, dist -(count-i-1)-(7+3*i), 127+(count-i-1)+(7+3*i) - dist);
219 dist > 127+ /* range of sjmp */
220 (7+3*i)+ /* offset between this jump and currPl,
221 should use pcDistance instead? */
222 (count-i-1) /* if peephole applies distance is shortened */
230 /*-----------------------------------------------------------------*/
231 /* labelIsReturnOnly - Check if label %5 is followed by RET */
232 /*-----------------------------------------------------------------*/
233 FBYNAME (labelIsReturnOnly)
235 /* assumes that %5 pattern variable has the label name */
236 const char *label, *p;
241 /* Don't optimize jumps in a jump table; a more generic test */
242 if (currPl->ic && currPl->ic->op == JUMPTABLE)
245 label = hTabItemWithKey (vars, 5);
246 if (!label) return FALSE;
249 for(pl = currPl; pl; pl = pl->next) {
250 if (pl->line && !pl->isDebug && !pl->isComment &&
251 pl->line[strlen(pl->line)-1] == ':') {
252 if (strncmp(pl->line, label, len) == 0) break; /* Found Label */
253 if (strlen(pl->line) != 7 || !ISCHARDIGIT(*(pl->line)) ||
254 !ISCHARDIGIT(*(pl->line+1)) || !ISCHARDIGIT(*(pl->line+2)) ||
255 !ISCHARDIGIT(*(pl->line+3)) || !ISCHARDIGIT(*(pl->line+4)) ||
256 *(pl->line+5) != '$') {
257 return FALSE; /* non-local label encountered */
261 if (!pl) return FALSE; /* did not find the label */
263 while (pl && (pl->isDebug || pl->isComment))
265 if (!pl || !pl->line || pl->isDebug) return FALSE; /* next line not valid */
267 for (p = pl->line; *p && ISCHARSPACE(*p); p++)
273 if (strcmp(p, retInst) == 0) return TRUE;
278 /*-----------------------------------------------------------------*/
279 /* okToRemoveSLOC - Check if label %1 is a SLOC and not other */
280 /* usage of it in the code depends on a value from this section */
281 /*-----------------------------------------------------------------*/
282 FBYNAME (okToRemoveSLOC)
285 const char *sloc, *p;
286 int dummy1, dummy2, dummy3;
288 /* assumes that %1 as the SLOC name */
289 sloc = hTabItemWithKey (vars, 1);
290 if (sloc == NULL) return FALSE;
291 p = strstr(sloc, "sloc");
292 if (p == NULL) return FALSE;
294 if (sscanf(p, "%d_%d_%d", &dummy1, &dummy2, &dummy3) != 3) return FALSE;
295 /*TODO: ultra-paranoid: get funtion name from "head" and check that */
296 /* the sloc name begins with that. Probably not really necessary */
298 /* Look for any occurance of this SLOC before the peephole match */
299 for (pl = currPl->prev; pl; pl = pl->prev) {
300 if (pl->line && !pl->isDebug && !pl->isComment
301 && *pl->line != ';' && strstr(pl->line, sloc))
304 /* Look for any occurance of this SLOC after the peephole match */
305 for (pl = endPl->next; pl; pl = pl->next) {
306 if (pl->line && !pl->isDebug && !pl->isComment
307 && *pl->line != ';' && strstr(pl->line, sloc))
310 return TRUE; /* safe for a peephole to remove it :) */
314 /*-----------------------------------------------------------------*/
315 /* operandsNotSame - check if %1 & %2 are the same */
316 /*-----------------------------------------------------------------*/
317 FBYNAME (operandsNotSame)
319 char *op1 = hTabItemWithKey (vars, 1);
320 char *op2 = hTabItemWithKey (vars, 2);
322 if (strcmp (op1, op2) == 0)
328 /*-----------------------------------------------------------------*/
329 /* operandsNotSame3- check if any pair of %1,%2,%3 are the same */
330 /*-----------------------------------------------------------------*/
331 FBYNAME (operandsNotSame3)
333 char *op1 = hTabItemWithKey (vars, 1);
334 char *op2 = hTabItemWithKey (vars, 2);
335 char *op3 = hTabItemWithKey (vars, 3);
337 if ( (strcmp (op1, op2) == 0) ||
338 (strcmp (op1, op3) == 0) ||
339 (strcmp (op2, op3) == 0) )
345 /*-----------------------------------------------------------------*/
346 /* operandsNotSame4- check if any pair of %1,%2,%3,.. are the same */
347 /*-----------------------------------------------------------------*/
348 FBYNAME (operandsNotSame4)
350 char *op1 = hTabItemWithKey (vars, 1);
351 char *op2 = hTabItemWithKey (vars, 2);
352 char *op3 = hTabItemWithKey (vars, 3);
353 char *op4 = hTabItemWithKey (vars, 4);
355 if ( (strcmp (op1, op2) == 0) ||
356 (strcmp (op1, op3) == 0) ||
357 (strcmp (op1, op4) == 0) ||
358 (strcmp (op2, op3) == 0) ||
359 (strcmp (op2, op4) == 0) ||
360 (strcmp (op3, op4) == 0) )
366 /*-----------------------------------------------------------------*/
367 /* operandsNotSame5- check if any pair of %1,%2,%3,.. are the same */
368 /*-----------------------------------------------------------------*/
369 FBYNAME (operandsNotSame5)
371 char *op1 = hTabItemWithKey (vars, 1);
372 char *op2 = hTabItemWithKey (vars, 2);
373 char *op3 = hTabItemWithKey (vars, 3);
374 char *op4 = hTabItemWithKey (vars, 4);
375 char *op5 = hTabItemWithKey (vars, 5);
377 if ( (strcmp (op1, op2) == 0) ||
378 (strcmp (op1, op3) == 0) ||
379 (strcmp (op1, op4) == 0) ||
380 (strcmp (op1, op5) == 0) ||
381 (strcmp (op2, op3) == 0) ||
382 (strcmp (op2, op4) == 0) ||
383 (strcmp (op2, op5) == 0) ||
384 (strcmp (op3, op4) == 0) ||
385 (strcmp (op3, op5) == 0) ||
386 (strcmp (op4, op5) == 0) )
392 /*-----------------------------------------------------------------*/
393 /* operandsNotSame6- check if any pair of %1,%2,%3,.. are the same */
394 /*-----------------------------------------------------------------*/
395 FBYNAME (operandsNotSame6)
397 char *op1 = hTabItemWithKey (vars, 1);
398 char *op2 = hTabItemWithKey (vars, 2);
399 char *op3 = hTabItemWithKey (vars, 3);
400 char *op4 = hTabItemWithKey (vars, 4);
401 char *op5 = hTabItemWithKey (vars, 5);
402 char *op6 = hTabItemWithKey (vars, 6);
404 if ( (strcmp (op1, op2) == 0) ||
405 (strcmp (op1, op3) == 0) ||
406 (strcmp (op1, op4) == 0) ||
407 (strcmp (op1, op5) == 0) ||
408 (strcmp (op1, op6) == 0) ||
409 (strcmp (op2, op3) == 0) ||
410 (strcmp (op2, op4) == 0) ||
411 (strcmp (op2, op5) == 0) ||
412 (strcmp (op2, op6) == 0) ||
413 (strcmp (op3, op4) == 0) ||
414 (strcmp (op3, op5) == 0) ||
415 (strcmp (op3, op6) == 0) ||
416 (strcmp (op4, op5) == 0) ||
417 (strcmp (op4, op6) == 0) ||
418 (strcmp (op5, op6) == 0) )
425 /*-----------------------------------------------------------------*/
426 /* operandsNotSame7- check if any pair of %1,%2,%3,.. are the same */
427 /*-----------------------------------------------------------------*/
428 FBYNAME (operandsNotSame7)
430 char *op1 = hTabItemWithKey (vars, 1);
431 char *op2 = hTabItemWithKey (vars, 2);
432 char *op3 = hTabItemWithKey (vars, 3);
433 char *op4 = hTabItemWithKey (vars, 4);
434 char *op5 = hTabItemWithKey (vars, 5);
435 char *op6 = hTabItemWithKey (vars, 6);
436 char *op7 = hTabItemWithKey (vars, 7);
438 if ( (strcmp (op1, op2) == 0) ||
439 (strcmp (op1, op3) == 0) ||
440 (strcmp (op1, op4) == 0) ||
441 (strcmp (op1, op5) == 0) ||
442 (strcmp (op1, op6) == 0) ||
443 (strcmp (op1, op7) == 0) ||
444 (strcmp (op2, op3) == 0) ||
445 (strcmp (op2, op4) == 0) ||
446 (strcmp (op2, op5) == 0) ||
447 (strcmp (op2, op6) == 0) ||
448 (strcmp (op2, op7) == 0) ||
449 (strcmp (op3, op4) == 0) ||
450 (strcmp (op3, op5) == 0) ||
451 (strcmp (op3, op6) == 0) ||
452 (strcmp (op3, op7) == 0) ||
453 (strcmp (op4, op5) == 0) ||
454 (strcmp (op4, op6) == 0) ||
455 (strcmp (op4, op7) == 0) ||
456 (strcmp (op5, op6) == 0) ||
457 (strcmp (op5, op7) == 0) ||
458 (strcmp (op6, op7) == 0) )
464 /*-----------------------------------------------------------------*/
465 /* operandsNotSame8- check if any pair of %1,%2,%3,.. are the same */
466 /*-----------------------------------------------------------------*/
467 FBYNAME (operandsNotSame8)
469 char *op1 = hTabItemWithKey (vars, 1);
470 char *op2 = hTabItemWithKey (vars, 2);
471 char *op3 = hTabItemWithKey (vars, 3);
472 char *op4 = hTabItemWithKey (vars, 4);
473 char *op5 = hTabItemWithKey (vars, 5);
474 char *op6 = hTabItemWithKey (vars, 6);
475 char *op7 = hTabItemWithKey (vars, 7);
476 char *op8 = hTabItemWithKey (vars, 8);
478 if ( (strcmp (op1, op2) == 0) ||
479 (strcmp (op1, op3) == 0) ||
480 (strcmp (op1, op4) == 0) ||
481 (strcmp (op1, op5) == 0) ||
482 (strcmp (op1, op6) == 0) ||
483 (strcmp (op1, op7) == 0) ||
484 (strcmp (op1, op8) == 0) ||
485 (strcmp (op2, op3) == 0) ||
486 (strcmp (op2, op4) == 0) ||
487 (strcmp (op2, op5) == 0) ||
488 (strcmp (op2, op6) == 0) ||
489 (strcmp (op2, op7) == 0) ||
490 (strcmp (op2, op8) == 0) ||
491 (strcmp (op3, op4) == 0) ||
492 (strcmp (op3, op5) == 0) ||
493 (strcmp (op3, op6) == 0) ||
494 (strcmp (op3, op7) == 0) ||
495 (strcmp (op3, op8) == 0) ||
496 (strcmp (op4, op5) == 0) ||
497 (strcmp (op4, op6) == 0) ||
498 (strcmp (op4, op7) == 0) ||
499 (strcmp (op4, op8) == 0) ||
500 (strcmp (op5, op6) == 0) ||
501 (strcmp (op5, op7) == 0) ||
502 (strcmp (op5, op8) == 0) ||
503 (strcmp (op6, op7) == 0) ||
504 (strcmp (op6, op8) == 0) ||
505 (strcmp (op7, op8) == 0) )
514 * takes two parameters: a variable (bound to a label name)
515 * and an expected reference count.
517 * Returns TRUE if that label is defined and referenced exactly
518 * the given number of times.
520 FBYNAME (labelRefCount)
522 int varNumber, expectedRefCount;
525 /* If we don't have the label hash table yet, build it. */
528 buildLabelRefCountHash (head);
531 if (sscanf (cmdLine, "%*[ \t%]%d %d", &varNumber, &expectedRefCount) == 2)
533 char *label = hTabItemWithKey (vars, varNumber);
537 labelHashEntry *entry;
539 entry = hTabFirstItemWK (labelHash, hashSymbolName (label));
543 if (!strcmp (label, entry->name))
547 entry = hTabNextItemWK (labelHash);
553 fprintf (stderr, "labelRefCount: %s has refCount %d, want %d\n",
554 label, entry->refCount, expectedRefCount);
557 rc = (expectedRefCount == entry->refCount);
561 fprintf (stderr, "*** internal error: no label has entry for"
562 " %s in labelRefCount peephole.\n",
568 fprintf (stderr, "*** internal error: var %d not bound"
569 " in peephole labelRefCount rule.\n",
577 "*** internal error: labelRefCount peephole restriction"
578 " malformed: %s\n", cmdLine);
584 /* labelRefCountChange:
585 * takes two parameters: a variable (bound to a label name)
586 * and a signed int for changing the reference count.
588 * Please note, this function is not a conditional. It unconditionally
589 * changes the label. It should be passed as the 'last' function
590 * so it only is applied if all other conditions have been met.
592 * should always return TRUE
594 FBYNAME (labelRefCountChange)
596 int varNumber, RefCountDelta;
599 /* If we don't have the label hash table yet, build it. */
602 buildLabelRefCountHash (head);
605 if (sscanf (cmdLine, "%*[ \t%]%d %i", &varNumber, &RefCountDelta) == 2)
607 char *label = hTabItemWithKey (vars, varNumber);
611 labelHashEntry *entry;
613 entry = hTabFirstItemWK (labelHash, hashSymbolName (label));
617 if (!strcmp (label, entry->name))
621 entry = hTabNextItemWK (labelHash);
625 if (0 <= entry->refCount + RefCountDelta)
627 entry->refCount += RefCountDelta;
632 fprintf (stderr, "*** internal error: label %s may not get"
633 " negative refCount in %s peephole.\n",
634 label, __FUNCTION__);
639 fprintf (stderr, "*** internal error: no label has entry for"
640 " %s in %s peephole.\n",
641 label, __FUNCTION__);
646 fprintf (stderr, "*** internal error: var %d not bound"
647 " in peephole %s rule.\n",
648 varNumber, __FUNCTION__);
654 "*** internal error: labelRefCount peephole restriction"
655 " malformed: %s\n", cmdLine);
661 /* Within the context of the lines currPl through endPl, determine
662 ** if the variable var contains a symbol that is volatile. Returns
663 ** TRUE only if it is certain that this was not volatile (the symbol
664 ** was found and not volatile, or var was a constant or CPU register).
665 ** Returns FALSE if the symbol was found and volatile, the symbol was
666 ** not found, or var was a indirect/pointer addressing mode.
669 notVolatileVariable(char *var, lineNode *currPl, lineNode *endPl)
671 char symname[SDCC_NAME_MAX + 1];
678 /* Can't tell if indirect accesses are volatile or not, so
679 ** assume they are, just to be safe.
681 if (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_DS400)
686 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
688 if (strstr(var,"(bc)"))
690 if (strstr(var,"(de)"))
692 if (strstr(var,"(hl)"))
694 if (strstr(var,"(ix"))
696 if (strstr(var,"(iy"))
700 /* Extract a symbol name from the variable */
701 while (*vp && (*vp!='_'))
703 while (*vp && (ISCHARALNUM(*vp) || *vp=='_'))
709 /* Nothing resembling a symbol name was found, so it can't
716 for (cl = currPl; cl!=endPl->next; cl = cl->next)
718 if (cl->ic && (cl->ic!=last_ic))
724 op = IC_COND (cl->ic);
725 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
726 return !op->isvolatile;
728 op = IC_JTCOND (cl->ic);
729 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
730 return !op->isvolatile;
732 op = IC_LEFT (cl->ic);
733 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
734 return !op->isvolatile;
735 op = IC_RIGHT (cl->ic);
736 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
737 return !op->isvolatile;
738 op = IC_RESULT (cl->ic);
739 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
740 return !op->isvolatile;
745 /* Couldn't find the symbol for some reason. Assume volatile. */
751 * This rule restriction has two different behaviours depending on
752 * the number of parameters given.
754 * if notVolatile (no parameters given)
755 * The rule is applied only if none of the iCodes originating
756 * the matched pattern reference a volatile operand.
758 * if notVolatile %1 ... (one or more parameters given)
759 * The rule is applied if the parameters are not expressions
760 * containing volatile symbols and are not pointer accesses.
763 FBYNAME (notVolatile)
774 /* If no parameters given, just scan the iCodes for volatile operands */
775 for (cl = currPl; cl!=endPl->next; cl = cl->next)
782 op = IC_COND (cl->ic);
783 if (IS_SYMOP (op) && op->isvolatile)
786 op = IC_JTCOND (cl->ic);
787 if (IS_SYMOP (op) && op->isvolatile)
790 op = IC_LEFT (cl->ic);
791 if (IS_SYMOP (op) && op->isvolatile)
793 op = IC_RIGHT (cl->ic);
794 if (IS_SYMOP (op) && op->isvolatile)
796 op = IC_RESULT (cl->ic);
797 if (IS_SYMOP (op) && op->isvolatile)
805 /* There were parameters; check the volatility of each */
806 while (*cmdLine && ISCHARSPACE(*cmdLine))
813 if (!ISCHARDIGIT(*cmdLine))
815 varNumber = strtol(cmdLine, &digitend, 10);
817 while (*cmdLine && ISCHARSPACE(*cmdLine))
820 var = hTabItemWithKey (vars, varNumber);
824 notvol = notVolatileVariable (var, currPl, endPl);
830 fprintf (stderr, "*** internal error: var %d not bound"
831 " in peephole notVolatile rule.\n",
842 "*** internal error: notVolatile peephole restriction"
843 " malformed: %s\n", cmdLine);
848 /*------------------------------------------------------------------*/
849 /* setFromConditionArgs - parse a peephole condition's arguments */
850 /* to produce a set of strings, one per argument. Variables %x will */
851 /* be replaced with their values. String literals (in single quotes)*/
852 /* are accepted and return in unquoted form. */
853 /*------------------------------------------------------------------*/
855 setFromConditionArgs (char *cmdLine, hTab * vars)
860 set *operands = NULL;
865 while (*cmdLine && ISCHARSPACE(*cmdLine))
873 if (!ISCHARDIGIT(*cmdLine))
875 varNumber = strtol(cmdLine, &digitend, 10);
878 var = hTabItemWithKey (vars, varNumber);
882 addSetHead (&operands, var);
887 else if (*cmdLine == '\'' )
889 char quote = *cmdLine;
892 while (*cmdLine && *cmdLine != quote)
894 if (*cmdLine == quote)
898 addSetHead (&operands, var);
903 while (*cmdLine && ISCHARSPACE(*cmdLine))
910 deleteSet (&operands);
915 operandBaseName (const char *op)
917 if (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_DS400)
919 if (!strcmp (op, "acc") || !strncmp (op, "acc.", 4))
921 if (!strncmp (op, "ar", 2) && ISCHARDIGIT(*(op+2)) && !*(op+3))
929 /*-------------------------------------------------------------------*/
930 /* operandsNotRelated - returns true of the condition's operands are */
931 /* not related (taking into account register name aliases). N-way */
932 /* comparison performed between all operands. */
933 /*-------------------------------------------------------------------*/
934 FBYNAME (operandsNotRelated)
937 const char *op1, *op2;
939 operands = setFromConditionArgs (cmdLine, vars);
944 "*** internal error: operandsNotRelated peephole restriction"
945 " malformed: %s\n", cmdLine);
949 while ((op1 = setFirstItem (operands)))
951 deleteSetItem (&operands, (void*)op1);
952 op1 = operandBaseName (op1);
954 for (op2 = setFirstItem (operands); op2; op2 = setNextItem (operands))
956 op2 = operandBaseName (op2);
957 if (strcmp (op1, op2) == 0)
959 deleteSet (&operands);
965 deleteSet (&operands);
970 /*-------------------------------------------------------------------*/
971 /* operandsLiteral - returns true of the condition's operands are */
973 /*-------------------------------------------------------------------*/
974 FBYNAME (operandsLiteral)
979 operands = setFromConditionArgs (cmdLine, vars);
984 "*** internal error: operandsLiteral peephole restriction"
985 " malformed: %s\n", cmdLine);
989 for (op = setFirstItem (operands); op; op = setNextItem (operands))
993 deleteSet (&operands);
998 deleteSet (&operands);
1003 /*-----------------------------------------------------------------*/
1004 /* callFuncByName - calls a function as defined in the table */
1005 /*-----------------------------------------------------------------*/
1007 callFuncByName (char *fname,
1016 int (*func) (hTab *, lineNode *, lineNode *, lineNode *, char *);
1021 "labelInRange", labelInRange
1025 "labelJTInRange", labelJTInRange
1029 "operandsNotSame", operandsNotSame
1033 "operandsNotSame3", operandsNotSame3
1037 "operandsNotSame4", operandsNotSame4
1041 "operandsNotSame5", operandsNotSame5
1045 "operandsNotSame6", operandsNotSame6
1049 "operandsNotSame7", operandsNotSame7
1053 "operandsNotSame8", operandsNotSame8
1057 "24bitMode", flat24bitMode
1061 "xramMovcOption", xramMovcOption
1065 "labelRefCount", labelRefCount
1069 "portIsDS390", portIsDS390
1072 "labelIsReturnOnly", labelIsReturnOnly
1075 "okToRemoveSLOC", okToRemoveSLOC
1078 "24bitModeAndPortDS390", flat24bitModeAndPortDS390
1081 "notVolatile", notVolatile
1084 "operandsNotRelated", operandsNotRelated
1087 "operandsLiteral", operandsLiteral
1090 "labelRefCountChange", labelRefCountChange
1094 char *cmdCopy, *funcName, *funcArgs, *cmdTerm;
1098 /* Isolate the function name part (we are passed the full condition
1099 * string including arguments)
1101 cmdTerm = cmdCopy = Safe_strdup(fname);
1105 funcArgs = funcName = cmdTerm;
1106 while ((c = *funcArgs) && c != ' ' && c != '\t' && c != '(')
1108 *funcArgs = '\0'; /* terminate the function name */
1112 /* Find the start of the arguments */
1113 if (c == ' ' || c == '\t')
1114 while ((c = *funcArgs) && (c == ' ' || c == '\t'))
1117 /* If the arguments started with an opening parenthesis, */
1118 /* use the closing parenthesis for the end of the */
1119 /* arguments and look for the start of another condition */
1120 /* that can optionally follow. If there was no opening */
1121 /* parethesis, then everything that follows are arguments */
1122 /* and there can be no additional conditions. */
1126 while ((c = *cmdTerm) && c != ')')
1128 *cmdTerm = '\0'; /* terminate the arguments */
1132 while ((c = *cmdTerm) && (c == ' ' || c == '\t' || c == ','))
1138 cmdTerm = NULL; /* closing parenthesis missing */
1147 for (i = 0; i < ((sizeof (ftab)) / (sizeof (struct ftab))); i++)
1149 if (strcmp (ftab[i].fname, funcName) == 0)
1151 rc = (*ftab[i].func) (vars, currPl, endPl, head,
1160 "could not find named function \"%s\" in "
1161 "peephole function table\n",
1163 // If the function couldn't be found, let's assume it's
1164 // a bad rule and refuse it.
1169 while (rc && cmdTerm);
1176 /*-----------------------------------------------------------------*/
1177 /* printLine - prints a line chain into a given file */
1178 /*-----------------------------------------------------------------*/
1180 printLine (lineNode * head, FILE * of)
1182 iCode *last_ic = NULL;
1183 bool debug_iCode_tracking = (getenv("DEBUG_ICODE_TRACKING")!=NULL);
1190 if (head->ic!=last_ic)
1193 if (debug_iCode_tracking)
1196 fprintf (of, "; block = %d, seq = %d\n",
1197 head->ic->block, head->ic->seq);
1199 fprintf (of, "; iCode lost\n");
1203 /* don't indent comments & labels */
1205 (*head->line == ';' ||
1206 head->line[strlen (head->line) - 1] == ':')) {
1207 fprintf (of, "%s\n", head->line);
1209 if (head->isInline && *head->line=='#') {
1210 // comment out preprocessor directives in inline asm
1213 fprintf (of, "\t%s\n", head->line);
1219 /*-----------------------------------------------------------------*/
1220 /* newPeepRule - creates a new peeprule and attach it to the root */
1221 /*-----------------------------------------------------------------*/
1223 newPeepRule (lineNode * match,
1230 pr = Safe_alloc ( sizeof (peepRule));
1232 pr->replace = replace;
1233 pr->restart = restart;
1237 pr->cond = Safe_strdup (cond);
1242 pr->vars = newHashTable (100);
1244 /* if root is empty */
1246 rootRules = currRule = pr;
1248 currRule = currRule->next = pr;
1253 /*-----------------------------------------------------------------*/
1254 /* newLineNode - creates a new peep line */
1255 /*-----------------------------------------------------------------*/
1257 newLineNode (char *line)
1261 pl = Safe_alloc ( sizeof (lineNode));
1262 pl->line = Safe_strdup (line);
1267 /*-----------------------------------------------------------------*/
1268 /* connectLine - connects two lines */
1269 /*-----------------------------------------------------------------*/
1271 connectLine (lineNode * pl1, lineNode * pl2)
1275 fprintf (stderr, "trying to connect null line\n");
1285 #define SKIP_SPACE(x,y) { while (*x && (ISCHARSPACE(*x) || *x == '\n')) x++; \
1286 if (!*x) { fprintf(stderr,y); return ; } }
1288 #define EXPECT_STR(x,y,z) { while (*x && strncmp(x,y,strlen(y))) x++ ; \
1289 if (!*x) { fprintf(stderr,z); return ; } }
1290 #define EXPECT_CHR(x,y,z) { while (*x && *x != y) x++ ; \
1291 if (!*x) { fprintf(stderr,z); return ; } }
1293 /*-----------------------------------------------------------------*/
1294 /* getPeepLine - parses the peep lines */
1295 /*-----------------------------------------------------------------*/
1297 getPeepLine (lineNode ** head, char **bpp)
1299 char lines[MAX_PATTERN_LEN];
1303 lineNode *currL = NULL;
1310 fprintf (stderr, "unexpected end of match pattern\n");
1317 while (ISCHARSPACE (*bp) ||
1328 /* read till end of line */
1330 while ((*bp != '\n' && *bp != '}') && *bp)
1335 while (*lp && ISCHARSPACE(*lp))
1337 isComment = (*lp == ';');
1339 if (!isComment || (isComment && !options.noPeepComments))
1342 *head = currL = newLineNode (lines);
1344 currL = connectLine (currL, newLineNode (lines));
1345 currL->isComment = isComment;
1353 /*-----------------------------------------------------------------*/
1354 /* readRules - reads the rules from a string buffer */
1355 /*-----------------------------------------------------------------*/
1357 readRules (char *bp)
1360 char lines[MAX_PATTERN_LEN];
1364 lineNode *currL = NULL;
1370 /* look for the token "replace" that is the
1372 while (*bp && strncmp (bp, "replace", 7))
1379 /* then look for either "restart" or '{' */
1380 while (strncmp (bp, "restart", 7) &&
1387 fprintf (stderr, "expected 'restart' or '{'\n");
1395 { /* must be restart */
1397 bp += strlen ("restart");
1399 EXPECT_CHR (bp, '{', "expected '{'\n");
1403 /* skip thru all the blank space */
1404 SKIP_SPACE (bp, "unexpected end of rule\n");
1406 match = replace = currL = NULL;
1407 /* we are the start of a rule */
1408 getPeepLine (&match, &bp);
1410 /* now look for by */
1411 EXPECT_STR (bp, "by", "expected 'by'\n");
1413 /* then look for a '{' */
1414 EXPECT_CHR (bp, '{', "expected '{'\n");
1417 /* save char position (needed for generating error msg) */
1420 SKIP_SPACE (bp, "unexpected end of rule\n");
1421 getPeepLine (&replace, &bp);
1423 /* look for a 'if' */
1424 while ((ISCHARSPACE (*bp) || *bp == '\n') && *bp)
1427 if (strncmp (bp, "if", 2) == 0)
1430 while ((ISCHARSPACE (*bp) || *bp == '\n') && *bp)
1434 fprintf (stderr, "expected condition name\n");
1438 /* look for the condition */
1440 while (*bp && (*bp != '\n'))
1446 newPeepRule (match, replace, lines, restart);
1450 if (*bp && strncmp (bp, "replace", 7))
1452 /* not the start of a new peeprule, so "if" should be here */
1457 /* go to the start of the line following "{" of the "by" token */
1458 while (*rp && (*rp == '\n'))
1461 /* copy text of rule starting with line after "by {" */
1463 while (*rp && (rp < bp) && ((cp - strbuff) < sizeof(strbuff)))
1466 /* and now the rest of the line */
1467 while (*rp && (*rp != '\n') && ((cp - strbuff) < sizeof(strbuff)))
1471 fprintf (stderr, "%s\nexpected '} if ...'\n", strbuff);
1474 newPeepRule (match, replace, NULL, restart);
1480 /*-----------------------------------------------------------------*/
1481 /* keyForVar - returns the numeric key for a var */
1482 /*-----------------------------------------------------------------*/
1488 while (ISCHARDIGIT (*d))
1497 /*-----------------------------------------------------------------*/
1498 /* bindVar - binds a value to a variable in the given hashtable */
1499 /*-----------------------------------------------------------------*/
1501 bindVar (int key, char **s, hTab ** vtab)
1503 char vval[MAX_PATTERN_LEN];
1507 /* first get the value of the variable */
1509 /* the value is ended by a ',' or space or newline or null or ) */
1512 !ISCHARSPACE (*vvx) &&
1518 /* if we find a '(' then we need to balance it */
1530 // include the trailing ')'
1539 vvx = traceAlloc (&_G.values, Safe_strdup(vval));
1541 hTabAddItem (vtab, key, vvx);
1544 /*-----------------------------------------------------------------*/
1545 /* matchLine - matches one line */
1546 /*-----------------------------------------------------------------*/
1548 matchLine (char *s, char *d, hTab ** vars)
1557 /* skip white space in both */
1558 while (ISCHARSPACE (*s))
1560 while (ISCHARSPACE (*d))
1563 /* if the destination is a var */
1564 if (*d == '%' && ISCHARDIGIT (*(d + 1)) && vars)
1566 char *v = hTabItemWithKey (*vars, keyForVar (d + 1));
1567 /* if the variable is already bound
1568 then it MUST match with dest */
1576 /* variable not bound we need to
1578 bindVar (keyForVar (d + 1), &s, vars);
1580 /* in either case go past the variable */
1582 while (ISCHARDIGIT (*d))
1585 while (ISCHARSPACE (*s))
1587 while (ISCHARSPACE (*d))
1591 /* they should be an exact match other wise */
1600 /* get rid of the trailing spaces
1601 in both source & destination */
1603 while (ISCHARSPACE (*s))
1607 while (ISCHARSPACE (*d))
1610 /* after all this if only one of them
1611 has something left over then no match */
1618 /*-----------------------------------------------------------------*/
1619 /* matchRule - matches a all the rule lines */
1620 /*-----------------------------------------------------------------*/
1622 matchRule (lineNode * pl,
1627 lineNode *spl; /* source pl */
1628 lineNode *rpl; /* rule peep line */
1630 /* setToNull((void *) &pr->vars); */
1631 /* pr->vars = newHashTable(100); */
1633 /* for all the lines defined in the rule */
1639 /* if the source line starts with a ';' then
1640 comment line don't process or the source line
1641 contains == . debugger information skip it */
1643 (*spl->line == ';' || spl->isDebug))
1649 if (!matchLine (spl->line, rpl->line, &pr->vars))
1657 /* if rules ended */
1660 /* if this rule has additional conditions */
1663 if (callFuncByName (pr->cond, pr->vars, pl, spl, head))
1682 reassociate_ic_down (lineNode *shead, lineNode *stail,
1683 lineNode *rhead, lineNode *rtail)
1685 lineNode *csl; /* current source line */
1686 lineNode *crl; /* current replacement line */
1692 /* skip over any comments */
1693 while (csl!=stail->next && csl->isComment)
1695 while (crl!=rtail->next && crl->isComment)
1698 /* quit if we reach the end */
1699 if ((csl==stail->next) || (crl==rtail->next) || crl->ic)
1702 if (matchLine(csl->line,crl->line,NULL))
1714 reassociate_ic_up (lineNode *shead, lineNode *stail,
1715 lineNode *rhead, lineNode *rtail)
1717 lineNode *csl; /* current source line */
1718 lineNode *crl; /* current replacement line */
1724 /* skip over any comments */
1725 while (csl!=shead->prev && csl->isComment)
1727 while (crl!=rhead->prev && crl->isComment)
1730 /* quit if we reach the end */
1731 if ((csl==shead->prev) || (crl==rhead->prev) || crl->ic)
1734 if (matchLine(csl->line,crl->line,NULL))
1745 /*------------------------------------------------------------------*/
1746 /* reassociate_ic - reassociate replacement lines with origin iCode */
1747 /*------------------------------------------------------------------*/
1749 reassociate_ic (lineNode *shead, lineNode *stail,
1750 lineNode *rhead, lineNode *rtail)
1752 lineNode *csl; /* current source line */
1753 lineNode *crl; /* current replacement line */
1757 /* Check to see if all the source lines (excluding comments) came
1758 ** for the same iCode
1761 for (csl=shead;csl!=stail->next;csl=csl->next)
1762 if (csl->ic && !csl->isComment)
1767 single_iCode = (ic!=NULL);
1768 for (csl=shead;csl!=stail->next;csl=csl->next)
1769 if ((csl->ic != ic) && !csl->isComment)
1771 /* More than one iCode was found. However, if it's just the
1772 ** last line with the different iCode and it was not changed
1773 ** in the replacement, everything else must be the first iCode.
1775 if ((csl==stail) && matchLine (stail->line, rtail->line, NULL))
1777 rtail->ic = stail->ic;
1778 for (crl=rhead;crl!=rtail;crl=crl->next)
1783 single_iCode = FALSE;
1787 /* If all of the source lines came from the same iCode, then so have
1788 ** all of the replacement lines too.
1792 for (crl=rhead;crl!=rtail->next;crl=crl->next)
1797 /* The source lines span iCodes, so we may end up with replacement
1798 ** lines that we don't know which iCode(s) to associate with. Do the
1799 ** best we can by using the following strategies:
1800 ** 1) Start at the top and scan down. As long as the source line
1801 ** matches the replacement line, they have the same iCode.
1802 ** 2) Start at the bottom and scan up. As long as the source line
1803 ** matches the replacement line, they have the same iCode.
1804 ** 3) For any label in the source, look for a matching label in
1805 ** the replacment. If found, they have the same iCode. From
1806 ** these matching labels, scan down for additional matching
1807 ** lines; if found, they also have the same iCode.
1810 /* Strategy #1: Start at the top and scan down for matches
1812 reassociate_ic_down(shead,stail,rhead,rtail);
1814 /* Strategy #2: Start at the bottom and scan up for matches
1816 reassociate_ic_up(shead,stail,rhead,rtail);
1818 /* Strategy #3: Try to match labels
1823 const char *labelStart;
1826 /* skip over any comments */
1827 while (csl!=stail->next && csl->isComment)
1829 if (csl==stail->next)
1832 if (isLabelDefinition(csl->line, &labelStart, &labelLength))
1834 /* found a source line label; look for it in the replacment lines */
1838 while (crl!=rtail->next && crl->isComment)
1840 if (crl==rtail->next)
1842 if (matchLine(csl->line, crl->line, NULL))
1844 reassociate_ic_down(csl,stail,crl,rtail);
1854 /* Try to assign a meaningful iCode to any comment that is missing
1855 one. Since they are comments, it's ok to make mistakes; we are just
1856 trying to improve continuity to simplify other tests.
1859 for (crl=rtail;crl!=rhead->prev;crl=crl->prev)
1861 if (!crl->ic && ic && crl->isComment)
1868 /*-----------------------------------------------------------------*/
1869 /* replaceRule - does replacement of a matching pattern */
1870 /*-----------------------------------------------------------------*/
1872 replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr)
1874 lineNode *cl = NULL;
1875 lineNode *pl = NULL, *lhead = NULL;
1876 /* a long function name and long variable name can evaluate to
1877 4x max pattern length e.g. "mov dptr,((fie_var>>8)<<8)+fie_var" */
1878 char lb[MAX_PATTERN_LEN*4];
1880 lineNode *comment = NULL;
1882 /* collect all the comment lines in the source */
1883 for (cl = *shead; cl != stail; cl = cl->next)
1885 if (cl->line && (*cl->line == ';' || cl->isDebug))
1887 pl = (pl ? connectLine (pl, newLineNode (cl->line)) :
1888 (comment = newLineNode (cl->line)));
1889 pl->isDebug = cl->isDebug;
1890 pl->isComment = cl->isComment || (*cl->line == ';');
1895 /* for all the lines in the replacement pattern do */
1896 for (pl = pr->replace; pl; pl = pl->next)
1906 /* if the line contains a variable */
1907 if (*l == '%' && ISCHARDIGIT (*(l + 1)))
1909 v = hTabItemWithKey (pr->vars, keyForVar (l + 1));
1912 fprintf (stderr, "used unbound variable in replacement\n");
1920 while (ISCHARDIGIT (*l)) {
1930 cl = connectLine (cl, newLineNode (lb));
1932 lhead = cl = newLineNode (lb);
1933 cl->isComment = pl->isComment;
1936 /* add the comments if any to the head of list */
1939 lineNode *lc = comment;
1950 /* determine which iCodes the replacment lines relate to */
1951 reassociate_ic(*shead,stail,lhead,cl);
1953 /* now we need to connect / replace the original chain */
1954 /* if there is a prev then change it */
1957 (*shead)->prev->next = lhead;
1958 lhead->prev = (*shead)->prev;
1961 /* now for the tail */
1962 if (stail && stail->next)
1964 stail->next->prev = cl;
1966 cl->next = stail->next;
1971 /* the replacement is empty - delete the source lines */
1973 (*shead)->prev->next = stail->next;
1975 stail->next->prev = (*shead)->prev;
1976 *shead = stail->next;
1980 /* Returns TRUE if this line is a label definition.
1982 * If so, start will point to the start of the label name,
1983 * and len will be it's length.
1986 isLabelDefinition (const char *line, const char **start, int *len)
1988 const char *cp = line;
1990 /* This line is a label if if consists of:
1991 * [optional whitespace] followed by identifier chars
1992 * (alnum | $ | _ ) followed by a colon.
1995 while (*cp && ISCHARSPACE (*cp))
2007 while (ISCHARALNUM (*cp) || (*cp == '$') || (*cp == '_'))
2012 if ((cp == *start) || (*cp != ':'))
2017 *len = (cp - (*start));
2021 /* Quick & dirty string hash function. */
2023 hashSymbolName (const char *name)
2029 hash = (hash << 6) ^ *name;
2038 return hash % HTAB_SIZE;
2041 /* Build a hash of all labels in the passed set of lines
2042 * and how many times they are referenced.
2045 buildLabelRefCountHash (lineNode * head)
2052 assert (labelHash == NULL);
2053 labelHash = newHashTable (HTAB_SIZE);
2055 /* First pass: locate all the labels. */
2060 if (isLabelDefinition (line->line, &label, &labelLen)
2061 && labelLen <= SDCC_NAME_MAX)
2063 labelHashEntry *entry;
2065 entry = traceAlloc (&_G.labels, Safe_alloc(sizeof (labelHashEntry)));
2067 memcpy (entry->name, label, labelLen);
2068 entry->name[labelLen] = 0;
2069 entry->refCount = -1;
2071 /* Assume function entry points are referenced somewhere, */
2072 /* even if we can't find a reference (might be from outside */
2074 if (line->ic && (line->ic->op == FUNCTION))
2077 hTabAddItem (&labelHash, hashSymbolName (entry->name), entry);
2083 /* Second pass: for each line, note all the referenced labels. */
2084 /* This is ugly, O(N^2) stuff. Optimizations welcome... */
2088 for (i = 0; i < HTAB_SIZE; i++)
2090 labelHashEntry *thisEntry;
2092 thisEntry = hTabFirstItemWK (labelHash, i);
2096 if (strstr (line->line, thisEntry->name))
2098 thisEntry->refCount++;
2100 thisEntry = hTabNextItemWK (labelHash);
2107 /* Spew the contents of the table. Debugging fun only. */
2108 for (i = 0; i < HTAB_SIZE; i++)
2110 labelHashEntry *thisEntry;
2112 thisEntry = hTabFirstItemWK (labelHash, i);
2116 fprintf (stderr, "label: %s ref %d\n",
2117 thisEntry->name, thisEntry->refCount);
2118 thisEntry = hTabNextItemWK (labelHash);
2124 /* How does this work?
2130 replace and restart.
2135 Where is stuff allocated?
2139 /*-----------------------------------------------------------------*/
2140 /* peepHole - matches & substitutes rules */
2141 /*-----------------------------------------------------------------*/
2143 peepHole (lineNode ** pls)
2147 lineNode *mtail = NULL;
2150 #if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
2151 /* The PIC port uses a different peep hole optimizer based on "pCode" */
2152 if (TARGET_IS_PIC || TARGET_IS_PIC16)
2156 assert(labelHash == NULL);
2163 for (pr = rootRules; pr; pr = pr->next)
2165 for (spl = *pls; spl; spl = spl->next)
2167 /* if inline assembler then no peep hole */
2171 /* don't waste time starting a match on debug symbol
2173 if (spl->isDebug || spl->isComment || *(spl->line)==';')
2178 /* Tidy up any data stored in the hTab */
2181 if (matchRule (spl, &mtail, pr, *pls))
2186 replaceRule (pls, mtail, pr);
2188 replaceRule (&spl, mtail, pr);
2190 /* if restart rule type then
2191 start at the top again */
2200 hTabDeleteAll (pr->vars);
2201 Safe_free (pr->vars);
2205 freeTrace (&_G.values);
2208 } while (restart == TRUE);
2212 hTabDeleteAll (labelHash);
2213 freeTrace (&_G.labels);
2219 /*-----------------------------------------------------------------*/
2220 /* readFileIntoBuffer - reads a file into a string buffer */
2221 /*-----------------------------------------------------------------*/
2223 readFileIntoBuffer (char *fname)
2229 char lb[MAX_PATTERN_LEN];
2231 if (!(f = fopen (fname, "r")))
2233 fprintf (stderr, "cannot open peep rule file\n");
2237 while ((ch = fgetc (f)) != EOF)
2241 /* if we maxed out our local buffer */
2242 if (nch >= (MAX_PATTERN_LEN - 2))
2245 /* copy it into allocated buffer */
2248 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
2249 strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
2253 rs = Safe_strdup (lb);
2259 /* if some charaters left over */
2263 /* copy it into allocated buffer */
2266 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
2267 strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
2271 rs = Safe_strdup (lb);
2277 /*-----------------------------------------------------------------*/
2278 /* initPeepHole - initialises the peep hole optimizer stuff */
2279 /*-----------------------------------------------------------------*/
2285 /* read in the default rules */
2286 if (!options.nopeep)
2288 readRules (port->peep.default_rules);
2291 /* if we have any additional file read it too */
2292 if (options.peep_file)
2294 readRules (s = readFileIntoBuffer (options.peep_file));
2295 setToNull ((void *) &s);
2296 /* override nopeep setting, default rules have not been read */
2301 #if !OPT_DISABLE_PIC
2302 /* Convert the peep rules into pcode.
2303 NOTE: this is only support in the PIC port (at the moment)
2306 peepRules2pCode(rootRules);
2309 #if !OPT_DISABLE_PIC16
2310 /* Convert the peep rules into pcode.
2311 NOTE: this is only support in the PIC port (at the moment)
2312 and the PIC16 port (VR 030601)
2314 if (TARGET_IS_PIC16)
2315 pic16_peepRules2pCode(rootRules);