Beispiel #1
0
/*-----------------------------------------------------------------*/
static S4O_RET
termScanAtFunc (const lineNode *pl, int rIdx)
{
  sym_link *ftype;
  bool banked_reg = (rIdx == R0_IDX) || (rIdx == R1_IDX) || (rIdx == R2_IDX);

  if (!isFunc (pl))
    return S4O_CONTINUE;
  // let's assume calls to literally given locations use the default
  // most notably :  (*(void (*)()) 0) ();  see bug 1749275
  if (IS_VALOP (IC_LEFT (pl->ic)))
    return (options.model == MODEL_HUGE) && banked_reg ? S4O_ABORT : options.all_callee_saves ? S4O_CONTINUE : S4O_TERM;
  ftype = OP_SYM_TYPE(IC_LEFT(pl->ic));
  if (IS_FUNCPTR (ftype))
    ftype = ftype->next;
  if (IFFUNC_ISBANKEDCALL(ftype) && banked_reg)
    return S4O_ABORT;
  if (FUNC_ARGS (ftype) && getSize (FUNC_ARGS (ftype)->type) > 4)
    return S4O_ABORT;
  if (FUNC_CALLEESAVES(ftype))
    return S4O_CONTINUE;
  if (FUNC_ISNAKED(ftype))
    return S4O_CONTINUE;
  return S4O_TERM;
}
Beispiel #2
0
/*-----------------------------------------------------------------*/
eBBlock *
iCode2eBBlock (iCode * ic)
{
  iCode *loop;
  eBBlock *ebb = neweBBlock (); /* allocate an entry */

  /* put the first one unconditionally */
  ebb->sch = ic;
  ic->seq = 0;

  /* if this is a label then */
  if (ic->op == LABEL)
    ebb->entryLabel = ic->label;
  else
    {
      struct dbuf_s dbuf;

      dbuf_init (&dbuf, 128);
      dbuf_printf (&dbuf, "_eBBlock%d", eBBNum++);
      ebb->entryLabel = newSymbol (dbuf_c_str (&dbuf), 1);
      dbuf_destroy (&dbuf);
      ebb->entryLabel->key = labelKey++;
    }

  if (ic && (ic->op == GOTO || ic->op == JUMPTABLE || ic->op == IFX))
    {
      ebb->ech = ebb->sch;
      return ebb;
    }

  /* if this is a function call */
  if (ic->op == CALL || ic->op == PCALL)
    {
      sym_link *type = operandType (IC_LEFT (ic));
      ebb->hasFcall = 1;
      if (currFunc)
        FUNC_HASFCALL (currFunc->type) = 1;
      if (IS_FUNCPTR (type))
        type = type->next;
      if (type && FUNC_ISNORETURN (type))
        {
          ebb->ech = ebb->sch;
          return ebb;
        }
    }

  if ((ic->next && ic->next->op == LABEL) || !ic->next)
    {
      ebb->ech = ebb->sch;
      return ebb;
    }

  /* loop thru till we find one with a label */
  for (loop = ic->next; loop; loop = loop->next)
    {
      loop->seq = 0;

      /* if this is the last one */
      if (!loop->next)
        break;
      /* if this is a function call */
      if (loop->op == CALL || loop->op == PCALL)
        {
          sym_link *type = operandType (IC_LEFT (loop));
          ebb->hasFcall = 1;
          if (currFunc)
            FUNC_HASFCALL (currFunc->type) = 1;
          if (IS_FUNCPTR (type))
            type = type->next;
          if (type && FUNC_ISNORETURN (type))
            break;
        }

      /* if the next one is a label */
      /* if this is a goto or ifx */
      if (loop->next->op == LABEL || loop->op == GOTO || loop->op == JUMPTABLE || loop->op == IFX)
        break;
    }

  /* mark the end of the chain */
  ebb->ech = loop;

  return ebb;
}
Beispiel #3
0
/**
  Mark variables for assignment by the register allocator.
 */
