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

📄 fold-const.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
     tree in;     enum tree_code code;     tree *varp, *conp;     int *varsignp;{  register tree outtype = TREE_TYPE (in);  *varp = 0;  *conp = 0;  /* Strip any conversions that don't change the machine mode.  */  while ((TREE_CODE (in) == NOP_EXPR	  || TREE_CODE (in) == CONVERT_EXPR)	 && (TYPE_MODE (TREE_TYPE (in))	     == TYPE_MODE (TREE_TYPE (TREE_OPERAND (in, 0)))))    in = TREE_OPERAND (in, 0);  if (TREE_CODE (in) == code      || (TREE_CODE (TREE_TYPE (in)) != REAL_TYPE	  /* We can associate addition and subtraction together	     (even though the C standard doesn't say so)	     for integers because the value is not affected.	     For reals, the value might be affected, so we can't.  */	  &&	  ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR)	   || (code == MINUS_EXPR && TREE_CODE (in) == PLUS_EXPR))))    {      enum tree_code code = TREE_CODE (TREE_OPERAND (in, 0));      if (code == INTEGER_CST)	{	  *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.  */static treeconst_binop (code, arg1, arg2)     enum tree_code code;     register tree arg1, arg2;{  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));      /* Propagate overflow flags from operands; also record new overflow.  */      int overflow	= TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2);      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:	  overflow = lshift_double (int1l, int1h, int2l,				    TYPE_PRECISION (TREE_TYPE (arg1)),				    &low, &hi,				    !uns);	  t = build_int_2 (low, hi);	  break;	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 = ! same_sign (hi, int2h);		}	      t = build_int_2 (int2l, int2h);	      break;	    }	  if (int2h == 0)	    {	      int1l += int2l;	      if ((unsigned HOST_WIDE_INT) int1l < int2l)		{		  hi = int1h++;		  overflow = ! same_sign (hi, int1h);		}	      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:	  /* Optimize simple cases.  */	  if (int1h == 0)	    {	      unsigned HOST_WIDE_INT temp;	      switch (int1l)		{		case 0:		  t = build_int_2 (0, 0);		  goto got_it;		case 1:		  t = build_int_2 (int2l, int2h);		  goto got_it;		case 2:		  overflow = left_shift_overflows (int2h, 1);		  temp = int2l + int2l;		  int2h = (int2h << 1) + (temp < int2l);		  t = build_int_2 (temp, int2h);		  goto got_it;#if 0 /* This code can lose carries.  */		case 3:		  temp = int2l + int2l + int2l;		  int2h = int2h * 3 + (temp < int2l);		  t = build_int_2 (temp, int2h);		  goto got_it;#endif		case 4:		  overflow = left_shift_overflows (int2h, 2);		  temp = int2l + int2l;		  int2h = (int2h << 2) + ((temp < int2l) << 1);		  int2l = temp;		  temp += temp;		  int2h += (temp < int2l);		  t = build_int_2 (temp, int2h);		  goto got_it;		case 8:		  overflow = left_shift_overflows (int2h, 3);		  temp = int2l + int2l;		  int2h = (int2h << 3) + ((temp < int2l) << 2);		  int2l = temp;		  temp += temp;		  int2h += (temp < int2l) << 1;		  int2l = temp;		  temp += temp;		  int2h += (temp < int2l);		  t = build_int_2 (temp, int2h);		  goto got_it;		default:		  break;		}	    }	  if (int2h == 0)	    {	      if (int2l == 0)		{		  t = build_int_2 (0, 0);		  break;		}	      if (int2l == 1)		{		  t = build_int_2 (int1l, int1h);		  break;		}	    }	  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);      force_fit_type (t);      TREE_CONSTANT_OVERFLOW (t) = overflow;      return t;    }#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)  if (TREE_CODE (arg1) == REAL_CST)    {      register REAL_VALUE_TYPE d1;      register REAL_VALUE_TYPE d2;      register REAL_VALUE_TYPE value;      tree t;      d1 = TREE_REAL_CST (arg1);      d2 = TREE_REAL_CST (arg2);      if (setjmp (float_error))	{	  pedwarn ("floating overflow in constant expression");	  return build (code, TREE_TYPE (arg1), arg1, arg2);	}      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));      set_float_handler (NULL_PTR);      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),			     const_binop (PLUS_EXPR, i1, i2));	  break;	case MINUS_EXPR:	  t = build_complex (const_binop (MINUS_EXPR, r1, r2),			     const_binop (MINUS_EXPR, i1, i2));	  break;	case MULT_EXPR:	  t = build_complex (const_binop (MINUS_EXPR,					  const_binop (MULT_EXPR, r1, r2),					  const_binop (MULT_EXPR, i1, i2)),			     const_binop (PLUS_EXPR,					  const_binop (MULT_EXPR, r1, i2),					  const_binop (MULT_EXPR, i1, r2)));	  break;	case RDIV_EXPR:	  {	    register tree magsquared	      = const_binop (PLUS_EXPR,			     const_binop (MULT_EXPR, r2, r2),			     const_binop (MULT_EXPR, i2, i2));	    t = build_complex (const_binop (RDIV_EXPR,					    const_binop (PLUS_EXPR,							 const_binop (MULT_EXPR, r1, r2),							 const_binop (MULT_EXPR, i1, i2)),					    magsquared),			       const_binop (RDIV_EXPR,					    const_binop (MINUS_EXPR,							 const_binop (MULT_EXPR, i1, r2),							 const_binop (MULT_EXPR, r1, i2)),					    magsquared));	  }	  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 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 >= 0 && number < 2*HOST_BITS_PER_WIDE_INT + 1      && size_table[number] != 0)    return size_table[number];  if (number >= 0 && 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.  */

⌨️ 快捷键说明

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