* device/lib/libsdcc.lib: added module rand
[fw/sdcc] / src / z80 / ralloc.c
index d73acaa0cd4286f85f442266ddc76aafefc68d8a..18e3d77e5b6c33faf977b7b604f4fc8b549c2853 100644 (file)
@@ -53,7 +53,7 @@ enum
     DISABLE_PACK_ACC = 0,
     DISABLE_PACK_ASSIGN = 0,
     DISABLE_PACK_ONE_USE = 0,
-    DISABLE_PACK_HL = 0,
+    DISABLE_PACK_HL = 1,
     DISABLE_PACK_IY = 0
   };
 
@@ -229,34 +229,6 @@ useReg (regs * reg)
   reg->isFree = 0;
 }
 
-#if 0
-/*-----------------------------------------------------------------*/
-/* allDefsOutOfRange - all definitions are out of a range          */
-/*-----------------------------------------------------------------*/
-static bool 
-allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
-{
-  int i;
-
-  if (!defs)
-    return TRUE;
-
-  for (i = 0; i < defs->size; i++)
-    {
-      iCode *ic;
-
-      if (bitVectBitValue (defs, i) &&
-         (ic = hTabItemWithKey (iCodehTab, i)) &&
-         (ic->seq >= fseq && ic->seq <= toseq))
-
-       return FALSE;
-
-    }
-
-  return TRUE;
-}
-#endif
-
 /*-----------------------------------------------------------------*/
 /* computeSpillable - given a point find the spillable live ranges */
 /*-----------------------------------------------------------------*/
@@ -384,7 +356,7 @@ leastUsedLR (set * sset)
 
     }
 
-  setToNull ((void **) &sset);
+  setToNull ((void *) &sset);
   sym->blockSpil = 0;
   return sym;
 }
@@ -587,17 +559,6 @@ hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
   return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
 }
 
-/*-----------------------------------------------------------------*/
-/* notUsedInBlock - not used in this block                         */
-/*-----------------------------------------------------------------*/
-static int
-notUsedInBlock (symbol * sym, eBBlock * ebp, iCode * ic)
-{
-  return (!bitVectBitsInCommon (sym->defs, ebp->usesDefs) &&
-         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
-/*     return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */
-}
-
 /*-----------------------------------------------------------------*/
 /* notUsedInRemaining - not used or defined in remain of the block */
 /*-----------------------------------------------------------------*/
@@ -802,6 +763,7 @@ regs *
 getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
 {
   regs *reg;
+  int j;
 
   D (D_ALLOC, ("getRegGpr: on ic %p\n", ic));
 tryAgain:
@@ -818,6 +780,11 @@ tryAgain:
       D (D_ALLOC, ("getRegGpr: have to spill.\n"));
       return NULL;
     }
+  
+  /* make sure partially assigned registers aren't reused */
+  for (j=0; j<=sym->nRegs; j++)
+    if (sym->regs[j])
+      sym->regs[j]->isFree = 0;
 
   /* this looks like an infinite loop but 
      in really selectSpil will abort  */
@@ -835,6 +802,9 @@ static regs *getRegGprNoSpil()
       return reg;
     }
   assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
 }
 
 /** Symbol has a given register.
@@ -916,6 +886,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
              (result = OP_SYMBOL (IC_RESULT (ic))) &&  /* has a result */
              result->liveTo > ic->seq &&       /* and will live beyond this */
              result->liveTo <= ebp->lSeq &&    /* does not go beyond this block */
+             result->liveFrom == ic->seq &&    /* does not start before here */
              result->regType == sym->regType &&        /* same register types */
              result->nRegs &&  /* which needs registers */
              !result->isspilt &&       /* and does not already have them */
@@ -1076,6 +1047,31 @@ tryAllocatingRegPair (symbol * sym)
   return FALSE;
 }
 
