⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fold-const.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
  return fold (build (code, sizetype, arg0, arg1));}/* Given T, a tree representing type conversion of ARG1, a constant,   return a constant tree representing the result of conversion.  */static treefold_convert (t, arg1)     register tree t;     register tree arg1;{  register tree type = TREE_TYPE (t);  int overflow = 0;  if (TREE_CODE (type) == POINTER_TYPE || INTEGRAL_TYPE_P (type))    {      if (TREE_CODE (arg1) == INTEGER_CST)	{	  /* If we would build a constant wider than GCC supports,	     leave the conversion unfolded.  */	  if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)	    return t;	  /* Given an integer constant, make new constant with new type,	     appropriately sign-extended or truncated.  */	  t = build_int_2 (TREE_INT_CST_LOW (arg1),			   TREE_INT_CST_HIGH (arg1));	  TREE_TYPE (t) = type;	  /* Indicate an overflow if (1) ARG1 already overflowed,	     or (2) force_fit_type indicates an overflow.	     Tell force_fit_type that an overflow has already occurred	     if ARG1 is a too-large unsigned value and T is signed.  */	  TREE_OVERFLOW (t)	    = (TREE_OVERFLOW (arg1)	       | force_fit_type (t,				 (TREE_INT_CST_HIGH (arg1) < 0				  & (TREE_UNSIGNED (type)				     < TREE_UNSIGNED (TREE_TYPE (arg1))))));	  TREE_CONSTANT_OVERFLOW (t)	    = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);	}#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)      else if (TREE_CODE (arg1) == REAL_CST)	{	  /* Don't initialize these, use assignments.	     Initialized local aggregates don't work on old compilers.  */	  REAL_VALUE_TYPE x;	  REAL_VALUE_TYPE l;	  REAL_VALUE_TYPE u;	  x = TREE_REAL_CST (arg1);	  l = real_value_from_int_cst (TYPE_MIN_VALUE (type));	  u = real_value_from_int_cst (TYPE_MAX_VALUE (type));	  /* See if X will be in range after truncation towards 0.	     To compensate for truncation, move the bounds away from 0,	     but reject if X exactly equals the adjusted bounds.  */#ifdef REAL_ARITHMETIC	  REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);	  REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);#else	  l--;	  u++;#endif	  /* If X is a NaN, use zero instead and show we have an overflow.	     Otherwise, range check.  */	  if (REAL_VALUE_ISNAN (x))	    overflow = 1, x = dconst0;	  else if (! (REAL_VALUES_LESS (l, x) && REAL_VALUES_LESS (x, u)))	    overflow = 1;#ifndef REAL_ARITHMETIC	  {	    HOST_WIDE_INT low, high;	    HOST_WIDE_INT half_word	      = (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2);	    if (x < 0)	      x = -x;	    high = (HOST_WIDE_INT) (x / half_word / half_word);	    x -= (REAL_VALUE_TYPE) high * half_word * half_word;	    if (x >= (REAL_VALUE_TYPE) half_word * half_word / 2)	      {		low = x - (REAL_VALUE_TYPE) half_word * half_word / 2;		low |= (HOST_WIDE_INT) -1 << (HOST_BITS_PER_WIDE_INT - 1);	      }	    else	      low = (HOST_WIDE_INT) x;	    if (TREE_REAL_CST (arg1) < 0)	      neg_double (low, high, &low, &high);	    t = build_int_2 (low, high);	  }#else	  {	    HOST_WIDE_INT low, high;	    REAL_VALUE_TO_INT (&low, &high, x);	    t = build_int_2 (low, high);	  }#endif	  TREE_TYPE (t) = type;	  TREE_OVERFLOW (t)	    = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);	  TREE_CONSTANT_OVERFLOW (t)	    = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);	}#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */      TREE_TYPE (t) = type;    }  else if (TREE_CODE (type) == REAL_TYPE)    {#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)      if (TREE_CODE (arg1) == INTEGER_CST)	return build_real_from_int_cst (type, arg1);#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */      if (TREE_CODE (arg1) == REAL_CST)	{	  if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))	    return arg1;	  else if (setjmp (float_error))	    {	      overflow = 1;	      t = copy_node (arg1);	      goto got_it;	    }	  set_float_handler (float_error);	  t = build_real (type, real_value_truncate (TYPE_MODE (type),						     TREE_REAL_CST (arg1)));	  set_float_handler (NULL_PTR);	got_it:	  TREE_OVERFLOW (t)	    = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);	  TREE_CONSTANT_OVERFLOW (t)	    = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);	  return t;	}    }  TREE_CONSTANT (t) = 1;  return t;}/* Return an expr equal to X but certainly not valid as an lvalue.   Also make sure it is not valid as an null pointer constant.  */treenon_lvalue (x)     tree x;{  tree result;  /* These things are certainly not lvalues.  */  if (TREE_CODE (x) == NON_LVALUE_EXPR      || TREE_CODE (x) == INTEGER_CST      || TREE_CODE (x) == REAL_CST      || TREE_CODE (x) == STRING_CST      || TREE_CODE (x) == ADDR_EXPR)    {      if (TREE_CODE (x) == INTEGER_CST && integer_zerop (x))	{	  /* Use NOP_EXPR instead of NON_LVALUE_EXPR	     so convert_for_assignment won't strip it.	     This is so this 0 won't be treated as a null pointer constant.  */	  result = build1 (NOP_EXPR, TREE_TYPE (x), x);	  TREE_CONSTANT (result) = TREE_CONSTANT (x);	  return result;	}      return x;    }  result = build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);  TREE_CONSTANT (result) = TREE_CONSTANT (x);  return result;}/* Nonzero means lvalues are limited to those valid in pedantic ANSI C.   Zero means allow extended lvalues.  */int pedantic_lvalues;/* When pedantic, return an expr equal to X but certainly not valid as a   pedantic lvalue.  Otherwise, return X.  */treepedantic_non_lvalue (x)     tree x;{  if (pedantic_lvalues)    return non_lvalue (x);  else    return x;}/* Given a tree comparison code, return the code that is the logical inverse   of the given code.  It is not safe to do this for floating-point   comparisons, except for NE_EXPR and EQ_EXPR.  */static enum tree_codeinvert_tree_comparison (code)     enum tree_code code;{  switch (code)    {    case EQ_EXPR:      return NE_EXPR;    case NE_EXPR:      return EQ_EXPR;    case GT_EXPR:      return LE_EXPR;    case GE_EXPR:      return LT_EXPR;    case LT_EXPR:      return GE_EXPR;    case LE_EXPR:      return GT_EXPR;    default:      abort ();    }}/* Similar, but return the comparison that results if the operands are   swapped.  This is safe for floating-point.  */static enum tree_codeswap_tree_comparison (code)     enum tree_code code;{  switch (code)    {    case EQ_EXPR:    case NE_EXPR:      return code;    case GT_EXPR:      return LT_EXPR;    case GE_EXPR:      return LE_EXPR;    case LT_EXPR:      return GT_EXPR;    case LE_EXPR:      return GE_EXPR;    default:      abort ();    }}/* Return nonzero if CODE is a tree code that represents a truth value.  */static inttruth_value_p (code)     enum tree_code code;{  return (TREE_CODE_CLASS (code) == '<'	  || code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR	  || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR	  || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR);}/* Return nonzero if two operands are necessarily equal.   If ONLY_CONST is non-zero, only return non-zero for constants.   This function tests whether the operands are indistinguishable;   it does not test whether they are equal using C's == operation.   The distinction is important for IEEE floating point, because   (1) -0.0 and 0.0 are distinguishable, but -0.0==0.0, and   (2) two NaNs may be indistinguishable, but NaN!=NaN.  */intoperand_equal_p (arg0, arg1, only_const)     tree arg0, arg1;     int only_const;{  /* If both types don't have the same signedness, then we can't consider     them equal.  We must check this before the STRIP_NOPS calls     because they may change the signedness of the arguments.  */  if (TREE_UNSIGNED (TREE_TYPE (arg0)) != TREE_UNSIGNED (TREE_TYPE (arg1)))    return 0;  STRIP_NOPS (arg0);  STRIP_NOPS (arg1);  /* If ARG0 and ARG1 are the same SAVE_EXPR, they are necessarily equal.     We don't care about side effects in that case because the SAVE_EXPR     takes care of that for us.  */  if (TREE_CODE (arg0) == SAVE_EXPR && arg0 == arg1)    return ! only_const;  if (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1))    return 0;  if (TREE_CODE (arg0) == TREE_CODE (arg1)      && TREE_CODE (arg0) == ADDR_EXPR      && TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0))    return 1;  if (TREE_CODE (arg0) == TREE_CODE (arg1)      && TREE_CODE (arg0) == INTEGER_CST      && TREE_INT_CST_LOW (arg0) == TREE_INT_CST_LOW (arg1)      && TREE_INT_CST_HIGH (arg0) == TREE_INT_CST_HIGH (arg1))    return 1;  /* Detect when real constants are equal.  */  if (TREE_CODE (arg0) == TREE_CODE (arg1)      && TREE_CODE (arg0) == REAL_CST)    return !bcmp ((char *) &TREE_REAL_CST (arg0),		  (char *) &TREE_REAL_CST (arg1),		  sizeof (REAL_VALUE_TYPE));  if (only_const)    return 0;  if (arg0 == arg1)    return 1;  if (TREE_CODE (arg0) != TREE_CODE (arg1))    return 0;  /* This is needed for conversions and for COMPONENT_REF.     Might as well play it safe and always test this.  */  if (TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1)))    return 0;  switch (TREE_CODE_CLASS (TREE_CODE (arg0)))    {    case '1':      /* Two conversions are equal only if signedness and modes match.  */      if ((TREE_CODE (arg0) == NOP_EXPR || TREE_CODE (arg0) == CONVERT_EXPR)	  && (TREE_UNSIGNED (TREE_TYPE (arg0))	      != TREE_UNSIGNED (TREE_TYPE (arg1))))	return 0;      return operand_equal_p (TREE_OPERAND (arg0, 0),			      TREE_OPERAND (arg1, 0), 0);    case '<':    case '2':      return (operand_equal_p (TREE_OPERAND (arg0, 0),			       TREE_OPERAND (arg1, 0), 0)	      && operand_equal_p (TREE_OPERAND (arg0, 1),				  TREE_OPERAND (arg1, 1), 0));    case 'r':      switch (TREE_CODE (arg0))	{	case INDIRECT_REF:	  return operand_equal_p (TREE_OPERAND (arg0, 0),				  TREE_OPERAND (arg1, 0), 0);	case COMPONENT_REF:	case ARRAY_REF:	  return (operand_equal_p (TREE_OPERAND (arg0, 0),				   TREE_OPERAND (arg1, 0), 0)		  && operand_equal_p (TREE_OPERAND (arg0, 1),				      TREE_OPERAND (arg1, 1), 0));	case BIT_FIELD_REF:	  return (operand_equal_p (TREE_OPERAND (arg0, 0),				   TREE_OPERAND (arg1, 0), 0)		  && operand_equal_p (TREE_OPERAND (arg0, 1),				      TREE_OPERAND (arg1, 1), 0)		  && operand_equal_p (TREE_OPERAND (arg0, 2),				      TREE_OPERAND (arg1, 2), 0));	}      break;    }  return 0;}/* Similar to operand_equal_p, but see if ARG0 might have been made by   shorten_compare from ARG1 when ARG1 was being compared with OTHER.    When in doubt, return 0.  */static int operand_equal_for_comparison_p (arg0, arg1, other)     tree arg0, arg1;     tree other;{  int unsignedp1, unsignedpo;  tree primarg1, primother;  unsigned correct_width;  if (operand_equal_p (arg0, arg1, 0))    return 1;  if (! INTEGRAL_TYPE_P (TREE_TYPE (arg0))      || ! INTEGRAL_TYPE_P (TREE_TYPE (arg1)))    return 0;  /* Duplicate what shorten_compare does to ARG1 and see if that gives the     actual comparison operand, ARG0.     First throw away any conversions to wider types     already present in the operands.  */  primarg1 = get_narrower (arg1, &unsignedp1);  primother = get_narrower (other, &unsignedpo);  correct_width = TYPE_PRECISION (TREE_TYPE (arg1));  if (unsignedp1 == unsignedpo      && TYPE_PRECISION (TREE_TYPE (primarg1)) < correct_width      && TYPE_PRECISION (TREE_TYPE (primother)) < correct_width)    {      tree type = TREE_TYPE (arg0);      /* Make sure shorter operand is extended the right way	 to match the longer operand.  */      primarg1 = convert (signed_or_unsigned_type (unsignedp1,						  TREE_TYPE (primarg1)),			 primarg1);      if (operand_equal_p (arg0, convert (type, primarg1), 0))	return 1;    }  return 0;}/* See if ARG is an expression that is either a comparison or is performing   arithmetic on comparisons.  The comparisons must only be comparing   two different values, which will be stored in *CVAL1 and *CVAL2; if   they are non-zero it means that some operands have already been found.   No variables may be used anywhere else in the expression except in the   comparisons.  If SAVE_P is true it means we removed a SAVE_EXPR around   the expression and save_expr needs to be called with CVAL1 and CVAL2.   If this is true, return 1.  Otherwise, return zero.  */static inttwoval_comparison_p (arg, cval1, cval2, save_p)     tree arg;     tree *cval1, *cval2;     int *save_p;{  enum tree_code code = TREE_CODE (arg);  char class = TREE_CODE_CLASS (code);  /* We can handle some of the 'e' cases here.  */  if (class == 'e' && code == TRUTH_NOT_EXPR)    class = '1';  else if (class == 'e'	   && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR	       || code == COMPOUND_EXPR))    class = '2';  /* ??? Disable this since the SAVE_EXPR might already be in use outside     the expression.  There may be no way to make this work, but it needs     to be looked at again for 2.6.  */#if 0  else if (class == 'e' && code == SAVE_EXPR && SAVE_EXPR_RTL (arg) == 0)    {      /* If we've already found a CVAL1 or CVAL2, this expression is	 two complex to handle.  */      if (*cval1 || *cval2)	return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -