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

📄 c-common.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	  code = LE_EXPR;	  break;	}      *rescode_ptr = code;    }  /* If comparing an integer against a constant more bits wide,     maybe we can deduce a value of 1 or 0 independent of the data.     Or else truncate the constant now     rather than extend the variable at run time.     This is only interesting if the constant is the wider arg.     Also, it is not safe if the constant is unsigned and the     variable arg is signed, since in this case the variable     would be sign-extended and then regarded as unsigned.     Our technique fails in this case because the lowest/highest     possible unsigned results don't follow naturally from the     lowest/highest possible values of the variable operand.     For just EQ_EXPR and NE_EXPR there is another technique that     could be used: see if the constant can be faithfully represented     in the other operand's type, by truncating it and reextending it     and see if that preserves the constant's value.  */  if (!real1 && !real2      && TREE_CODE (primop1) == INTEGER_CST      && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr))    {      int min_gt, max_gt, min_lt, max_lt;      tree maxval, minval;      /* 1 if comparison is nominally unsigned.  */      int unsignedp = TREE_UNSIGNED (*restype_ptr);      tree val;      type = signed_or_unsigned_type (unsignedp0, TREE_TYPE (primop0));      maxval = TYPE_MAX_VALUE (type);      minval = TYPE_MIN_VALUE (type);      if (unsignedp && !unsignedp0)	*restype_ptr = signed_type (*restype_ptr);      if (TREE_TYPE (primop1) != *restype_ptr)	primop1 = convert (*restype_ptr, primop1);      if (type != *restype_ptr)	{	  minval = convert (*restype_ptr, minval);	  maxval = convert (*restype_ptr, maxval);	}      if (unsignedp && unsignedp0)	{	  min_gt = INT_CST_LT_UNSIGNED (primop1, minval);	  max_gt = INT_CST_LT_UNSIGNED (primop1, maxval);	  min_lt = INT_CST_LT_UNSIGNED (minval, primop1);	  max_lt = INT_CST_LT_UNSIGNED (maxval, primop1);	}      else	{	  min_gt = INT_CST_LT (primop1, minval);	  max_gt = INT_CST_LT (primop1, maxval);	  min_lt = INT_CST_LT (minval, primop1);	  max_lt = INT_CST_LT (maxval, primop1);	}      val = 0;      /* This used to be a switch, but Genix compiler can't handle that.  */      if (code == NE_EXPR)	{	  if (max_lt || min_gt)	    val = boolean_true_node;	}      else if (code == EQ_EXPR)	{	  if (max_lt || min_gt)	    val = boolean_false_node;	}      else if (code == LT_EXPR)	{	  if (max_lt)	    val = boolean_true_node;	  if (!min_lt)	    val = boolean_false_node;	}      else if (code == GT_EXPR)	{	  if (min_gt)	    val = boolean_true_node;	  if (!max_gt)	    val = boolean_false_node;	}      else if (code == LE_EXPR)	{	  if (!max_gt)	    val = boolean_true_node;	  if (min_gt)	    val = boolean_false_node;	}      else if (code == GE_EXPR)	{	  if (!min_lt)	    val = boolean_true_node;	  if (max_lt)	    val = boolean_false_node;	}      /* If primop0 was sign-extended and unsigned comparison specd,	 we did a signed comparison above using the signed type bounds.	 But the comparison we output must be unsigned.	 Also, for inequalities, VAL is no good; but if the signed	 comparison had *any* fixed result, it follows that the	 unsigned comparison just tests the sign in reverse	 (positive values are LE, negative ones GE).	 So we can generate an unsigned comparison	 against an extreme value of the signed type.  */      if (unsignedp && !unsignedp0)	{	  if (val != 0)	    switch (code)	      {	      case LT_EXPR:	      case GE_EXPR:		primop1 = TYPE_MIN_VALUE (type);		val = 0;		break;	      case LE_EXPR:	      case GT_EXPR:		primop1 = TYPE_MAX_VALUE (type);		val = 0;		break;	      }	  type = unsigned_type (type);	}      if (!max_gt && !unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)	{	  /* This is the case of (char)x >?< 0x80, which people used to use	     expecting old C compilers to change the 0x80 into -0x80.  */	  if (val == boolean_false_node)	    warning ("comparison is always 0 due to limited range of data type");	  if (val == boolean_true_node)	    warning ("comparison is always 1 due to limited range of data type");	}      if (!min_lt && unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)	{	  /* This is the case of (unsigned char)x >?< -1 or < 0.  */	  if (val == boolean_false_node)	    warning ("comparison is always 0 due to limited range of data type");	  if (val == boolean_true_node)	    warning ("comparison is always 1 due to limited range of data type");	}      if (val != 0)	{	  /* Don't forget to evaluate PRIMOP0 if it has side effects.  */	  if (TREE_SIDE_EFFECTS (primop0))	    return build (COMPOUND_EXPR, TREE_TYPE (val), primop0, val);	  return val;	}      /* Value is not predetermined, but do the comparison	 in the type of the operand that is not constant.	 TYPE is already properly set.  */    }  else if (real1 && real2	   && (TYPE_PRECISION (TREE_TYPE (primop0))	       == TYPE_PRECISION (TREE_TYPE (primop1))))    type = TREE_TYPE (primop0);  /* If args' natural types are both narrower than nominal type     and both extend in the same manner, compare them     in the type of the wider arg.     Otherwise must actually extend both to the nominal     common type lest different ways of extending     alter the result.     (eg, (short)-1 == (unsigned short)-1  should be 0.)  */  else if (unsignedp0 == unsignedp1 && real1 == real2	   && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr)	   && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr))    {      type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));      type = signed_or_unsigned_type (unsignedp0				      || TREE_UNSIGNED (*restype_ptr),				      type);      /* Make sure shorter operand is extended the right way	 to match the longer operand.  */      primop0 = convert (signed_or_unsigned_type (unsignedp0, TREE_TYPE (primop0)),			 primop0);      primop1 = convert (signed_or_unsigned_type (unsignedp1, TREE_TYPE (primop1)),			 primop1);    }  else    {      /* Here we must do the comparison on the nominal type	 using the args exactly as we received them.  */      type = *restype_ptr;      primop0 = op0;      primop1 = op1;      if (!real1 && !real2 && integer_zerop (primop1)	  && TREE_UNSIGNED (*restype_ptr))	{	  tree value = 0;	  switch (code)	    {	    case GE_EXPR:	      /* All unsigned values are >= 0, so we warn if extra warnings		 are requested.  However, if OP0 is a constant that is		 >= 0, the signedness of the comparison isn't an issue,		 so suppress the warning.  */	      if (extra_warnings		  && ! (TREE_CODE (primop0) == INTEGER_CST			&& ! TREE_OVERFLOW (convert (signed_type (type),						     primop0))))		warning ("unsigned value >= 0 is always 1");	      value = boolean_true_node;	      break;	    case LT_EXPR:	      if (extra_warnings		  && ! (TREE_CODE (primop0) == INTEGER_CST			&& ! TREE_OVERFLOW (convert (signed_type (type),						     primop0))))		warning ("unsigned value < 0 is always 0");	      value = boolean_false_node;	    }	  if (value != 0)	    {	      /* Don't forget to evaluate PRIMOP0 if it has side effects.  */	      if (TREE_SIDE_EFFECTS (primop0))		return build (COMPOUND_EXPR, TREE_TYPE (value),			      primop0, value);	      return value;	    }	}    }  *op0_ptr = convert (type, primop0);  *op1_ptr = convert (type, primop1);  *restype_ptr = boolean_type_node;  return 0;}/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,   or validate its data type for an `if' or `while' statement or ?..: exp.   This preparation consists of taking the ordinary   representation of an expression expr and producing a valid tree   boolean expression describing whether expr is nonzero.  We could   simply always do build_binary_op (NE_EXPR, expr, boolean_false_node, 1),   but we optimize comparisons, &&, ||, and !.   The resulting type should always be `boolean_type_node'.  */treetruthvalue_conversion (expr)     tree expr;{  if (TREE_CODE (expr) == ERROR_MARK)    return expr;#if 0 /* This appears to be wrong for C++.  */  /* These really should return error_mark_node after 2.4 is stable.     But not all callers handle ERROR_MARK properly.  */  switch (TREE_CODE (TREE_TYPE (expr)))    {    case RECORD_TYPE:      error ("struct type value used where scalar is required");      return boolean_false_node;    case UNION_TYPE:      error ("union type value used where scalar is required");      return boolean_false_node;    case ARRAY_TYPE:      error ("array type value used where scalar is required");      return boolean_false_node;    default:      break;    }#endif /* 0 */  switch (TREE_CODE (expr))    {      /* It is simpler and generates better code to have only TRUTH_*_EXPR	 or comparison expressions as truth values at this level.  */#if 0    case COMPONENT_REF:      /* A one-bit unsigned bit-field is already acceptable.  */      if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))	  && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))	return expr;      break;#endif    case EQ_EXPR:      /* It is simpler and generates better code to have only TRUTH_*_EXPR	 or comparison expressions as truth values at this level.  */#if 0      if (integer_zerop (TREE_OPERAND (expr, 1)))	return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);#endif    case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:    case TRUTH_ANDIF_EXPR:    case TRUTH_ORIF_EXPR:    case TRUTH_AND_EXPR:    case TRUTH_OR_EXPR:    case TRUTH_XOR_EXPR:    case TRUTH_NOT_EXPR:      TREE_TYPE (expr) = boolean_type_node;      return expr;    case ERROR_MARK:      return expr;    case INTEGER_CST:      return integer_zerop (expr) ? boolean_false_node : boolean_true_node;    case REAL_CST:      return real_zerop (expr) ? boolean_false_node : boolean_true_node;    case ADDR_EXPR:      if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))	return build (COMPOUND_EXPR, boolean_type_node,		      TREE_OPERAND (expr, 0), boolean_true_node);      else	return boolean_true_node;    case COMPLEX_EXPR:      return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))			       ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),			      truthvalue_conversion (TREE_OPERAND (expr, 0)),			      truthvalue_conversion (TREE_OPERAND (expr, 1)),			      0);    case NEGATE_EXPR:    case ABS_EXPR:    case FLOAT_EXPR:    case FFS_EXPR:      /* These don't change whether an object is non-zero or zero.  */      return truthvalue_conversion (TREE_OPERAND (expr, 0));    case LROTATE_EXPR:    case RROTATE_EXPR:      /* These don't change whether an object is zero or non-zero, but	 we can't ignore them if their second arg has side-effects.  */      if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))	return build (COMPOUND_EXPR, boolean_type_node, TREE_OPERAND (expr, 1),		      truthvalue_conversion (TREE_OPERAND (expr, 0)));      else	return truthvalue_conversion (TREE_OPERAND (expr, 0));          case COND_EXPR:      /* Distribute the conversion into the arms of a COND_EXPR.  */      return fold (build (COND_EXPR, boolean_type_node, TREE_OPERAND (expr, 0),			  truthvalue_conversion (TREE_OPERAND (expr, 1)),			  truthvalue_conversion (TREE_OPERAND (expr, 2))));    case CONVERT_EXPR:      /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,	 since that affects how `default_conversion' will behave.  */      if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE	  || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)	break;      /* fall through... */    case NOP_EXPR:      /* If this is widening the argument, we can ignore it.  */      if (TYPE_PRECISION (TREE_TYPE (expr))	  >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))	return truthvalue_conversion (TREE_OPERAND (expr, 0));      break;    case MINUS_EXPR:      /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize	 this case.  */      if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT	  && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)	break;      /* fall through... */    case BIT_XOR_EXPR:      /* This and MINUS_EXPR can be changed into a comparison of the	 two objects.  */      if (TREE_TYPE (TREE_OPERAND (expr, 0))	  == TREE_TYPE (TREE_OPERAND (expr, 1)))	return build_binary_op (NE_EXPR, TREE_OPERAND (expr, 0),				TREE_OPERAND (expr, 1), 1);      return build_binary_op (NE_EXPR, TREE_OPERAND (expr, 0),			      fold (build1 (NOP_EXPR,					    TREE_TYPE (TREE_OPERAND (expr, 0)),					    TREE_OPERAND (expr, 1))), 1);    case BIT_AND_EXPR:      if (integer_onep (TREE_OPERAND (expr, 1))	  && TREE_TYPE (expr) != boolean_type_node)	/* Using convert here would cause infinite recursion.  */	return build1 (NOP_EXPR, boolean_type_node, expr);      break;    case MODIFY_EXPR:      if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)	warning ("suggest parentheses around assignment used as truth value");      break;    }  if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)    return (build_binary_op	    ((TREE_SIDE_EFFECTS (expr)	      ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),	     truthvalue_conversion (build_unary_op (REALPART_EXPR, expr, 0)),	     truthvalue_conversion (build_unary_op (IMAGPART_EXPR, expr, 0)),	     0));  return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);}/* Read the rest of a #-directive from input stream FINPUT.   In normal use, the directive name and the white space after it   have already been read, so they won't be included in the result.   We allow for the fact that the directive line may contain   a newline embedded within a character or st

⌨️ 快捷键说明

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