Example #1
0
/*------------------------------------------------------------------*/
static void
markWholeLoop (eBBlock *ebp, int key)
{
  eBBlock *ebpi;

  /* avoid endless loops */
  ebp->visited = 1;

  /* 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);
    }

  markAlive (ebp->sch, ebp->ech, key);
}
Example #2
0
void
outputDebugStackSymbols (void)
{
  if (getenv ("SDCC_DEBUG_VAR_STORAGE"))
    {
      dumpSymInfo ("XStack", xstack);
      dumpSymInfo ("IStack", istack);
    }

  if (options.debug && debugFile)
    {
      symbol *sym;

      if (xstack)
        {
          for (sym = setFirstItem (xstack->syms); sym; sym = setNextItem (xstack->syms))
            debugFile->writeSymbol (sym);
        }

      if (istack)
        {
          for (sym = setFirstItem (istack->syms); sym; sym = setNextItem (istack->syms))
            debugFile->writeSymbol(sym);
        }
    }
}
Example #3
0
static void dbg_regusage(set *fregs)
{
  regs *reg;
  pCode *pcfl;
  pCode *pc;


  for (reg = setFirstItem(fregs) ; reg ;
       reg = setNextItem(fregs)) {

    if(elementsInSet(reg->reglives.usedpCodes)) {
    
      fprintf (stderr, "%s  addr=0x%03x rIdx=0x%03x",
	       reg->name,
	       reg->address,
	       reg->rIdx);

      pcfl = setFirstItem(reg->reglives.usedpFlows);
      if(pcfl)
	fprintf(stderr, "\n   used in seq");

      while(pcfl) {
	fprintf(stderr," 0x%03x",pcfl->seq);
	pcfl = setNextItem(reg->reglives.usedpFlows);
      }

      pcfl = setFirstItem(reg->reglives.assignedpFlows);
      if(pcfl)
	fprintf(stderr, "\n   assigned in seq");

      while(pcfl) {
	fprintf(stderr," 0x%03x",pcfl->seq);
	pcfl = setNextItem(reg->reglives.assignedpFlows);
      }

      pc = setFirstItem(reg->reglives.usedpCodes);
      if(pc)
	fprintf(stderr, "\n   used in instructions ");

      while(pc) {
	pcfl = PCODE(PCI(pc)->pcflow);
	if(pcfl)
	  fprintf(stderr," 0x%03x:",pcfl->seq);
	fprintf(stderr,"0x%03x",pc->seq);

	pc = setNextItem(reg->reglives.usedpCodes);
      }

      fprintf(stderr, "\n");
    }
  }
}
Example #4
0
static void visit (set **visited, iCode *ic, const int key)
{
  symbol *lbl;

  while (ic && !isinSet (*visited, ic) && bitVectBitValue (ic->rlive, key))
    {
      addSet (visited, ic);

      switch (ic->op)
        {
        case GOTO:
          ic = hTabItemWithKey (labelDef, (IC_LABEL (ic))->key);
          break;
        case RETURN:
          ic = hTabItemWithKey (labelDef, returnLabel->key);
          break;
        case JUMPTABLE:
          for (lbl = setFirstItem (IC_JTLABELS (ic)); lbl; lbl = setNextItem (IC_JTLABELS (ic)))
            visit (visited, hTabItemWithKey (labelDef, lbl->key), key);
          break;
        case IFX:
          visit (visited, hTabItemWithKey (labelDef, (IC_TRUE(ic) ? IC_TRUE (ic) : IC_FALSE (ic))->key), key);
          ic = ic->next;
          break;
        default:
          ic = ic->next;
          if (!POINTER_SET (ic) && IC_RESULT (ic) && IS_SYMOP (IC_RESULT (ic)) && OP_SYMBOL_CONST (IC_RESULT (ic))->key == key)
            {
              addSet (visited, ic);
              return;
            }
        }
    }
}
Example #5
0
void dumpSymInfo(char *pcName, memmap *memItem)
{
  symbol *sym;

  if (!memItem)
    return;

  printf("--------------------------------------------\n");
  printf(" %s\n", pcName);

  for(sym = setFirstItem(memItem->syms); 
      sym;       sym = setNextItem(memItem->syms))
    {          
      printf("   %s, isReqv:%d, reqv:0x%p, onStack:%d, Stack:%d, nRegs:%d, [", 
	     sym->rname, sym->isreqv, sym->reqv, sym->onStack, sym->stack, sym->nRegs);

      if(sym->reqv)
      {	
	  int i;
	  symbol *TempSym = OP_SYMBOL (sym->reqv);
	 
	  for (i = 0; i < 4; i++)	    
	    if(TempSym->regs[i])
	      printf("%s,", port->getRegName(TempSym->regs[i]));	       
      }
          
      printf("]\n");
    }

  printf("\n");
}
Example #6
0
static void dbg_dumpFlow(pBlock *pb)
{
	pCode *pcflow;
	
	for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
	pcflow != NULL;
	pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
		
		if(!isPCFL(pcflow))
			fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
		
		fprintf(stderr, "Flow: 0x%x",pcflow->seq);
		if(PCFL(pcflow) && PCFL(pcflow)->ancestor)
			fprintf(stderr,", ancestor 0x%x\n",
			PCFL(pcflow)->ancestor->pc.seq);
		else {
			pCodeFlowLink *from = (PCFL(pcflow)->from) ? (PCFLINK(setFirstItem(PCFL(pcflow)->from))) : NULL;
			fprintf(stderr," no ancestor");
			while(from) {
				fprintf(stderr," (0x%x)",from->pcflow->pc.seq);
				from = setNextItem(PCFL(pcflow)->from);
			}
			fprintf(stderr,"\n");
		}
	}
	
}
Example #7
0
/*-----------------------------------------------------------------*/
int returnAtEnd (eBBlock *ebp)
{
    /* case 1.
       This basic block ends in a return statment 
    */
    if (ebp->ech && ebp->ech->op == RETURN) return 1;

    /* case 2.
       This basic block has only one successor and that
       successor has only one return statement
    */
    if (elementsInSet(ebp->succList) == 1) {
	eBBlock *succ = setFirstItem(ebp->succList);
	/* could happen for dummy blocks */
	if (!succ->sch || !succ->ech) return 0;

	/* first iCode is a return */
	if (succ->sch->op == RETURN) return 2;

	/* or first iCode is a label & the next &
	   last icode is a return */
	if (succ->sch->op == LABEL && succ->sch->next == succ->ech &&
	    succ->ech->op == RETURN ) return 2;
    }

    return 0;
}
Example #8
0
/*------------------------------------------------------------------*/
static bool
findPrevUseSym  (eBBlock *ebp, iCode *ic, symbol * sym)
{
  eBBlock * pred;
  iCode * uic;

  if (ebp->visited)
    {
     /* already visited: this branch must have been succesfull, */
     /* because otherwise the search would have been aborted. */
      return TRUE;
    }
  ebp->visited = 1;

  /* search backward in the current block */
  for (uic = ic; uic; uic = uic->prev)
    {
      if (!POINTER_SET (uic) && IS_AUTOSYM (IC_RESULT (uic)))
        {
          if (IC_RESULT (uic)->key == sym->key)
            {
              /* Ok, found a definition */
              return TRUE;
            }
        }
      /* address taken from symbol? */
      if (uic->op == ADDRESS_OF && IS_AUTOSYM (IC_LEFT (uic)))
        {
          if (IC_LEFT (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)
    {
      /* 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;
}
Example #9
0
/*-----------------------------------------------------------------*/
set *
edgesTo (eBBlock * to)
{
  set *result = NULL;
  edge *loop;

  for (loop = setFirstItem (graphEdges); loop; loop = setNextItem (graphEdges))
    if (loop->to == to && !loop->from->noPath)
      addSet (&result, loop->from);

  return result;
}
Example #10
0
/*-----------------------------------------------------------------*/
static void
printAllocInfoSeg (memmap * map, symbol * func, struct dbuf_s *oBuf)
{
  symbol *sym;

  if (!map)
    return;
  if (!map->syms)
    return;

  for (sym = setFirstItem (map->syms); sym;
       sym = setNextItem (map->syms))
    {

      if (sym->level == 0)
        continue;
      if (sym->localof != func)
        continue;

      dbuf_printf (oBuf, ";%-25s Allocated ", sym->name);

      /* if assigned to registers */
      if (!sym->allocreq && sym->reqv)
        {
          int i;

          sym = OP_SYMBOL (sym->reqv);
          if (!sym->isspilt || sym->remat)
            {
              dbuf_append_str (oBuf, "to registers ");
              for (i = 0; i < 4 && sym->regs[i]; i++)
                dbuf_printf (oBuf, "%s ", port->getRegName (sym->regs[i]));
              dbuf_append_char (oBuf, '\n');
              continue;
            }
          else
            {
              sym = sym->usl.spillLoc;
            }
        }

      /* if on stack */
      if (sym->onStack)
        {
          dbuf_printf (oBuf, "to stack - offset %d\n", sym->stack);
          continue;
        }

      /* otherwise give rname */
      dbuf_printf (oBuf, "with name '%s'\n", sym->rname);
    }
}
Example #11
0
/*-----------------------------------------------------------------*/
void
overlay2data ()
{
  symbol *sym;

  for (sym = setFirstItem (overlay->syms); sym;
       sym = setNextItem (overlay->syms))
    {

      SPEC_OCLS (sym->etype) = data;
      allocIntoSeg (sym);
    }

  setToNull ((void *) &overlay->syms);
}
Example #12
0
/*-----------------------------------------------------------------*/
void
overlay2Set ()
{
  symbol *sym;
  set *oset = NULL;

  for (sym = setFirstItem (overlay->syms); sym;
       sym = setNextItem (overlay->syms))
    {

      addSet (&oset, sym);
    }

  setToNull ((void *) &overlay->syms);
  addSet (&ovrSetSets, oset);
}
Example #13
0
int
pic14_stringInSet(const char *str, set **world, int autoAdd)
{
  char *s;

  if (!str) return 1;
  assert(world);

  for (s = setFirstItem(*world); s; s = setNextItem(*world))
  {
    /* found in set */
    if (0 == strcmp(s, str)) return 1;
  }

  /* not found */
  if (autoAdd) addSet(world, Safe_strdup(str));
  return 0;
}
Example #14
0
static void
pic14printLocals (struct dbuf_s *oBuf)
{
    set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
        dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
    regs *reg;
    int i, is_first = 1;
    static unsigned sectionNr = 0;

    /* emit all registers from all possible sets */
    for (i = 0; i < 6; i++) {
        if (allregs[i] == NULL) continue;

        for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
            if (reg->isEmitted) continue;

            if (reg->wasUsed && !reg->isExtern) {
                if (!pic14_stringInSet(reg->name, &emitted, 1)) {
                    if (reg->isFixed) {
                        // Should not happen, really...
                        assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
                        dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
                                moduleName, sectionNr++, reg->address, reg->name, reg->size);
                    } else {
                        if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
                            // assign each local register into its own section
                            dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
                                    moduleName, sectionNr++, reg->name, reg->size);
                        } else {
                            // group all local registers into a single section
                            // This should greatly improve BANKSEL generation...
                            if (is_first) {
                                dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
                                is_first = 0;
                            }
                            dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
                        }
                    }
                }
            }
            reg->isEmitted = 1;
        } // for
    } // for
}
Example #15
0
/*-----------------------------------------------------------------*/
eBBlock *
immedDom (ebbIndex * ebbi, eBBlock * ebp)
{
  /* first delete self from the list */
  set *iset = domSetFromVect (ebbi, ebp->domVect);
  eBBlock *loop;
  eBBlock *idom = NULL;

  deleteSetItem (&iset, ebp);
  /* then just return the one with the greatest */
  /* depthfirst number, this will be the immed dominator */
  if ((loop = setFirstItem (iset)))
    idom = loop;
  for (; loop; loop = setNextItem (iset))
    if (loop->dfnum > idom->dfnum)
      idom = loop;

  setToNull ((void *) &iset);
  return idom;

}
Example #16
0
/** noOverLap - will iterate through the list looking for over lap
 */
static int
noOverLap (set *itmpStack, symbol *fsym)
{
  symbol *sym;

  for (sym = setFirstItem (itmpStack); sym; sym = setNextItem (itmpStack))
    {
      if (bitVectBitValue (sym->clashes, fsym->key))
        return 0;
#if 0
      // if sym starts before (or on) our end point
      // and ends after (or on) our start point,
      // it is an overlap.
      if (sym->liveFrom <= fsym->liveTo && sym->liveTo >= fsym->liveFrom)
        {
          return 0;
        }
#endif
    }
  return 1;
}
Example #17
0
/*-----------------------------------------------------------------*/
void
printAllocInfo (symbol * func, struct dbuf_s * oBuf)
{
#define BREAKLINE ";------------------------------------------------------------\n"
  int cnt = 0;
  set *ovrset;
  set *tempOverlaySyms;

  if (!func)
    return;

  /* must be called after register allocation is complete */
  dbuf_append_str (oBuf, BREAKLINE);
  dbuf_printf (oBuf, ";Allocation info for local variables in function '%s'\n", func->name);
  dbuf_append_str (oBuf, BREAKLINE);

  cnt += printAllocInfoSeg (xstack, func, oBuf);
  cnt += printAllocInfoSeg (istack, func, oBuf);
  cnt += printAllocInfoSeg (code, func, oBuf);
  cnt += printAllocInfoSeg (data, func, oBuf);
  cnt += printAllocInfoSeg (xdata, func, oBuf);
  cnt += printAllocInfoSeg (idata, func, oBuf);
  cnt += printAllocInfoSeg (sfr, func, oBuf);
  cnt += printAllocInfoSeg (sfrbit, func, oBuf);

  tempOverlaySyms = overlay->syms;

  /* search the set of overlay sets for local variables/parameters */
  for (ovrset = setFirstItem (ovrSetSets); ovrset;
       ovrset = setNextItem (ovrSetSets))
    {
      overlay->syms = ovrset;
      cnt += printAllocInfoSeg (overlay, func, oBuf);
    }
  overlay->syms = tempOverlaySyms;

  if (cnt)
    dbuf_append_str (oBuf, BREAKLINE);
}
Example #18
0
/*-----------------------------------------------------------------*
 * void pic16_pCodeRegMapLiveRanges(pBlock *pb) 
 *-----------------------------------------------------------------*/
void pic16_pCodeRegMapLiveRanges(pBlock *pb)
{
  pCode *pcflow;

  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
       pcflow != NULL;
       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {

    if(!isPCFL(pcflow)) {
      fprintf(stderr, "pCodeRegMapLiveRanges - pcflow is not a flow object ");
      continue;
    }
    pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
  }

#if 0
  for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
       pcflow != NULL;
       pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {

    regs *r = setFirstItem(PCFL(pcflow)->registers);
    fprintf(stderr,"flow seq %d\n", pcflow->seq);

    while (r) {
      fprintf(stderr, "  %s\n",r->name);
      r = setNextItem(PCFL(pcflow)->registers);

    }

  }
#endif

#if HAVE_DBGREGUSAGE
  dbg_dumpregusage();
#endif

}
Example #19
0
void outputDebugSymbols(void)
{
  if(getenv("SDCC_DEBUG_VAR_STORAGE"))
    {
      dumpSymInfo("Code", code);
      dumpSymInfo("Data", data);
      dumpSymInfo("PData", pdata);
      dumpSymInfo("XData", xdata);
      dumpSymInfo("XIData", xidata);
      dumpSymInfo("XInit", xinit);
      dumpSymInfo("IData", idata);
      dumpSymInfo("Bit", bit);
      dumpSymInfo("Statics", statsg);
      dumpSymInfo("SFR", sfr);
      dumpSymInfo("SFRBits", sfrbit);
      dumpSymInfo("Reg", reg);
      dumpSymInfo("Generic", generic);
      dumpSymInfo("Overlay", overlay);
      dumpSymInfo("EEProm", eeprom);
      dumpSymInfo("Home", home);
    }

  if(options.debug && debugFile)
  {
    symbol *sym;
           
    if (data) {
      for (sym = setFirstItem (data->syms); sym; sym = setNextItem (data->syms))
        debugFile->writeSymbol(sym);
    }

    if (idata) {
      for (sym = setFirstItem (idata->syms); sym; sym = setNextItem (idata->syms))
        debugFile->writeSymbol(sym);
    }

    if (bit) {
      for (sym = setFirstItem (bit->syms); sym; sym = setNextItem (bit->syms))
        debugFile->writeSymbol(sym);
    }

	if (pdata) {
      for (sym = setFirstItem (pdata->syms); sym; sym = setNextItem (pdata->syms))
        debugFile->writeSymbol(sym);
    }

    if (xdata) {
      for (sym = setFirstItem (xdata->syms); sym; sym = setNextItem (xdata->syms))
        debugFile->writeSymbol(sym);
    }

    if(port->genXINIT && xidata) {
      for (sym = setFirstItem (xidata->syms); sym; sym = setNextItem (xidata->syms))
	debugFile->writeSymbol(sym);        
    }

    if (sfr) {
      for (sym = setFirstItem (sfr->syms); sym; sym = setNextItem (sfr->syms))
        debugFile->writeSymbol(sym);
    }

    if (sfrbit) {
      for (sym = setFirstItem (sfrbit->syms); sym; sym = setNextItem (sfrbit->syms))
        debugFile->writeSymbol(sym);
    }

    if (home) {
      for (sym = setFirstItem (home->syms); sym; sym = setNextItem (home->syms))
        debugFile->writeSymbol(sym);
    }

    if (code) {
      for (sym = setFirstItem (code->syms); sym; sym = setNextItem (code->syms))
        debugFile->writeSymbol(sym);
    }

    if (statsg) {
      for (sym = setFirstItem (statsg->syms); sym; sym = setNextItem (statsg->syms))
        debugFile->writeSymbol(sym);
    }

    if(port->genXINIT && xinit) {
      for (sym = setFirstItem (xinit->syms); sym; sym = setNextItem (xinit->syms))
	debugFile->writeSymbol(sym);        
    }
  }

  return;
}
Example #20
0
/*-----------------------------------------------------------------*/
static void
rlivePoint (eBBlock ** ebbs, int count, bool emitWarnings)
{
  int i, key;
  eBBlock *succ;
  bitVect *alive;

  /* for all blocks do */
  for (i = 0; i < count; i++)
    {
      iCode *ic;

      /* for all instructions in this block do */
      for (ic = ebbs[i]->sch; ic; ic = ic->next)
        {

	  if (!ic->rlive)
	    ic->rlive = newBitVect (operandKey);

	  if (SKIP_IC2(ic))
	    continue;

	  if (ic->op == JUMPTABLE && IS_SYMOP(IC_JTCOND(ic)))
	    {
	      incUsed (ic, IC_JTCOND(ic));

	      if (!IS_AUTOSYM(IC_JTCOND(ic)))
	        continue;

	      findPrevUse (ebbs[i], ic, IC_JTCOND(ic), ebbs, count, emitWarnings);
              if (IS_ITEMP(IC_JTCOND(ic)))
                {
                  unvisitBlocks(ebbs, count);
                  ic->rlive = bitVectSetBit (ic->rlive, IC_JTCOND(ic)->key);
                  findNextUse (ebbs[i], ic->next, IC_JTCOND(ic));
                }

	      continue;
	    }

	  if (ic->op == IFX && IS_SYMOP(IC_COND(ic)))
	    {
	      incUsed (ic, IC_COND(ic));

	      if (!IS_AUTOSYM(IC_COND(ic)))
	        continue;

	      findPrevUse (ebbs[i], ic, IC_COND(ic), ebbs, count, emitWarnings);
              if (IS_ITEMP(IC_COND(ic)))
                {
                  unvisitBlocks (ebbs, count);
                  ic->rlive = bitVectSetBit (ic->rlive, IC_COND(ic)->key);
                  findNextUse (ebbs[i], ic->next, IC_COND(ic));
                }

	      continue;
	    }

	  if (IS_SYMOP(IC_LEFT(ic)))
	    {
	      incUsed (ic, IC_LEFT(ic));
	      if (IS_AUTOSYM(IC_LEFT(ic)) &&
	          ic->op != ADDRESS_OF)
	        {
	          findPrevUse (ebbs[i], ic, IC_LEFT(ic), ebbs, count, emitWarnings);
                  if (IS_ITEMP(IC_LEFT(ic)))
                    {
                      unvisitBlocks(ebbs, count);
                      ic->rlive = bitVectSetBit (ic->rlive, IC_LEFT(ic)->key);
                      findNextUse (ebbs[i], ic->next, IC_LEFT(ic));

                      /* if this is a send extend the LR to the call */
                      if (ic->op == SEND)
                        {
                          iCode *lic;
                          for (lic = ic; lic; lic = lic->next)
                            {
                              if (lic->op == CALL || lic->op == PCALL)
                                {
                                  markAlive (ic, lic->prev, IC_LEFT (ic)->key);
                                  break;
                                }
                            }
                        }
                    }
		}
	    }

	  if (IS_SYMOP(IC_RIGHT(ic)))
	    {
	      incUsed (ic, IC_RIGHT(ic));
              if (IS_AUTOSYM(IC_RIGHT(ic)))
	        {
	          findPrevUse (ebbs[i], ic, IC_RIGHT(ic), ebbs, count, emitWarnings);
                  if (IS_ITEMP(IC_RIGHT(ic)))
                    {
                      unvisitBlocks(ebbs, count);
                      ic->rlive = bitVectSetBit (ic->rlive, IC_RIGHT(ic)->key);
                      findNextUse (ebbs[i], ic->next, IC_RIGHT(ic));
                    }
		}
	    }

	  if (POINTER_SET(ic) && IS_SYMOP(IC_RESULT(ic)))
	    incUsed (ic, IC_RESULT(ic));

          if (IS_AUTOSYM(IC_RESULT(ic)))
	    {
	      if (POINTER_SET(ic))
	        {
	          findPrevUse (ebbs[i], ic, IC_RESULT(ic), ebbs, count, emitWarnings);
		}
              if (IS_ITEMP(IC_RESULT(ic)))
                {
                  unvisitBlocks(ebbs, count);
                  ic->rlive = bitVectSetBit (ic->rlive, IC_RESULT(ic)->key);
                  findNextUse (ebbs[i], ic->next, IC_RESULT(ic));
                  /* findNextUse sometimes returns 0 here, which means that ic is
                     dead code. Something should be done about this dead code since
                     e.g. register allocation suffers. */
                }
	    }

	  if (!POINTER_SET(ic) && IC_RESULT(ic))
	    ic->defKey = IC_RESULT(ic)->key;

	}

      /* check all symbols that are alive in the last instruction */
      /* but are not alive in all successors */

      succ = setFirstItem (ebbs[i]->succList);
      if (!succ)
        continue;

      alive = succ->sch->rlive;
      while ((succ = setNextItem (ebbs[i]->succList)))
        {
	  if (succ->sch)
            alive = bitVectIntersect (alive, succ->sch->rlive);
	}

      if (ebbs[i]->ech)
        alive = bitVectCplAnd ( bitVectCopy (ebbs[i]->ech->rlive), alive);

      if(!alive)
        continue;
      for (key = 1; key < alive->size; key++)
        {
	  if (!bitVectBitValue (alive, key))
	    continue;

	  unvisitBlocks(ebbs, count);
	  findNextUseSym (ebbs[i], NULL, hTabItemWithKey (liveRanges, key));
	}

    }
}
Example #21
0
/*-----------------------------------------------------------------*/
void
separateLiveRanges (iCode *sic, ebbIndex *ebbi)
{
  iCode *ic;
  set *candidates = 0;
  symbol *sym;

  // printf("separateLiveRanges()\n");

  for (ic = sic; ic; ic = ic->next)
    {
      if (ic->op == IFX || ic->op == GOTO || ic->op == JUMPTABLE || !IC_RESULT (ic) || !IS_ITEMP (IC_RESULT (ic)) || bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) <= 1 || isinSet (candidates, OP_SYMBOL (IC_RESULT (ic))))
        continue;

      addSet (&candidates, OP_SYMBOL (IC_RESULT (ic)));
    }

  if (!candidates)
    return;

  for(sym = setFirstItem (candidates); sym; sym = setNextItem (candidates))
    {
      // printf("Looking at %s, %d definitions\n", sym->name, bitVectnBitsOn (sym->defs));

      int i;
      set *defs = 0;

      for (i = 0; i < sym->defs->size; i++)
        if (bitVectBitValue (sym->defs, i))
          {
            iCode *dic;
            if(dic = hTabItemWithKey (iCodehTab, i))
              addSet (&defs, hTabItemWithKey (iCodehTab, i));
            else
              {
                werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Definition not found");
                return;
              }
          }

      do
        {
          set *visited = 0;
          set *newdefs = 0;
          int oldsize;

          wassert (defs);
          wassert (setFirstItem (defs));

          // printf("Looking at def at %d now\n", ((iCode *)(setFirstItem (defs)))->key);

          if (!bitVectBitValue (((iCode *)(setFirstItem (defs)))->rlive, sym->key))
            {
              werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Variable is not alive at one of its definitions");
              break;
            }
 
          visit (&visited, setFirstItem (defs), sym->key);
          addSet (&newdefs, setFirstItem (defs));

          do
            {
              oldsize = elementsInSet(visited);
              ic = setFirstItem (defs);
              for(ic = setNextItem (defs); ic; ic = setNextItem (defs))
                {
                  // printf("Looking at other def at %d now\n", ic->key);
                  set *visited2 = 0;
                  set *intersection = 0;
                  visit (&visited2, ic, sym->key);
                  intersection = intersectSets (visited, visited2, THROW_NONE);
                  intersection = subtractFromSet (intersection, defs, THROW_DEST);
                  if (intersection)
                    {
                      visited = unionSets (visited, visited2, THROW_DEST);
                      addSet (&newdefs, ic);
                    }
                  deleteSet (&intersection);
                  deleteSet (&visited2);
                }
             }
          while (oldsize < elementsInSet(visited));

          defs = subtractFromSet (defs, newdefs, THROW_DEST);

          if (newdefs && defs)
            {
              operand *tmpop = newiTempOperand (operandType (IC_RESULT ((iCode *)(setFirstItem (newdefs)))), TRUE);

              // printf("Splitting %s from %s, using def at %d, op %d\n", OP_SYMBOL_CONST(tmpop)->name, sym->name, ((iCode *)(setFirstItem (newdefs)))->key, ((iCode *)(setFirstItem (newdefs)))->op);

              for (ic = setFirstItem (visited); ic; ic = setNextItem (visited))
                {
                  if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic)) == sym)
                    IC_LEFT (ic) = operandFromOperand (tmpop);
                  if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic)) == sym)
                      IC_RIGHT (ic) = operandFromOperand (tmpop);
                  if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym && !POINTER_SET(ic) && ic->next && !isinSet (visited, ic->next))
                    continue;
                  if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym)
                    {
                      bool pset = POINTER_SET(ic);
                      IC_RESULT (ic) = operandFromOperand (tmpop);
                      if (pset)
                        IC_RESULT(ic)->isaddr = TRUE;
                    }
                  bitVectUnSetBit (sym->uses, ic->key);
                }
            }
          deleteSet (&newdefs);
          deleteSet (&visited);
        }
      while (elementsInSet(defs) > 1);

      deleteSet (&defs);
    }

  deleteSet (&candidates);
}
Example #22
0
/*-----------------------------------------------------------------*/
static int
printAllocInfoSeg (memmap * map, symbol * func, struct dbuf_s *oBuf)
{
  symbol *sym;
  int flg = FALSE;

  if (!map || !map->syms)
    return 0;

  for (sym = setFirstItem (map->syms); sym;
       sym = setNextItem (map->syms))
    {
      if (sym->level == 0)
        continue;
      if (sym->localof != func)
        continue;

      dbuf_printf (oBuf, ";%-25s Allocated ", sym->name);
      flg = TRUE;

      /* if assigned to registers */
      if (!sym->allocreq && sym->reqv)
        {
          int i;

          sym = OP_SYMBOL (sym->reqv);
          if (!sym->isspilt || sym->remat)
            {
              dbuf_append_str (oBuf, "to registers ");
              for (i = 0; i < 4 && sym->regs[i]; i++)
                dbuf_printf (oBuf, "%s ", port->getRegName (sym->regs[i]));
              dbuf_append_char (oBuf, '\n');
              continue;
            }
          else
            {
              sym = sym->usl.spillLoc;
            }
        }

      /* if on stack */
      if (sym->onStack)
        {
          int stack_offset = 0;

          if (options.omitFramePtr)
            {
              if (SPEC_OCLS (sym->etype)->paged)
                stack_offset = func->xstack;
              else
                stack_offset = func->stack;
            }

          dbuf_printf (oBuf, "to stack - %s %+d\n", SYM_BP (sym), sym->stack - stack_offset);
          continue;
        }

      /* otherwise give rname */
      dbuf_printf (oBuf, "with name '%s'\n", sym->rname);
    }

  return flg;
}
Example #23
0
/*-----------------------------------------------------------------*/
void
redoStackOffsets (void)
{
  symbol *sym;
  int sPtr = 0;
  int xsPtr = -1;

  /* after register allocation is complete we know
     which variables will need to be assigned space
     on the stack. We will eliminate those variables
     which do not have the allocReq flag thus reducing
     the stack space */
  for (sym = setFirstItem (istack->syms); sym; sym = setNextItem (istack->syms))
    {
      int size = getSize (sym->type);
      /* nothing to do with parameters so continue */
      if ((sym->_isparm && !IS_REGPARM (sym->etype)))
        continue;

      if (BTREE_STACK)
        {
          /* Remove them all, and let btree_alloc() below put them back in more efficiently. */
          currFunc->stack -= size;
          SPEC_STAK (currFunc->etype) -= size;
      
          if(IS_AGGREGATE (sym->type) || sym->allocreq)
            btree_add_symbol (sym);
        }
       /* Do it the old way - compared to the btree approach we waste space when allocating
          variables that had their address taken, unions and aggregates. */
       else
        {
          /* if allocation not required then subtract
             size from overall stack size & continue */
          if (!IS_AGGREGATE (sym->type) && !sym->allocreq)
            {
              currFunc->stack -= size;
              SPEC_STAK (currFunc->etype) -= size;
              continue;
            }

          if (port->stack.direction > 0)
            {
              SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
              sPtr += size;
            }
          else
            {
              sPtr -= size;
              SPEC_STAK (sym->etype) = sym->stack = sPtr;
            }
        }
    }

  if (BTREE_STACK && elementsInSet (istack->syms))
    {
      btree_alloc ();
      btree_clear ();
    }

  /* do the same for the external stack */

  if (!xstack)
    return;

  for (sym = setFirstItem (xstack->syms); sym; sym = setNextItem (xstack->syms))
    {
      int size = getSize (sym->type);
      /* nothing to do with parameters so continue */
      if ((sym->_isparm && !IS_REGPARM (sym->etype)))
        continue;

      if (IS_AGGREGATE (sym->type))
        {
          SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
          xsPtr += size;
          continue;
        }

      /* if allocation not required then subtract
         size from overall stack size & continue */
      if (!sym->allocreq)
        {
          currFunc->xstack -= size;
          SPEC_STAK (currFunc->etype) -= size;
          continue;
        }

      SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
      xsPtr += size;
    }
}
Example #24
0
/*-----------------------------------------------------------------*/
void 
computeDataFlow (eBBlock ** ebbs, int count)
{
  int i;
  int change = 1;

  while (change)
    {

      change = 0;

      /* for all blocks */
      for (i = 0; i < count; i++)
	{

	  set *pred;
	  set *oldOut;
	  int firstTime;
	  eBBlock *pBlock;

	  /* if this is the entry block then continue     */
	  /* since entry block can never have any inExprs */
	  if (ebbs[i]->noPath)
	    continue;

	  /* get blocks that can come to this block */
	  pred = edgesTo (ebbs[i]);

	  /* make a copy of the outExpressions : to be */
	  /* used for iteration   */
	  oldOut = setFromSet (ebbs[i]->outExprs);
	  setToNull ((void **) &ebbs[i]->inDefs);

	  /* indefitions are easy just merge them by union */
	  /* these are the definitions that can possibly   */
	  /* reach this block                              */
	  firstTime = 1;
	  applyToSet (pred, mergeInDefs, ebbs[i], &firstTime);

	  /* if none of the edges coming to this block */
	  /* dominate this block then add the immediate dominator */
	  /* of this block to the list of predecessors */
	  for (pBlock = setFirstItem (pred); pBlock;
	       pBlock = setNextItem (pred))
	    {
	      if (bitVectBitValue (ebbs[i]->domVect, pBlock->bbnum))
		break;
	    }

	  /* get the immediate dominator and put it there */
	  if (!pBlock)
	    {
	      eBBlock *idom = immedDom (ebbs, ebbs[i]);
	      if (idom)
		addSetHead (&pred, idom);
	    }

	  /* figure out the incoming expressions */
	  /* this is a little more complex       */
	  setToNull ((void **) &ebbs[i]->inExprs);
	  if (optimize.global_cse)
	    {
	      firstTime = 1;
	      applyToSet (pred, mergeInExprs, ebbs[i], &firstTime);
	    }
	  setToNull ((void **) &pred);

	  /* do cse with computeOnly flag set to TRUE */
	  /* this by far the quickest way of computing */
	  cseBBlock (ebbs[i], TRUE, ebbs, count);

	  /* if it change we will need to iterate */
	  change += !isSetsEqualWith (ebbs[i]->outExprs, oldOut, isCseDefEqual);
	}

      if (!change)		/* iterate till no change */
	break;
    }

  return;
}
Example #25
0
/*-----------------------------------------------------------------*
 * void pCodeRegOptimeRegUsage(pBlock *pb) 
 *-----------------------------------------------------------------*/
static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
{
  regs *reg;
  int used;
  pCode *pc1=NULL, *pc2=NULL;


  while(fregs) {
    pCode *pcfl_used, *pcfl_assigned;

    /* Step through the set by directly accessing the 'next' pointer.
     * We could also step through by using the set API, but the 
     * the (debug) calls to print instructions affect the state
     * of the set pointers */

    reg = fregs->item;
    fregs = fregs->next;

	if(reg->type == REG_SFR) {
//		fprintf(stderr,"skipping SFR: %s\n",reg->name);
		continue;
	}

    pcfl_used = setFirstItem(reg->reglives.usedpFlows);
    pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows);

    used = elementsInSet(reg->reglives.usedpCodes);
//	fprintf(stderr, "%s:%d register %s used %d times in pCode\n", __FILE__, __LINE__, reg->name, used);
    if(used == 2) { 

      /*
       * In this section, all registers that are used in only in two 
       * instructions are examined. If possible, they're optimized out.
       */

#if 0
      fprintf (stderr, "OptimizeRegUsage: %s  addr=0x%03x rIdx=0x%03x type=%d used=%d\n",
	       reg->name,
	       reg->address,
	       reg->rIdx, reg->type, used);
#endif

      pc1 = setFirstItem(reg->reglives.usedpCodes);
      pc2 = setNextItem(reg->reglives.usedpCodes);

      if(pcfl_used && pcfl_assigned) {

	/* 
	   expected case - the register has been assigned a value and is
	   subsequently used 
	*/

	//fprintf(stderr," used only twice\n");
	if(pcfl_used->seq == pcfl_assigned->seq && !(setNextItem(reg->reglives.usedpFlows)) && !(setNextItem(reg->reglives.assignedpFlows))) {

	  //fprintf(stderr, "  and used in same flow\n");

	  pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1,optimize_level);

	} else {
	  // fprintf(stderr, "  and used in different flows\n");

	}

      } else if(pcfl_used) {

	/*
	  register has been used twice without ever being assigned */
	//fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name);

      } else {
//		fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
	Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1);
	total_registers_saved++;  // debugging stats.
      }
    } else {

      /* register has been used either once, or more than twice */

      if(used && !pcfl_used && pcfl_assigned) {
	pCode *pc;

		fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);

	pc = setFirstItem(reg->reglives.usedpCodes);
	while(pc) {

	  pcfl_assigned = PCODE(PCI(pc)->pcflow);
	  Remove1pcode(pc, reg);

	  deleteSetItem (&(PCFL(pcfl_assigned)->registers), reg);
	  /*
	  deleteSetItem (&(reg->reglives.usedpCodes),pc);
	  pc->destruct(pc);
	  */
	  pc = setNextItem(reg->reglives.usedpCodes);
	}


	reg->isFree = 1;
	reg->wasUsed = 0;

	total_registers_saved++;  // debugging stats.
      } else if( (used > 2) && optimize_multi_uses) {

	set *rset1=NULL;
	set *rset2=NULL;
	int searching=1;

	pCodeFlow *pcfl1=NULL, *pcfl2=NULL;

	/* examine the number of times this register is used */


	rset1 = reg->reglives.usedpCodes;
	while(rset1 && searching) {

	  pc1 = rset1->item;
	  rset2 = rset1->next;

	  if(pc1 && isPCI(pc1) &&  ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) {

	    //while(rset2 && searching) {
	    if(rset2) {

	      pc2 = rset2->item;
	      if(pc2 && isPCI(pc2)  &&  ( (pcfl2 = PCI(pc2)->pcflow) != NULL) )  {
		if(pcfl2 == pcfl1) {

		  if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 0,optimize_level))
		    searching = 0;
		}
	      }

	      //rset2 = rset2->next;
	      
	    }
	  }
	  rset1 = rset1->next;
	}
      }
    }

  }

}
Example #26
0
/*
 * Emit a set of symbols.
 * type - 0: have symbol tell whether it is local, extern or global
 *        1: assume all symbols in set to be global
 *        2: assume all symbols in set to be extern
 */
static void
emitSymbolSet(set *s, int type)
{
    symbol *sym;
    initList *list;
    unsigned sectionNr = 0;

    for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
#if 0
        fprintf (stdout, ";    name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
                sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
#endif

        if (sym->etype && SPEC_ABSA(sym->etype)
                && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))
                && sym->ival)
        {
            // handle config words
            pic14_assignConfigWordValue(SPEC_ADDR(sym->etype),
                    (int)list2int(sym->ival));
            pic14_stringInSet(sym->rname, &emitted, 1);
            continue;
        }

        if (sym->isstrlit) {
            // special case: string literals
            emitInitVal(ivalBuf, sym, sym->type, NULL);
            continue;
        }

        if (type != 0 || sym->cdef
                || (!IS_STATIC(sym->etype)
                    && IS_GLOBAL(sym)))
        {
            // bail out for ___fsadd and friends
            if (sym->cdef && !sym->used) continue;

            /* export or import non-static globals */
            if (!pic14_stringInSet(sym->rname, &emitted, 0)) {

                if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
                {
                    /* do not add to emitted set, it might occur again! */
                    //if (!sym->used) continue;
                    // declare symbol
                    emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
                } else {
                    // declare symbol
                    emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
                    if (!sym->ival && !IS_FUNC(sym->type)) {
                        // also define symbol
                        if (IS_ABSOLUTE(sym->etype)) {
                            // absolute location?
                            //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
                            // deferred to pic14_constructAbsMap
                        } else {
                            dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
                            dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
                        }
                    } // if
                } // if
                pic14_stringInSet(sym->rname, &emitted, 1);
            } // if
        } // if
        list = sym->ival;
        //if (list) showInitList(list, 0);
        if (list) {
            resolveIvalSym( list, sym->type );
            emitInitVal(ivalBuf, sym, sym->type, sym->ival);
            dbuf_printf (ivalBuf, "\n");
        }
    } // for sym
}
Example #27
0
/*-----------------------------------------------------------------*
 * void pCodeOptime2pCodes(pCode *pc1, pCode *pc2) 
 *
 * ADHOC pattern checking 
 * Now look for specific sequences that are easy to optimize.
 * Many of these sequences are characteristic of the compiler
 * (i.e. it'd probably be a waste of time to apply these adhoc
 * checks to hand written assembly.)
 * 
 *
 *-----------------------------------------------------------------*/
