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

📄 tree.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Same as `tree_cons' but make a permanent object.  */treeperm_tree_cons (purpose, value, chain)     tree purpose, value, chain;{  register tree node;  register struct obstack *ambient_obstack = current_obstack;  current_obstack = &permanent_obstack;  node = tree_cons (purpose, value, chain);  current_obstack = ambient_obstack;  return node;}/* Same as `tree_cons', but make this node temporary, regardless.  */treetemp_tree_cons (purpose, value, chain)     tree purpose, value, chain;{  register tree node;  register struct obstack *ambient_obstack = current_obstack;  current_obstack = &temporary_obstack;  node = tree_cons (purpose, value, chain);  current_obstack = ambient_obstack;  return node;}/* Same as `tree_cons', but save this node if the function's RTL is saved.  */treesaveable_tree_cons (purpose, value, chain)     tree purpose, value, chain;{  register tree node;  register struct obstack *ambient_obstack = current_obstack;  current_obstack = saveable_obstack;  node = tree_cons (purpose, value, chain);  current_obstack = ambient_obstack;  return node;}/* Return the size nominally occupied by an object of type TYPE   when it resides in memory.  The value is measured in units of bytes,   and its data type is that normally used for type sizes   (which is the first type created by make_signed_type or   make_unsigned_type).  */treesize_in_bytes (type)     tree type;{  tree t;  if (type == error_mark_node)    return integer_zero_node;  type = TYPE_MAIN_VARIANT (type);  if (TYPE_SIZE (type) == 0)    {      incomplete_type_error (NULL_TREE, type);      return integer_zero_node;    }  t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),		  size_int (BITS_PER_UNIT));  if (TREE_CODE (t) == INTEGER_CST)    force_fit_type (t, 0);  return t;}/* Return the size of TYPE (in bytes) as an integer,   or return -1 if the size can vary.  */intint_size_in_bytes (type)     tree type;{  unsigned int size;  if (type == error_mark_node)    return 0;  type = TYPE_MAIN_VARIANT (type);  if (TYPE_SIZE (type) == 0)    return -1;  if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)    return -1;  if (TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0)    {      tree t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),			   size_int (BITS_PER_UNIT));      return TREE_INT_CST_LOW (t);    }  size = TREE_INT_CST_LOW (TYPE_SIZE (type));  return (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;}/* Return, as a tree node, the number of elements for TYPE (which is an   ARRAY_TYPE) minus one. This counts only elements of the top array.  */treearray_type_nelts (type)     tree type;{  tree index_type = TYPE_DOMAIN (type);  return (integer_zerop (TYPE_MIN_VALUE (index_type))	  ? TYPE_MAX_VALUE (index_type)	  : fold (build (MINUS_EXPR, TREE_TYPE (TYPE_MAX_VALUE (index_type)),			 TYPE_MAX_VALUE (index_type),			 TYPE_MIN_VALUE (index_type))));}/* Return nonzero if arg is static -- a reference to an object in   static storage.  This is not the same as the C meaning of `static'.  */intstaticp (arg)     tree arg;{  switch (TREE_CODE (arg))    {    case FUNCTION_DECL:      /* Nested functions aren't static, since taking their address	 involves a trampoline.  */       return decl_function_context (arg) == 0;    case VAR_DECL:      return TREE_STATIC (arg) || DECL_EXTERNAL (arg);    case CONSTRUCTOR:      return TREE_STATIC (arg);    case STRING_CST:      return 1;    case COMPONENT_REF:    case BIT_FIELD_REF:      return staticp (TREE_OPERAND (arg, 0));#if 0       /* This case is technically correct, but results in setting	  TREE_CONSTANT on ADDR_EXPRs that cannot be evaluated at	  compile time.  */    case INDIRECT_REF:      return TREE_CONSTANT (TREE_OPERAND (arg, 0));#endif    case ARRAY_REF:      if (TREE_CODE (TYPE_SIZE (TREE_TYPE (arg))) == INTEGER_CST	  && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST)	return staticp (TREE_OPERAND (arg, 0));    }  return 0;}/* Wrap a SAVE_EXPR around EXPR, if appropriate.   Do this to any expression which may be used in more than one place,   but must be evaluated only once.   Normally, expand_expr would reevaluate the expression each time.   Calling save_expr produces something that is evaluated and recorded   the first time expand_expr is called on it.  Subsequent calls to   expand_expr just reuse the recorded value.   The call to expand_expr that generates code that actually computes   the value is the first call *at compile time*.  Subsequent calls   *at compile time* generate code to use the saved value.   This produces correct result provided that *at run time* control   always flows through the insns made by the first expand_expr   before reaching the other places where the save_expr was evaluated.   You, the caller of save_expr, must make sure this is so.   Constants, and certain read-only nodes, are returned with no   SAVE_EXPR because that is safe.  Expressions containing placeholders   are not touched; see tree.def for an explanation of what these   are used for.  */treesave_expr (expr)     tree expr;{  register tree t = fold (expr);  /* We don't care about whether this can be used as an lvalue in this     context.  */  while (TREE_CODE (t) == NON_LVALUE_EXPR)    t = TREE_OPERAND (t, 0);  /* If the tree evaluates to a constant, then we don't want to hide that     fact (i.e. this allows further folding, and direct checks for constants).     However, a read-only object that has side effects cannot be bypassed.     Since it is no problem to reevaluate literals, we just return the      literal node. */  if (TREE_CONSTANT (t) || (TREE_READONLY (t) && ! TREE_SIDE_EFFECTS (t))      || TREE_CODE (t) == SAVE_EXPR || TREE_CODE (t) == ERROR_MARK)    return t;  /* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since     it means that the size or offset of some field of an object depends on     the value within another field.     Note that it must not be the case that T contains both a PLACEHOLDER_EXPR     and some variable since it would then need to be both evaluated once and     evaluated more than once.  Front-ends must assure this case cannot     happen by surrounding any such subexpressions in their own SAVE_EXPR     and forcing evaluation at the proper time.  */  if (contains_placeholder_p (t))    return t;  t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE);  /* This expression might be placed ahead of a jump to ensure that the     value was computed on both sides of the jump.  So make sure it isn't     eliminated as dead.  */  TREE_SIDE_EFFECTS (t) = 1;  return t;}/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size   or offset that depends on a field within a record.   Note that we only allow such expressions within simple arithmetic   or a COND_EXPR.  */intcontains_placeholder_p (exp)     tree exp;{  register enum tree_code code = TREE_CODE (exp);  tree inner;  /* If we have a WITH_RECORD_EXPR, it "cancels" any PLACEHOLDER_EXPR     in it since it is supplying a value for it.  */  if (code == WITH_RECORD_EXPR)    return 0;  switch (TREE_CODE_CLASS (code))    {    case 'r':      for (inner = TREE_OPERAND (exp, 0);	   TREE_CODE_CLASS (TREE_CODE (inner)) == 'r';	   inner = TREE_OPERAND (inner, 0))	;      return TREE_CODE (inner) == PLACEHOLDER_EXPR;    case '1':    case '2':  case '<':    case 'e':      switch (tree_code_length[(int) code])	{	case 1:	  return contains_placeholder_p (TREE_OPERAND (exp, 0));	case 2:	  return (code != RTL_EXPR		  && code != CONSTRUCTOR		  && ! (code == SAVE_EXPR && SAVE_EXPR_RTL (exp) != 0)		  && code != WITH_RECORD_EXPR		  && (contains_placeholder_p (TREE_OPERAND (exp, 0))		      || contains_placeholder_p (TREE_OPERAND (exp, 1))));	case 3:	  return (code == COND_EXPR		  && (contains_placeholder_p (TREE_OPERAND (exp, 0))		      || contains_placeholder_p (TREE_OPERAND (exp, 1))		      || contains_placeholder_p (TREE_OPERAND (exp, 2))));	}    }  return 0;}/* Given a tree EXP, a FIELD_DECL F, and a replacement value R,   return a tree with all occurrences of references to F in a   PLACEHOLDER_EXPR replaced by R.   Note that we assume here that EXP   contains only arithmetic expressions.  */treesubstitute_in_expr (exp, f, r)     tree exp;     tree f;     tree r;{  enum tree_code code = TREE_CODE (exp);  tree new = 0;  tree inner;  switch (TREE_CODE_CLASS (code))    {    case 'c':    case 'd':      return exp;    case 'x':      if (code == PLACEHOLDER_EXPR)	return exp;      break;    case '1':    case '2':    case '<':    case 'e':      switch (tree_code_length[(int) code])	{	case 1:	  new = fold (build1 (code, TREE_TYPE (exp),			      substitute_in_expr (TREE_OPERAND (exp, 0),						  f, r)));	  break;	case 2:	  /* An RTL_EXPR cannot contain a PLACEHOLDER_EXPR; a CONSTRUCTOR	     could, but we don't support it.  */	  if (code == RTL_EXPR)	    return exp;	  else if (code == CONSTRUCTOR)	    abort ();	  new = fold (build (code, TREE_TYPE (exp),			     substitute_in_expr (TREE_OPERAND (exp, 0), f, r),			     substitute_in_expr (TREE_OPERAND (exp, 1),						 f, r)));	  break;	case 3:	  /* It cannot be that anything inside a SAVE_EXPR contains a	     PLACEHOLDER_EXPR.  */	  if (code == SAVE_EXPR)	    return exp;	  if (code != COND_EXPR)	    abort ();	  new = fold (build (code, TREE_TYPE (exp),			     substitute_in_expr (TREE_OPERAND (exp, 0), f, r),			     substitute_in_expr (TREE_OPERAND (exp, 1), f, r),			     substitute_in_expr (TREE_OPERAND (exp, 2),						 f, r)));	}      break;    case 'r':      switch (code)	{	case COMPONENT_REF:	  /* If this expression is getting a value from a PLACEHOLDER_EXPR	     and it is the right field, replace it with R.  */	  for (inner = TREE_OPERAND (exp, 0);	       TREE_CODE_CLASS (TREE_CODE (inner)) == 'r';	       inner = TREE_OPERAND (inner, 0))	    ;	  if (TREE_CODE (inner) == PLACEHOLDER_EXPR	      && TREE_OPERAND (exp, 1) == f)	    return r;	  new = fold (build (code, TREE_TYPE (exp),			     substitute_in_expr (TREE_OPERAND (exp, 0), f, r),			     TREE_OPERAND (exp, 1)));	  break;	case BIT_FIELD_REF:	  new = fold (build (code, TREE_TYPE (exp),			     substitute_in_expr (TREE_OPERAND (exp, 0), f, r),			     substitute_in_expr (TREE_OPERAND (exp, 1), f, r),			     substitute_in_expr (TREE_OPERAND (exp, 2), f, r)));	  break;	case INDIRECT_REF:	case BUFFER_REF:	  new = fold (build1 (code, TREE_TYPE (exp),			      substitute_in_expr (TREE_OPERAND (exp, 0),						  f, r)));	  break;	case OFFSET_REF:	  new = fold (build (code, TREE_TYPE (exp),			     substitute_in_expr (TREE_OPERAND (exp, 0), f, r),			     substitute_in_expr (TREE_OPERAND (exp, 1), f, r)));	  break;	}    }  /* If it wasn't one of the cases we handle, give up.  */  if (new == 0)    abort ();  TREE_READONLY (new) = TREE_READONLY (exp);  return new;}/* Given a type T, a FIELD_DECL F, and a replacement value R,   return a new type with all size expressions that contain F   updated by replacing F with R.  */treesubstitute_in_type (t, f, r)     tree t, f, r;{  switch (TREE_CODE (t))    {    case POINTER_TYPE:    case VOID_TYPE:      return t;    case INTEGER_TYPE:    case ENUMERAL_TYPE:    case BOOLEAN_TYPE:    case CHAR_TYPE:      if ((TREE_CODE (TYPE_MIN_VALUE (t)) != INTEGER_CST	   && contains_placeholder_p (TYPE_MIN_VALUE (t)))	  || (TREE_CODE (TYPE_MAX_VALUE (t)) != INTEGER_CST	      && contains_placeholder_p (TYPE_MAX_VALUE (t))))	return build_range_type (t,				 substitute_in_expr (TYPE_MIN_VALUE (t), f, r),				 substitute_in_expr (TYPE_MAX_VALUE (t), f, r));      return t;    case REAL_TYPE:      if ((TYPE_MIN_VALUE (t) != 0	   && TREE_CODE (TYPE_MIN_VALUE (t)) != REAL_CST	   && contains_placeholder_p (TYPE_MIN_VALUE (t)))	  || (TYPE_MAX_VALUE (t) != 0	      && TREE_CODE (TYPE_MAX_VALUE (t)) != REAL_CST	      && contains_placeholder_p (TYPE_MAX_VALUE (t))))	{	  t = build_type_copy (t);	  if (TYPE_MIN_VALUE (t))	    TYPE_MIN_VALUE (t) = substitute_in_expr (TYPE_MIN_VALUE (t), f, r);	  if (TYPE_MAX_VALUE (t))	    TYPE_MAX_VALUE (t) = substitute_in_expr (TYPE_MAX_VALUE (t), f, r);	}      return t;    case COMPLEX_TYPE:      return build_complex_type (substitute_in_type (TREE_TYPE (t), f, r));    case OFFSET_TYPE:    case METHOD_TYPE:    case REFERENCE_TYPE:    case FILE_TYPE:    case SET_TYPE:    case FUNCTION_TYPE:    case LANG_TYPE:      /* Don't know how to do these yet.  */      abort ();    case ARRAY_TYPE:      t = build_array_type (substitute_in_type (TREE_TYPE (t), f, r),			    substitute_in_type (TYPE_DOMAIN (t), f, r));      TYPE_SIZE (t) = 0;      layout_type (t);      return t;    case RECORD_TYPE:    case UNION_TYPE:    case QUAL_UNION_TYPE:      {	tree new = copy_node (t);	tree field;	tree last_field = 0;	/* Start out with no fields, make new fields, and chain them	   in.  */	TYPE_FIELDS (new) = 0;	TYPE_SIZE (new) = 0;	for (field = TYPE_FIELDS (t); field;	     field = TREE_CHAIN (field))	  {	    tree new_field = copy_node (field);	    TREE_TYPE (new_field)	      = substitute_in_type (TREE_TYPE (new_field), f, r);	    /* If this is an ano

⌨️ 快捷键说明

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