* src/mcs51/gen.c (gen51Code): show final register usage after fillGaps in asm with...
authorbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 28 Dec 2005 22:01:43 +0000 (22:01 +0000)
committerbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 28 Dec 2005 22:01:43 +0000 (22:01 +0000)
* src/SDCClrange.c (sequenceiCode, setLiveFrom, setLiveTo, markLiveRanges, markAlive, findNextUseSym, findNextUse, unvisitBlocks, incUsed, rliveClear, adjustIChain): made static,
(setFromRange): excluded because it's unused,
(findPrevUseSym, markWholeLoop): added,
(findPrevUse): rewritten; fixes bug 895992; now a complete search through all branches of predecessors enables sdcc to emit the warning W_LOCAL_NOINIT, marking of outermost loop was incomplete,
(rlivePoint): made static, added parameter emitWarnings which is only true during the first run out of two,
(findRecursiveSucc, findRecursivePred): removed,
(computeLiveRanges): made static, added parameter emitWarnings,
(dumpIcRlive): added for debugging only
* src/SDCClrange.h: added boolean parameter to computeLiveRanges(), removed prototype of setFromRange()
* src/SDCCopt.c (eBBlockFromiCode): added new parameter emitWarnings in call of computeLiveRanges()
* support/regression/tests/bug-895992.c: added
* support/regression/tests/bug-971834.c: added
* support/valdiag/tests/bug-895992.c: added
* support/valdiag/tests/bug-971834.c: added

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4014 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/SDCClrange.c
src/SDCClrange.h
src/SDCCopt.c
src/mcs51/gen.c
support/regression/tests/bug-895992.c [new file with mode: 0644]
support/regression/tests/bug-971834.c [new file with mode: 0644]
support/valdiag/tests/bug-895992.c [new file with mode: 0644]
support/valdiag/tests/bug-971834.c [new file with mode: 0644]

index 48878579b3024892671f33450d486dd9aab39837..708f9a3d3bb98b08b28ce7418677667927ab4db2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,29 @@
 2005-12-28 Bernhard Held <bernhard AT bernhardheld.de>
 
        * device/lib/Makefile.in: added --std-sdcc99 to CFLAGS
+       * src/mcs51/gen.c (gen51Code): show final register usage after
+       fillGaps in asm with --i-code-in-asm
+       * src/SDCClrange.c (sequenceiCode, setLiveFrom, setLiveTo,
+       markLiveRanges, markAlive, findNextUseSym, findNextUse, unvisitBlocks,
+       incUsed, rliveClear, adjustIChain): made static,
+       (setFromRange): excluded because it's unused,
+       (findPrevUseSym, markWholeLoop): added,
+       (findPrevUse): rewritten; fixes bug 895992; now a complete search
+       through all branches of predecessors enables sdcc to emit the warning
+       W_LOCAL_NOINIT, marking of outermost loop was incomplete,
+       (rlivePoint): made static, added parameter emitWarnings which is only
+       true during the first run out of two,
+       (findRecursiveSucc, findRecursivePred): removed,
+       (computeLiveRanges): made static, added parameter emitWarnings,
+       (dumpIcRlive): added for debugging only
+       * src/SDCClrange.h: added boolean parameter to computeLiveRanges(),
+       removed prototype of setFromRange()
+       * src/SDCCopt.c (eBBlockFromiCode): added new parameter emitWarnings
+       in call of computeLiveRanges()
+       * support/regression/tests/bug-895992.c: added
+       * support/regression/tests/bug-971834.c: added
+       * support/valdiag/tests/bug-895992.c: added
+       * support/valdiag/tests/bug-971834.c: added
 
 2005-12-18 Raphael Neider <rneider AT web.de>
 
index 194d37a22bdad0b642bb2adfc8aec7306e9fb9f9..3d05ad80a67a88a3a7b829ed6ad59141931072fc 100644 (file)
@@ -50,7 +50,7 @@ hashiCodeKeys (eBBlock ** ebbs, int count)
 /*-----------------------------------------------------------------*/
 /* sequenceiCode - creates a sequence number for the iCode & add   */
 /*-----------------------------------------------------------------*/
-void
+static void
 sequenceiCode (eBBlock ** ebbs, int count)
 {
   int i;
@@ -74,7 +74,8 @@ sequenceiCode (eBBlock ** ebbs, int count)
 /*-----------------------------------------------------------------*/
 /* setFromRange - sets the from range of a given operand           */
 /*-----------------------------------------------------------------*/
-void
+#if 0
+static void
 setFromRange (operand * op, int from)
 {
   /* only for compiler defined temporaries */
@@ -90,6 +91,7 @@ setFromRange (operand * op, int from)
       OP_LIVEFROM (op) > from)
     OP_LIVEFROM (op) = from;
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* setToRange - set the range to for an operand                    */
@@ -118,7 +120,7 @@ setToRange (operand * op, int to, bool check)
 /*-----------------------------------------------------------------*/
 /* setFromRange - sets the from range of a given operand           */
 /*-----------------------------------------------------------------*/
-void
+static void
 setLiveFrom (symbol * sym, int from)
 {
   if (!sym->liveFrom || sym->liveFrom > from)
@@ -128,7 +130,7 @@ setLiveFrom (symbol * sym, int from)
 /*-----------------------------------------------------------------*/
 /* setToRange - set the range to for an operand                    */
 /*-----------------------------------------------------------------*/
-void
+static void
 setLiveTo (symbol * sym, int to)
 {
   if (!sym->liveTo || sym->liveTo < to)
@@ -138,7 +140,7 @@ setLiveTo (symbol * sym, int to)
 /*-----------------------------------------------------------------*/
 /* markLiveRanges - for each operand mark the liveFrom & liveTo    */
 /*-----------------------------------------------------------------*/
-void
+static void
 markLiveRanges (eBBlock ** ebbs, int count)
 {
   int i, key;
@@ -172,7 +174,7 @@ markLiveRanges (eBBlock ** ebbs, int count)
 /*-----------------------------------------------------------------*/
 /* markAlive - marks the operand as alive between sic and eic      */
 /*-----------------------------------------------------------------*/
-void
+static void
 markAlive (iCode * sic, iCode * eic, int key)
 {
   iCode *dic;
@@ -187,7 +189,7 @@ markAlive (iCode * sic, iCode * eic, int key)
 /* findNextUseSym - finds the next use of the symbol and marks it  */
 /*                  alive in between                               */
 /*-----------------------------------------------------------------*/
-int
+static int
 findNextUseSym (eBBlock *ebp, iCode *ic, symbol * sym)
 {
   int retval = 0;
@@ -299,7 +301,7 @@ check_successors:
 /* findNextUse - finds the next use of the operand and marks it    */
 /*               alive in between                                  */
 /*-----------------------------------------------------------------*/
-int
+static int
 findNextUse (eBBlock *ebp, iCode *ic, operand *op)
 {
   if (op->isaddr)
@@ -313,7 +315,8 @@ findNextUse (eBBlock *ebp, iCode *ic, operand *op)
 /*-----------------------------------------------------------------*/
 /* unvisitBlocks - clears visited in all blocks                    */
 /*-----------------------------------------------------------------*/
-void unvisitBlocks (eBBlock ** ebbs, int count)
+static void
+unvisitBlocks (eBBlock ** ebbs, int count)
 {
   int i;
 
@@ -322,105 +325,139 @@ void unvisitBlocks (eBBlock ** ebbs, int count)
 }
 
 /*------------------------------------------------------------------*/
-/* findRecursiveSucc - build a bit vector of recursive successors   */
+/* markWholeLoop - mark the symbol 'key' alive in all blocks        */
+/*                 included by the outermost loop                   */
 /*------------------------------------------------------------------*/
-DEFSETFUNC (findRecursiveSucc)
+static void
+markWholeLoop (eBBlock *ebp, int key)
 {
-  eBBlock *ebp = item;
-  V_ARG (bitVect *, succVect);
-  
-  if (ebp->visited)
-    return 0;
-  
+  eBBlock *ebpi;
+
+  /* avoid endless loops */
   ebp->visited = 1;
-  bitVectSetBit (succVect, ebp->bbnum);
-  applyToSet (ebp->succList, findRecursiveSucc, succVect);
-  return 0;
-}
 
+  /* recurse through all predecessors */
+  for (ebpi = setFirstItem (ebp->predList);
+       ebpi;
+       ebpi = setNextItem (ebp->predList))
+    {
+      if (ebpi->visited)
+        continue;
+      /* is the predecessor still in the loop? */
+      if (ebpi->depth == 0)
+        continue;
+      markWholeLoop (ebpi, key);
+    }
+
+  /* recurse through all successors */
+  for (ebpi = setFirstItem (ebp->succList);
+       ebpi;
+       ebpi = setNextItem (ebp->succList))
+    {
+      if (ebpi->visited)
+        continue;
+      if (ebpi->depth == 0)
+        continue;
+      markWholeLoop (ebpi, key);
+    }
 
-/*------------------------------------------------------------------*/
-/* findRecursivePred - build a bit vector of recursive predecessors */
-/*------------------------------------------------------------------*/
-DEFSETFUNC (findRecursivePred)
-{
-  eBBlock *ebp = item;
-  V_ARG (bitVect *, predVect);
-  
-  if (ebp->visited)
-    return 0;
-  
-  ebp->visited = 1;
-  bitVectSetBit (predVect, ebp->bbnum);
-  applyToSet (ebp->predList, findRecursivePred, predVect);
-  return 0;
+  markAlive (ebp->sch, ebp->ech, key);
 }
 
-
 /*------------------------------------------------------------------*/
-/* findPrevUse - handle degenerate case of a symbol used prior to   */
-/*               findNextUse() marking any definition.              */
+/* findPrevUseSym - search for a previous definition of a symbol in */
+/*                  - the previous icodes                           */
+/*                  - all branches of predecessors                  */
 /*------------------------------------------------------------------*/
-void
-findPrevUse (eBBlock *ebp, iCode *ic, operand *op, eBBlock **ebbs, int count)
+static bool
+findPrevUseSym  (eBBlock *ebp, iCode *ic, symbol * sym)
 {
-  int i;
-  bitVect * succVect;
-  bitVect * predVect;
   eBBlock * pred;
+  iCode * uic;
 
-  /* If liveness is already known, then a previous call to findNextUse() */
-  /* has already taken care of everything. */
-  if (ic && bitVectBitValue(ic->rlive, op->key))
-    return;
+  if (ebp->visited)
+    {
+     /* already visited: this branch must have been succesfull, */
+     /* because otherwise the search would have been aborted. */
+      return TRUE;
+    }
+  ebp->visited = 1;
 
-  if (!ic)
+  /* search backward in the current block */
+  for (uic = ic; uic; uic = uic->prev)
+    {
+      if (!POINTER_SET (uic) && IS_ITEMP (IC_RESULT (uic)))
+        {
+          if (IC_RESULT (uic)->key == sym->key)
+            {
+              /* Ok, found a definition */
+              return TRUE;
+            }
+        }
+    }
+
+  /* There's no definition in this bblock, */
+  /* let's have a look at all predecessors. */
+  pred = setFirstItem (ebp->predList);
+  if (!pred)
     {
-      /* We are at the start of a block. If the operand is alive at the */
-      /* end of all predecessors, then a previous call to findNextUse() */
-      /* has already taken care of everything. */
-      
-      pred = setFirstItem (ebp->predList);
-      for (; pred; pred = setNextItem (ebp->predList))
-        if (pred->ech && !bitVectBitValue(pred->ech->rlive, op->key))
-          break;
-      
-      if (!pred)
-        return;
+      /* no more predecessors and nothing found yet :-( */
+      return FALSE;
+    }
+  for (; pred; pred = setNextItem (ebp->predList))
+    {
+      /* recurse into all predecessors */
+      if (!findPrevUseSym (pred, pred->ech, sym))
+        {
+          /* found nothing: abort */
+          return FALSE;
+        }
     }
 
+  /* Success! Went through all branches with no abort: */
+  /* all branches end with a definition */
+  return TRUE;
+}
+
+/*------------------------------------------------------------------*/
+/* findPrevUse - search for a previous definition of an operand     */
+/*                  If there's no definition let's:                 */
+/*                  - emit a warning                                */
+/*                  - fix the life range, if the symbol is used in  */
+/*                    a loop                                        */
+/*------------------------------------------------------------------*/
+static void
+findPrevUse (eBBlock *ebp, iCode *ic, operand *op,
+             eBBlock ** ebbs, int count,
+             bool emitWarnings)
+{
+  unvisitBlocks (ebbs, count);
+
   if (op->isaddr)
     OP_SYMBOL (op)->isptr = 1;
-
   OP_SYMBOL (op)->key = op->key;
 
-  /* Otherwise, it appears that this symbol was used prior to definition.     */
-  /* Just fix the live range; we'll deal with a diagnostic message elsewhere. */
-  /* If the symbol use was in a loop, we need to extend the live range to the */
-  /* outermost loop. */
-  unvisitBlocks (ebbs, count);
-  succVect = newBitVect (count);
-  applyToSet (ebp->succList, findRecursiveSucc, succVect);
-  unvisitBlocks (ebbs, count);
-  predVect = newBitVect (count);
-  applyToSet (ebp->predList, findRecursivePred, predVect);
-
-  /* Blocks that are both recursively predecessors and successors are in */
-  /* a loop with the current iCode. Mark the operand as alive in them.   */
-  for (i = 0; i < count; i++)
+  /* There must be a definition in each branch of predecessors */
+  if (!findPrevUseSym (ebp, ic->prev, OP_SYMBOL(op)))
     {
-      if (bitVectBitValue(succVect, i) && bitVectBitValue(predVect, i))
-        markAlive (ebbs[i]->sch, ebbs[i]->ech, op->key);
+      /* computeLiveRanges() is called twice */
+      if (!emitWarnings)
+        werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT,
+                  OP_SYMBOL (op)->prereqv);
+      /* is this block part of a loop? */
+      if (ebp->depth != 0)
+        {
+          /* extend the life range to the outermost loop */
+          unvisitBlocks(ebbs, count);
+          markWholeLoop (ebp, op->key);
+        }
     }
-
-  freeBitVect (succVect);
-  freeBitVect (predVect);
 }
 
 /*-----------------------------------------------------------------*/
 /* incUsed - increment a symbol's usage count                      */
 /*-----------------------------------------------------------------*/
-void
+static void
 incUsed (iCode *ic, operand *op)
 {
   if (ic->depth)
@@ -432,7 +469,7 @@ incUsed (iCode *ic, operand *op)
 /*-----------------------------------------------------------------*/
 /* rliveClear - clears the rlive bitVectors                        */
 /*-----------------------------------------------------------------*/
-void
+static void
 rliveClear (eBBlock ** ebbs, int count)
 {
   int i;
@@ -454,8 +491,8 @@ rliveClear (eBBlock ** ebbs, int count)
 /*-----------------------------------------------------------------*/
 /* rlivePoint - for each point compute the ranges that are alive   */
 /*-----------------------------------------------------------------*/
-void
-rlivePoint (eBBlock ** ebbs, int count)
+static void
+rlivePoint (eBBlock ** ebbs, int count, bool emitWarnings)
 {
   int i, key;
   eBBlock *succ;
@@ -483,7 +520,7 @@ rlivePoint (eBBlock ** ebbs, int count)
              if (!IS_ITEMP(IC_JTCOND(ic)))
                continue;
 
-             findPrevUse (ebbs[i], ic->prev, IC_JTCOND(ic), ebbs, count);
+             findPrevUse (ebbs[i], ic, IC_JTCOND(ic), ebbs, count, emitWarnings);
              unvisitBlocks(ebbs, count);
              ic->rlive = bitVectSetBit (ic->rlive, IC_JTCOND(ic)->key);
              findNextUse (ebbs[i], ic->next, IC_JTCOND(ic));
@@ -498,7 +535,7 @@ rlivePoint (eBBlock ** ebbs, int count)
              if (!IS_ITEMP(IC_COND(ic)))
                continue;
 
-             findPrevUse (ebbs[i], ic->prev, IC_COND(ic), ebbs, count);
+             findPrevUse (ebbs[i], ic, IC_COND(ic), ebbs, count, emitWarnings);
              unvisitBlocks (ebbs, count);
              ic->rlive = bitVectSetBit (ic->rlive, IC_COND(ic)->key);
              findNextUse (ebbs[i], ic->next, IC_COND(ic));
@@ -511,8 +548,7 @@ rlivePoint (eBBlock ** ebbs, int count)
              incUsed (ic, IC_LEFT(ic));
              if (IS_ITEMP(IC_LEFT(ic)))
                {
-
-                 findPrevUse (ebbs[i], ic->prev, IC_LEFT(ic), ebbs, count);
+                 findPrevUse (ebbs[i], ic, IC_LEFT(ic), ebbs, count, emitWarnings);
                  unvisitBlocks(ebbs, count);
                  ic->rlive = bitVectSetBit (ic->rlive, IC_LEFT(ic)->key);
                  findNextUse (ebbs[i], ic->next, IC_LEFT(ic));
@@ -531,8 +567,6 @@ rlivePoint (eBBlock ** ebbs, int count)
                        }
                    }
                }
-//                fprintf(stderr, "%s:%d IS_SYMOP left\t", __FILE__, __LINE__);printOperand(IC_LEFT(ic), stderr);
-//                fprintf(stderr, "\n");
            }
 
          if (IS_SYMOP(IC_RIGHT(ic)))
@@ -540,13 +574,11 @@ rlivePoint (eBBlock ** ebbs, int count)
              incUsed (ic, IC_RIGHT(ic));
              if (IS_ITEMP(IC_RIGHT(ic)))
                {
-                 findPrevUse (ebbs[i], ic->prev, IC_RIGHT(ic), ebbs, count);
+                 findPrevUse (ebbs[i], ic, IC_RIGHT(ic), ebbs, count, emitWarnings);
                  unvisitBlocks(ebbs, count);
                  ic->rlive = bitVectSetBit (ic->rlive, IC_RIGHT(ic)->key);
                  findNextUse (ebbs[i], ic->next, IC_RIGHT(ic));
                }
-//                fprintf(stderr, "%s:%d IS_SYMOP right\t", __FILE__, __LINE__);printOperand(IC_RIGHT(ic), stderr);
-//                fprintf(stderr, "\n");
            }
 
          if (POINTER_SET(ic) && IS_SYMOP(IC_RESULT(ic)))
@@ -556,7 +588,7 @@ rlivePoint (eBBlock ** ebbs, int count)
            {
              if (POINTER_SET(ic))
                {
-                 findPrevUse (ebbs[i], ic->prev, IC_RESULT(ic), ebbs, count);
+                 findPrevUse (ebbs[i], ic, IC_RESULT(ic), ebbs, count, emitWarnings);
                }
              unvisitBlocks(ebbs, count);
              ic->rlive = bitVectSetBit (ic->rlive, IC_RESULT(ic)->key);
@@ -730,7 +762,7 @@ notUsedInBlock (symbol * sym, eBBlock * ebp, iCode *ic)
 /*-----------------------------------------------------------------*/
 /* adjustIChain - correct the sch and ech pointers                 */
 /*-----------------------------------------------------------------*/
-void
+static void
 adjustIChain (eBBlock ** ebbs, int count)
 {
   int i;
@@ -762,7 +794,7 @@ adjustIChain (eBBlock ** ebbs, int count)
 /* computeLiveRanges - computes the live ranges for variables      */
 /*-----------------------------------------------------------------*/
 void
-computeLiveRanges (eBBlock ** ebbs, int count)
+computeLiveRanges (eBBlock ** ebbs, int count, bool emitWarnings)
 {
   /* first look through all blocks and adjust the
      sch and ech pointers */
@@ -781,7 +813,7 @@ computeLiveRanges (eBBlock ** ebbs, int count)
 
   /* mark the ranges live for each point */
   setToNull ((void *) &liveRanges);
-  rlivePoint (ebbs, count);
+  rlivePoint (ebbs, count, emitWarnings);
 
   /* mark the from & to live ranges for variables used */
   markLiveRanges (ebbs, count);
@@ -815,6 +847,43 @@ recomputeLiveRanges (eBBlock ** ebbs, int count)
     }
 
   /* do the LR computation again */
-  computeLiveRanges (ebbs, count);
+  computeLiveRanges (ebbs, count, FALSE);
 }
 
+/*-----------------------------------------------------------------*/
+/* dump icode->rlive in all blocks                                 */
+/*-----------------------------------------------------------------*/
+#if 0
+void
+dumpIcRlive (eBBlock ** ebbs, int count)
+{
+  int i, j;
+  iCode *ic;
+
+  /* for all blocks do */
+  for (i = 0; i < count; i++)
+    {
+      printf ("bb %d %s alive symbols:\n", i, ebbs[i]->entryLabel->name);
+      /* for all instructions in this block do */
+      for (ic = ebbs[i]->sch; ic; ic = ic->next)
+        {
+          printf ("\tic->key %d\n", ic->key);
+
+          if (!ic->rlive)
+            continue;
+          /* for all live Ranges alive at this point */
+          for (j = 1; j < ic->rlive->size; j++)
+            {
+              symbol *sym;
+
+              if (!bitVectBitValue (ic->rlive, j))
+                continue;
+
+              /* find the live range we are interested in */
+              if ((sym = hTabItemWithKey (liveRanges, j)))
+                printf ("\t\tsym->key %2d: %s\n", sym->key, sym->rname[0] ? sym->rname : sym->name);
+            }
+        }
+    }
+}
+#endif
index a422e1f4d93b0c27fa4d701ff97047b7cee0ae38..4ef0cc0a824d89cb4cde36d7f5b5f9230d8ca413 100644 (file)
@@ -32,10 +32,9 @@ extern hTab *iCodeSeqhTab;
 
 int  notUsedInBlock (symbol *, eBBlock *, iCode *);
 bool allDefsOutOfRange (bitVect *, int, int);
-void computeLiveRanges (eBBlock **, int);
+void computeLiveRanges (eBBlock **, int, bool);
 void recomputeLiveRanges (eBBlock **, int);
 
-void setFromRange (operand *, int);
 void setToRange (operand *, int, bool);
 void hashiCodeKeys (eBBlock **, int);
 
index 6c24ba6b7a06c0e48011e085cad02452c3347986..e88c3050d8b1dcad192dc7d7893aaa3bf6c266ef 100644 (file)
@@ -1558,7 +1558,7 @@ eBBlockFromiCode (iCode * ic)
   convertToFcall (ebbi->bbOrder, ebbi->count);
 
   /* compute the live ranges */
-  computeLiveRanges (ebbi->bbOrder, ebbi->count);
+  computeLiveRanges (ebbi->bbOrder, ebbi->count, TRUE);
 
   if (options.dump_range)
     dumpEbbsToFileExt (DUMP_RANGE, ebbi);
index 1707317e5267b55928d756ec40068de3f5e4fccb..6b8eeefb45187dd78cc2e56bd37bac78103e5938 100644 (file)
@@ -11391,11 +11391,21 @@ gen51Code (iCode * lic)
         char regsInUse[80];
         int i;
 
+        #if 0
         for (i=0; i<8; i++) {
           sprintf (&regsInUse[i],
-                   "%c", ic->riu & (1<<i) ? i+'0' : '-');
-        }
+                   "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
         regsInUse[i]=0;
+        #else
+        strcpy (regsInUse, "--------");
+        for (i=0; i < 8; i++) {
+          if (bitVectBitValue (ic->rMask, i))
+            {
+              int offset = regs8051[i].offset;
+              regsInUse[offset] = offset + '0'; /* show rMask */
+            }
+        #endif
+        }
         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
       }
       /* if the result is marked as
diff --git a/support/regression/tests/bug-895992.c b/support/regression/tests/bug-895992.c
new file mode 100644 (file)
index 0000000..203250b
--- /dev/null
@@ -0,0 +1,59 @@
+/* bug-895992.c
+
+   Life Range problem with
+   - uninitialized variable
+   - loop
+   - conditional block
+
+   LR problem hits all ports, but this test is mcs51 specific
+ */
+#include <testfwk.h>
+
+char p0 = 2;
+unsigned short loops;
+
+static void
+wait (void)
+{
+  long i, j;
+
+  /* just clobber all registers: */
+  for (i = 0; i < 2; ++i)
+    for (j = 0; j < 2; ++j)
+      ;
+}
+
+#if !defined(PORT_HOST)
+#  pragma save
+#  pragma disable_warning 84
+#endif
+
+static void
+testLR(void)
+{
+  unsigned char number;
+  unsigned char start = 1;
+  unsigned char i;
+
+  do
+    {
+      for (i = 1; i > 0 ; i--)
+        wait();         /* destroys all registers */
+      if (start)
+        {
+          number = p0;
+          start = 0;
+        }
+      number--;         /* 'number' might be used before initialization     */
+                        /* the life range of 'number' must be extended to   */
+                        /* the whole loop _including_ the conditional block */
+      ++loops;
+    }
+  while (number != 0);
+
+  ASSERT(loops == p0);
+}
+
+#if !defined(PORT_HOST)
+#  pragma restore
+#endif
diff --git a/support/regression/tests/bug-971834.c b/support/regression/tests/bug-971834.c
new file mode 100644 (file)
index 0000000..4c23097
--- /dev/null
@@ -0,0 +1,51 @@
+/* bug-971834.c
+
+   Life Range problem with
+   - uninitialized variable
+   - loop
+
+   LR problem hits all ports, but this test is mcs51 specific
+ */
+
+#include <testfwk.h>
+
+unsigned char ttt[] = {0xff, 1};
+unsigned char b;
+
+#if !defined(PORT_HOST)
+#  pragma save
+#  pragma disable_warning 84
+#endif
+
+unsigned char orsh (void)
+{
+  unsigned char a, i;
+  for (i = 0; i < sizeof(ttt); i++)
+    a |= ttt[i];
+  return a;
+}
+
+unsigned char orsh1 (void)
+{
+  unsigned char i, j;
+  unsigned char a;
+  for (j = 0; j < sizeof(ttt); j++)
+    {
+      for (i = 0; i < sizeof(ttt); i++)
+        {
+          a |= ttt[i];
+          b = a;
+        }
+    }
+  return b;
+}
+#if !defined(PORT_HOST)
+#  pragma restore
+#endif
+
+void
+testLR(void)
+{
+  ASSERT(orsh()  == 0xff);
+  ASSERT(orsh1() == 0xff);
+}
diff --git a/support/valdiag/tests/bug-895992.c b/support/valdiag/tests/bug-895992.c
new file mode 100644 (file)
index 0000000..24bf327
--- /dev/null
@@ -0,0 +1,34 @@
+
+/* bug-895992.c
+
+   Life Range problem with
+   - uninitialized variable
+   - loop
+   - conditional block
+ */
+
+#ifdef TEST1
+char p0;
+
+void wait (void);
+
+void foo(void)
+{
+  unsigned char number;
+  unsigned char start = 1;
+  unsigned char i;
+
+  do
+    {
+      for (i = 1; i > 0 ; i--)
+        wait();
+      if (start)
+        {
+          number = p0;
+          start = 0;
+        }
+      number--;                /* WARNING(SDCC) */
+    }
+  while (number != 0);
+}
+#endif
diff --git a/support/valdiag/tests/bug-971834.c b/support/valdiag/tests/bug-971834.c
new file mode 100644 (file)
index 0000000..310de8a
--- /dev/null
@@ -0,0 +1,49 @@
+
+/* bug-971834.c
+
+   Life Range problem with
+   - uninitialized variable
+   - loop
+ */
+
+#ifdef TEST1
+unsigned char ttt = 2;
+
+short foo (void)
+{
+  unsigned short a;
+  a |= ttt;            /* WARNING(SDCC) */
+  return a;
+}
+#endif
+
+
+#ifdef TEST2
+unsigned char ttt[] = {0xff, 1};
+
+char foo (void)
+{
+  unsigned char a, i;
+  for (i = 0; i < sizeof(ttt); i++)
+    a |= ttt[i];       /* WARNING(SDCC) */
+  return a;            /* WARNING(SDCC) */
+}
+#endif
+
+#ifdef TEST3
+unsigned char ttt[] = {0xff, 1};
+unsigned char b;
+
+char foo (void)
+{
+  unsigned char i, j;
+  unsigned char a;
+  for (j = 0; j < sizeof(ttt); j++) {
+    for (i = 0; i < sizeof(ttt); i++) {
+      a |= ttt[i];     /* WARNING(SDCC) */
+      b = a;
+    }
+  }
+  return b;
+}
+#endif