+/*------------------------------------------------------------------*/
+/* verifyRegsAssigned - make sure an iTemp is properly initialized; */
+/* it should either have registers or have beed spilled. Otherwise, */
+/* there was an uninitialized variable, so just spill this to get   */
+/* the operand in a valid state.                                    */
+/*------------------------------------------------------------------*/
+static void
+verifyRegsAssigned (operand *op, iCode * ic)
+{
+  symbol * sym;
+  
+  if (!op) return;
+  if (!IS_ITEMP (op)) return;
+  
+  sym = OP_SYMBOL (op);
+  if (sym->isspilt) return;
+  if (!sym->nRegs) return;
+  if (sym->regs[0]) return;
+  
+  werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT, 
+           sym->prereqv ? sym->prereqv->name : sym->name);
+  spillThis (sym);
+}
+
+
 /** Serially allocate registers to the variables.
     This is the main register allocation function.  It is called after
     packing.
@@ -1135,6 +1131,13 @@ serialRegAssign (eBBlock ** ebbs, int count)
              int j;
 
              D (D_ALLOC, ("serialRegAssign: in loop on result %p\n", sym));
+                
+             /* Make sure any spill location is definately allocated */
+             if (sym->isspilt && !sym->remat && sym->usl.spillLoc &&
+                 !sym->usl.spillLoc->allocreq)
+               {
+                 sym->usl.spillLoc->allocreq++;
+               }
 
              /* if it does not need or is spilt 
                 or is already assigned to registers
@@ -1173,6 +1176,17 @@ serialRegAssign (eBBlock ** ebbs, int count)
 
                }
 
+             /* If the live range preceeds the point of definition 
+                then ideally we must take into account registers that 
+                have been allocated after sym->liveFrom but freed
+                before ic->seq. This is complicated, so spill this
+                symbol instead and let fillGaps handle the allocation. */
+             if (sym->liveFrom < ic->seq)
+               {
+                   spillThis (sym);
+                   continue;                 
+               }
+
              /* if it has a spillocation & is used less than
                 all other live ranges then spill this */
              if (willCS) {
@@ -1236,6 +1250,40 @@ serialRegAssign (eBBlock ** ebbs, int count)
            }
        }
     }
+
+    /* Check for and fix any problems with uninitialized operands */
+    for (i = 0; i < count; i++)
+      {
+       iCode *ic;
+
+       if (ebbs[i]->noPath &&
+           (ebbs[i]->entryLabel != entryLabel &&
+            ebbs[i]->entryLabel != returnLabel))
+           continue;
+
+       for (ic = ebbs[i]->sch; ic; ic = ic->next)
+         {
+           if (SKIP_IC2 (ic))
+             continue;
+
+           if (ic->op == IFX)
+             {
+               verifyRegsAssigned (IC_COND (ic), ic);
+               continue;
+             }
+
+           if (ic->op == JUMPTABLE)
+             {
+               verifyRegsAssigned (IC_JTCOND (ic), ic);
+               continue;
+             }
+
+           verifyRegsAssigned (IC_RESULT (ic), ic);
+           verifyRegsAssigned (IC_LEFT (ic), ic);
+           verifyRegsAssigned (IC_RIGHT (ic), ic);
+          }
+      }    
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -1267,7 +1315,8 @@ static void fillGaps()
                bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
                continue ;
 
-           assert (clr = hTabItemWithKey(liveRanges,i));
+           clr = hTabItemWithKey(liveRanges,i);
+           assert(clr);
         
            /* mark these registers as used */
            for (k = 0 ; k < clr->nRegs ; k++ ) 
@@ -1491,29 +1540,51 @@ createRegMask (eBBlock ** ebbs, int count)
 
 /** Returns the rematerialized string for a remat var.
  */
-char *
+static char *
 rematStr (symbol * sym)
 {
-  char *s = buffer;
   iCode *ic = sym->rematiCode;
+  int offset = 0;
 
   while (1)
     {
+      /* if plus adjust offset to right hand side */
+      if (ic->op == '+')
+        {
+          offset += (int) operandLitValue (IC_RIGHT (ic));
+          ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+          continue;
+        }
 
-      /* if plus or minus print the right hand side */
-      if (ic->op == '+' || ic->op == '-')
+      /* if minus adjust offset to right hand side */
+      if (ic->op == '-')
        {
-         sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
-                  ic->op);
-         s += strlen (s);
+          offset -= (int) operandLitValue (IC_RIGHT (ic));
          ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
          continue;
        }
+
+      /* cast then continue */
+      if (IS_CAST_ICODE(ic)) {
+          ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+          continue;
+      }
       /* we reached the end */
-      sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
       break;
     }
 
+  if (offset)
+    {
+      SNPRINTF (buffer, sizeof(buffer),
+                "(%s %c 0x%04x)",
+                OP_SYMBOL (IC_LEFT (ic))->rname,
+                offset >= 0 ? '+' : '-',
+                abs (offset) & 0xffff);
+    }
+  else
+    {
+      strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
+    }
   return buffer;
 }
 
@@ -1642,32 +1713,78 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
       if (SKIP_IC2 (dic))
        continue;
 