static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level)
{
  pCode *pct1, *pct2;
  regs  *reg1, *reg2;

  int t = total_registers_saved;

  if(reg->type == REG_SFR)return 0;

  if(pc2->seq < pc1->seq) {
    pct1 = pc2;
    pc2 = pc1;
    pc1 = pct1;
  }
/*
  fprintf(stderr,"pCodeOptime2pCodes\n");
  pc1->print(stderr,pc1);
  pc2->print(stderr,pc2);
*/
  if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){

    /*
      clrf  reg
      stuff...
      movf  reg,w

      can be replaced with

      stuff...
      movlw 0
    */

    pCode *newpc;
    //fprintf(stderr, "   CLRF/MOVFW. instruction after MOVFW is:\n");
    pct1 = pic16_findNextInstruction(pc2->next);

    if(PCI(pct1)->op == POC_MOVWF) {
      newpc = pic16_newpCode(POC_CLRF, PCI(pct1)->pcop);
      pct1->destruct(pct1);
    } else {
      newpc = pic16_newpCode(POC_MOVLW, pic16_newpCodeOpLit(0));
    }

    pic16_pCodeInsertAfter(pc2, newpc);
    PCI(newpc)->pcflow = PCFL(pcfl_used);
    newpc->seq = pc2->seq;

    /* take care if register is used after pc2, if yes, then don't delete
     * clrf reg, because, reg should be initialized with zero */
    {
      pCode *spc;
      int maxSeq=0;

        for(spc=setFirstItem(reg->reglives.usedpCodes);spc;spc=setNextItem(reg->reglives.usedpCodes)) {
          if(maxSeq < spc->seq)maxSeq = spc->seq;
        }

//        fprintf(stderr, "pc1->seq = %d\tpc2->seq = %d\tspc->seq = %d\n", pc1->seq, pc2->seq, maxSeq);

        if(maxSeq > pc2->seq) {
          /* this means that a pCode uses register after pc2, then
           * we can't delete pc1 pCode */
          Remove2pcodes(pcfl_used, NULL, pc2, reg, can_free);
        } else {
          /* we can remove both pCodes */
          Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
        }
    }
    total_registers_saved++;  // debugging stats.

  } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
    //fprintf(stderr, "   CLRF/IORFW.\n");

    pct2 = pic16_findNextInstruction(pc2->next);

    if(pic16_pCodeSearchCondition(pct2, PCC_Z) > 0) {
      pct2 = pic16_newpCode(POC_IORLW, pic16_newpCodeOpLit(0));
      pct2->seq = pc2->seq;
      PCI(pct2)->pcflow = PCFL(pcfl_used);
      pic16_pCodeInsertAfter(pc1,pct2);
    }
    Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
    total_registers_saved++;  // debugging stats.

  }  else if(PCI(pc1)->op == POC_MOVWF) {

    reg1 = pic16_getRegFromInstruction(pc1);

    if(reg1->type == REG_SFR)return (total_registers_saved != t);

    pct2 = pic16_findNextInstruction(pc2->next);

    if(PCI(pc2)->op == POC_MOVFW) {

#if 0
	fprintf(stderr, "   MOVWF/MOVFW. instruction after MOVFW is:\n");
	pct2->print(stderr,pct2);
#endif

      if(PCI(pct2)->op == POC_MOVWF) {
	/*
	  Change:

	    movwf   reg

	    stuff...

	    movf    reg,w
            movwf   reg2

	  To:

	    
	*/
	reg2 = pic16_getRegFromInstruction(pct2);
	if(reg2 && !regUsedinRange(pc1,pc2,reg2) && (reg2->type != REG_SFR)) {
//	if(reg2 && !regUsedinRange(pc1,pc2,reg2)) 

	  if(pic16_pCodeSearchCondition(pct2, PCC_Z) < 1) {
	    pCode *pct3 = pic16_findNextInstruction(pct2->next);
	    pct2->seq = pc1->seq;
	    pic16_unlinkpCode(pct2);
	    pic16_pCodeInsertAfter(pic16_findPrevInstruction(pc1->prev),pct2);

#define usesW(x)       ((x) && (isPCI(x)) && ( (PCI(x)->inCond & PCC_W) != 0))

	    if(usesW(pct3))
	      ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free);
	    else {
	      Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
	      total_registers_saved++;  // debugging stats.
	      return 1;
            }
          } else {
//            fprintf(stderr,"didn't optimize because Z bit is used\n");
	  }
	}
#if 0
	fprintf(stderr, " couldn't optimize\n");
	if(reg2)
	  fprintf(stderr, " %s is used in range\n", reg2->name);
	else
	  fprintf(stderr, " reg2 is NULL\n");
#endif
      }
    }

    pct1 = pic16_findPrevInstruction(pc1->prev);
    if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {

      if ( (PCI(pct1)->op == POC_MOVFW) &&
	   (PCI(pc2)->op == POC_MOVFW)) {

	reg1 = pic16_getRegFromInstruction(pct1);
	if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
	  
#if 0
	    fprintf(stderr, "   MOVF/MOVFW. \n");
	    fprintf(stderr, "     ...optimizing\n");
#endif

	  /*
	    Change:

	    movf   reg1,w
	    movwf  reg

	    stuff...
	    movf   reg,w

	    To:

	    stuff...

	    movf   reg1,w

	    Or, if we're not deleting the register then the "To" is:

	    stuff...

	    movf   reg1,w
	    movwf  reg


	  */
	  pct2 = pic16_newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
	  pic16_pCodeInsertAfter(pc2, pct2);
	  PCI(pct2)->pcflow = PCFL(pcfl_used);
	  pct2->seq = pc2->seq;

	  if(can_free) {
	    Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
	  } else {
	    /* If we're not freeing the register then that means (probably)
	     * the register is needed somewhere else.*/
	    pic16_unlinkpCode(pc1);
	    pic16_pCodeInsertAfter(pct2, pc1);

	    Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
	  }

	  Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
	  total_registers_saved++;  // debugging stats.

	}
      } else if ( (PCI(pct1)->op == POC_MOVWF) &&
	   (PCI(pc2)->op == POC_MOVFW)) {

//	   fprintf(stderr,"movwf MOVWF/MOVFW\n");

	if(optimize_level > 1 && can_free) {
	  pct2 = pic16_newpCode(POC_MOVFW, PCI(pc1)->pcop);
	  pic16_pCodeInsertAfter(pc2, pct2);
	  Remove2pcodes(pcfl_used, pc1, pc2, reg, 1);
	  total_registers_saved++;  // debugging stats.
	}
      }


    }

  }

  return (total_registers_saved != t);
}
Example #28
0
/*-----------------------------------------------------------------*
 * void RemoveRegsFromSet(set *regset)
 *
 *-----------------------------------------------------------------*/