static void
serialRegMark (eBBlock ** ebbs, int count)
{
  int i;
  short int max_alloc_bytes = SHRT_MAX; // Byte limit. Set this to a low value to pass only few variables to the register allocator. This can be useful for debugging.

  stm8_call_stack_size = 2; // Saving of register to stack temporarily.

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

      if (ebbs[i]->noPath && (ebbs[i]->entryLabel != entryLabel && ebbs[i]->entryLabel != returnLabel))
        continue;

      /* for all instructions do */
      for (ic = ebbs[i]->sch; ic; ic = ic->next)
        {
          if ((ic->op == CALL || ic->op == PCALL) && ic->parmBytes + 5 > stm8_call_stack_size)
            {
              sym_link *dtype = operandType (IC_LEFT (ic));
              sym_link *ftype = IS_FUNCPTR (dtype) ? dtype->next : dtype;

              /* 5 for saving all registers at call site + 2 for big return value */
              stm8_call_stack_size = ic->parmBytes + 5 + 2 * (getSize (ftype->next) > 4);
            }

          if (ic->op == IPOP)
            wassert (0);

          /* if result is present && is a true symbol */
          if (IC_RESULT (ic) && ic->op != IFX && IS_TRUE_SYMOP (IC_RESULT (ic)))
            OP_SYMBOL (IC_RESULT (ic))->allocreq++;

          /* some don't need registers, since there is no result. */
          if (SKIP_IC2 (ic) ||
              ic->op == JUMPTABLE || ic->op == IFX || ic->op == IPUSH || ic->op == IPOP || (IC_RESULT (ic) && POINTER_SET (ic)))
            continue;

          /* now we need to allocate registers only for the result */
          if (IC_RESULT (ic))
            {
              symbol *sym = OP_SYMBOL (IC_RESULT (ic));

              D (D_ALLOC, ("serialRegAssign: in loop on result %p\n", sym));

              if (sym->isspilt && sym->usl.spillLoc) // todo: Remove once remat is supported!
                {
                  sym->usl.spillLoc->allocreq--;
                  sym->isspilt = FALSE;
                }

              /* 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 marked for the new allocator
                 or will not live beyond this instructions */
              if (!sym->nRegs ||
                  sym->isspilt || sym->for_newralloc || sym->liveTo <= ic->seq)
                {
                  D (D_ALLOC, ("serialRegAssign: won't live long enough.\n"));
                  continue;
                }

              if (sym->nRegs > 4 && ic->op == CALL)
                {
                  spillThis (sym, TRUE);
                }
              else if (max_alloc_bytes >= sym->nRegs)
                {
                  sym->for_newralloc = 1;
                  max_alloc_bytes -= sym->nRegs;
                }
              else if (!sym->for_newralloc)
                {
                  spillThis (sym, TRUE);
                  printf ("Spilt %s due to byte limit.\n", sym->name);
                }
            }
        }
    }
}
Beispiel #4
0
/*-----------------------------------------------------------------*/
static void 
eBBSuccessors (ebbIndex * ebbi)
{
  eBBlock ** ebbs = ebbi->bbOrder;
  int count = ebbi->count;
  int i = 0;

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

      if (ebbs[i]->noPath)
	continue;

      ebbs[i]->succVect = newBitVect (count);

      /* if the next on exists & this one does not */
      /* end in a GOTO or RETURN then the next is  */
      /* a natural successor of this. Note we have */
      /* consider eBBlocks with no instructions    */
      if (ebbs[i + 1])
	{

	  if (ebbs[i]->ech)
	    {
              bool foundNoReturn = FALSE;
              if (ebbs[i]->ech->op == CALL || ebbs[i]->ech->op == PCALL)
                {
                  sym_link *type = operandType (IC_LEFT (ebbs[i]->ech));
                  if (IS_FUNCPTR (type))
                    type = type->next;
                  if (type && FUNC_ISNORETURN (type))
                    foundNoReturn = TRUE;
                }
	      if (!foundNoReturn &&
                 ebbs[i]->ech->op != GOTO &&
		  ebbs[i]->ech->op != RETURN &&
		  ebbs[i]->ech->op != JUMPTABLE)
		{
		  int j = i + 1;

		  while (ebbs[j] && ebbs[j]->noPath)
		    j++;

		  addSuccessor (ebbs[i], ebbs[j]);	/* add it */
		}
	      else
		{
		  if (i && ebbs[i-1]->ech && ebbs[i-1]->ech->op==IFX) {
		    ebbs[i]->isConditionalExitFrom=ebbs[i-1];
		  }
		}
	    }			/* no instructions in the block */
	  /* could happen for dummy blocks */
	  else
	    addSuccessor (ebbs[i], ebbs[i + 1]);
	}

      /* go thru all the instructions: if we find a */
      /* goto or ifx or a return then we have a succ */
      if ((ic = ebbs[i]->ech))
	{
	  eBBlock *succ;

	  /* special case for jumptable */
	  if (ic->op == JUMPTABLE)
	    {
	      symbol *lbl;
	      for (lbl = setFirstItem (IC_JTLABELS (ic)); lbl;
		   lbl = setNextItem (IC_JTLABELS (ic)))
		addSuccessor (ebbs[i],
			      eBBWithEntryLabel (ebbi, lbl));
	    }
	  else
	    {

	      succ = NULL;
	      /* depending on the instruction operator */
	      switch (ic->op)
		{
		case GOTO:	/* goto has edge to label */
		  succ = eBBWithEntryLabel (ebbi, ic->label);
		  break;

		case IFX:	/* conditional jump */
		  /* if true label is present */
		  if (IC_TRUE (ic))
		    succ = eBBWithEntryLabel (ebbi, IC_TRUE (ic));
		  else
		    succ = eBBWithEntryLabel (ebbi, IC_FALSE (ic));
		  break;

		case RETURN:	/* block with return */
		  succ = eBBWithEntryLabel (ebbi, returnLabel);
		  break;
		}

	      /* if there is a successor add to the list */
	      /* if it is not already present in the list */
	      if (succ)
		addSuccessor (ebbs[i], succ);
	    }
	}
    }
}