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