Beispiel #1
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;
            }
        }
    }
}
Beispiel #2
0
/*-----------------------------------------------------------------*/
iCode *
usedInRemaining (operand * op, iCode * ic)
{
  iCode *lic = ic;

  if (!IS_SYMOP (op))
    return 0;

  for (; lic; lic = lic->next)
    {

      /* if the operand is a parameter */
      /* then check for calls and return */
      /* true if there is a call       */
      /* if this is a global variable then 
         return true */
      if (lic->op == CALL || lic->op == PCALL)
	{

	  if ((IS_PARM (op) &&
	       isParameterToCall (IC_ARGS (lic), op)) ||
	      isOperandGlobal (op))
	    return lic;
	}

      if (ic->op == SEND &&
	  isOperandEqual (IC_LEFT (lic), op))
	return lic;

      if (SKIP_IC1 (lic))
	continue;

      /* if ifx then check the condition */
      if (lic->op == IFX &&
	  isOperandEqual (IC_COND (lic), op))
	return lic;

      if (lic->op == JUMPTABLE &&
	  isOperandEqual (IC_JTCOND (lic), op))
	return lic;

      if (IC_RIGHT (lic) &&
	  isOperandEqual (IC_RIGHT (lic), op))
	return lic;

      if (IC_LEFT (lic) &&
	  isOperandEqual (IC_LEFT (lic), op))
	return lic;

      /* for a pointer assignment usage */
      if (POINTER_SET (lic) &&
	  isOperandEqual (op, IC_RESULT (lic)))
	return lic;
      else if (IC_RESULT (lic) && isOperandEqual (IC_RESULT (lic), op))
	return NULL;
    }

  return NULL;
}
Beispiel #3
0
static bool
_hasNativeMulFor (iCode * ic, sym_link * left, sym_link * right)
{
  sym_link *test = NULL;
  int result_size = IS_SYMOP(IC_RESULT(ic)) ? getSize(OP_SYM_TYPE(IC_RESULT(ic))) : 4;

  if (ic->op != '*')
    {
      return FALSE;
    }

  if (IS_LITERAL (left))
    test = left;
  else if (IS_LITERAL (right))
    test = right;
  /* 8x8 unsigned multiplication code is shorter than
     call overhead for the multiplication routine. */
  else if (IS_CHAR (right) && IS_UNSIGNED (right) && IS_CHAR (left) && IS_UNSIGNED (left) && !IS_GB)
    {
      return TRUE;
    }
  /* Same for any multiplication with 8 bit result. */
  else if (result_size == 1 && !IS_GB)
    {
      return TRUE;
    }
  else
    {
      return FALSE;
    }

  if (getSize (test) <= 2)
    {
      return TRUE;
    }

  return FALSE;
}
Beispiel #4
0
/*--------------------------------------------------------------------*/
symbol *
ptrBaseRematSym (symbol *ptrsym)
{
  iCode * ric;
  
  if (!ptrsym->remat)
    return NULL;
  
  ric = ptrsym->rematiCode;
  while (ric)
    {
      if (ric->op == '+' || ric->op == '-')
        ric = OP_SYMBOL (IC_LEFT (ric))->rematiCode;
      else if (IS_CAST_ICODE (ric))
        ric = OP_SYMBOL (IC_RIGHT (ric))->rematiCode;
      else
        break;
    }
  
  if (ric && IS_SYMOP (IC_LEFT (ric)))
    return OP_SYMBOL (IC_LEFT (ric));
  else
    return NULL;
}
Beispiel #5
0
/*-----------------------------------------------------------------*/
static S4O_RET
scan4op (lineNode **pl, const char *pReg, const char *untilOp,
         lineNode **plCond)
{
  char *p;
  int len;
  bool isConditionalJump;
  int rIdx;
  S4O_RET ret;
  bool findPushPop;

  findPushPop = untilOp && (strcmp (untilOp, "push") == 0 || strcmp (untilOp, "pop") == 0);

  /* pReg points to e.g. "ar0"..."ar7" */
  len = strlen (pReg);

  /* get index into pReg table */
  for (rIdx = 0; rIdx < mcs51_nRegs; ++rIdx)
    if (strcmp (regs8051[rIdx].name, pReg + 1) == 0)
      break;

  /* sanity check */
  if (rIdx >= mcs51_nRegs)
    {
      DEADMOVEERROR();
      return S4O_ABORT;
    }

  for (; *pl; *pl = (*pl)->next)
    {
      if (!(*pl)->line || (*pl)->isDebug || (*pl)->isComment)
        continue;

      /* don't optimize across inline assembler,
         e.g. isLabel doesn't work there */
      if ((*pl)->isInline)
        return S4O_ABORT;

      if ((*pl)->visited)
        return S4O_VISITED;
      (*pl)->visited = TRUE;

      /* found untilOp? */
      if (untilOp && strncmp ((*pl)->line, untilOp, strlen (untilOp)) == 0)
        {
          p = (*pl)->line + strlen (untilOp);
          if (*p == '\t' && strncmp (p + 1, pReg, len) == 0)
            return S4O_FOUNDOPCODE;
          else
            {
              /* found untilOp but without our pReg */
              return S4O_ABORT;
            }
        }

      /* found pReg? */
      p = strchr ((*pl)->line, '\t');
      if (p)
        {
          /* skip '\t' */
          p++;

          /* when looking for push or pop and we find a direct access of sp: abort */
          if (findPushPop && strstr (p, "sp"))
            return S4O_ABORT;

          /* course search */
          if (strstr (p, pReg + 1))
            {
              /* ok, let's have a closer look */

              /* does opcode read from pReg? */
              if (bitVectBitValue (port->peep.getRegsRead ((*pl)), rIdx))
                return S4O_RD_OP;
              /* does opcode write to pReg? */
              if (bitVectBitValue (port->peep.getRegsWritten ((*pl)), rIdx))
                return S4O_WR_OP;

              /* we can get here, if the register name is
                 part of a variable name: ignore it */
            }
        }

      /* found label? */
      if ((*pl)->isLabel)
        {
          const char *start;
          char label[SDCC_NAME_MAX + 1];
          int len;

          if (!isLabelDefinition ((*pl)->line, &start, &len, FALSE))
            return S4O_ABORT;
          memcpy (label, start, len);
          label[len] = '\0';
          /* register passing this label */
          if (!setLabelRefPassedLabel (label))
            {
              DEADMOVEERROR();
              return S4O_ABORT;
            }
          continue;
        }

      /* branch or terminate? */
      isConditionalJump = FALSE;
      switch ((*pl)->line[0])
        {
          case 'a':
            if (strncmp ("acall", (*pl)->line, 5) == 0)
              {
                /* for comments see 'lcall' */
                ret = termScanAtFunc (*pl, rIdx);
                if (ret != S4O_CONTINUE)
                  return ret;
                break;
              }
            if (strncmp ("ajmp", (*pl)->line, 4) == 0)
              {
                *pl = findLabel (*pl);
                if (!*pl)
                  return S4O_ABORT;
              }
            break;
          case 'c':
            if (strncmp ("cjne", (*pl)->line, 4) == 0)
              {
                isConditionalJump = TRUE;
                break;
              }
            break;
          case 'd':
            if (strncmp ("djnz", (*pl)->line, 4) == 0)
              {
                isConditionalJump = TRUE;
                break;
              }
            break;
          case 'j':
            if (strncmp ("jmp", (*pl)->line, 3) == 0)
              /* "jmp @a+dptr": no chance to trace execution */
              return S4O_ABORT;
            if (strncmp ("jc",  (*pl)->line, 2) == 0 ||
                strncmp ("jnc", (*pl)->line, 3) == 0 ||
                strncmp ("jz",  (*pl)->line, 2) == 0 ||
                strncmp ("jnz", (*pl)->line, 3) == 0)
              {
                isConditionalJump = TRUE;
                break;
              }
            if (strncmp ("jbc", (*pl)->line, 3) == 0 ||
                strncmp ("jb",  (*pl)->line, 2) == 0 ||
                strncmp ("jnb", (*pl)->line, 3) == 0)
              {
                isConditionalJump = TRUE;
                break;
              }
            break;
          case 'l':
            if (strncmp ("lcall", (*pl)->line, 5) == 0)
              {
                const char *p = (*pl)->line+5;
                while (*p == ' ' || *p == '\t')
                  p++;
                while (isdigit (*p))
                  p++;
                if (isdigit(p[-1]) && *p == '$') /* at least one digit */
                  {
                    /* this is a temp label for a pcall */
                    *pl = findLabel (*pl);
                    if (!*pl)
                      return S4O_ABORT;
                    break;
                  }

                ret = termScanAtFunc (*pl, rIdx);
                /* If it's a 'normal' 'caller save' function call, all
                   registers have been saved until the 'lcall'. The
                   'life range' of all registers end at the lcall,
                   and we can terminate our search.
                 * If the function is 'banked', the registers r0, r1 and r2
                   are used to tell the trampoline the destination. After
                   that their 'life range' ends just like the other registers.
                 * If it's a 'callee save' function call, registers are saved
                   by the callee. We've got no information, if the register
                   might live beyond the lcall. Therefore we've to continue
                   the search.
                */
                if (ret != S4O_CONTINUE)
                  return ret;
                break;
              }
            if (strncmp ("ljmp", (*pl)->line, 4) == 0)
              {
                *pl = findLabel (*pl);
                if (!*pl)
                  return S4O_ABORT;
              }
            break;
          case 'p':
            if (strncmp ("pop", (*pl)->line, 3) == 0 ||
                strncmp ("push", (*pl)->line, 4) == 0)
              return S4O_PUSHPOP;
            break;
          case 'r':
            if (strncmp ("reti", (*pl)->line, 4) == 0)
              return S4O_TERM;

            if (strncmp ("ret", (*pl)->line, 3) == 0)
              {
                /* pcall uses 'ret' */
                if (isFunc (*pl))
                  {
                    /* for comments see 'lcall' */
                    ret = termScanAtFunc (*pl, rIdx);
                    if (ret != S4O_CONTINUE)
                      return ret;
                    break;
                  }

                /* it's a normal function return */
                if (!((*pl)->ic) || (IS_SYMOP (IC_LEFT ((*pl)->ic)) &&
                    IS_FUNC (OP_SYM_TYPE(IC_LEFT ((*pl)->ic))) &&
                    FUNC_CALLEESAVES (OP_SYM_TYPE(IC_LEFT ((*pl)->ic)))))
                  return S4O_ABORT;
                else
                  return S4O_TERM;
              }
            break;
          case 's':
            if (strncmp ("sjmp", (*pl)->line, 4) == 0)
              {
                *pl = findLabel (*pl);
                if (!*pl)
                  return S4O_ABORT;
              }
            break;
          default:
            break;
        } /* switch ((*pl)->line[0]) */

      if (isConditionalJump)
        {
          *plCond = findLabel (*pl);
          if (!*plCond)
            return S4O_ABORT;
          return S4O_CONDJMP;
        }
    } /* for (; *pl; *pl = (*pl)->next) */
  return S4O_ABORT;
}
Beispiel #6
0
/*
 * Actually emit the initial values in .asm format.
 */
static void
emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
{
    int i;
    ast *node;
    operand *op;
    value *val = NULL;
    int inCodeSpace = 0;
    char *str = NULL;
    int in_code;

    assert (size <= sizeof(long));
    assert (!list || (list->type == INIT_NODE));
    node = list ? list->init.node : NULL;

    in_code = emitIvalLabel(oBuf, sym);
    if (!in_code)
        dbuf_printf (oBuf, "\tdb\t");

    if (!node) {
        // initialize as zero
        for (i = 0; i < size; i++) {
            if (in_code) {
                dbuf_printf (oBuf, "\tretlw 0x%02x\n", lit & 0xff);
            } else {
                dbuf_printf (oBuf, "%s0x%02x", (i == 0) ? "" : ", ", lit & 0xff);
            }
            lit >>= 8;
        } // for
        if (!in_code)
            dbuf_printf (oBuf, "\n");
        return;
    } // if

    op = NULL;
    if (constExprTree(node) && (val = constExprValue(node, 0))) {
        op = operandFromValue(val);
        DEBUGprintf ("%s: constExpr ", __FUNCTION__);
    } else if (IS_AST_VALUE(node)) {
        op = operandFromAst(node, 0);
    } else if (IS_AST_OP(node)) {
        str = parseIvalAst(node, &inCodeSpace);
        DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
        op = NULL;
    } else {
        assert ( !"Unhandled construct in intializer." );
    }

    if (op) {
        aopOp(op, NULL, 1);
        assert(AOP(op));
        //printOperand(op, of);
    }

    for (i = 0; i < size; i++) {
        char *text;

        /*
         * FIXME: This is hacky and needs some more thought.
         */
        if (op && IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) {
            /* This branch is introduced to fix #1427663. */
            PCOI(AOP(op)->aopu.pcop)->offset+=i;
            text = get_op(AOP(op)->aopu.pcop, NULL, 0);
            PCOI(AOP(op)->aopu.pcop)->offset-=i;
        } else {
            text = op ? aopGet(AOP(op), i, 0, 0)
                : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
        } // if
        if (in_code) {
            dbuf_printf (oBuf, "\tretlw %s\n", text);
        } else {
            dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
        }
    } // for
    if (!in_code)
        dbuf_printf (oBuf, "\n");
}
Beispiel #7
0
/*-----------------------------------------------------------------*/
int 
killDeadCode (eBBlock ** ebbs, int count)
{
  int change = 1;
  int gchange = 0;
  int i = 0;


  /* basic algorithm :-                                          */
  /* first the exclusion rules :-                                */
  /*  1. if result is a global or volatile then skip             */
  /*  2. if assignment and result is a temp & isaddr  then skip  */
  /*     since this means array & pointer access, will be taken  */
  /*     care of by alias analysis.                              */
  /*  3. if the result is used in the remainder of the block skip */
  /*  4. if this definition does not reach the end of the block  */
  /*     i.e. the result is not present in the outExprs then KILL */
  /*  5. if it reaches the end of block & is used by some success */
  /*     or then skip                                            */
  /*     else            KILL                                    */
  /* this whole process is carried on iteratively till no change */
  while (1)
    {

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

	  /* for all instructions in the block do */
	  for (ic = ebbs[i]->sch; ic; ic = ic->next)
	    {
	      int kill, j;
	      kill = 0;

	      if (SKIP_IC (ic) ||
		  ic->op == IFX ||
		  ic->op == RETURN)
		continue;

	      /* if the result is volatile then continue */
	      if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE))
		continue;

	      /* if the result is a temp & isaddr then skip */
	      if (IC_RESULT (ic) && POINTER_SET (ic))
		continue;

	      /* if the result is used in the remainder of the */
	      /* block then skip */
	      if (usedInRemaining (IC_RESULT (ic), ic->next))
		continue;

	      /* does this definition reach the end of the block 
	         or the usage is zero then we can kill */
	      if (!bitVectBitValue (ebbs[i]->outDefs, ic->key))
		kill = 1;	/* if not we can kill it */
	      else
		{
		  /* if this is a global variable or function parameter */
		  /* we cannot kill anyway             */
		  if (isOperandGlobal (IC_RESULT (ic)) ||
		      (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
		       !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
		    continue;

		  /* if we are sure there are no usages */
		  if (bitVectIsZero (OP_USES (IC_RESULT (ic))))
		    {
		      kill = 1;
		      goto kill;
		    }

		  /* reset visited flag */
		  for (j = 0; j < count; ebbs[j++]->visited = 0);

		  /* find out if this definition is alive */
		  if (applyToSet (ebbs[i]->succList,
				  isDefAlive,
				  ic))
		    continue;

		  kill = 1;
		}

	    kill:
	      /* kill this one if required */
	      if (kill)
		{
		  change = 1;
		  gchange++;
		  /* eliminate this */
		  remiCodeFromeBBlock (ebbs[i], ic);

		  /* now delete from defUseSet */
		  deleteItemIf (&ebbs[i]->outExprs, ifDiCodeIsX, ic);
		  bitVectUnSetBit (ebbs[i]->outDefs, ic->key);

		  /* and defset of the block */
		  bitVectUnSetBit (ebbs[i]->defSet, ic->key);

		  /* for the left & right remove the usage */
		  if (IS_SYMOP (IC_LEFT (ic)))
		    bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);

		  if (IS_SYMOP (IC_RIGHT (ic)))
		    bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
		}

	    }			/* end of all instructions */

	  if (!ebbs[i]->sch && !ebbs[i]->noPath)
	    disconBBlock (ebbs[i], ebbs, count);

	}			/* end of for all blocks */

      if (!change)
	break;
    }				/* end of while(1) */

  return gchange;
}
Beispiel #8
0
/*-----------------------------------------------------------------*/
static void
computeClash (eBBlock ** ebbs, int count)
{
  int i;

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

      /* for every iCode do */
      for (ic = ebbs[i]->sch; ic; ic = ic->next)
	{
	  symbol *sym1, *sym2;
	  int key1, key2;

	  /* for all iTemps alive at this iCode */
	  for (key1 = 1; key1 < ic->rlive->size; key1++)
	    {
	      if (!bitVectBitValue(ic->rlive, key1))
	        continue;

	      sym1 = hTabItemWithKey(liveRanges, key1);

	      if (!sym1->isitmp)
	        continue;

	      /* for all other iTemps alive at this iCode */
	      for (key2 = key1+1; key2 < ic->rlive->size; key2++)
	        {
		  if (!bitVectBitValue(ic->rlive, key2))
		    continue;

		  sym2 = hTabItemWithKey(liveRanges, key2);

		  if (!sym2->isitmp)
		    continue;

		  /* if the result and left or right is an iTemp */
		  /* than possibly the iTemps do not clash */
		  if ((ic->op != JUMPTABLE) && (ic->op != IFX) &&
		      IS_ITEMP(IC_RESULT(ic)) &&
		      (IS_ITEMP(IC_LEFT(ic)) || IS_ITEMP(IC_RIGHT(ic))))
		    {
		      if (OP_SYMBOL(IC_RESULT(ic))->key == key1
			  && sym1->liveFrom == ic->seq
			  && sym2->liveTo == ic->seq)
		        {
		          if (IS_SYMOP(IC_LEFT(ic)))
			    if (OP_SYMBOL(IC_LEFT(ic))->key == key2)
			      continue;
		          if (IS_SYMOP(IC_RIGHT(ic)))
			    if (OP_SYMBOL(IC_RIGHT(ic))->key == key2)
			      continue;
			}

		      if (OP_SYMBOL(IC_RESULT(ic))->key == key2
			  && sym2->liveFrom == ic->seq
			  && sym1->liveTo == ic->seq)
		        {
		          if (IS_SYMOP(IC_LEFT(ic)))
			    if (OP_SYMBOL(IC_LEFT(ic))->key == key1)
			      continue;
		          if (IS_SYMOP(IC_RIGHT(ic)))
			    if (OP_SYMBOL(IC_RIGHT(ic))->key == key1)
			      continue;
			}
		    }

		  /* the iTemps do clash. set the bits in clashes */
		  sym1->clashes = bitVectSetBit (sym1->clashes, key2);
		  sym2->clashes = bitVectSetBit (sym2->clashes, key1);

		  /* check if they share the same spill location */
		  /* what is this good for? */
	          if (SYM_SPIL_LOC(sym1) && SYM_SPIL_LOC(sym2) &&
		      SYM_SPIL_LOC(sym1) == SYM_SPIL_LOC(sym2))
		    {
		      if (sym1->reqv && !sym2->reqv) SYM_SPIL_LOC(sym2)=NULL;
		      else if (sym2->reqv && !sym1->reqv) SYM_SPIL_LOC(sym1)=NULL;
		      else if (sym1->used > sym2->used) SYM_SPIL_LOC(sym2)=NULL;
		      else SYM_SPIL_LOC(sym1)=NULL;
		    }
		}
	    }
	}
    }
}
Beispiel #9
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));
	}

    }
}
Beispiel #10
0
/** Register reduction for assignment.
 */
