Use 'ao-dbg' instead of 's51' to communicate with TeleMetrum
[fw/sdcc] / src / SDCCBBlock.c
1 /*-------------------------------------------------------------------------
2
3   SDCCBBlock.c - routines to manipulate basic Blocks
4
5              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
6
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
10    later version.
11
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.
16
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.
20
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 -------------------------------------------------------------------------*/
25
26 #include "common.h"
27
28 int eBBNum = 0;
29 set *graphEdges = NULL;         /* list of edges in this flow graph */
30
31 struct _dumpFiles dumpFiles[] = {
32   {DUMP_RAW0, ".dumpraw0", NULL},
33   {DUMP_RAW1, ".dumpraw1", NULL},
34   {DUMP_CSE, ".dumpcse", NULL},
35   {DUMP_DFLOW, ".dumpdflow", NULL},
36   {DUMP_GCSE, ".dumpgcse", NULL},
37   {DUMP_DEADCODE, ".dumpdeadcode", NULL},
38   {DUMP_LOOP, ".dumploop", NULL},
39   {DUMP_LOOPG, ".dumploopg", NULL},
40   {DUMP_LOOPD, ".dumploopd", NULL},
41   {DUMP_RANGE, ".dumprange", NULL},
42   {DUMP_PACK, ".dumppack", NULL},
43   {DUMP_RASSGN, ".dumprassgn", NULL},
44   {DUMP_LRANGE, ".dumplrange", NULL},
45   {0, NULL, NULL}
46 };
47
48 /*-----------------------------------------------------------------*/
49 /* printEntryLabel - prints entry label of a ebblock               */
50 /*-----------------------------------------------------------------*/
51 DEFSETFUNC (printEntryLabel)
52 {
53   eBBlock *bp = item;
54
55   fprintf (stdout, " %-20s ", bp->entryLabel->name);
56   return 0;
57 }
58
59 /*-----------------------------------------------------------------*/
60 /* neweBBlock - allocate & return a new extended basic block       */
61 /*-----------------------------------------------------------------*/
62 eBBlock *
63 neweBBlock ()
64 {
65   eBBlock *ebb;
66
67   ebb = Safe_alloc (sizeof (eBBlock));
68   return ebb;
69 }
70
71 /*-----------------------------------------------------------------*/
72 /* newEdge - allocates & initialises an edge to given values       */
73 /*-----------------------------------------------------------------*/
74 edge *
75 newEdge (eBBlock * from, eBBlock * to)
76 {
77   edge *ep;
78
79   ep = Safe_alloc (sizeof (edge));
80
81   ep->from = from;
82   ep->to = to;
83   return ep;
84 }
85
86 /*-----------------------------------------------------------------*/
87 /* createDumpFile - create the dump file                           */
88 /*-----------------------------------------------------------------*/
89 FILE *createDumpFile (int id) {
90   struct _dumpFiles *dumpFilesPtr=dumpFiles;
91   static int dumpIndex=0;
92   static char dumpIndexStr[32];
93
94   while (dumpFilesPtr->id) {
95     if (dumpFilesPtr->id==id)
96       break;
97     dumpFilesPtr++;
98   }
99
100   if (!dumpFilesPtr->id) {
101     fprintf (stdout, "internal error: createDumpFile: unknown dump file.\n");
102     exit (1);
103   }
104
105   sprintf(dumpIndexStr, ".%d", dumpIndex);
106   dumpIndex++;
107
108   if (!dumpFilesPtr->filePtr) {
109     // not used before, create it
110     strncpyz (scratchFileName, dstFileName, PATH_MAX);
111 #if 0
112     strncatz (scratchFileName, dumpIndexStr, PATH_MAX);
113 #endif
114     strncatz (scratchFileName, dumpFilesPtr->ext, PATH_MAX);
115     if (!(dumpFilesPtr->filePtr = fopen (scratchFileName, "w"))) {
116       werror (E_FILE_OPEN_ERR, scratchFileName);
117       exit (1);
118     }
119   }
120
121 #if 0
122   fprintf(dumpFilesPtr->filePtr, "Dump file index: %d\n", dumpIndex);
123 #endif
124
125   return dumpFilesPtr->filePtr;
126 }
127
128 /*-----------------------------------------------------------------*/
129 /* closeDumpFiles - close possible opened dumpfiles                */
130 /*-----------------------------------------------------------------*/
131 void closeDumpFiles() {
132   struct _dumpFiles *dumpFilesPtr;
133
134   for (dumpFilesPtr=dumpFiles; dumpFilesPtr->id; dumpFilesPtr++) {
135     if (dumpFilesPtr->filePtr) {
136       fclose (dumpFilesPtr->filePtr);
137     }
138   }
139 }
140
141 /*-----------------------------------------------------------------*/
142 /* dumpLiveRanges - dump liverange information into a file         */
143 /*-----------------------------------------------------------------*/
144 void
145 dumpLiveRanges (int id, hTab * liveRanges)
146 {
147   FILE *file;
148   symbol *sym;
149   int k;
150
151   if (id) {
152     file=createDumpFile(id);
153   } else {
154     file = stdout;
155   }
156
157   if (currFunc)
158       fprintf(file,"------------- Func %s -------------\n",currFunc->name);
159   for (sym = hTabFirstItem (liveRanges, &k); sym;
160        sym = hTabNextItem (liveRanges, &k))
161     {
162
163       fprintf (file, "%s [k%d lr%d:%d so:%d]{ re%d rm%d}",
164                (sym->rname[0] ? sym->rname : sym->name),
165                sym->key,
166                sym->liveFrom, sym->liveTo,
167                sym->stack,
168                sym->isreqv, sym->remat
169         );
170
171       fprintf (file, "{");
172       printTypeChain (sym->type, file);
173       if (sym->usl.spillLoc)
174         {
175           fprintf (file, "}{ sir@ %s", sym->usl.spillLoc->rname);
176         }
177       fprintf (file, "} clashes with ");
178       bitVectDebugOn(sym->clashes,file);
179       fprintf (file, "\n");
180     }
181
182   fflush(file);
183 }
184
185
186 /*-----------------------------------------------------------------*/
187 /* dumpEbbsToFileExt - writeall the basic blocks to a file         */
188 /*-----------------------------------------------------------------*/
189 void
190 dumpEbbsToFileExt (int id, ebbIndex * ebbi)
191 {
192   FILE *of;
193   int i;
194   eBBlock *bb;
195   set *cseSet;
196   eBBlock ** ebbs = ebbi->dfOrder ? ebbi->dfOrder : ebbi->bbOrder;
197   int count = ebbi->count;
198
199   if (id) {
200     of=createDumpFile(id);
201   } else {
202     of = stdout;
203   }
204
205   for (i = 0; i < count; i++)
206     {
207       fprintf (of, "\n----------------------------------------------------------------\n");
208       fprintf (of, "Basic Block %s (df:%d bb:%d lvl:%d): loopDepth=%d%s%s%s\n",
209                ebbs[i]->entryLabel->name,
210                ebbs[i]->dfnum, ebbs[i]->bbnum, ebbs[i]->entryLabel->level,
211                ebbs[i]->depth,
212                ebbs[i]->noPath ? " noPath" : "",
213                ebbs[i]->partOfLoop ? " partOfLoop" : "",
214                ebbs[i]->isLastInLoop ? " isLastInLoop" : "");
215
216       // a --nolabelopt makes this more readable
217       fprintf (of, "\nsuccessors: ");
218       for (bb=setFirstItem(ebbs[i]->succList);
219            bb;
220            bb=setNextItem(ebbs[i]->succList)) {
221         fprintf (of, "%s ", bb->entryLabel->name);
222       }
223       fprintf (of, "\npredecessors: ");
224       for (bb=setFirstItem(ebbs[i]->predList);
225            bb;
226            bb=setNextItem(ebbs[i]->predList)) {
227         fprintf (of, "%s ", bb->entryLabel->name);
228       }
229       {
230         int d;
231         fprintf (of, "\ndominators: ");
232         for (d=0; d<ebbs[i]->domVect->size; d++) {
233           if (bitVectBitValue(ebbs[i]->domVect, d)) {
234             fprintf (of, "%s ", ebbi->bbOrder[d]->entryLabel->name); //ebbs[d]->entryLabel->name);
235           }
236         }
237       }
238       fprintf (of, "\n");
239
240       fprintf (of, "\ndefines bitVector :");
241       bitVectDebugOn (ebbs[i]->defSet, of);
242       fprintf (of, "\nlocal defines bitVector :");
243       bitVectDebugOn (ebbs[i]->ldefs, of);
244       fprintf (of, "\npointers Set bitvector :");
245       bitVectDebugOn (ebbs[i]->ptrsSet, of);
246 #if 0
247       fprintf (of, "\nin coming definitions :");
248       bitVectDebugOn (ebbs[i]->inDefs, of);
249       fprintf (of, "\nout going definitions :");
250       bitVectDebugOn (ebbs[i]->outDefs, of);
251       fprintf (of, "\ndefines used :");
252       bitVectDebugOn (ebbs[i]->usesDefs, of);
253 #endif
254
255       if (ebbs[i]->isLastInLoop) {
256               fprintf (of, "\nInductions Set bitvector :");
257               bitVectDebugOn (ebbs[i]->linds, of);
258       }
259
260       fprintf (of, "\ninExprs:");
261       for (cseSet = ebbs[i]->inExprs; cseSet; cseSet=cseSet->next) {
262         cseDef *item=cseSet->item;
263         fprintf (of, " %s(%d)",OP_SYMBOL(item->sym)->name,item->diCode->key);
264         if (item->fromGlobal)
265           fprintf (of, "g");
266       }
267       fprintf (of, "\noutExprs:");
268       for (cseSet = ebbs[i]->outExprs; cseSet; cseSet=cseSet->next) {
269         cseDef *item=cseSet->item;
270         fprintf (of, " %s(%d)",OP_SYMBOL(item->sym)->name,item->diCode->key);
271         if (item->fromGlobal)
272           fprintf (of, "g");
273       }
274       fprintf (of, "\nkilledExprs:");
275       for (cseSet = ebbs[i]->killedExprs; cseSet; cseSet=cseSet->next) {
276         cseDef *item=cseSet->item;
277         fprintf (of, " %s(%d)",OP_SYMBOL(item->sym)->name,item->diCode->key);
278         if (item->fromGlobal)
279           fprintf (of, "g");
280       }
281
282       fprintf (of, "\n----------------------------------------------------------------\n");
283       printiCChain (ebbs[i]->sch, of);
284     }
285   fflush(of);
286 }
287
288 /*-----------------------------------------------------------------*/
289 /* iCode2eBBlock - converts a sequnce till label to a ebb          */
290 /*-----------------------------------------------------------------*/
291 eBBlock *
292 iCode2eBBlock (iCode * ic)
293 {
294   iCode *loop;
295   eBBlock *ebb = neweBBlock (); /* allocate an entry */
296
297   /* put the first one unconditionally */
298   ebb->sch = ic;
299
300   /* if this is a label then */
301   if (ic->op == LABEL)
302     ebb->entryLabel = ic->label;
303   else
304     {
305       SNPRINTF (buffer, sizeof(buffer), "_eBBlock%d", eBBNum++);
306       ebb->entryLabel = newSymbol (buffer, 1);
307       ebb->entryLabel->key = labelKey++;
308     }
309
310   if (ic &&
311       (ic->op == GOTO ||
312        ic->op == JUMPTABLE ||
313        ic->op == IFX))
314     {
315       ebb->ech = ebb->sch;
316       return ebb;
317     }
318
319   /* if this is a function call */
320   if (ic->op == CALL || ic->op == PCALL)
321     {
322       ebb->hasFcall = 1;
323       if (currFunc)
324         FUNC_HASFCALL(currFunc->type) = 1;
325     }
326
327   if ((ic->next && ic->next->op == LABEL) ||
328       !ic->next)
329     {
330       ebb->ech = ebb->sch;
331       return ebb;
332     }
333
334   /* loop thru till we find one with a label */
335   for (loop = ic->next; loop; loop = loop->next)
336     {
337
338       /* if this is the last one */
339       if (!loop->next)
340         break;
341       /* if this is a function call */
342       if (loop->op == CALL || loop->op == PCALL)
343         {
344           ebb->hasFcall = 1;
345           if (currFunc)
346             FUNC_HASFCALL(currFunc->type) = 1;
347         }
348
349       /* if the next one is a label */
350       /* if this is a goto or ifx */
351       if (loop->next->op == LABEL ||
352           loop->op == GOTO ||
353           loop->op == JUMPTABLE ||
354           loop->op == IFX)
355         break;
356     }
357
358   /* mark the end of the chain */
359   ebb->ech = loop;
360
361   return ebb;
362 }
363
364 /*-----------------------------------------------------------------*/
365 /* eBBWithEntryLabel - finds the basic block with the entry label  */
366 /*-----------------------------------------------------------------*/
367 eBBlock *
368 eBBWithEntryLabel (ebbIndex * ebbi, symbol * eLabel)
369 {
370   eBBlock ** ebbs = ebbi->bbOrder;
371   int count = ebbi->count;
372   int i;
373
374   for (i = 0; i < count; i++)
375     {
376       if (isSymbolEqual (ebbs[i]->entryLabel, eLabel))
377         return ebbs[i];
378     }
379
380   return NULL;
381 }
382
383
384 /*-----------------------------------------------------------------*/
385 /* ifFromIs - will return 1 if the from block matches this         */
386 /*-----------------------------------------------------------------*/
387 DEFSETFUNC (ifFromIs)
388 {
389   edge *ep = item;
390   V_ARG (eBBlock *, this);
391
392   if (ep->from == this)
393     return 1;
394
395   return 0;
396 }
397
398
399 /*-----------------------------------------------------------------*/
400 /* edgesTo  - returns a set of edges with to == supplied value     */
401 /*-----------------------------------------------------------------*/
402 set *
403 edgesTo (eBBlock * to)
404 {
405   set *result = NULL;
406   edge *loop;
407
408   for (loop = setFirstItem (graphEdges); loop; loop = setNextItem (graphEdges))
409     if (loop->to == to && !loop->from->noPath)
410       addSet (&result, loop->from);
411
412   return result;
413 }
414
415
416 /*-----------------------------------------------------------------*/
417 /* addiCodeToeBBlock - will add an iCode to the end of a block     */
418 /*-----------------------------------------------------------------*/
419 void
420 addiCodeToeBBlock (eBBlock * ebp, iCode * ic, iCode * ip)
421 {
422   ic->prev = ic->next = NULL;
423   /* if the insert point is given */
424   if (ip)
425     {
426       ic->filename = ip->filename;
427       ic->lineno = ip->lineno;
428       ic->prev = ip->prev;
429       ip->prev = ic;
430       ic->next = ip;
431       if (!ic->prev)
432         ebp->sch = ic;
433       else
434         ic->prev->next = ic;
435       return;
436     }
437
438   /* if the block has no  instructions */
439   if (ebp->ech == NULL)
440     {
441       ebp->sch = ebp->ech = ic;
442       ic->next = NULL;
443       return;
444     }
445
446   /* if the last instruction is a goto */
447   /* we add it just before the goto    */
448   if (ebp->ech->op == GOTO || ebp->ech->op == JUMPTABLE
449       || ebp->ech->op == RETURN)
450     {
451       ic->filename = ebp->ech->filename;
452       ic->lineno = ebp->ech->lineno;
453       ic->prev = ebp->ech->prev;
454       ebp->ech->prev = ic;
455       ic->next = ebp->ech;
456       if (!ic->prev)            /* was the last only on in the block */
457         ebp->sch = ic;
458       else
459         ic->prev->next = ic;
460       return;
461     }
462
463   /* if the last one was a ifx statement we check to see */
464   /* if the condition was defined in the previous instruction */
465   /* if this is true then we put it before the condition else */
466   /* we put it before if, this is to reduce register pressure, */
467   /* we don't have to hold  condition too long in a register  */
468
469   /* loop induction sometimes appends a GOTO instruction, */
470   /* it must be at the very end */
471   if (ebp->ech->op == IFX && ic->op != GOTO)
472     {
473       iCode *ipoint;
474
475 /*  if ( !ebp->ech->prev )  */
476 /*      ipoint = ebp->ech ; */
477 /*  else  */
478 /*      if (!IC_RESULT(ebp->ech->prev)) */
479 /*    ipoint = ebp->ech ; */
480 /*      else */
481 /*    if (IC_COND(ebp->ech)->key == IC_RESULT(ebp->ech->prev)->key) */
482 /*        ipoint = ebp->ech->prev; */
483 /*    else */
484 /*        ipoint = ebp->ech ; */
485       ipoint = ebp->ech;
486       ic->filename = ipoint->filename;
487       ic->lineno = ipoint->lineno;
488       ic->prev = ipoint->prev;
489       ipoint->prev = ic;
490       ic->next = ipoint;
491       if (!ic->prev)
492         ebp->sch = ic;
493       else
494         ic->prev->next = ic;
495       return;
496     }
497
498   /* will add it to the very end */
499   ip = ebp->ech;
500   ip->next = ic;
501   ic->prev = ip;
502   ic->next = NULL;
503   ebp->ech = ic;
504
505   return;
506 }
507
508 /*-----------------------------------------------------------------*/
509 /* remiCodeFromeBBlock - remove an iCode from BBlock               */
510 /*-----------------------------------------------------------------*/
511 void
512 remiCodeFromeBBlock (eBBlock * ebb, iCode * ic)
513 {
514   wassert (ic->seq>=ebb->fSeq && ic->seq<=ebb->lSeq);
515   if (ic->prev)
516     ic->prev->next = ic->next;
517   else
518     ebb->sch = ic->next;
519
520   if (ic->next)
521     ic->next->prev = ic->prev;
522   else
523     ebb->ech = ic->prev;
524 }
525
526 /*-----------------------------------------------------------------*/
527 /* iCodeBreakDown : breakDown iCode chain to blocks                */
528 /*-----------------------------------------------------------------*/
529 ebbIndex *
530 iCodeBreakDown (iCode * ic)
531 {
532   eBBlock **ebbs = NULL;
533   iCode *loop = ic;
534   ebbIndex *ebbi;
535
536   ebbi = Safe_alloc (sizeof (ebbIndex));
537   ebbi->count = 0;
538   ebbi->dfOrder = NULL; /* no depth first order information yet */
539
540   /* allocate for the first entry */
541
542   ebbs = Safe_alloc (sizeof (eBBlock *));
543   ebbi->bbOrder = ebbs;
544
545   while (loop)
546     {
547
548       /* convert 2 block */
549       eBBlock *ebb = iCode2eBBlock (loop);
550       loop = ebb->ech->next;
551
552       ebb->ech->next = NULL;    /* mark the end of this chain */
553       if (loop)
554         loop->prev = NULL;
555       ebb->bbnum = ebbi->count; /* save this block number     */
556       /* put it in the array */
557       ebbs[(ebbi->count)++] = ebb;
558
559       /* allocate for the next one. Remember to clear the new */
560       /*  pointer at the end, that was created by realloc. */
561
562       ebbs = Safe_realloc (ebbs, (ebbi->count + 1) * sizeof (eBBlock *));
563       ebbi->bbOrder = ebbs;
564
565       ebbs[ebbi->count] = 0;
566
567       /* if this one ends in a goto or a conditional */
568       /* branch then check if the block it is going  */
569       /* to already exists, if yes then this could   */
570       /* be a loop, add a preheader to the block it  */
571       /* goes to  if it does not already have one    */
572       if (ebbs[(ebbi->count) - 1]->ech &&
573           (ebbs[(ebbi->count) - 1]->ech->op == GOTO ||
574            ebbs[(ebbi->count) - 1]->ech->op == IFX))
575         {
576
577           symbol *label;
578           eBBlock *destBlock;
579
580           if (ebbs[(ebbi->count) - 1]->ech->op == GOTO)
581             label = IC_LABEL (ebbs[(ebbi->count) - 1]->ech);
582           else if (!(label = IC_TRUE (ebbs[(ebbi->count) - 1]->ech)))
583             label = IC_FALSE (ebbs[(ebbi->count) - 1]->ech);
584
585           if ((destBlock = eBBWithEntryLabel (ebbi, label)) &&
586               destBlock->preHeader == NULL &&
587               otherPathsPresent (ebbs, destBlock))
588             {
589
590               symbol *preHeaderLabel  = newiTempLoopHeaderLabel (1);
591               int i, j;
592               eBBlock *pBlock;
593
594               /* go thru all block replacing the entryLabel with new label */
595               /* till we reach the block , then we insert a new ebblock    */
596               for (i = 0; i < (ebbi->count); i++)
597                 {
598                   if (ebbs[i] == destBlock)
599                     break;
600                   replaceLabel (ebbs[i], label, preHeaderLabel);
601                 }
602
603               (ebbi->count)++;
604
605               /* if we have stopped at the block , allocate for an extra one */
606
607               ebbs = Safe_realloc (ebbs, (ebbi->count + 1) * sizeof (eBBlock *));
608               ebbi->bbOrder = ebbs;
609
610               ebbs[ebbi->count] = 0;
611
612               /* then move the block down one count */
613               pBlock = ebbs[j = i];
614               for (i += 1; i < (ebbi->count); i++)
615                 {
616                   eBBlock *xBlock;
617
618                   xBlock = ebbs[i];
619                   ebbs[i] = pBlock;
620                   ebbs[i]->bbnum = i;
621                   pBlock = xBlock;
622                 }
623
624               destBlock->preHeader = ebbs[j] = neweBBlock ();
625               ebbs[j]->bbnum = j;
626               ebbs[j]->entryLabel = preHeaderLabel;
627               ebbs[j]->sch = ebbs[j]->ech = newiCodeLabelGoto (LABEL, preHeaderLabel);
628               ebbs[j]->sch->filename = destBlock->sch->filename;
629               ebbs[j]->sch->lineno = destBlock->sch->lineno;
630             }
631         }
632     }
633
634   /* mark the end */
635   ebbs[ebbi->count] = NULL;
636
637   return ebbi;
638 }
639
640 /*-----------------------------------------------------------------*/
641 /* replaceSymBySym : - replace operand by operand in blocks        */
642 /*                     replaces only left & right in blocks        */
643 /*-----------------------------------------------------------------*/
644 void
645 replaceSymBySym (set * sset, operand * src, operand * dest)
646 {
647   set *loop;
648   eBBlock *rBlock;
649
650   /* for all blocks in the set do */
651   for (loop = sset; loop; loop = loop->next)
652     {
653       iCode *ic;
654
655       rBlock = loop->item;
656       /* for all instructions in this block do */
657       for (ic = rBlock->sch; ic; ic = ic->next)
658         {
659
660           /* if we find usage */
661           if (ic->op == IFX && isOperandEqual (src, IC_COND (ic)))
662             {
663               bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
664               IC_COND (ic) = operandFromOperand (dest);
665               OP_USES(dest)=bitVectSetBit (OP_USES (dest), ic->key);
666               continue;
667             }
668
669           if (isOperandEqual (IC_RIGHT (ic), src))
670             {
671               bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
672               IC_RIGHT (ic) = operandFromOperand (dest);
673               IC_RIGHT (ic)->isaddr = 0;
674               OP_USES(dest)=bitVectSetBit (OP_USES (dest), ic->key);
675             }
676
677           if (isOperandEqual (IC_LEFT (ic), src))
678             {
679               bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
680               if (POINTER_GET (ic) && IS_ITEMP (dest))
681                 {
682                   IC_LEFT (ic) = operandFromOperand (dest);
683                   IC_LEFT (ic)->isaddr = 1;
684                 }
685               else
686                 {
687                   IC_LEFT (ic) = operandFromOperand (dest);
688                   IC_LEFT (ic)->isaddr = 0;
689                 }
690               OP_USES(dest)=bitVectSetBit (OP_USES (dest), ic->key);
691             }
692
693           /* special case for pointer sets */
694           if (POINTER_SET (ic) &&
695               isOperandEqual (IC_RESULT (ic), src))
696             {
697               bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key);
698               IC_RESULT (ic) = operandFromOperand (dest);
699               IC_RESULT (ic)->isaddr = 1;
700               OP_USES(dest)=bitVectSetBit (OP_USES (dest), ic->key);
701             }
702         }
703     }
704 }
705
706 /*-----------------------------------------------------------------*/
707 /* replaceLabel - replace reference to one label by another        */
708 /*-----------------------------------------------------------------*/
709 void
710 replaceLabel (eBBlock * ebp, symbol * fromLbl, symbol * toLbl)
711 {
712   iCode *ic;
713
714   if (!ebp)
715     return;
716
717   for (ic = ebp->sch; ic; ic = ic->next)
718     {
719       switch (ic->op)
720         {
721
722         case GOTO:
723           if (isSymbolEqual (IC_LABEL (ic), fromLbl))
724             IC_LABEL (ic) = toLbl;
725           break;
726
727         case IFX:
728           if (IC_TRUE (ic) && isSymbolEqual (IC_TRUE (ic), fromLbl))
729             IC_TRUE (ic) = toLbl;
730           else if (isSymbolEqual (IC_FALSE (ic), fromLbl))
731             IC_FALSE (ic) = toLbl;
732           break;
733         }
734     }
735
736   return;
737
738 }
739
740
741 /*-----------------------------------------------------------------*/
742 /* iCodeFromeBBlock - convert basic block to iCode chain           */
743 /*-----------------------------------------------------------------*/
744 iCode *
745 iCodeFromeBBlock (eBBlock ** ebbs, int count)
746 {
747   int i = 1;
748   iCode *ric = ebbs[0]->sch;
749   iCode *lic = ebbs[0]->ech;
750
751   for (; i < count; i++)
752     {
753       if (ebbs[i]->sch == NULL)
754         continue;
755
756       if (ebbs[i]->noPath &&
757           (ebbs[i]->entryLabel != entryLabel &&
758            ebbs[i]->entryLabel != returnLabel))
759         {
760           iCode *ic = NULL;
761           bool foundNonlabel = 0;
762           ic=ebbs[i]->sch;
763           do
764             {
765               if (ic->op != LABEL)
766                 {
767                   foundNonlabel = 1;
768                   break;
769                 }
770               if (ic==ebbs[i]->ech)
771                 break;
772               ic = ic->next;
773             }
774           while (ic);
775           if (foundNonlabel && ic)
776             {
777               werrorfl (ic->filename, ic->lineno, W_CODE_UNREACH);
778               continue;
779             }
780         }
781
782       lic->next = ebbs[i]->sch;
783       lic->next->prev = lic;
784       lic = ebbs[i]->ech;
785
786     }
787
788   return ric;
789 }
790
791 /*-----------------------------------------------------------------*/
792 /* otherPathsPresent - determines if there is a path from _entry   */
793 /*      to this block in a half constructed set of blocks          */
794 /*-----------------------------------------------------------------*/
795 int
796 otherPathsPresent (eBBlock ** ebbs, eBBlock * this)
797 {
798   int i;
799
800   /* for all blocks preceding this block */
801   for (i = 0; i < this->bbnum; i++)
802     {
803       iCode *ic;
804
805       /* if there is a reference to the entry label of this block */
806       for (ic = ebbs[i]->sch; ic; ic = ic->next)
807         {
808           switch (ic->op)
809             {
810             case GOTO:
811               if (IC_LABEL (ic)->key == this->entryLabel->key)
812                 return 1;
813               break;
814
815             case IFX:
816               if (IC_TRUE (ic))
817                 {
818                   if (IC_TRUE (ic)->key == this->entryLabel->key)
819                     return 1;
820                 }
821               else if (IC_FALSE (ic)->key == this->entryLabel->key)
822                 return 1;
823               break;
824             }
825         }
826     }
827
828   /* comes here means we have not found it yet */
829   /* in this case check if the previous block  */
830   /* ends in a goto if it does then we have no */
831   /* path else we have a path                  */
832   if (this->bbnum && ebbs[this->bbnum - 1]->ech &&
833       ebbs[this->bbnum - 1]->ech->op == GOTO)
834     return 0;
835   else
836     return 1;
837 }