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

📄 tree.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
treemake_node (code)     enum tree_code code;{  register tree t;  register int type = TREE_CODE_CLASS (code);  register int length;  register struct obstack *obstack = current_obstack;  register int i;  register tree_node_kind kind;  switch (type)    {    case 'd':  /* A decl node */#ifdef GATHER_STATISTICS      kind = d_kind;#endif      length = sizeof (struct tree_decl);      /* All decls in an inline function need to be saved.  */      if (obstack != &permanent_obstack)	obstack = saveable_obstack;      /* PARM_DECLs go on the context of the parent. If this is a nested	 function, then we must allocate the PARM_DECL on the parent's	 obstack, so that they will live to the end of the parent's	 closing brace.  This is necessary in case we try to inline the	 function into its parent.	 PARM_DECLs of top-level functions do not have this problem.  However,	 we allocate them where we put the FUNCTION_DECL for languages such as	 Ada that need to consult some flags in the PARM_DECLs of the function	 when calling it. 	 See comment in restore_tree_status for why we can't put this	 in function_obstack.  */      if (code == PARM_DECL && obstack != &permanent_obstack)	{	  tree context = 0;	  if (current_function_decl)	    context = decl_function_context (current_function_decl);	  if (context)	    obstack	      = find_function_data (context)->function_maybepermanent_obstack;	}      break;    case 't':  /* a type node */#ifdef GATHER_STATISTICS      kind = t_kind;#endif      length = sizeof (struct tree_type);      /* All data types are put where we can preserve them if nec.  */      if (obstack != &permanent_obstack)	obstack = all_types_permanent ? &permanent_obstack : saveable_obstack;      break;    case 'b':  /* a lexical block */#ifdef GATHER_STATISTICS      kind = b_kind;#endif      length = sizeof (struct tree_block);      /* All BLOCK nodes are put where we can preserve them if nec.  */      if (obstack != &permanent_obstack)	obstack = saveable_obstack;      break;    case 's':  /* an expression with side effects */#ifdef GATHER_STATISTICS      kind = s_kind;      goto usual_kind;#endif    case 'r':  /* a reference */#ifdef GATHER_STATISTICS      kind = r_kind;      goto usual_kind;#endif    case 'e':  /* an expression */    case '<':  /* a comparison expression */    case '1':  /* a unary arithmetic expression */    case '2':  /* a binary arithmetic expression */#ifdef GATHER_STATISTICS      kind = e_kind;    usual_kind:#endif      obstack = expression_obstack;      /* All BIND_EXPR nodes are put where we can preserve them if nec.  */      if (code == BIND_EXPR && obstack != &permanent_obstack)	obstack = saveable_obstack;      length = sizeof (struct tree_exp)	+ (tree_code_length[(int) code] - 1) * sizeof (char *);      break;    case 'c':  /* a constant */#ifdef GATHER_STATISTICS      kind = c_kind;#endif      obstack = expression_obstack;      /* We can't use tree_code_length for INTEGER_CST, since the number of	 words is machine-dependent due to varying length of HOST_WIDE_INT,	 which might be wider than a pointer (e.g., long long).  Similarly	 for REAL_CST, since the number of words is machine-dependent due	 to varying size and alignment of `double'.  */      if (code == INTEGER_CST)	length = sizeof (struct tree_int_cst);      else if (code == REAL_CST)	length = sizeof (struct tree_real_cst);      else	length = sizeof (struct tree_common)	  + tree_code_length[(int) code] * sizeof (char *);      break;    case 'x':  /* something random, like an identifier.  */#ifdef GATHER_STATISTICS      if (code == IDENTIFIER_NODE)	kind = id_kind;      else if (code == OP_IDENTIFIER)	kind = op_id_kind;      else if (code == TREE_VEC)	kind = vec_kind;      else	kind = x_kind;#endif      length = sizeof (struct tree_common)	+ tree_code_length[(int) code] * sizeof (char *);      /* Identifier nodes are always permanent since they are	 unique in a compiler run.  */      if (code == IDENTIFIER_NODE) obstack = &permanent_obstack;      break;    default:      abort ();    }  t = (tree) obstack_alloc (obstack, length);#ifdef GATHER_STATISTICS  tree_node_counts[(int)kind]++;  tree_node_sizes[(int)kind] += length;#endif  /* Clear a word at a time.  */  for (i = (length / sizeof (int)) - 1; i >= 0; i--)    ((int *) t)[i] = 0;  /* Clear any extra bytes.  */  for (i = length / sizeof (int) * sizeof (int); i < length; i++)    ((char *) t)[i] = 0;  TREE_SET_CODE (t, code);  if (obstack == &permanent_obstack)    TREE_PERMANENT (t) = 1;  switch (type)    {    case 's':      TREE_SIDE_EFFECTS (t) = 1;      TREE_TYPE (t) = void_type_node;      break;    case 'd':      if (code != FUNCTION_DECL)	DECL_ALIGN (t) = 1;      DECL_IN_SYSTEM_HEADER (t)	= in_system_header && (obstack == &permanent_obstack);      DECL_SOURCE_LINE (t) = lineno;      DECL_SOURCE_FILE (t) = (input_filename) ? input_filename : "<built-in>";      DECL_UID (t) = next_decl_uid++;      break;    case 't':      TYPE_UID (t) = next_type_uid++;      TYPE_ALIGN (t) = 1;      TYPE_MAIN_VARIANT (t) = t;      TYPE_OBSTACK (t) = obstack;      TYPE_ATTRIBUTES (t) = NULL_TREE;#ifdef SET_DEFAULT_TYPE_ATTRIBUTES      SET_DEFAULT_TYPE_ATTRIBUTES (t);#endif      break;    case 'c':      TREE_CONSTANT (t) = 1;      break;    }  return t;}/* Return a new node with the same contents as NODE   except that its TREE_CHAIN is zero and it has a fresh uid.  */treecopy_node (node)     tree node;{  register tree t;  register enum tree_code code = TREE_CODE (node);  register int length;  register int i;  switch (TREE_CODE_CLASS (code))    {    case 'd':  /* A decl node */      length = sizeof (struct tree_decl);      break;    case 't':  /* a type node */      length = sizeof (struct tree_type);      break;    case 'b':  /* a lexical block node */      length = sizeof (struct tree_block);      break;    case 'r':  /* a reference */    case 'e':  /* an expression */    case 's':  /* an expression with side effects */    case '<':  /* a comparison expression */    case '1':  /* a unary arithmetic expression */    case '2':  /* a binary arithmetic expression */      length = sizeof (struct tree_exp)	+ (tree_code_length[(int) code] - 1) * sizeof (char *);      break;    case 'c':  /* a constant */      /* We can't use tree_code_length for INTEGER_CST, since the number of	 words is machine-dependent due to varying length of HOST_WIDE_INT,	 which might be wider than a pointer (e.g., long long).  Similarly	 for REAL_CST, since the number of words is machine-dependent due	 to varying size and alignment of `double'.  */      if (code == INTEGER_CST)	length = sizeof (struct tree_int_cst);      else if (code == REAL_CST)	length = sizeof (struct tree_real_cst);      else	length = (sizeof (struct tree_common)		  + tree_code_length[(int) code] * sizeof (char *));      break;    case 'x':  /* something random, like an identifier.  */      length = sizeof (struct tree_common)	+ tree_code_length[(int) code] * sizeof (char *);      if (code == TREE_VEC)	length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *);    }  t = (tree) obstack_alloc (current_obstack, length);  for (i = (length / sizeof (int)) - 1; i >= 0; i--)    ((int *) t)[i] = ((int *) node)[i];  /* Clear any extra bytes.  */  for (i = length / sizeof (int) * sizeof (int); i < length; i++)    ((char *) t)[i] = ((char *) node)[i];  TREE_CHAIN (t) = 0;  TREE_ASM_WRITTEN (t) = 0;  if (TREE_CODE_CLASS (code) == 'd')    DECL_UID (t) = next_decl_uid++;  else if (TREE_CODE_CLASS (code) == 't')    {      TYPE_UID (t) = next_type_uid++;      TYPE_OBSTACK (t) = current_obstack;      /* The following is so that the debug code for	 the copy is different from the original type.	 The two statements usually duplicate each other	 (because they clear fields of the same union),	 but the optimizer should catch that.  */      TYPE_SYMTAB_POINTER (t) = 0;      TYPE_SYMTAB_ADDRESS (t) = 0;    }  TREE_PERMANENT (t) = (current_obstack == &permanent_obstack);  return t;}/* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.   For example, this can copy a list made of TREE_LIST nodes.  */treecopy_list (list)     tree list;{  tree head;  register tree prev, next;  if (list == 0)    return 0;  head = prev = copy_node (list);  next = TREE_CHAIN (list);  while (next)    {      TREE_CHAIN (prev) = copy_node (next);      prev = TREE_CHAIN (prev);      next = TREE_CHAIN (next);    }  return head;}#define HASHBITS 30/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).   If an identifier with that name has previously been referred to,   the same node is returned this time.  */treeget_identifier (text)     register char *text;{  register int hi;  register int i;  register tree idp;  register int len, hash_len;  /* Compute length of text in len.  */  for (len = 0; text[len]; len++);  /* Decide how much of that length to hash on */  hash_len = len;  if (warn_id_clash && len > id_clash_len)    hash_len = id_clash_len;  /* Compute hash code */  hi = hash_len * 613 + (unsigned) text[0];  for (i = 1; i < hash_len; i += 2)    hi = ((hi * 613) + (unsigned) (text[i]));  hi &= (1 << HASHBITS) - 1;  hi %= MAX_HASH_TABLE;    /* Search table for identifier */  for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))    if (IDENTIFIER_LENGTH (idp) == len	&& IDENTIFIER_POINTER (idp)[0] == text[0]	&& !bcmp (IDENTIFIER_POINTER (idp), text, len))      return idp;		/* <-- return if found */  /* Not found; optionally warn about a similar identifier */  if (warn_id_clash && do_identifier_warnings && len >= id_clash_len)    for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))      if (!strncmp (IDENTIFIER_POINTER (idp), text, id_clash_len))	{	  warning ("`%s' and `%s' identical in first %d characters",		   IDENTIFIER_POINTER (idp), text, id_clash_len);	  break;	}  if (tree_code_length[(int) IDENTIFIER_NODE] < 0)    abort ();			/* set_identifier_size hasn't been called.  */  /* Not found, create one, add to chain */  idp = make_node (IDENTIFIER_NODE);  IDENTIFIER_LENGTH (idp) = len;#ifdef GATHER_STATISTICS  id_string_size += len;#endif  IDENTIFIER_POINTER (idp) = obstack_copy0 (&permanent_obstack, text, len);  TREE_CHAIN (idp) = hash_table[hi];  hash_table[hi] = idp;  return idp;			/* <-- return if created */}/* If an identifier with the name TEXT (a null-terminated string) has   previously been referred to, return that node; otherwise return   NULL_TREE.  */treemaybe_get_identifier (text)     register char *text;{  register int hi;  register int i;  register tree idp;  register int len, hash_len;  /* Compute length of text in len.  */  for (len = 0; text[len]; len++);  /* Decide how much of that length to hash on */  hash_len = len;  if (warn_id_clash && len > id_clash_len)    hash_len = id_clash_len;  /* Compute hash code */  hi = hash_len * 613 + (unsigned) text[0];  for (i = 1; i < hash_len; i += 2)    hi = ((hi * 613) + (unsigned) (text[i]));  hi &= (1 << HASHBITS) - 1;  hi %= MAX_HASH_TABLE;    /* Search table for identifier */  for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))    if (IDENTIFIER_LENGTH (idp) == len	&& IDENTIFIER_POINTER (idp)[0] == text[0]	&& !bcmp (IDENTIFIER_POINTER (idp), text, len))      return idp;		/* <-- return if found */  return NULL_TREE;}/* Enable warnings on similar identifiers (if requested).   Done after the built-in identifiers are created.  */voidstart_identifier_warnings (){  do_identifier_warnings = 1;}/* Record the size of an identifier node for the language in use.   SIZE is the total size in bytes.   This is called by the language-specific files.  This must be   called before allocating any identifiers.  */voidset_identifier_size (size)     int size;{  tree_code_length[(int) IDENTIFIER_NODE]    = (size - sizeof (struct tree_common)) / sizeof (tree);}/* Return a newly constructed INTEGER_CST node whose constant value   is specified by the two ints LOW and HI.   The TREE_TYPE is set to `int'.    This function should be used via the `build_int_2' macro.  */treebuild_int_2_wide (low, hi)     HOST_WIDE_INT low, hi;{  register tree t = make_node (INTEGER_CST);  TREE_INT_CST_LOW (t) = low;  TREE_INT_CST_HIGH (t) = hi;  TREE_TYPE (t) = integer_type_node;  return t;}/* Return a new REAL_CST node whose type is TYPE and value is D.  */treebuild_real (type, d)     tree type;     REAL_VALUE_TYPE d;{  tree v;  int overflow = 0;  /* Check for valid float value for this type on this target machine;     if not, can print error message and store a valid value in D.  */#ifdef CHECK_FLOAT_VALUE  CHECK_FLOAT_VALUE (TYPE_MODE (type), d, overflow);#endif  v = make_node (REAL_CST);  TREE_TYPE (v) = type;  TREE_REAL_CST (v) = d;  TREE_OVERFLOW (v) = TREE_CONSTANT_OVERFLOW (v) = overflow;  return v;}/* Return a new REAL_CST node whose type is TYPE   and whose value is the integer value of the INTEGER_CST node I.  */#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)REAL_VALUE_TYPEreal_value_from_int_cst (type, i)

⌨️ 快捷键说明

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