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

📄 fold-const.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	  *conp = TREE_OPERAND (in, 0);	  *varp = TREE_OPERAND (in, 1);	  if (TYPE_MODE (TREE_TYPE (*varp)) != TYPE_MODE (outtype)	      && TREE_TYPE (*varp) != outtype)	    *varp = convert (outtype, *varp);	  *varsignp = (TREE_CODE (in) == MINUS_EXPR) ? -1 : 1;	  return 1;	}      if (TREE_CONSTANT (TREE_OPERAND (in, 1)))	{	  *conp = TREE_OPERAND (in, 1);	  *varp = TREE_OPERAND (in, 0);	  *varsignp = 1;	  if (TYPE_MODE (TREE_TYPE (*varp)) != TYPE_MODE (outtype)	      && TREE_TYPE (*varp) != outtype)	    *varp = convert (outtype, *varp);	  if (TREE_CODE (in) == MINUS_EXPR)	    {	      /* If operation is subtraction and constant is second,		 must negate it to get an additive constant.		 And this cannot be done unless it is a manifest constant.		 It could also be the address of a static variable.		 We cannot negate that, so give up.  */	      if (TREE_CODE (*conp) == INTEGER_CST)		/* Subtracting from integer_zero_node loses for long long.  */		*conp = fold (build1 (NEGATE_EXPR, TREE_TYPE (*conp), *conp));	      else		return 0;	    }	  return 1;	}      if (TREE_CONSTANT (TREE_OPERAND (in, 0)))	{	  *conp = TREE_OPERAND (in, 0);	  *varp = TREE_OPERAND (in, 1);	  if (TYPE_MODE (TREE_TYPE (*varp)) != TYPE_MODE (outtype)	      && TREE_TYPE (*varp) != outtype)	    *varp = convert (outtype, *varp);	  *varsignp = (TREE_CODE (in) == MINUS_EXPR) ? -1 : 1;	  return 1;	}    }  return 0;}/* Combine two constants NUM and ARG2 under operation CODE   to produce a new constant.   We assume ARG1 and ARG2 have the same data type,   or at least are the same kind of constant and the same machine mode.   If NOTRUNC is nonzero, do not truncate the result to fit the data type.  */static treeconst_binop (code, arg1, arg2, notrunc)     enum tree_code code;     register tree arg1, arg2;     int notrunc;{  if (TREE_CODE (arg1) == INTEGER_CST)    {      register HOST_WIDE_INT int1l = TREE_INT_CST_LOW (arg1);      register HOST_WIDE_INT int1h = TREE_INT_CST_HIGH (arg1);      HOST_WIDE_INT int2l = TREE_INT_CST_LOW (arg2);      HOST_WIDE_INT int2h = TREE_INT_CST_HIGH (arg2);      HOST_WIDE_INT low, hi;      HOST_WIDE_INT garbagel, garbageh;      register tree t;      int uns = TREE_UNSIGNED (TREE_TYPE (arg1));      int overflow = 0;      switch (code)	{	case BIT_IOR_EXPR:	  t = build_int_2 (int1l | int2l, int1h | int2h);	  break;	case BIT_XOR_EXPR:	  t = build_int_2 (int1l ^ int2l, int1h ^ int2h);	  break;	case BIT_AND_EXPR:	  t = build_int_2 (int1l & int2l, int1h & int2h);	  break;	case BIT_ANDTC_EXPR:	  t = build_int_2 (int1l & ~int2l, int1h & ~int2h);	  break;	case RSHIFT_EXPR:	  int2l = - int2l;	case LSHIFT_EXPR:	  /* It's unclear from the C standard whether shifts can overflow.	     The following code ignores overflow; perhaps a C standard	     interpretation ruling is needed.  */	  lshift_double (int1l, int1h, int2l,			 TYPE_PRECISION (TREE_TYPE (arg1)),			 &low, &hi,			 !uns);	  t = build_int_2 (low, hi);	  TREE_TYPE (t) = TREE_TYPE (arg1);	  if (!notrunc)	    force_fit_type (t, 0);	  TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2);	  TREE_CONSTANT_OVERFLOW (t)	    = TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2);	  return t;	case RROTATE_EXPR:	  int2l = - int2l;	case LROTATE_EXPR:	  lrotate_double (int1l, int1h, int2l,			  TYPE_PRECISION (TREE_TYPE (arg1)),			  &low, &hi);	  t = build_int_2 (low, hi);	  break;	case PLUS_EXPR:	  if (int1h == 0)	    {	      int2l += int1l;	      if ((unsigned HOST_WIDE_INT) int2l < int1l)		{		  hi = int2h++;		  overflow = int2h < hi;		}	      t = build_int_2 (int2l, int2h);	      break;	    }	  if (int2h == 0)	    {	      int1l += int2l;	      if ((unsigned HOST_WIDE_INT) int1l < int2l)		{		  hi = int1h++;		  overflow = int1h < hi;		}	      t = build_int_2 (int1l, int1h);	      break;	    }	  overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);	  t = build_int_2 (low, hi);	  break;	case MINUS_EXPR:	  if (int2h == 0 && int2l == 0)	    {	      t = build_int_2 (int1l, int1h);	      break;	    }	  neg_double (int2l, int2h, &low, &hi);	  add_double (int1l, int1h, low, hi, &low, &hi);	  overflow = overflow_sum_sign (hi, int2h, int1h);	  t = build_int_2 (low, hi);	  break;	case MULT_EXPR:	  overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);	  t = build_int_2 (low, hi);	  break;	case TRUNC_DIV_EXPR:	case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:	case EXACT_DIV_EXPR:	  /* This is a shortcut for a common special case.	     It reduces the number of tree nodes generated	     and saves time.  */	  if (int2h == 0 && int2l > 0	      && TREE_TYPE (arg1) == sizetype	      && int1h == 0 && int1l >= 0)	    {	      if (code == CEIL_DIV_EXPR)		int1l += int2l-1;	      return size_int (int1l / int2l);	    }	case ROUND_DIV_EXPR: 	  if (int2h == 0 && int2l == 1)	    {	      t = build_int_2 (int1l, int1h);	      break;	    }	  if (int1l == int2l && int1h == int2h)	    {	      if ((int1l | int1h) == 0)		abort ();	      t = build_int_2 (1, 0);	      break;	    }	  overflow = div_and_round_double (code, uns,					   int1l, int1h, int2l, int2h,					   &low, &hi, &garbagel, &garbageh);	  t = build_int_2 (low, hi);	  break;	case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR: 	case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:	  overflow = div_and_round_double (code, uns,					   int1l, int1h, int2l, int2h,					   &garbagel, &garbageh, &low, &hi);	  t = build_int_2 (low, hi);	  break;	case MIN_EXPR:	case MAX_EXPR:	  if (uns)	    {	      low = (((unsigned HOST_WIDE_INT) int1h		      < (unsigned HOST_WIDE_INT) int2h)		     || (((unsigned HOST_WIDE_INT) int1h			  == (unsigned HOST_WIDE_INT) int2h)			 && ((unsigned HOST_WIDE_INT) int1l			     < (unsigned HOST_WIDE_INT) int2l)));	    }	  else	    {	      low = ((int1h < int2h)		     || ((int1h == int2h)			 && ((unsigned HOST_WIDE_INT) int1l			     < (unsigned HOST_WIDE_INT) int2l)));	    }	  if (low == (code == MIN_EXPR))	    t = build_int_2 (int1l, int1h);	  else	    t = build_int_2 (int2l, int2h);	  break;	default:	  abort ();	}    got_it:      TREE_TYPE (t) = TREE_TYPE (arg1);      TREE_OVERFLOW (t)	= ((notrunc ? !uns && overflow : force_fit_type (t, overflow && !uns))	   | TREE_OVERFLOW (arg1)	   | TREE_OVERFLOW (arg2));      TREE_CONSTANT_OVERFLOW (t) = (TREE_OVERFLOW (t)				    | TREE_CONSTANT_OVERFLOW (arg1)				    | TREE_CONSTANT_OVERFLOW (arg2));      return t;    }#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)  if (TREE_CODE (arg1) == REAL_CST)    {      REAL_VALUE_TYPE d1;      REAL_VALUE_TYPE d2;      int overflow = 0;      REAL_VALUE_TYPE value;      tree t;      d1 = TREE_REAL_CST (arg1);      d2 = TREE_REAL_CST (arg2);      /* If either operand is a NaN, just return it.  Otherwise, set up	 for floating-point trap; we return an overflow.  */      if (REAL_VALUE_ISNAN (d1))	return arg1;      else if (REAL_VALUE_ISNAN (d2))	return arg2;      else if (setjmp (float_error))	{	  t = copy_node (arg1);	  overflow = 1;	  goto got_float;	}      set_float_handler (float_error);#ifdef REAL_ARITHMETIC      REAL_ARITHMETIC (value, code, d1, d2);#else      switch (code)	{	case PLUS_EXPR:	  value = d1 + d2;	  break;	case MINUS_EXPR:	  value = d1 - d2;	  break;	case MULT_EXPR:	  value = d1 * d2;	  break;	case RDIV_EXPR:#ifndef REAL_INFINITY	  if (d2 == 0)	    abort ();#endif	  value = d1 / d2;	  break;	case MIN_EXPR:	  value = MIN (d1, d2);	  break;	case MAX_EXPR:	  value = MAX (d1, d2);	  break;	default:	  abort ();	}#endif /* no REAL_ARITHMETIC */      t = build_real (TREE_TYPE (arg1),		      real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)), value));    got_float:      set_float_handler (NULL_PTR);      TREE_OVERFLOW (t)	= (force_fit_type (t, overflow)	   | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));      TREE_CONSTANT_OVERFLOW (t)	= TREE_OVERFLOW (t)	  | TREE_CONSTANT_OVERFLOW (arg1)	  | TREE_CONSTANT_OVERFLOW (arg2);      return t;    }#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */  if (TREE_CODE (arg1) == COMPLEX_CST)    {      register tree r1 = TREE_REALPART (arg1);      register tree i1 = TREE_IMAGPART (arg1);      register tree r2 = TREE_REALPART (arg2);      register tree i2 = TREE_IMAGPART (arg2);      register tree t;      switch (code)	{	case PLUS_EXPR:	  t = build_complex (const_binop (PLUS_EXPR, r1, r2, notrunc),			     const_binop (PLUS_EXPR, i1, i2, notrunc));	  break;	case MINUS_EXPR:	  t = build_complex (const_binop (MINUS_EXPR, r1, r2, notrunc),			     const_binop (MINUS_EXPR, i1, i2, notrunc));	  break;	case MULT_EXPR:	  t = build_complex (const_binop (MINUS_EXPR,					  const_binop (MULT_EXPR,						       r1, r2, notrunc),					  const_binop (MULT_EXPR,						       i1, i2, notrunc),					  notrunc),			     const_binop (PLUS_EXPR,					  const_binop (MULT_EXPR,						       r1, i2, notrunc),					  const_binop (MULT_EXPR,						       i1, r2, notrunc),					  notrunc));	  break;	case RDIV_EXPR:	  {	    register tree magsquared	      = const_binop (PLUS_EXPR,			     const_binop (MULT_EXPR, r2, r2, notrunc),			     const_binop (MULT_EXPR, i2, i2, notrunc),			     notrunc);	    t = build_complex	      (const_binop (INTEGRAL_TYPE_P (TREE_TYPE (r1))			    ? TRUNC_DIV_EXPR : RDIV_EXPR,			    const_binop (PLUS_EXPR,					 const_binop (MULT_EXPR, r1, r2,						      notrunc),					 const_binop (MULT_EXPR, i1, i2,						      notrunc),					 notrunc),			    magsquared, notrunc),	       const_binop (INTEGRAL_TYPE_P (TREE_TYPE (r1))			    ? TRUNC_DIV_EXPR : RDIV_EXPR,			    const_binop (MINUS_EXPR,					 const_binop (MULT_EXPR, i1, r2,						      notrunc),					 const_binop (MULT_EXPR, r1, i2,						      notrunc),					 notrunc),			    magsquared, notrunc));	  }	  break;	default:	  abort ();	}      TREE_TYPE (t) = TREE_TYPE (arg1);      return t;    }  return 0;}/* Return an INTEGER_CST with value V and type from `sizetype'.  */treesize_int (number)     unsigned HOST_WIDE_INT number;{  register tree t;  /* Type-size nodes already made for small sizes.  */  static tree size_table[2*HOST_BITS_PER_WIDE_INT + 1];  if (number < 2*HOST_BITS_PER_WIDE_INT + 1      && size_table[number] != 0)    return size_table[number];  if (number < 2*HOST_BITS_PER_WIDE_INT + 1)    {      push_obstacks_nochange ();      /* Make this a permanent node.  */      end_temporary_allocation ();      t = build_int_2 (number, 0);      TREE_TYPE (t) = sizetype;      size_table[number] = t;      pop_obstacks ();    }  else    {      t = build_int_2 (number, 0);      TREE_TYPE (t) = sizetype;    }  return t;}/* Combine operands OP1 and OP2 with arithmetic operation CODE.   CODE is a tree code.  Data type is taken from `sizetype',   If the operands are constant, so is the result.  */treesize_binop (code, arg0, arg1)     enum tree_code code;     tree arg0, arg1;{  /* Handle the special case of two integer constants faster.  */  if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)    {      /* And some specific cases even faster than that.  */      if (code == PLUS_EXPR	  && TREE_INT_CST_LOW (arg0) == 0	  && TREE_INT_CST_HIGH (arg0) == 0)	return arg1;      if (code == MINUS_EXPR	  && TREE_INT_CST_LOW (arg1) == 0	  && TREE_INT_CST_HIGH (arg1) == 0)	return arg0;      if (code == MULT_EXPR	  && TREE_INT_CST_LOW (arg0) == 1	  && TREE_INT_CST_HIGH (arg0) == 0)	return arg1;      /* Handle general case of two integer constants.  */      return const_binop (code, arg0, arg1, 0);    }  if (arg0 == error_mark_node || arg1 == error_mark_node)    return error_mark_node;

⌨️ 快捷键说明

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