-      if (IS_SYMOP (IC_RESULT (dic)) &&
-         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
-       {
-         break;
-       }
+      if (dic->op == IFX)
+        {
+          if (IS_SYMOP (IC_COND (dic)) &&
+             (IC_COND (dic)->key == IC_RESULT (ic)->key ||
+              IC_COND (dic)->key == IC_RIGHT (ic)->key))
+           {
+             dic = NULL;
+             break;
+           }
+        }
+      else
+        {
+          if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+             IS_OP_VOLATILE (IC_RESULT (dic)))
+           {
+             dic = NULL;
+             break;
+           }
 
-      if (IS_SYMOP (IC_RIGHT (dic)) &&
-         (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
-          IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
-       {
-         dic = NULL;
-         break;
-       }
+          if (IS_SYMOP (IC_RESULT (dic)) &&
+             IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+           {
+             if (POINTER_SET (dic))
+               dic = NULL;
 
-      if (IS_SYMOP (IC_LEFT (dic)) &&
-         (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
-          IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
-       {
-         dic = NULL;
-         break;
+             break;
+           }
+
+          if (IS_SYMOP (IC_RIGHT (dic)) &&
+             (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
+              IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
+           {
+             dic = NULL;
+             break;
+           }
+
+          if (IS_SYMOP (IC_LEFT (dic)) &&
+             (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
+              IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+           {
+             dic = NULL;
+             break;
+           }
+
+          if (IS_SYMOP (IC_RESULT (dic)) &&
+             IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+           {
+             dic = NULL;
+             break;
+           }
+           
        }
     }
 
   if (!dic)
     return 0;                  /* did not find */
 
+  /* if assignment then check that right is not a bit */
+  if (ASSIGNMENT (ic) && !POINTER_SET (ic))
+    {
+      sym_link *etype = operandType (IC_RESULT (dic));
+      if (IS_BITFIELD (etype))
+        {
+          /* if result is a bit too then it's ok */
+          etype = operandType (IC_RESULT (ic));
+          if (!IS_BITFIELD (etype))
+            {
+              return 0;
+            }
+       }
+    }
+
   /* if the result is on stack or iaccess then it must be
      the same atleast one of the operands */
   if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
@@ -1710,7 +1827,7 @@ pack:
   // PENDING: Check vs mcs51
   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
   hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
-  OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+  OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
   return 1;
 }
 
@@ -2442,6 +2559,12 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
       return NULL;
     }
 
+  if (getSize (operandType (op)) != 2)
+    {
+      D (D_ACCUSE2, ("  + Dropping as operation has size is too big\n"));
+      return FALSE;
+    }
+
   /* Nothing else that clashes with this is using the scratch
      register.  Scan through all of the intermediate instructions and
      see if any of them could nuke HL.
@@ -2909,6 +3032,7 @@ packRegisters (eBBlock * ebp)
       /* if pointer get */
       if (!DISABLE_PACK_ONE_USE &&
          POINTER_GET (ic) &&
+         IS_SYMOP (IC_LEFT (ic)) &&
       /* MLH: dont have far space
          !isOperandInFarSpace(IC_RESULT(ic))&& */
          !OP_SYMBOL (IC_LEFT (ic))->remat &&
@@ -2928,10 +3052,16 @@ packRegisters (eBBlock * ebp)
 
       if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)))
        {
+         /* PENDING */
           if (IS_GB)
-            packRegsForHLUse (ic);
+           {
+             if (0)
+               packRegsForHLUse (ic);
+           }
           else
-            packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
+           {
+             packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
+           }
        }
 
       if (!DISABLE_PACK_IY && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
@@ -2986,9 +3116,10 @@ joinPushes (iCode *lic)
       first = (int)operandLitValue ( IC_LEFT (ic));
       second = (int)operandLitValue ( IC_LEFT (uic));
 
-      sprintf (buffer, "%u", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
+      sprintf (buffer, "%uu", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
       val = constVal (buffer);
       SPEC_NOUN (val->type) = V_INT;
+      IC_LEFT (ic) = operandFromOperand (IC_LEFT (ic));
       IC_LEFT (ic)->operand.valOperand = val;
       
       /* Now remove the second one from the list. */
@@ -3007,8 +3138,10 @@ joinPushes (iCode *lic)
 /* assignRegisters - assigns registers to each live range as need  */
 /*-----------------------------------------------------------------*/
 void 
-z80_assignRegisters (eBBlock ** ebbs, int count)
+z80_assignRegisters (ebbIndex * ebbi)
 {
+  eBBlock ** ebbs = ebbi->bbOrder;
+  int count = ebbi->count;
   iCode *ic;
   int i;
 
@@ -3035,8 +3168,12 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
   for (i = 0; i < count; i++)
     packRegisters (ebbs[i]);
 
+  /* liveranges probably changed by register packing
+     so we compute them again */
+  recomputeLiveRanges (ebbs, count);
+
   if (options.dump_pack)
-    dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
+    dumpEbbsToFileExt (DUMP_PACK, ebbi);
 
   /* first determine for each live range the number of 
      registers & the type of registers required for each */
@@ -3064,7 +3201,7 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
     }
 
   if (options.dump_rassgn) {
-    dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+    dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
     dumpLiveRanges (DUMP_LRANGE, liveRanges);
   }
 
@@ -3085,8 +3222,8 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
   /* free up any stackSpil locations allocated */
   applyToSet (_G.stackSpil, deallocStackSpil);
   _G.slocNum = 0;
-  setToNull ((void **) &_G.stackSpil);
-  setToNull ((void **) &_G.spiltSet);
+  setToNull ((void *) &_G.stackSpil);
+  setToNull ((void *) &_G.spiltSet);
   /* mark all registers as free */
   freeAllRegs ();