static void  RemoveRegsFromSet(set *regset)
{
  regs *reg;
  int used;

  while(regset) {
    reg = regset->item;
    regset = regset->next;

    used = elementsInSet(reg->reglives.usedpCodes);

    if(used <= 1) {

//	fprintf(stderr," reg %s isfree=%d, wasused=%d\n",reg->name,reg->isFree,reg->wasUsed);

      if(used == 0) {

//  fprintf(stderr,"%s:%d: getting rid of reg %s\n",__FILE__, __LINE__, reg->name);

	reg->isFree = 1;
	reg->wasUsed = 0;
      } else {
	pCode *pc;


	pc = setFirstItem(reg->reglives.usedpCodes);

	if(reg->type == REG_SFR) {
		fprintf(stderr, "not removing SFR reg %s even though used only once\n", reg->name);
	  continue;
	}

	if(isPCI(pc)) {
	  if(PCI(pc)->label) {
	    pCode *pcn = pic16_findNextInstruction(pc->next);

	    if(pcn && PCI(pcn)->label) {
	      //fprintf(stderr,"can't delete instruction with label...\n");
	      //pc->print(stderr,pc);
	      continue;
	    } 
	    /* Move the label to the next instruction */

            assert (PCI(pcn) != NULL);
	    PCI(pcn)->label = PCI(pc)->label;

	  }

	  if(isPCI_SKIP(pc)) {
	    regs *r = pic16_getRegFromInstruction(pc);
	    fprintf(stderr, "WARNING, a skip instruction is being optimized out\n");
	    pc->print(stderr,pc);
	    fprintf(stderr,"reg %s, type =%d\n",r->name, r->type);
	  }

	  Remove1pcode(pc, reg);
	  /*
	    pic16_unlinkpCode(pc);
	    deleteSetItem (&(reg->reglives.usedpCodes),pc);
	  */
	  reg->isFree = 1;
	  reg->wasUsed = 0;
	  total_registers_saved++;  // debugging stats.
	}
      }
    }

  }
}
Example #29
0
/*-----------------------------------------------------------------*/
static void
pic14emitOverlay (struct dbuf_s * aBuf)
{
        set *ovrset;

        /*  if (!elementsInSet (ovrSetSets))*/

        /* the hack below, fixes translates for devices which
        * only have udata_shr memory */
        dbuf_printf (aBuf, "%s\t%s\n",
                (elementsInSet(ovrSetSets)?"":";"),
                port->mem.overlay_name);

        /* for each of the sets in the overlay segment do */
        for (ovrset = setFirstItem (ovrSetSets); ovrset;
        ovrset = setNextItem (ovrSetSets))
        {

                symbol *sym;

                if (elementsInSet (ovrset))
                {
                /* this dummy area is used to fool the assembler
                otherwise the assembler will append each of these
                declarations into one chunk and will not overlay
                        sad but true */

                        /* I don't think this applies to us. We are using gpasm.  CRF */

                        dbuf_printf (aBuf, ";\t.area _DUMMY\n");
                        /* output the area informtion */
                        dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);   /* MOF */
                }

                for (sym = setFirstItem (ovrset); sym;
                sym = setNextItem (ovrset))
                {

                        /* if extern then do nothing */
                        if (IS_EXTERN (sym->etype))
                                continue;

                                /* if allocation required check is needed
                                then check if the symbol really requires
                        allocation only for local variables */
                        if (!IS_AGGREGATE (sym->type) &&
                                !(sym->_isparm && !IS_REGPARM (sym->etype))
                                && !sym->allocreq && sym->level)
                                continue;

                                /* if global variable & not static or extern
                        and addPublics allowed then add it to the public set */
                        if ((sym->_isparm && !IS_REGPARM (sym->etype))
                                && !IS_STATIC (sym->etype))
                                addSetHead (&publics, sym);

                                /* if extern then do nothing or is a function
                        then do nothing */
                        if (IS_FUNC (sym->type))
                                continue;

                        /* print extra debug info if required */
                        if (options.debug || sym->level == 0)
                        {
                                if (!sym->level)
                                {               /* global */
                                        if (IS_STATIC (sym->etype))
                                                dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
                                        else
                                                dbuf_printf (aBuf, "G_");       /* scope is global */
                                }
                                else
                                        /* symbol is local */
                                        dbuf_printf (aBuf, "L%s_",
                                        (sym->localof ? sym->localof->name : "-null-"));
                                dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
                        }

                        /* if is has an absolute address then generate
                        an equate for this no need to allocate space */
                        if (SPEC_ABSA (sym->etype))
                        {

                                if (options.debug || sym->level == 0)
                                        dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));

                                dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
                                        sym->rname,
                                        SPEC_ADDR (sym->etype));
                        }
                        else
                        {
                                if (options.debug || sym->level == 0)
                                        dbuf_printf (aBuf, "==.\n");

                                /* allocate space */
                                dbuf_printf (aBuf, "%s:\n", sym->rname);
                                dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
                        }

                }
        }
}
Example #30
0
static void
pic14_constructAbsMap (struct dbuf_s *oBuf, struct dbuf_s *gloBuf)
{
  memmap *maps[] = { data, sfr, NULL };
  int i;
  hTab *ht = NULL;
  symbol *sym;
  set *aliases;
  int addr, min=-1, max=-1;
  int size;

  for (i=0; maps[i] != NULL; i++)
  {
    for (sym = (symbol *)setFirstItem (maps[i]->syms);
        sym; sym = setNextItem (maps[i]->syms))
    {
      if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
      {
        addr = SPEC_ADDR(sym->etype);

        /* handle CONFIG words here */
        if (IS_CONFIG_ADDRESS( addr ))
        {
          //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
          //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
          if (sym->ival) {
            pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
          } else {
            fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
          }
          continue;
        }

        if (max == -1 || addr > max) max = addr;
        if (min == -1 || addr < min) min = addr;
        //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
        aliases = hTabItemWithKey (ht, addr);
        if (aliases) {
          /* May not use addSetHead, as we cannot update the
           * list's head in the hastable `ht'. */
          addSet (&aliases, sym);
#if 0
          fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
              __FUNCTION__, elementsInSet(aliases), sym->name, addr);
#endif
        } else {
          addSet (&aliases, sym);
          hTabAddItem (&ht, addr, aliases);
        } // if
      } // if
    } // for sym
  } // for i

  /* now emit definitions for all absolute symbols */
  dbuf_printf (oBuf, "%s", iComments2);
  dbuf_printf (oBuf, "; absolute symbol definitions\n");
  dbuf_printf (oBuf, "%s", iComments2);
  for (addr=min; addr <= max; addr++)
  {
    size = 1;
    aliases = hTabItemWithKey (ht, addr);
    if (aliases && elementsInSet(aliases)) {
      /* Make sure there is no initialized value at this location! */
      for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) {
          if (sym->ival) break;
      } // for
      if (sym) continue;

      dbuf_printf (oBuf, "UD_abs_%s_%x\tudata_ovr\t0x%04x\n",
          moduleName, addr, addr);
      for (sym = setFirstItem (aliases); sym;
          sym = setNextItem (aliases))
      {
        if (getSize(sym->type) > size) {
          size = getSize(sym->type);
        }

        /* initialized values are handled somewhere else */
        if (sym->ival) continue;

        /* emit STATUS as well as _STATUS, required for SFRs only */
        //dbuf_printf (oBuf, "%s\tres\t0\n", sym->name);
        dbuf_printf (oBuf, "%s\n", sym->rname);

        if (IS_GLOBAL(sym) && !IS_STATIC(sym->etype)) {
            //emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->name);
            emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
        } // if
      } // for
      dbuf_printf (oBuf, "\tres\t%d\n", size);
    } // if
  } // for i
}