static int
packRegsForAssign (iCode *ic, eBBlock *ebp)
{
  iCode *dic, *sic;

  if (!IS_ITEMP (IC_RIGHT (ic)) || OP_SYMBOL (IC_RIGHT (ic))->isind || OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
    return 0;
  
  /* Avoid having multiple named address spaces in one iCode. */
  if (IS_SYMOP (IC_RESULT (ic)) && SPEC_ADDRSPACE (OP_SYMBOL (IC_RESULT (ic))->etype))
    return 0;

  /* find the definition of iTempNN scanning backwards if we find a
     a use of the true symbol in before we find the definition then
     we cannot */
  for (dic = ic->prev; dic; dic = dic->prev)
    {
      /* PENDING: Don't pack across function calls. */
      if (dic->op == CALL || dic->op == PCALL)
        {
          dic = NULL;
          break;
        }

      if (SKIP_IC2 (dic))
        continue;

      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_RESULT (dic)) && IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
            {
              if (POINTER_SET (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_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 || OP_SYMBOL (IC_RESULT (ic))->iaccess)
    {
      /* the operation has only one symbol
         operator then we can pack */
      if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) || (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
        goto pack;

      if (!((IC_LEFT (dic) &&
             IC_RESULT (ic)->key == IC_LEFT (dic)->key) || (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
        return 0;
    }
pack:
  /* found the definition */
  /* replace the result with the result of */
  /* this assignment and remove this assignment */
  bitVectUnSetBit (OP_SYMBOL (IC_RESULT (dic))->defs, dic->key);
  IC_RESULT (dic) = IC_RESULT (ic);

  if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
    {
      OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
    }
  /* delete from liverange table also
     delete from all the points inbetween and the new
     one */
  for (sic = dic; sic != ic; sic = sic->next)
    {
      bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
      if (IS_ITEMP (IC_RESULT (dic)))
        bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
    }

  remiCodeFromeBBlock (ebp, ic);
  // 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);
  return 1;
}
Beispiel #11
0
/*--------------------------------------------------------------------*/
int
ptrPseudoSymSafe (symbol *sym, iCode *dic)
{
  symbol * ptrsym;
  symbol * basesym;
  iCode * ric;
  iCode * ic;
  int ptrsymDclType;
  //int isGlobal;
  
  assert(POINTER_GET (dic));

  /* Can't if spills to this symbol are prohibited */
  if (sym->noSpilLoc)
    return 0;
  
  /* Get the pointer */
  if (!IS_SYMOP (IC_LEFT (dic)))
    return 0;
  ptrsym = OP_SYMBOL (IC_LEFT (dic));
  
  /* Must be a rematerializable pointer */
  if (!ptrsym->remat)
    return 0;
  
  /* The pointer type must be uncasted */
  if (IS_CAST_ICODE (ptrsym->rematiCode))
    return 0;
  
  /* The symbol's live range must not preceed its definition */
  if (dic->seq > sym->liveFrom)
    return 0;
        
  /* Ok, this is a good candidate for a pseudo symbol.      */
  /* However, we must check for two hazards:                */
  /*   1) The symbol's live range must not include a CALL   */
  /*      or PCALL iCode.                                   */
  /*   2) The symbol's live range must not include any      */
  /*      writes to the variable the pointer rematerializes */
  /*      within (to avoid aliasing problems)               */
  
  /* Find the base symbol the rematerialization is based on */
  ric = ptrsym->rematiCode;
  while (ric->op == '+' || ric->op == '-')
    ric = OP_SYMBOL (IC_LEFT (ric))->rematiCode;
  if (IS_CAST_ICODE(ric))
    return 0;
  basesym = OP_SYMBOL (IC_LEFT (ric));

  //isGlobal = !basesym->islocal && !basesym->ismyparm;
  ptrsymDclType = aggrToPtrDclType (ptrsym->type, FALSE);

  ic = dic->next;
  while (ic && ic->seq <= sym->liveTo)
    {
      if (!(SKIP_IC3 (ic) || ic->op == IFX))
        {
          /* Check for hazard #1 */
          if ((ic->op == CALL || ic->op == PCALL) /* && isGlobal */ )
            {
              if (ic->seq <= sym->liveTo)
                return 0;
            }
          /* Check for hazard #2 */
          else if (POINTER_SET (ic))
            {
              symbol * ptrsym2 = OP_SYMBOL (IC_RESULT (ic));
          
              if (ptrsym2->remat)
                {
                  /* Must not be the same base symbol */
                  if (basesym == ptrBaseRematSym (ptrsym2))
                    return 0;
                }
              else
                {
                  int ptrsym2DclType = aggrToPtrDclType (ptrsym2->type, FALSE);

                  /* Pointer must have no memory space in common */
                  if (ptrsym2DclType == ptrsymDclType
                      || ptrsym2DclType == GPOINTER
                      || ptrsymDclType == GPOINTER)
                    return 0;
                }
            }
          else if (IC_RESULT (ic))
            {
              symbol * rsym = OP_SYMBOL (IC_RESULT (ic));
          
              /* Make sure there is no conflict with another pseudo symbol */
              if (rsym->psbase == basesym)
                return 0;
              if (rsym->isspilt && rsym->usl.spillLoc)
                rsym = rsym->usl.spillLoc;
              if (rsym->psbase == basesym)
                return 0;
            }
        }
        
      if (ic->seq == sym->liveTo)
         break;
      ic = ic->next;
    }

  /* If the live range went past the end of the defining basic */
  /* block, then a full analysis is too complicated to attempt */
  /* here. To be safe, we must assume the worst.               */
  if (!ic)
    return 0;
    
  /* Ok, looks safe */
  return 1;
}