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

📄 tree.c

📁 使用yacc和lex编写的cmm语言的词法分析和语法分析程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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;}/* 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  ((int *)node)[(sizeof (struct tree_common)/sizeof (int)) - 1] = 0;  TREE_SET_CODE (node, TREE_LIST);  if (current_obstack == &permanent_obstack)    TREE_PERMANENT (node) = 1;  TREE_TYPE (node) = 0;#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;}/* 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;{  if (type == error_mark_node)    return integer_zero_node;  type = TYPE_MAIN_VARIANT (type);  if (TYPE_SIZE (type) == 0)    {      incomplete_type_error (0, type);      return integer_zero_node;    }  return size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),		     size_int (BITS_PER_UNIT));}/* 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;{  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;  size = TREE_INT_CST_LOW (TYPE_SIZE (type));  return (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;}/* Return, as an INTEGER_CST node, the number of elements for   TYPE (which is an ARRAY_TYPE).  */treearray_type_nelts (type)     tree type;{  tree index_type = TYPE_DOMAIN (type);  return (tree_int_cst_equal (TYPE_MIN_VALUE (index_type), integer_zero_node)	  ? TYPE_MAX_VALUE (index_type)	  : fold (build (MINUS_EXPR, integer_type_node,			 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 VAR_DECL:    case FUNCTION_DECL:    case CONSTRUCTOR:      return TREE_STATIC (arg) || TREE_EXTERNAL (arg);    case STRING_CST:      return 1;    case COMPONENT_REF:    case BIT_FIELD_REF:      return staticp (TREE_OPERAND (arg, 0));    case INDIRECT_REF:      return TREE_CONSTANT (TREE_OPERAND (arg, 0));    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;}/* This should be applied to any node which may be used in more than one place,   but must be evaluated only once.  Normally, the code generator would   reevaluate the node each time; this forces it to compute it once and save   the result.  This is done by encapsulating the node in a SAVE_EXPR.  */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).     Since it is no problem to reevaluate literals, we just return the      literal node. */  if (TREE_CONSTANT (t) || TREE_READONLY (t) || TREE_CODE (t) == SAVE_EXPR)    return t;  t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL);  /* 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;}/* Stabilize a reference so that we can use it any number of times   without causing its operands to be evaluated more than once.   Returns the stabilized reference.   Also allows conversion expressions whose operands are references.   Any other kind of expression is returned unchanged.  */treestabilize_reference (ref)     tree ref;{  register tree result;  register enum tree_code code = TREE_CODE (ref);  switch (code)    {    case VAR_DECL:    case PARM_DECL:    case RESULT_DECL:      /* No action is needed in this case.  */      return ref;    case NOP_EXPR:    case CONVERT_EXPR:    case FLOAT_EXPR:    case FIX_TRUNC_EXPR:    case FIX_FLOOR_EXPR:    case FIX_ROUND_EXPR:    case FIX_CEIL_EXPR:      result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));      break;    case INDIRECT_REF:      result = build_nt (INDIRECT_REF,			 stabilize_reference_1 (TREE_OPERAND (ref, 0)));      break;    case COMPONENT_REF:      result = build_nt (COMPONENT_REF,			 stabilize_reference (TREE_OPERAND (ref, 0)),			 TREE_OPERAND (ref, 1));      break;    case BIT_FIELD_REF:      result = build_nt (BIT_FIELD_REF,			 stabilize_reference (TREE_OPERAND (ref, 0)),			 stabilize_reference_1 (TREE_OPERAND (ref, 1)),			 stabilize_reference_1 (TREE_OPERAND (ref, 2)));      break;    case ARRAY_REF:      result = build_nt (ARRAY_REF,			 stabilize_reference (TREE_OPERAND (ref, 0)),			 stabilize_reference_1 (TREE_OPERAND (ref, 1)));      break;      /* If arg isn't a kind of lvalue we recognize, make no change.	 Caller should recognize the error for an invalid lvalue.  */    default:      return ref;    case ERROR_MARK:      return error_mark_node;    }  TREE_TYPE (result) = TREE_TYPE (ref);  TREE_READONLY (result) = TREE_READONLY (ref);  TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);  TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);  TREE_RAISES (result) = TREE_RAISES (ref);  return result;}/* Subroutine of stabilize_reference; this is called for subtrees of   references.  Any expression with side-effects must be put in a SAVE_EXPR   to ensure that it is only evaluated once.   We don't put SAVE_EXPR nodes around everything, because assigning very   simple expressions to temporaries causes us to miss good opportunities   for optimizations.  Among other things, the opportunity to fold in the   addition of a constant into an addressing mode often gets lost, e.g.   "y[i+1] += x;".  In general, we take the approach that we should not make   an assignment unless we are forced into it - i.e., that any non-side effect   operator should be allowed, and that cse should take care of coalescing   multiple utterances of the same expression should that prove fruitful.  */static treestabilize_reference_1 (e)     tree e;{  register tree result;  register int length;  register enum tree_code code = TREE_CODE (e);  if (TREE_CONSTANT (e) || TREE_READONLY (e) || code == SAVE_EXPR)    return e;  switch (TREE_CODE_CLASS (code))    {    case 'x':    case 't':    case 'd':    case '<':    case 's':    case 'e':    case 'r':      /* If the expression has side-effects, then encase it in a SAVE_EXPR	 so that it will only be evaluated once.  */      /* The reference (r) and comparison (<) classes could be handled as	 below, but it is generally faster to only evaluate them once.  */      if (TREE_SIDE_EFFECTS (e))	return save_expr (e);      return e;    case 'c':      /* Constants need no processing.  In fact, we should never reach	 here.  */      return e;          case '2':      /* Recursively stabilize each operand.  */      result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)),			 stabilize_reference_1 (TREE_OPERAND (e, 1)));      break;    case '1':      /* Recursively stabilize each operand.  */      result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)));      break;    }    TREE_TYPE (result) = TREE_TYPE (e);  TREE_READONLY (result) = TREE_READONLY (e);  TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);  TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);  TREE_RAISES (result) = TREE_RAISES (e);  return result;}/* Low-level constructors for expressions.  *//* Build an expression of code CODE, data type TYPE,   and operands as specified by the arguments ARG1 and following arguments.   Expressions and reference nodes can be created this way.   Constants, decls, types and misc nodes cannot be.  */treebuild (va_alist)     va_dcl{  va_list p;  enum tree_code code;  register tree t;  register int length;  register int i;  va_start (p);  code = va_arg (p, enum tree_code);  t = make_node (code);  length = tree_code_length[(int) code];  TREE_TYPE (t) = va_arg (p, tree);  if (length == 2)    {      /* This is equivalent to the loop below, but faster.  */      register tree arg0 = va_arg (p, tree);      register tree arg1 = va_arg (p, tree);      TREE_OPERAND (t, 0) = arg0;      TREE_OPERAND (t, 1) = arg1;      if ((arg0 && TREE_SIDE_EFFECTS (arg0))	  || (arg1 && TREE_SIDE_EFFECTS (arg1)))	TREE_SIDE_EFFECTS (t) = 1;      TREE_RAISES (t)	= (arg0 && TREE_RAISES (arg0)) || (arg1 && TREE_RAISES (arg1));    }  else if (length == 1)    {      register tree arg0 = va_arg (p, tree);      /* Call build1 for this!  */      if (TREE_CODE_CLASS (code) != 's')	abort ();      TREE_OPERAND (t, 0) = arg0;      if (arg0 && TREE_SIDE_EFFECTS (arg0))	TREE_SIDE_EFFECTS (t) = 1;      TREE_RAISES (t) = (arg0 && TREE_RAISES (arg0));    }  else    {      for (i = 0; i < length; i++)	{	  register tree operand = va_arg (p, tree);	  TREE_OPERAND (t, i) = operand;	  if (operand)	    {	      if (TREE_SIDE_EFFECTS (operand))		TREE_SIDE_EFFECTS (t) = 1;	      if (TREE_RAISES (operand))		TREE_RAISES (t) = 1;	    }	}    }  va_end (p);  return t;}/* Same as above, but only builds for unary operators.   Saves lions share of calls to `build'; cuts down use

⌨️ 快捷键说明

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