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