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

📄 tree.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
   don't use it.  */intchain_member_purpose (elem, chain)     tree elem, chain;{  while (chain)    {      if (elem == TREE_PURPOSE (chain))	return 1;      chain = TREE_CHAIN (chain);    }  return 0;}/* Return the length of a chain of nodes chained through TREE_CHAIN.   We expect a null pointer to mark the end of the chain.   This is the Lisp primitive `length'.  */intlist_length (t)     tree t;{  register tree tail;  register int len = 0;  for (tail = t; tail; tail = TREE_CHAIN (tail))    len++;  return len;}/* Concatenate two chains of nodes (chained through TREE_CHAIN)   by modifying the last node in chain 1 to point to chain 2.   This is the Lisp primitive `nconc'.  */treechainon (op1, op2)     tree op1, op2;{  if (op1)    {      register tree t1;      register tree t2;      for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))	;      TREE_CHAIN (t1) = op2;      for (t2 = op2; t2; t2 = TREE_CHAIN (t2))        if (t2 == t1)          abort ();  /* Circularity created.  */      return op1;    }  else return op2;}/* Return the last node in a chain of nodes (chained through TREE_CHAIN).  */treetree_last (chain)     register tree chain;{  register tree next;  if (chain)    while (next = TREE_CHAIN (chain))      chain = next;  return chain;}/* Reverse the order of elements in the chain T,   and return the new head of the chain (old last element).  */treenreverse (t)     tree t;{  register tree prev = 0, decl, next;  for (decl = t; decl; decl = next)    {      next = TREE_CHAIN (decl);      TREE_CHAIN (decl) = prev;      prev = decl;    }  return prev;}/* Given a chain CHAIN of tree nodes,   construct and return a list of those nodes.  */treelistify (chain)     tree chain;{  tree result = NULL_TREE;  tree in_tail = chain;  tree out_tail = NULL_TREE;  while (in_tail)    {      tree next = tree_cons (NULL_TREE, in_tail, NULL_TREE);      if (out_tail)	TREE_CHAIN (out_tail) = next;      else	result = next;      out_tail = next;      in_tail = TREE_CHAIN (in_tail);    }  return result;}/* Return a newly created TREE_LIST node whose   purpose and value fields are PARM and VALUE.  */treebuild_tree_list (parm, value)     tree parm, value;{  register tree t = make_node (TREE_LIST);  TREE_PURPOSE (t) = parm;  TREE_VALUE (t) = value;  return t;}/* Similar, but build on the temp_decl_obstack.  */treebuild_decl_list (parm, value)     tree parm, value;{  register tree node;  register struct obstack *ambient_obstack = current_obstack;  current_obstack = &temp_decl_obstack;  node = build_tree_list (parm, value);  current_obstack = ambient_obstack;  return node;}/* Similar, but build on the expression_obstack.  */treebuild_expr_list (parm, value)     tree parm, value;{  register tree node;  register struct obstack *ambient_obstack = current_obstack;  current_obstack = expression_obstack;  node = build_tree_list (parm, value);  current_obstack = ambient_obstack;  return node;}/* Return a newly created TREE_LIST node whose   purpose and value fields are PARM and VALUE   and whose TREE_CHAIN is CHAIN.  */treetree_cons (purpose, value, chain)     tree purpose, value, chain;{#if 0  register tree node = make_node (TREE_LIST);#else  register int i;  register tree node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));#ifdef GATHER_STATISTICS  tree_node_counts[(int)x_kind]++;  tree_node_sizes[(int)x_kind] += sizeof (struct tree_list);#endif  for (i = (sizeof (struct tree_common) / sizeof (int)) - 1; i >= 0; i--)    ((int *) node)[i] = 0;  TREE_SET_CODE (node, TREE_LIST);  if (current_obstack == &permanent_obstack)    TREE_PERMANENT (node) = 1;#endif  TREE_CHAIN (node) = chain;  TREE_PURPOSE (node) = purpose;  TREE_VALUE (node) = value;  return node;}/* Similar, but build on the temp_decl_obstack.  */treedecl_tree_cons (purpose, value, chain)     tree purpose, value, chain;{  register tree node;  register struct obstack *ambient_obstack = current_obstack;  current_obstack = &temp_decl_obstack;  node = tree_cons (purpose, value, chain);  current_obstack = ambient_obstack;  return node;}/* Similar, but build on the expression_obstack.  */treeexpr_tree_cons (purpose, value, chain)     tree purpose, value, chain;{  register tree node;  register struct obstack *ambient_obstack = current_obstack;  current_obstack = expression_obstack;  node = tree_cons (purpose, value, chain);  current_obstack = ambient_obstack;  return node;}/* 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.   Don't let any SAVE_EXPRs escape; if we are called as part of a cleanup   action, they would get unsaved.  */treearray_type_nelts (type)     tree type;{  tree index_type, min, max;  /* If they did it with unspecified bounds, then we should have already     given an error about it before we got here.  */  if (! TYPE_DOMAIN (type))    return error_mark_node;  index_type = TYPE_DOMAIN (type);  min = TYPE_MIN_VALUE (index_type);  max = TYPE_MAX_VALUE (index_type);  if (! TREE_CONSTANT (min))    {      STRIP_NOPS (min);      if (TREE_CODE (min) == SAVE_EXPR)	min = build (RTL_EXPR, TREE_TYPE (TYPE_MIN_VALUE (index_type)), 0,		     SAVE_EXPR_RTL (min));      else	min = TYPE_MIN_VALUE (index_type);    }  if (! TREE_CONSTANT (max))    {      STRIP_NOPS (max);      if (TREE_CODE (max) == SAVE_EXPR)	max = build (RTL_EXPR, TREE_TYPE (TYPE_MAX_VALUE (index_type)), 0,		     SAVE_EXPR_RTL (max));      else	max = TYPE_MAX_VALUE (index_type);    }  return (integer_zerop (min)	  ? max	  : fold (build (MINUS_EXPR, TREE_TYPE (max), max, min)));}/* 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 || DECL_NO_STATIC_CHAIN (arg);    case VAR_DECL:      return TREE_STATIC (arg) || DECL_EXTERNAL (arg);    case CONSTRUCTOR:      return TREE_STATIC (arg);    case STRING_CST:      return 1;      /* If we are referencing a bitfield, we can't evaluate an	 ADDR_EXPR at compile time and so it isn't a constant.  */    case COMPONENT_REF:      return (! DECL_BIT_FIELD (TREE_OPERAND (arg, 1))	      && staticp (TREE_OPERAND (arg, 0)));    case BIT_FIELD_REF:      return 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));    default:      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;}/* Arrange for an expression to be expanded multiple independent   times.  This is useful for cleanup actions, as the backend can   e

⌨️ 快捷键说明

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