📄 tree.c
字号:
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; for (i = 0; i < hash_len; i++) 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 && !strcmp (IDENTIFIER_POINTER (idp), text)) 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 n characters", IDENTIFIER_POINTER (idp), text); break; } /* Not found, create one, add to chain */ idp = make_node (IDENTIFIER_NODE); IDENTIFIER_LENGTH (idp) = len; 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. This is called by the language-specific files. */voidset_identifier_size (size) int size;{ tree_code_length[(int) IDENTIFIER_NODE] = size;}/* 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'. */treebuild_int_2 (low, hi) 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; /* 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);#endif v = make_node (REAL_CST); TREE_TYPE (v) = type; TREE_REAL_CST (v) = d; 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;#ifdef REAL_ARITHMETIC REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i));#else /* not REAL_ARITHMETIC */ if (TREE_INT_CST_HIGH (i) < 0) {#define MASK ((unsigned)1 << (HOST_BITS_PER_INT - 1)) d = (double) (~ TREE_INT_CST_HIGH (i)); d *= ((double) (1 << (HOST_BITS_PER_INT / 2)) * (double) (1 << (HOST_BITS_PER_INT / 2))); /* The following four lines are equivalent to converting ~ TREE_INT_CST_LOW (i) from unsigned to double, but that is broken in some compilers. */ if (((~ TREE_INT_CST_LOW (i)) & MASK) != 0) d += ((double) MASK + (double) ((~ MASK) & ~ TREE_INT_CST_LOW (i))); else d += (double) (unsigned) (~ TREE_INT_CST_LOW (i)); d = (- d - 1.0); } else { d = (double) TREE_INT_CST_HIGH (i); d *= ((double) (1 << (HOST_BITS_PER_INT / 2)) * (double) (1 << (HOST_BITS_PER_INT / 2))); if ((TREE_INT_CST_LOW (i) & MASK) != 0) d += ((double) MASK + (double) ((~ MASK) & TREE_INT_CST_LOW (i))); else d += (double) (unsigned) TREE_INT_CST_LOW (i); }#undef MASK#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; REAL_VALUE_TYPE d; v = make_node (REAL_CST); TREE_TYPE (v) = type; d = real_value_from_int_cst (i); /* 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);#endif TREE_REAL_CST (v) = d; 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;{ 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; return t;}/* Return 1 if EXPR is the integer constant zero. */intinteger_zerop (expr) tree expr;{ return (TREE_CODE (expr) == INTEGER_CST && TREE_INT_CST_LOW (expr) == 0 && TREE_INT_CST_HIGH (expr) == 0);}/* Return 1 if EXPR is the integer constant one. */intinteger_onep (expr) tree expr;{ return (TREE_CODE (expr) == INTEGER_CST && TREE_INT_CST_LOW (expr) == 1 && TREE_INT_CST_HIGH (expr) == 0);}/* Return 1 if EXPR is an integer containing all 1's in as much precision as it contains. */intinteger_all_onesp (expr) tree expr;{ register int prec; register int uns; if (TREE_CODE (expr) != INTEGER_CST) return 0; uns = TREE_UNSIGNED (TREE_TYPE (expr)); if (!uns) return TREE_INT_CST_LOW (expr) == -1 && TREE_INT_CST_HIGH (expr) == -1; prec = TYPE_PRECISION (TREE_TYPE (expr)); if (prec >= HOST_BITS_PER_INT) return TREE_INT_CST_LOW (expr) == -1 && TREE_INT_CST_HIGH (expr) == (1 << (prec - HOST_BITS_PER_INT)) - 1; else return TREE_INT_CST_LOW (expr) == (1 << prec) - 1;}/* 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;{ tree t; if (op1) { for (t = op1; TREE_CHAIN (t); t = TREE_CHAIN (t)) if (t == op2) abort (); /* Circularity being created */ TREE_CHAIN (t) = op2; return op1; } else return op2;}/* 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;}/* 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;{ register tree node = make_node (TREE_LIST); TREE_CHAIN (node) = chain; TREE_PURPOSE (node) = purpose; TREE_VALUE (node) = value; 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 = make_node (TREE_LIST); TREE_CHAIN (node) = chain; TREE_PURPOSE (node) = purpose; TREE_VALUE (node) = value; 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 = make_node (TREE_LIST); TREE_CHAIN (node) = chain; TREE_PURPOSE (node) = purpose; TREE_VALUE (node) = value; 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 = make_node (TREE_LIST); TREE_CHAIN (node) = chain; TREE_PURPOSE (node) = purpose; TREE_VALUE (node) = value; current_obstack = ambient_obstack; return node;}/* 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;}/* 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 convert_units (TYPE_SIZE (type), TYPE_SIZE_UNIT (type), 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)) * TYPE_SIZE_UNIT (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;{ register enum tree_code code = TREE_CODE (arg); if ((code == VAR_DECL || code == FUNCTION_DECL || code == CONSTRUCTOR) && (TREE_STATIC (arg) || TREE_EXTERNAL (arg))) return 1; if (code == STRING_CST) return 1; if (code == COMPONENT_REF) return (DECL_VOFFSET (TREE_OPERAND (arg, 1)) == 0 && staticp (TREE_OPERAND (arg, 0))); if (code == INDIRECT_REF) return TREE_LITERAL (TREE_OPERAND (arg, 0)); if (code == 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;}/* Return nonzero if REF is an lvalue valid for this language. Lvalues can be assigned, unless they have TREE_READONLY. Lvalues can have their address taken, unless they have TREE_REGDECL. */intlvalue_p (ref) tree ref;{ register enum tree_code code = TREE_CODE (ref); if (language_lvalue_valid (ref)) switch (code) { case COMPONENT_REF: return lvalue_p (TREE_OPERAND (ref, 0)); case STRING_CST: return 1; case INDIRECT_REF: case ARRAY_REF: case VAR_DECL: case PARM_DECL: case RESULT_DECL: case ERROR_MARK: if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) return 1; break; case NEW_EXPR: return 1; case CALL_EXPR: if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) return 1; } return 0;}/* Return nonzero if REF is an lvalue valid for this language; otherwise, print an error message and return zero. */intlvalue_or_else (ref, string) tree ref; char *string;{ int win = lvalue_p (ref); if (! win) error ("invalid lvalue in %s", string); return win;}/* 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -