📄 tree.c
字号:
/* 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); break; } else if (code == REAL_CST) { length = sizeof (struct tree_real_cst); 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; 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; } 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 */}/* 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 (i) tree i;{ REAL_VALUE_TYPE d; REAL_VALUE_TYPE e; /* Some 386 compilers mishandle unsigned int to float conversions, so introduce a temporary variable E to avoid those bugs. */#ifdef REAL_ARITHMETIC if (! TREE_UNSIGNED (TREE_TYPE (i))) REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i)); else REAL_VALUE_FROM_UNSIGNED_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i));#else /* not REAL_ARITHMETIC */ if (TREE_INT_CST_HIGH (i) < 0 && ! TREE_UNSIGNED (TREE_TYPE (i))) { d = (double) (~ TREE_INT_CST_HIGH (i)); e = ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))); d *= e; e = (double) (unsigned HOST_WIDE_INT) (~ TREE_INT_CST_LOW (i)); d += e; d = (- d - 1.0); } else { d = (double) (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (i); e = ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))); d *= e; e = (double) (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (i); d += e; }#endif /* not REAL_ARITHMETIC */ return d;}/* This function can't be implemented if we can't do arithmetic on the float representation. */treebuild_real_from_int_cst (type, i) tree type; tree i;{ tree v; int overflow = TREE_OVERFLOW (i); REAL_VALUE_TYPE d; jmp_buf float_error; v = make_node (REAL_CST); TREE_TYPE (v) = type; if (setjmp (float_error)) { d = dconst0; overflow = 1; goto got_it; } set_float_handler (float_error); d = REAL_VALUE_TRUNCATE (TYPE_MODE (type), real_value_from_int_cst (i)); /* Check for valid float value for this type on this target machine. */ got_it: set_float_handler (NULL_PTR);#ifdef CHECK_FLOAT_VALUE CHECK_FLOAT_VALUE (TYPE_MODE (type), d, overflow);#endif TREE_REAL_CST (v) = d; TREE_OVERFLOW (v) = TREE_CONSTANT_OVERFLOW (v) = overflow; return v;}#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC *//* Return a newly constructed STRING_CST node whose value is the LEN characters at STR. The TREE_TYPE is not initialized. */treebuild_string (len, str) int len; char *str;{ /* Put the string in saveable_obstack since it will be placed in the RTL for an "asm" statement and will also be kept around a while if deferring constant output in varasm.c. */ register tree s = make_node (STRING_CST); TREE_STRING_LENGTH (s) = len; TREE_STRING_POINTER (s) = obstack_copy0 (saveable_obstack, str, len); return s;}/* Return a newly constructed COMPLEX_CST node whose value is specified by the real and imaginary parts REAL and IMAG. Both REAL and IMAG should be constant nodes. The TREE_TYPE is not initialized. */treebuild_complex (real, imag) tree real, imag;{ register tree t = make_node (COMPLEX_CST); TREE_REALPART (t) = real; TREE_IMAGPART (t) = imag;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -