diff options
author | kan <kan@FreeBSD.org> | 2004-07-28 03:11:36 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2004-07-28 03:11:36 +0000 |
commit | 5e00ec74d8ce58f99801200d4d3d0412c7cc1b28 (patch) | |
tree | 052f4bb635f2bea2c5e350bd60c902be100a0d1e /contrib/gcc/tree.c | |
parent | 87b8398a7d9f9bf0e28bbcd54a4fc27db2125f38 (diff) | |
download | FreeBSD-src-5e00ec74d8ce58f99801200d4d3d0412c7cc1b28.zip FreeBSD-src-5e00ec74d8ce58f99801200d4d3d0412c7cc1b28.tar.gz |
Gcc 3.4.2 20040728.
Diffstat (limited to 'contrib/gcc/tree.c')
-rw-r--r-- | contrib/gcc/tree.c | 1661 |
1 files changed, 903 insertions, 758 deletions
diff --git a/contrib/gcc/tree.c b/contrib/gcc/tree.c index e8c2541..32f1c18 100644 --- a/contrib/gcc/tree.c +++ b/contrib/gcc/tree.c @@ -1,6 +1,6 @@ /* Language-independent node constructors for parse phase of GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -31,6 +31,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "flags.h" #include "tree.h" #include "real.h" @@ -45,32 +47,15 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "langhooks.h" /* obstack.[ch] explicitly declined to prototype this. */ -extern int _obstack_allocated_p PARAMS ((struct obstack *h, PTR obj)); +extern int _obstack_allocated_p (struct obstack *h, void *obj); #ifdef GATHER_STATISTICS /* Statistics-gathering stuff. */ -typedef enum -{ - d_kind, - t_kind, - b_kind, - s_kind, - r_kind, - e_kind, - c_kind, - id_kind, - perm_list_kind, - temp_list_kind, - vec_kind, - x_kind, - lang_decl, - lang_type, - all_kinds -} tree_node_kind; int tree_node_counts[(int) all_kinds]; int tree_node_sizes[(int) all_kinds]; +/* Keep in sync with tree.h:enum tree_node_kind. */ static const char * const tree_node_kind_names[] = { "decls", "types", @@ -90,9 +75,9 @@ static const char * const tree_node_kind_names[] = { #endif /* GATHER_STATISTICS */ /* Unique id for next decl created. */ -static int next_decl_uid; +static GTY(()) int next_decl_uid; /* Unique id for next type created. */ -static int next_type_uid = 1; +static GTY(()) int next_type_uid = 1; /* Since we cannot rehash a type after it is in the table, we have to keep the hash code. */ @@ -116,14 +101,13 @@ struct type_hash GTY(()) static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash))) htab_t type_hash_table; -static void set_type_quals PARAMS ((tree, int)); -static void append_random_chars PARAMS ((char *)); -static int type_hash_eq PARAMS ((const void *, const void *)); -static hashval_t type_hash_hash PARAMS ((const void *)); -static void print_type_hash_statistics PARAMS((void)); -static void finish_vector_type PARAMS((tree)); -static tree make_vector PARAMS ((enum machine_mode, tree, int)); -static int type_hash_marked_p PARAMS ((const void *)); +static void set_type_quals (tree, int); +static int type_hash_eq (const void *, const void *); +static hashval_t type_hash_hash (const void *); +static void print_type_hash_statistics (void); +static void finish_vector_type (tree); +static tree make_vector (enum machine_mode, tree, int); +static int type_hash_marked_p (const void *); tree global_trees[TI_MAX]; tree integer_types[itk_none]; @@ -131,11 +115,11 @@ tree integer_types[itk_none]; /* Init tree.c. */ void -init_ttree () +init_ttree (void) { /* Initialize the hash table of types. */ - type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash, - type_hash_eq, 0); + type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash, + type_hash_eq, 0); } @@ -143,8 +127,7 @@ init_ttree () translations made by ASM_OUTPUT_LABELREF). Often this is the same as DECL_NAME. It is an IDENTIFIER_NODE. */ tree -decl_assembler_name (decl) - tree decl; +decl_assembler_name (tree decl) { if (!DECL_ASSEMBLER_NAME_SET_P (decl)) (*lang_hooks.set_decl_assembler_name) (decl); @@ -154,8 +137,7 @@ decl_assembler_name (decl) /* Compute the number of bytes occupied by 'node'. This routine only looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH. */ size_t -tree_size (node) - tree node; +tree_size (tree node) { enum tree_code code = TREE_CODE (node); @@ -180,28 +162,32 @@ tree_size (node) + TREE_CODE_LENGTH (code) * sizeof (char *) - sizeof (char *)); 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) - return sizeof (struct tree_int_cst); - else if (code == REAL_CST) - return sizeof (struct tree_real_cst); - else - return (sizeof (struct tree_common) - + TREE_CODE_LENGTH (code) * sizeof (char *)); + switch (code) + { + case INTEGER_CST: return sizeof (struct tree_int_cst); + case REAL_CST: return sizeof (struct tree_real_cst); + case COMPLEX_CST: return sizeof (struct tree_complex); + case VECTOR_CST: return sizeof (struct tree_vector); + case STRING_CST: return sizeof (struct tree_string); + default: + return (*lang_hooks.tree_size) (code); + } case 'x': /* something random, like an identifier. */ - { - size_t length; - length = (sizeof (struct tree_common) - + TREE_CODE_LENGTH (code) * sizeof (char *)); - if (code == TREE_VEC) - length += TREE_VEC_LENGTH (node) * sizeof (char *) - sizeof (char *); - return length; - } + switch (code) + { + case IDENTIFIER_NODE: return lang_hooks.identifier_size; + case TREE_LIST: return sizeof (struct tree_list); + case TREE_VEC: return (sizeof (struct tree_vec) + + TREE_VEC_LENGTH(node) * sizeof(char *) + - sizeof (char *)); + + case ERROR_MARK: + case PLACEHOLDER_EXPR: return sizeof (struct tree_common); + + default: + return (*lang_hooks.tree_size) (code); + } default: abort (); @@ -215,8 +201,7 @@ tree_size (node) Achoo! I got a code in the node. */ tree -make_node (code) - enum tree_code code; +make_node (enum tree_code code) { tree t; int type = TREE_CODE_CLASS (code); @@ -287,7 +272,7 @@ make_node (code) t = ggc_alloc_tree (length); - memset ((PTR) t, 0, length); + memset (t, 0, length); TREE_SET_CODE (t, code); @@ -295,7 +280,6 @@ make_node (code) { case 's': TREE_SIDE_EFFECTS (t) = 1; - TREE_TYPE (t) = void_type_node; break; case 'd': @@ -303,9 +287,7 @@ make_node (code) DECL_ALIGN (t) = 1; DECL_USER_ALIGN (t) = 0; DECL_IN_SYSTEM_HEADER (t) = in_system_header; - DECL_SOURCE_LINE (t) = lineno; - DECL_SOURCE_FILE (t) = - (input_filename) ? input_filename : "<built-in>"; + DECL_SOURCE_LOCATION (t) = input_location; DECL_UID (t) = next_decl_uid++; /* We have not yet computed the alias set for this declaration. */ @@ -359,8 +341,7 @@ make_node (code) TREE_CHAIN is zero and it has a fresh uid. */ tree -copy_node (node) - tree node; +copy_node (tree node) { tree t; enum tree_code code = TREE_CODE (node); @@ -394,8 +375,7 @@ copy_node (node) For example, this can copy a list made of TREE_LIST nodes. */ tree -copy_list (list) - tree list; +copy_list (tree list) { tree head; tree prev, next; @@ -422,9 +402,7 @@ copy_list (list) This function should be used via the `build_int_2' macro. */ tree -build_int_2_wide (low, hi) - unsigned HOST_WIDE_INT low; - HOST_WIDE_INT hi; +build_int_2_wide (unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) { tree t = make_node (INTEGER_CST); @@ -438,8 +416,7 @@ build_int_2_wide (low, hi) are in a list pointed by VALS. */ tree -build_vector (type, vals) - tree type, vals; +build_vector (tree type, tree vals) { tree v = make_node (VECTOR_CST); int over1 = 0, over2 = 0; @@ -463,12 +440,32 @@ build_vector (type, vals) return v; } +/* Return a new CONSTRUCTOR node whose type is TYPE and whose values + are in a list pointed to by VALS. */ +tree +build_constructor (tree type, tree vals) +{ + tree c = make_node (CONSTRUCTOR); + TREE_TYPE (c) = type; + CONSTRUCTOR_ELTS (c) = vals; + + /* ??? May not be necessary. Mirrors what build does. */ + if (vals) + { + TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS (vals); + TREE_READONLY (c) = TREE_READONLY (vals); + TREE_CONSTANT (c) = TREE_CONSTANT (vals); + } + else + TREE_CONSTANT (c) = 0; /* safe side */ + + return c; +} + /* Return a new REAL_CST node whose type is TYPE and value is D. */ tree -build_real (type, d) - tree type; - REAL_VALUE_TYPE d; +build_real (tree type, REAL_VALUE_TYPE d) { tree v; REAL_VALUE_TYPE *dp; @@ -491,21 +488,17 @@ build_real (type, d) and whose value is the integer value of the INTEGER_CST node I. */ REAL_VALUE_TYPE -real_value_from_int_cst (type, i) - tree type ATTRIBUTE_UNUSED, i; +real_value_from_int_cst (tree type, tree i) { REAL_VALUE_TYPE d; /* Clear all bits of the real value type so that we can later do bitwise comparisons to see if two values are the same. */ - memset ((char *) &d, 0, sizeof d); + memset (&d, 0, sizeof d); - if (! TREE_UNSIGNED (TREE_TYPE (i))) - REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i), - TYPE_MODE (type)); - else - REAL_VALUE_FROM_UNSIGNED_INT (d, TREE_INT_CST_LOW (i), - TREE_INT_CST_HIGH (i), TYPE_MODE (type)); + real_from_integer (&d, type ? TYPE_MODE (type) : VOIDmode, + TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i), + TREE_UNSIGNED (TREE_TYPE (i))); return d; } @@ -513,9 +506,7 @@ real_value_from_int_cst (type, i) representing the same value as a floating-point constant of type TYPE. */ tree -build_real_from_int_cst (type, i) - tree type; - tree i; +build_real_from_int_cst (tree type, tree i) { tree v; int overflow = TREE_OVERFLOW (i); @@ -532,9 +523,7 @@ build_real_from_int_cst (type, i) The TREE_TYPE is not initialized. */ tree -build_string (len, str) - int len; - const char *str; +build_string (int len, const char *str) { tree s = make_node (STRING_CST); @@ -550,9 +539,7 @@ build_string (len, str) will be the type of the COMPLEX_CST; otherwise a new type will be made. */ tree -build_complex (type, real, imag) - tree type; - tree real, imag; +build_complex (tree type, tree real, tree imag) { tree t = make_node (COMPLEX_CST); @@ -568,8 +555,7 @@ build_complex (type, real, imag) /* Build a newly constructed TREE_VEC node of length LEN. */ tree -make_tree_vec (len) - int len; +make_tree_vec (int len) { tree t; int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec); @@ -581,7 +567,7 @@ make_tree_vec (len) t = ggc_alloc_tree (length); - memset ((PTR) t, 0, length); + memset (t, 0, length); TREE_SET_CODE (t, TREE_VEC); TREE_VEC_LENGTH (t) = len; @@ -592,8 +578,7 @@ make_tree_vec (len) of zero. */ int -integer_zerop (expr) - tree expr; +integer_zerop (tree expr) { STRIP_NOPS (expr); @@ -610,8 +595,7 @@ integer_zerop (expr) complex constant. */ int -integer_onep (expr) - tree expr; +integer_onep (tree expr) { STRIP_NOPS (expr); @@ -628,8 +612,7 @@ integer_onep (expr) it contains. Likewise for the corresponding complex constant. */ int -integer_all_onesp (expr) - tree expr; +integer_all_onesp (tree expr) { int prec; int uns; @@ -681,8 +664,7 @@ integer_all_onesp (expr) one bit on). */ int -integer_pow2p (expr) - tree expr; +integer_pow2p (tree expr) { int prec; HOST_WIDE_INT high, low; @@ -723,12 +705,28 @@ integer_pow2p (expr) || (low == 0 && (high & (high - 1)) == 0)); } +/* Return 1 if EXPR is an integer constant other than zero or a + complex constant other than zero. */ + +int +integer_nonzerop (tree expr) +{ + STRIP_NOPS (expr); + + return ((TREE_CODE (expr) == INTEGER_CST + && ! TREE_CONSTANT_OVERFLOW (expr) + && (TREE_INT_CST_LOW (expr) != 0 + || TREE_INT_CST_HIGH (expr) != 0)) + || (TREE_CODE (expr) == COMPLEX_CST + && (integer_nonzerop (TREE_REALPART (expr)) + || integer_nonzerop (TREE_IMAGPART (expr))))); +} + /* Return the power of two represented by a tree node known to be a power of two. */ int -tree_log2 (expr) - tree expr; +tree_log2 (tree expr) { int prec; HOST_WIDE_INT high, low; @@ -766,8 +764,7 @@ tree_log2 (expr) than or equal to EXPR. */ int -tree_floor_log2 (expr) - tree expr; +tree_floor_log2 (tree expr) { int prec; HOST_WIDE_INT high, low; @@ -805,8 +802,7 @@ tree_floor_log2 (expr) /* Return 1 if EXPR is the real constant zero. */ int -real_zerop (expr) - tree expr; +real_zerop (tree expr) { STRIP_NOPS (expr); @@ -821,8 +817,7 @@ real_zerop (expr) /* Return 1 if EXPR is the real constant one in real or complex form. */ int -real_onep (expr) - tree expr; +real_onep (tree expr) { STRIP_NOPS (expr); @@ -837,8 +832,7 @@ real_onep (expr) /* Return 1 if EXPR is the real constant two. */ int -real_twop (expr) - tree expr; +real_twop (tree expr) { STRIP_NOPS (expr); @@ -853,8 +847,7 @@ real_twop (expr) /* Return 1 if EXPR is the real constant minus one. */ int -real_minus_onep (expr) - tree expr; +real_minus_onep (tree expr) { STRIP_NOPS (expr); @@ -869,8 +862,7 @@ real_minus_onep (expr) /* Nonzero if EXP is a constant or a cast of a constant. */ int -really_constant_p (exp) - tree exp; +really_constant_p (tree exp) { /* This is not quite the same as STRIP_NOPS. It does more. */ while (TREE_CODE (exp) == NOP_EXPR @@ -884,8 +876,7 @@ really_constant_p (exp) Return 0 if ELEM is not in LIST. */ tree -value_member (elem, list) - tree elem, list; +value_member (tree elem, tree list) { while (list) { @@ -900,8 +891,7 @@ value_member (elem, list) Return 0 if ELEM is not in LIST. */ tree -purpose_member (elem, list) - tree elem, list; +purpose_member (tree elem, tree list) { while (list) { @@ -916,8 +906,7 @@ purpose_member (elem, list) Return 0 if ELEM is not in LIST. */ tree -binfo_member (elem, list) - tree elem, list; +binfo_member (tree elem, tree list) { while (list) { @@ -931,8 +920,7 @@ binfo_member (elem, list) /* Return nonzero if ELEM is part of the chain CHAIN. */ int -chain_member (elem, chain) - tree elem, chain; +chain_member (tree elem, tree chain) { while (chain) { @@ -944,48 +932,12 @@ chain_member (elem, chain) return 0; } -/* Return nonzero if ELEM is equal to TREE_VALUE (CHAIN) for any piece of - chain CHAIN. This and the next function are currently unused, but - are retained for completeness. */ - -int -chain_member_value (elem, chain) - tree elem, chain; -{ - while (chain) - { - if (elem == TREE_VALUE (chain)) - return 1; - chain = TREE_CHAIN (chain); - } - - return 0; -} - -/* Return nonzero if ELEM is equal to TREE_PURPOSE (CHAIN) - for any piece of chain CHAIN. */ - -int -chain_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'. */ int -list_length (t) - tree t; +list_length (tree t) { tree tail; int len = 0; @@ -999,8 +951,7 @@ list_length (t) /* Returns the number of FIELD_DECLs in TYPE. */ int -fields_length (type) - tree type; +fields_length (tree type) { tree t = TYPE_FIELDS (type); int count = 0; @@ -1017,36 +968,35 @@ fields_length (type) This is the Lisp primitive `nconc'. */ tree -chainon (op1, op2) - tree op1, op2; +chainon (tree op1, tree op2) { + tree t1; - if (op1) - { - tree t1; -#ifdef ENABLE_TREE_CHECKING - tree t2; -#endif + if (!op1) + return op2; + if (!op2) + return op1; + + for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1)) + continue; + TREE_CHAIN (t1) = op2; - for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1)) - ; - TREE_CHAIN (t1) = op2; #ifdef ENABLE_TREE_CHECKING - for (t2 = op2; t2; t2 = TREE_CHAIN (t2)) - if (t2 == t1) - abort (); /* Circularity created. */ + { + tree t2; + for (t2 = op2; t2; t2 = TREE_CHAIN (t2)) + if (t2 == t1) + abort (); /* Circularity created. */ + } #endif - return op1; - } - else - return op2; + + return op1; } /* Return the last node in a chain of nodes (chained through TREE_CHAIN). */ tree -tree_last (chain) - tree chain; +tree_last (tree chain) { tree next; if (chain) @@ -1059,8 +1009,7 @@ tree_last (chain) and return the new head of the chain (old last element). */ tree -nreverse (t) - tree t; +nreverse (tree t) { tree prev = 0, decl, next; for (decl = t; decl; decl = next) @@ -1071,38 +1020,12 @@ nreverse (t) } return prev; } - -/* Given a chain CHAIN of tree nodes, - construct and return a list of those nodes. */ - -tree -listify (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. */ tree -build_tree_list (parm, value) - tree parm, value; +build_tree_list (tree parm, tree value) { tree t = make_node (TREE_LIST); TREE_PURPOSE (t) = parm; @@ -1111,12 +1034,11 @@ build_tree_list (parm, value) } /* Return a newly created TREE_LIST node whose - purpose and value fields are PARM and VALUE + purpose and value fields are PURPOSE and VALUE and whose TREE_CHAIN is CHAIN. */ tree -tree_cons (purpose, value, chain) - tree purpose, value, chain; +tree_cons (tree purpose, tree value, tree chain) { tree node; @@ -1136,6 +1058,44 @@ tree_cons (purpose, value, chain) return node; } +/* Return the first expression in a sequence of COMPOUND_EXPRs. */ + +tree +expr_first (tree expr) +{ + if (expr == NULL_TREE) + return expr; + while (TREE_CODE (expr) == COMPOUND_EXPR) + expr = TREE_OPERAND (expr, 0); + return expr; +} + +/* Return the last expression in a sequence of COMPOUND_EXPRs. */ + +tree +expr_last (tree expr) +{ + if (expr == NULL_TREE) + return expr; + while (TREE_CODE (expr) == COMPOUND_EXPR) + expr = TREE_OPERAND (expr, 1); + return expr; +} + +/* Return the number of subexpressions in a sequence of COMPOUND_EXPRs. */ + +int +expr_length (tree expr) +{ + int len = 0; + + if (expr == NULL_TREE) + return 0; + for (; TREE_CODE (expr) == COMPOUND_EXPR; expr = TREE_OPERAND (expr, 1)) + len += expr_length (TREE_OPERAND (expr, 0)); + ++len; + return len; +} /* Return the size nominally occupied by an object of type TYPE when it resides in memory. The value is measured in units of bytes, @@ -1144,8 +1104,7 @@ tree_cons (purpose, value, chain) make_unsigned_type). */ tree -size_in_bytes (type) - tree type; +size_in_bytes (tree type) { tree t; @@ -1171,8 +1130,7 @@ size_in_bytes (type) or return -1 if the size can vary or is larger than an integer. */ HOST_WIDE_INT -int_size_in_bytes (type) - tree type; +int_size_in_bytes (tree type) { tree t; @@ -1196,10 +1154,8 @@ int_size_in_bytes (type) This is a tree of type bitsizetype. */ tree -bit_position (field) - tree field; +bit_position (tree field) { - return bit_from_pos (DECL_FIELD_OFFSET (field), DECL_FIELD_BIT_OFFSET (field)); } @@ -1209,8 +1165,7 @@ bit_position (field) of returning -1 like int_size_in_byte can. */ HOST_WIDE_INT -int_bit_position (field) - tree field; +int_bit_position (tree field) { return tree_low_cst (bit_position (field), 0); } @@ -1219,8 +1174,7 @@ int_bit_position (field) This is a tree of type sizetype. */ tree -byte_position (field) - tree field; +byte_position (tree field) { return byte_from_pos (DECL_FIELD_OFFSET (field), DECL_FIELD_BIT_OFFSET (field)); @@ -1231,8 +1185,7 @@ byte_position (field) of returning -1 like int_size_in_byte can. */ HOST_WIDE_INT -int_byte_position (field) - tree field; +int_byte_position (tree field) { return tree_low_cst (byte_position (field), 0); } @@ -1240,8 +1193,7 @@ int_byte_position (field) /* Return the strictest alignment, in bits, that T is known to have. */ unsigned int -expr_align (t) - tree t; +expr_align (tree t) { unsigned int align0, align1; @@ -1288,8 +1240,7 @@ expr_align (t) ARRAY_TYPE) minus one. This counts only elements of the top array. */ tree -array_type_nelts (type) - tree type; +array_type_nelts (tree type) { tree index_type, min, max; @@ -1311,8 +1262,7 @@ array_type_nelts (type) static storage. This is not the same as the C meaning of `static'. */ int -staticp (arg) - tree arg; +staticp (tree arg) { switch (TREE_CODE (arg)) { @@ -1389,39 +1339,24 @@ staticp (arg) are used for. */ tree -save_expr (expr) - tree expr; +save_expr (tree expr) { tree t = fold (expr); tree inner; - /* 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 we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and - a constant, it will be more efficient to not make another SAVE_EXPR since - it will allow better simplification and GCSE will be able to merge the - computations if they actualy occur. */ - for (inner = t; - (TREE_CODE_CLASS (TREE_CODE (inner)) == '1' - || (TREE_CODE_CLASS (TREE_CODE (inner)) == '2' - && TREE_CONSTANT (TREE_OPERAND (inner, 1)))); - inner = TREE_OPERAND (inner, 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. */ + inner = skip_simple_arithmetic (t); if (TREE_CONSTANT (inner) || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner)) - || TREE_CODE (inner) == SAVE_EXPR || TREE_CODE (inner) == ERROR_MARK) + || TREE_CODE (inner) == SAVE_EXPR + || TREE_CODE (inner) == ERROR_MARK) return t; - /* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since + /* If INNER 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. @@ -1430,7 +1365,7 @@ save_expr (expr) 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)) + if (contains_placeholder_p (inner)) return t; t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE); @@ -1443,13 +1378,59 @@ save_expr (expr) return t; } +/* Look inside EXPR and into any simple arithmetic operations. Return + the innermost non-arithmetic node. */ + +tree +skip_simple_arithmetic (tree expr) +{ + tree inner; + + /* We don't care about whether this can be used as an lvalue in this + context. */ + while (TREE_CODE (expr) == NON_LVALUE_EXPR) + expr = TREE_OPERAND (expr, 0); + + /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and + a constant, it will be more efficient to not make another SAVE_EXPR since + it will allow better simplification and GCSE will be able to merge the + computations if they actually occur. */ + inner = expr; + while (1) + { + if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1') + inner = TREE_OPERAND (inner, 0); + else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2') + { + if (TREE_CONSTANT (TREE_OPERAND (inner, 1))) + inner = TREE_OPERAND (inner, 0); + else if (TREE_CONSTANT (TREE_OPERAND (inner, 0))) + inner = TREE_OPERAND (inner, 1); + else + break; + } + else + break; + } + + return inner; +} + +/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a + SAVE_EXPR. Return FALSE otherwise. */ + +bool +saved_expr_p (tree expr) +{ + return TREE_CODE (skip_simple_arithmetic (expr)) == SAVE_EXPR; +} + /* Arrange for an expression to be expanded multiple independent times. This is useful for cleanup actions, as the backend can expand them multiple times in different places. */ tree -unsave_expr (expr) - tree expr; +unsave_expr (tree expr) { tree t; @@ -1466,8 +1447,7 @@ unsave_expr (expr) of operands if all are trees. */ int -first_rtl_op (code) - enum tree_code code; +first_rtl_op (enum tree_code code) { switch (code) { @@ -1478,8 +1458,6 @@ first_rtl_op (code) return 0; case WITH_CLEANUP_EXPR: return 2; - case METHOD_CALL_EXPR: - return 3; default: return TREE_CODE_LENGTH (code); } @@ -1488,17 +1466,16 @@ first_rtl_op (code) /* Return which tree structure is used by T. */ enum tree_node_structure_enum -tree_node_structure (t) - tree t; +tree_node_structure (tree t) { enum tree_code code = TREE_CODE (t); - + switch (TREE_CODE_CLASS (code)) { case 'd': return TS_DECL; case 't': return TS_TYPE; case 'b': return TS_BLOCK; - case 'r': case '<': case '1': case '2': case 'e': case 's': + case 'r': case '<': case '1': case '2': case 'e': case 's': return TS_EXP; default: /* 'c' and 'x' */ break; @@ -1527,8 +1504,7 @@ tree_node_structure (t) not recurse into EXPR's subtrees. */ void -unsave_expr_1 (expr) - tree expr; +unsave_expr_1 (tree expr) { switch (TREE_CODE (expr)) { @@ -1563,8 +1539,7 @@ unsave_expr_1 (expr) /* Default lang hook for "unsave_expr_now". */ tree -lhd_unsave_expr_now (expr) - tree expr; +lhd_unsave_expr_now (tree expr) { enum tree_code code; @@ -1629,8 +1604,7 @@ lhd_unsave_expr_now (expr) never possible to unsave them. */ int -unsafe_for_reeval (expr) - tree expr; +unsafe_for_reeval (tree expr) { int unsafeness = 0; enum tree_code code; @@ -1648,6 +1622,7 @@ unsafe_for_reeval (expr) { case SAVE_EXPR: case RTL_EXPR: + case TRY_CATCH_EXPR: return 2; case TREE_LIST: @@ -1668,6 +1643,13 @@ unsafe_for_reeval (expr) unsafeness = 1; break; + case EXIT_BLOCK_EXPR: + /* EXIT_BLOCK_LABELED_BLOCK, a.k.a. TREE_OPERAND (expr, 0), holds + a reference to an ancestor LABELED_BLOCK, so we need to avoid + unbounded recursion in the 'e' traversal code below. */ + exp = EXIT_BLOCK_RETURN (expr); + return exp ? unsafe_for_reeval (exp) : 0; + default: tmp = (*lang_hooks.unsafe_for_reeval) (expr); if (tmp >= 0) @@ -1706,9 +1688,8 @@ unsafe_for_reeval (expr) /* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size or offset that depends on a field within a record. */ -int -contains_placeholder_p (exp) - tree exp; +bool +contains_placeholder_p (tree exp) { enum tree_code code; int result; @@ -1731,13 +1712,12 @@ contains_placeholder_p (exp) position computations since they will be converted into a WITH_RECORD_EXPR involving the reference, which will assume here will be valid. */ - return contains_placeholder_p (TREE_OPERAND (exp, 0)); + return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0)); case 'x': if (code == TREE_LIST) - return (contains_placeholder_p (TREE_VALUE (exp)) - || (TREE_CHAIN (exp) != 0 - && contains_placeholder_p (TREE_CHAIN (exp)))); + return (CONTAINS_PLACEHOLDER_P (TREE_VALUE (exp)) + || CONTAINS_PLACEHOLDER_P (TREE_CHAIN (exp))); break; case '1': @@ -1747,16 +1727,16 @@ contains_placeholder_p (exp) { case COMPOUND_EXPR: /* Ignoring the first operand isn't quite right, but works best. */ - return contains_placeholder_p (TREE_OPERAND (exp, 1)); + return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)); case RTL_EXPR: case CONSTRUCTOR: return 0; case COND_EXPR: - return (contains_placeholder_p (TREE_OPERAND (exp, 0)) - || contains_placeholder_p (TREE_OPERAND (exp, 1)) - || contains_placeholder_p (TREE_OPERAND (exp, 2))); + return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0)) + || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)) + || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2))); case SAVE_EXPR: /* If we already know this doesn't have a placeholder, don't @@ -1765,15 +1745,14 @@ contains_placeholder_p (exp) return 0; SAVE_EXPR_NOPLACEHOLDER (exp) = 1; - result = contains_placeholder_p (TREE_OPERAND (exp, 0)); + result = CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0)); if (result) SAVE_EXPR_NOPLACEHOLDER (exp) = 0; return result; case CALL_EXPR: - return (TREE_OPERAND (exp, 1) != 0 - && contains_placeholder_p (TREE_OPERAND (exp, 1))); + return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)); default: break; @@ -1782,10 +1761,10 @@ contains_placeholder_p (exp) switch (TREE_CODE_LENGTH (code)) { case 1: - return contains_placeholder_p (TREE_OPERAND (exp, 0)); + return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0)); case 2: - return (contains_placeholder_p (TREE_OPERAND (exp, 0)) - || contains_placeholder_p (TREE_OPERAND (exp, 1))); + return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0)) + || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))); default: return 0; } @@ -1796,12 +1775,113 @@ contains_placeholder_p (exp) return 0; } +/* Return 1 if any part of the computation of TYPE involves a PLACEHOLDER_EXPR. + This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and field + positions. */ + +bool +type_contains_placeholder_p (tree type) +{ + /* If the size contains a placeholder or the parent type (component type in + the case of arrays) type involves a placeholder, this type does. */ + if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type)) + || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type)) + || (TREE_TYPE (type) != 0 + && type_contains_placeholder_p (TREE_TYPE (type)))) + return 1; + + /* Now do type-specific checks. Note that the last part of the check above + greatly limits what we have to do below. */ + switch (TREE_CODE (type)) + { + case VOID_TYPE: + case COMPLEX_TYPE: + case VECTOR_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case CHAR_TYPE: + case POINTER_TYPE: + case OFFSET_TYPE: + case REFERENCE_TYPE: + case METHOD_TYPE: + case FILE_TYPE: + case FUNCTION_TYPE: + return 0; + + case INTEGER_TYPE: + case REAL_TYPE: + /* Here we just check the bounds. */ + return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type)) + || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type))); + + case ARRAY_TYPE: + case SET_TYPE: + /* We're already checked the component type (TREE_TYPE), so just check + the index type. */ + return type_contains_placeholder_p (TYPE_DOMAIN (type)); + + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + { + static tree seen_types = 0; + tree field; + bool ret = 0; + + /* We have to be careful here that we don't end up in infinite + recursions due to a field of a type being a pointer to that type + or to a mutually-recursive type. So we store a list of record + types that we've seen and see if this type is in them. To save + memory, we don't use a list for just one type. Here we check + whether we've seen this type before and store it if not. */ + if (seen_types == 0) + seen_types = type; + else if (TREE_CODE (seen_types) != TREE_LIST) + { + if (seen_types == type) + return 0; + + seen_types = tree_cons (NULL_TREE, type, + build_tree_list (NULL_TREE, seen_types)); + } + else + { + if (value_member (type, seen_types) != 0) + return 0; + + seen_types = tree_cons (NULL_TREE, type, seen_types); + } + + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL + && (CONTAINS_PLACEHOLDER_P (DECL_FIELD_OFFSET (field)) + || (TREE_CODE (type) == QUAL_UNION_TYPE + && CONTAINS_PLACEHOLDER_P (DECL_QUALIFIER (field))) + || type_contains_placeholder_p (TREE_TYPE (field)))) + { + ret = true; + break; + } + + /* Now remove us from seen_types and return the result. */ + if (seen_types == type) + seen_types = 0; + else + seen_types = TREE_CHAIN (seen_types); + + return ret; + } + + default: + abort (); + } +} + /* Return 1 if EXP contains any expressions that produce cleanups for an outer scope to deal with. Used by fold. */ int -has_cleanups (exp) - tree exp; +has_cleanups (tree exp) { int i, nops, cmp; @@ -1862,10 +1942,7 @@ has_cleanups (exp) PLACEHOLDER_EXPR occurring only in its arglist. */ tree -substitute_in_expr (exp, f, r) - tree exp; - tree f; - tree r; +substitute_in_expr (tree exp, tree f, tree r) { enum tree_code code = TREE_CODE (exp); tree op0, op1, op2; @@ -1919,8 +1996,13 @@ substitute_in_expr (exp, f, r) else if (code == CONSTRUCTOR) abort (); - op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r); - op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r); + op0 = TREE_OPERAND (exp, 0); + op1 = TREE_OPERAND (exp, 1); + if (CONTAINS_PLACEHOLDER_P (op0)) + op0 = substitute_in_expr (op0, f, r); + if (CONTAINS_PLACEHOLDER_P (op1)) + op1 = substitute_in_expr (op1, f, r); + if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)) return exp; @@ -1946,9 +2028,17 @@ substitute_in_expr (exp, f, r) else if (code != COND_EXPR) abort (); - op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r); - op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r); - op2 = substitute_in_expr (TREE_OPERAND (exp, 2), f, r); + op0 = TREE_OPERAND (exp, 0); + op1 = TREE_OPERAND (exp, 1); + op2 = TREE_OPERAND (exp, 2); + + if (CONTAINS_PLACEHOLDER_P (op0)) + op0 = substitute_in_expr (op0, f, r); + if (CONTAINS_PLACEHOLDER_P (op1)) + op1 = substitute_in_expr (op1, f, r); + if (CONTAINS_PLACEHOLDER_P (op2)) + op2 = substitute_in_expr (op2, f, r); + if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1) && op2 == TREE_OPERAND (exp, 2)) return exp; @@ -2032,8 +2122,7 @@ substitute_in_expr (exp, f, r) Any other kind of expression is returned unchanged. */ tree -stabilize_reference (ref) - tree ref; +stabilize_reference (tree ref) { tree result; enum tree_code code = TREE_CODE (ref); @@ -2130,8 +2219,7 @@ stabilize_reference (ref) multiple utterances of the same expression should that prove fruitful. */ tree -stabilize_reference_1 (e) - tree e; +stabilize_reference_1 (tree e) { tree result; enum tree_code code = TREE_CODE (e); @@ -2206,17 +2294,17 @@ stabilize_reference_1 (e) Constants, decls, types and misc nodes cannot be. */ tree -build VPARAMS ((enum tree_code code, tree tt, ...)) +build (enum tree_code code, tree tt, ...) { tree t; int length; int i; int fro; int constant; + va_list p; + tree node; - VA_OPEN (p, tt); - VA_FIXEDARG (p, enum tree_code, code); - VA_FIXEDARG (p, tree, tt); + va_start (p, tt); t = make_node (code); length = TREE_CODE_LENGTH (code); @@ -2293,9 +2381,27 @@ build VPARAMS ((enum tree_code code, tree tt, ...)) } } } - VA_CLOSE (p); + va_end (p); TREE_CONSTANT (t) = constant; + + if (code == CALL_EXPR && !TREE_SIDE_EFFECTS (t)) + { + /* Calls have side-effects, except those to const or + pure functions. */ + i = call_expr_flags (t); + if (!(i & (ECF_CONST | ECF_PURE))) + TREE_SIDE_EFFECTS (t) = 1; + + /* And even those have side-effects if their arguments do. */ + else for (node = TREE_OPERAND (t, 1); node; node = TREE_CHAIN (node)) + if (TREE_SIDE_EFFECTS (TREE_VALUE (node))) + { + TREE_SIDE_EFFECTS (t) = 1; + break; + } + } + return t; } @@ -2304,22 +2410,30 @@ build VPARAMS ((enum tree_code code, tree tt, ...)) of varargs, which is expensive for RISC machines. */ tree -build1 (code, type, node) - enum tree_code code; - tree type; - tree node; +build1 (enum tree_code code, tree type, tree node) { - int length; + int length = sizeof (struct tree_exp); #ifdef GATHER_STATISTICS tree_node_kind kind; #endif tree t; #ifdef GATHER_STATISTICS - if (TREE_CODE_CLASS (code) == 'r') - kind = r_kind; - else - kind = e_kind; + switch (TREE_CODE_CLASS (code)) + { + case 's': /* an expression with side effects */ + kind = s_kind; + break; + case 'r': /* a reference */ + kind = r_kind; + break; + default: + kind = e_kind; + break; + } + + tree_node_counts[(int) kind]++; + tree_node_sizes[(int) kind] += length; #endif #ifdef ENABLE_CHECKING @@ -2329,16 +2443,9 @@ build1 (code, type, node) abort (); #endif /* ENABLE_CHECKING */ - length = sizeof (struct tree_exp); - t = ggc_alloc_tree (length); - memset ((PTR) t, 0, sizeof (struct tree_common)); - -#ifdef GATHER_STATISTICS - tree_node_counts[(int) kind]++; - tree_node_sizes[(int) kind] += length; -#endif + memset (t, 0, sizeof (struct tree_common)); TREE_SET_CODE (t, code); @@ -2351,7 +2458,9 @@ build1 (code, type, node) TREE_READONLY (t) = TREE_READONLY (node); } - switch (code) + if (TREE_CODE_CLASS (code) == 's') + TREE_SIDE_EFFECTS (t) = 1; + else switch (code) { case INIT_EXPR: case MODIFY_EXPR: @@ -2373,6 +2482,29 @@ build1 (code, type, node) TREE_READONLY (t) = 0; break; + case ADDR_EXPR: + if (node) + { + /* The address of a volatile decl or reference does not have + side-effects. But be careful not to ignore side-effects from + other sources deeper in the expression--if node is a _REF and + one of its operands has side-effects, so do we. */ + if (TREE_THIS_VOLATILE (node)) + { + TREE_SIDE_EFFECTS (t) = 0; + if (!DECL_P (node)) + { + int i = first_rtl_op (TREE_CODE (node)) - 1; + for (; i >= 0; --i) + { + if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, i))) + TREE_SIDE_EFFECTS (t) = 1; + } + } + } + } + break; + default: if (TREE_CODE_CLASS (code) == '1' && node && TREE_CONSTANT (node)) TREE_CONSTANT (t) = 1; @@ -2388,14 +2520,14 @@ build1 (code, type, node) or even garbage if their values do not matter. */ tree -build_nt VPARAMS ((enum tree_code code, ...)) +build_nt (enum tree_code code, ...) { tree t; int length; int i; + va_list p; - VA_OPEN (p, code); - VA_FIXEDARG (p, enum tree_code, code); + va_start (p, code); t = make_node (code); length = TREE_CODE_LENGTH (code); @@ -2403,7 +2535,7 @@ build_nt VPARAMS ((enum tree_code code, ...)) for (i = 0; i < length; i++) TREE_OPERAND (t, i) = va_arg (p, tree); - VA_CLOSE (p); + va_end (p); return t; } @@ -2414,9 +2546,7 @@ build_nt VPARAMS ((enum tree_code code, ...)) Other slots are initialized to 0 or null pointers. */ tree -build_decl (code, name, type) - enum tree_code code; - tree name, type; +build_decl (enum tree_code code, tree name, tree type) { tree t; @@ -2443,8 +2573,8 @@ build_decl (code, name, type) compiled. This information is used for outputting debugging info. */ tree -build_block (vars, tags, subblocks, supercontext, chain) - tree vars, tags ATTRIBUTE_UNUSED, subblocks, supercontext, chain; +build_block (tree vars, tree tags ATTRIBUTE_UNUSED, tree subblocks, + tree supercontext, tree chain) { tree block = make_node (BLOCK); @@ -2461,10 +2591,7 @@ build_block (vars, tags, subblocks, supercontext, chain) recursively more than one file (Java is one of them). */ tree -build_expr_wfl (node, file, line, col) - tree node; - const char *file; - int line, col; +build_expr_wfl (tree node, const char *file, int line, int col) { static const char *last_file = 0; static tree last_filenode = NULL_TREE; @@ -2492,8 +2619,7 @@ build_expr_wfl (node, file, line, col) is ATTRIBUTE. */ tree -build_decl_attribute_variant (ddecl, attribute) - tree ddecl, attribute; +build_decl_attribute_variant (tree ddecl, tree attribute) { DECL_ATTRIBUTES (ddecl) = attribute; return ddecl; @@ -2505,8 +2631,7 @@ build_decl_attribute_variant (ddecl, attribute) Record such modified types already made so we don't make duplicates. */ tree -build_type_attribute_variant (ttype, attribute) - tree ttype, attribute; +build_type_attribute_variant (tree ttype, tree attribute) { if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute)) { @@ -2562,9 +2687,7 @@ build_type_attribute_variant (ttype, attribute) their canonicalized form. */ int -is_attribute_p (attr, ident) - const char *attr; - tree ident; +is_attribute_p (const char *attr, tree ident) { int ident_len, attr_len; const char *p; @@ -2609,9 +2732,7 @@ is_attribute_p (attr, ident) be passed back in if further occurrences are wanted. */ tree -lookup_attribute (attr_name, list) - const char *attr_name; - tree list; +lookup_attribute (const char *attr_name, tree list) { tree l; @@ -2629,8 +2750,7 @@ lookup_attribute (attr_name, list) /* Return an attribute list that is the union of a1 and a2. */ tree -merge_attributes (a1, a2) - tree a1, a2; +merge_attributes (tree a1, tree a2) { tree attributes; @@ -2680,8 +2800,7 @@ merge_attributes (a1, a2) the result. */ tree -merge_type_attributes (t1, t2) - tree t1, t2; +merge_type_attributes (tree t1, tree t2) { return merge_attributes (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)); @@ -2691,8 +2810,7 @@ merge_type_attributes (t1, t2) the result. */ tree -merge_decl_attributes (olddecl, newdecl) - tree olddecl, newdecl; +merge_decl_attributes (tree olddecl, tree newdecl) { return merge_attributes (DECL_ATTRIBUTES (olddecl), DECL_ATTRIBUTES (newdecl)); @@ -2710,9 +2828,7 @@ merge_decl_attributes (olddecl, newdecl) The second instance of `foo' nullifies the dllimport. */ tree -merge_dllimport_decl_attributes (old, new) - tree old; - tree new; +merge_dllimport_decl_attributes (tree old, tree new) { tree a; int delete_dllimport_p; @@ -2759,9 +2875,7 @@ merge_dllimport_decl_attributes (old, new) of the various TYPE_QUAL values. */ static void -set_type_quals (type, type_quals) - tree type; - int type_quals; +set_type_quals (tree type, int type_quals) { TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0; TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0; @@ -2773,9 +2887,7 @@ set_type_quals (type, type_quals) return NULL_TREE. */ tree -get_qualified_type (type, type_quals) - tree type; - int type_quals; +get_qualified_type (tree type, int type_quals) { tree t; @@ -2784,7 +2896,8 @@ get_qualified_type (type, type_quals) preserve the TYPE_NAME, since there is code that depends on this. */ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type) - && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)) + && TYPE_CONTEXT (t) == TYPE_CONTEXT (type) + && attribute_list_equal (TYPE_ATTRIBUTES (t), TYPE_ATTRIBUTES (type))) return t; return NULL_TREE; @@ -2794,9 +2907,7 @@ get_qualified_type (type, type_quals) exist. This function never returns NULL_TREE. */ tree -build_qualified_type (type, type_quals) - tree type; - int type_quals; +build_qualified_type (tree type, int type_quals) { tree t; @@ -2817,8 +2928,7 @@ build_qualified_type (type, type_quals) This is so the caller can modify it. */ tree -build_type_copy (type) - tree type; +build_type_copy (tree type) { tree t, m = TYPE_MAIN_VARIANT (type); @@ -2842,8 +2952,7 @@ build_type_copy (type) of the individual types. */ unsigned int -type_hash_list (list) - tree list; +type_hash_list (tree list) { unsigned int hashcode; tree tail; @@ -2859,9 +2968,7 @@ type_hash_list (list) /* Returns true if the types are equal. */ static int -type_hash_eq (va, vb) - const void *va; - const void *vb; +type_hash_eq (const void *va, const void *vb) { const struct type_hash *a = va, *b = vb; if (a->hash == b->hash @@ -2891,8 +2998,7 @@ type_hash_eq (va, vb) /* Return the cached hash value. */ static hashval_t -type_hash_hash (item) - const void *item; +type_hash_hash (const void *item) { return ((const struct type_hash *) item)->hash; } @@ -2901,9 +3007,7 @@ type_hash_hash (item) If one is found, return it. Otherwise return 0. */ tree -type_hash_lookup (hashcode, type) - unsigned int hashcode; - tree type; +type_hash_lookup (unsigned int hashcode, tree type) { struct type_hash *h, in; @@ -2924,14 +3028,12 @@ type_hash_lookup (hashcode, type) for a type TYPE whose hash code is HASHCODE. */ void -type_hash_add (hashcode, type) - unsigned int hashcode; - tree type; +type_hash_add (unsigned int hashcode, tree type) { struct type_hash *h; void **loc; - h = (struct type_hash *) ggc_alloc (sizeof (struct type_hash)); + h = ggc_alloc (sizeof (struct type_hash)); h->hash = hashcode; h->type = type; loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT); @@ -2953,9 +3055,7 @@ type_hash_add (hashcode, type) int debug_no_type_hash = 0; tree -type_hash_canon (hashcode, type) - unsigned int hashcode; - tree type; +type_hash_canon (unsigned int hashcode, tree type) { tree t1; @@ -2987,8 +3087,7 @@ type_hash_canon (hashcode, type) the number of garbage collections. */ static int -type_hash_marked_p (p) - const void *p; +type_hash_marked_p (const void *p) { tree type = ((struct type_hash *) p)->type; @@ -2996,7 +3095,7 @@ type_hash_marked_p (p) } static void -print_type_hash_statistics () +print_type_hash_statistics (void) { fprintf (stderr, "Type hash: size %ld, %ld elements, %f collisions\n", (long) htab_size (type_hash_table), @@ -3009,8 +3108,7 @@ print_type_hash_statistics () by adding the hash codes of the individual attributes. */ unsigned int -attribute_hash_list (list) - tree list; +attribute_hash_list (tree list) { unsigned int hashcode; tree tail; @@ -3025,8 +3123,7 @@ attribute_hash_list (list) equivalent to l1. */ int -attribute_list_equal (l1, l2) - tree l1, l2; +attribute_list_equal (tree l1, tree l2) { return attribute_list_contained (l1, l2) && attribute_list_contained (l2, l1); @@ -3041,8 +3138,7 @@ attribute_list_equal (l1, l2) correctly. */ int -attribute_list_contained (l1, l2) - tree l1, l2; +attribute_list_contained (tree l1, tree l2) { tree t1, t2; @@ -3089,8 +3185,7 @@ attribute_list_contained (l1, l2) Also, the TREE_PURPOSEs must match. */ int -type_list_equal (l1, l2) - tree l1, l2; +type_list_equal (tree l1, tree l2) { tree t1, t2; @@ -3110,8 +3205,7 @@ type_list_equal (l1, l2) then this function counts only the ordinary arguments. */ int -type_num_arguments (type) - tree type; +type_num_arguments (tree type) { int i = 0; tree t; @@ -3131,8 +3225,7 @@ type_num_arguments (type) represent the same constant value. */ int -tree_int_cst_equal (t1, t2) - tree t1, t2; +tree_int_cst_equal (tree t1, tree t2) { if (t1 == t2) return 1; @@ -3153,8 +3246,7 @@ tree_int_cst_equal (t1, t2) The precise way of comparison depends on their data type. */ int -tree_int_cst_lt (t1, t2) - tree t1, t2; +tree_int_cst_lt (tree t1, tree t2) { if (t1 == t2) return 0; @@ -3181,9 +3273,7 @@ tree_int_cst_lt (t1, t2) /* Returns -1 if T1 < T2, 0 if T1 == T2, and 1 if T1 > T2. */ int -tree_int_cst_compare (t1, t2) - tree t1; - tree t2; +tree_int_cst_compare (tree t1, tree t2) { if (tree_int_cst_lt (t1, t2)) return -1; @@ -3199,9 +3289,7 @@ tree_int_cst_compare (t1, t2) be represented in a single unsigned HOST_WIDE_INT. */ int -host_integerp (t, pos) - tree t; - int pos; +host_integerp (tree t, int pos) { return (TREE_CODE (t) == INTEGER_CST && ! TREE_OVERFLOW (t) @@ -3218,9 +3306,7 @@ host_integerp (t, pos) be positive. Abort if we cannot satisfy the above conditions. */ HOST_WIDE_INT -tree_low_cst (t, pos) - tree t; - int pos; +tree_low_cst (tree t, int pos) { if (host_integerp (t, pos)) return TREE_INT_CST_LOW (t); @@ -3231,8 +3317,7 @@ tree_low_cst (t, pos) /* Return the most significant bit of the integer constant T. */ int -tree_int_cst_msb (t) - tree t; +tree_int_cst_msb (tree t) { int prec; HOST_WIDE_INT h; @@ -3251,8 +3336,7 @@ tree_int_cst_msb (t) Note that -1 will never be returned it T's type is unsigned. */ int -tree_int_cst_sgn (t) - tree t; +tree_int_cst_sgn (tree t) { if (TREE_INT_CST_LOW (t) == 0 && TREE_INT_CST_HIGH (t) == 0) return 0; @@ -3268,8 +3352,7 @@ tree_int_cst_sgn (t) are known to be equal; otherwise return 0. */ int -simple_cst_list_equal (l1, l2) - tree l1, l2; +simple_cst_list_equal (tree l1, tree l2) { while (l1 != NULL_TREE && l2 != NULL_TREE) { @@ -3290,8 +3373,7 @@ simple_cst_list_equal (l1, l2) this function. */ int -simple_cst_equal (t1, t2) - tree t1, t2; +simple_cst_equal (tree t1, tree t2) { enum tree_code code1, code2; int cmp; @@ -3429,9 +3511,7 @@ simple_cst_equal (t1, t2) than U, respectively. */ int -compare_tree_int (t, u) - tree t; - unsigned HOST_WIDE_INT u; +compare_tree_int (tree t, unsigned HOST_WIDE_INT u) { if (tree_int_cst_sgn (t) < 0) return -1; @@ -3444,31 +3524,123 @@ compare_tree_int (t, u) else return 1; } + +/* Generate a hash value for an expression. This can be used iteratively + by passing a previous result as the "val" argument. + + This function is intended to produce the same hash for expressions which + would compare equal using operand_equal_p. */ + +hashval_t +iterative_hash_expr (tree t, hashval_t val) +{ + int i; + enum tree_code code; + char class; + + if (t == NULL_TREE) + return iterative_hash_object (t, val); + + code = TREE_CODE (t); + class = TREE_CODE_CLASS (code); + + if (class == 'd') + { + /* Decls we can just compare by pointer. */ + val = iterative_hash_object (t, val); + } + else if (class == 'c') + { + /* Alas, constants aren't shared, so we can't rely on pointer + identity. */ + if (code == INTEGER_CST) + { + val = iterative_hash_object (TREE_INT_CST_LOW (t), val); + val = iterative_hash_object (TREE_INT_CST_HIGH (t), val); + } + else if (code == REAL_CST) + val = iterative_hash (TREE_REAL_CST_PTR (t), + sizeof (REAL_VALUE_TYPE), val); + else if (code == STRING_CST) + val = iterative_hash (TREE_STRING_POINTER (t), + TREE_STRING_LENGTH (t), val); + else if (code == COMPLEX_CST) + { + val = iterative_hash_expr (TREE_REALPART (t), val); + val = iterative_hash_expr (TREE_IMAGPART (t), val); + } + else if (code == VECTOR_CST) + val = iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val); + else + abort (); + } + else if (IS_EXPR_CODE_CLASS (class)) + { + val = iterative_hash_object (code, val); + + if (code == NOP_EXPR || code == CONVERT_EXPR + || code == NON_LVALUE_EXPR) + val = iterative_hash_object (TREE_TYPE (t), val); + + if (code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR + || code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR + || code == BIT_AND_EXPR || code == NE_EXPR || code == EQ_EXPR) + { + /* It's a commutative expression. We want to hash it the same + however it appears. We do this by first hashing both operands + and then rehashing based on the order of their independent + hashes. */ + hashval_t one = iterative_hash_expr (TREE_OPERAND (t, 0), 0); + hashval_t two = iterative_hash_expr (TREE_OPERAND (t, 1), 0); + hashval_t t; + + if (one > two) + t = one, one = two, two = t; + + val = iterative_hash_object (one, val); + val = iterative_hash_object (two, val); + } + else + for (i = first_rtl_op (code) - 1; i >= 0; --i) + val = iterative_hash_expr (TREE_OPERAND (t, i), val); + } + else if (code == TREE_LIST) + { + /* A list of expressions, for a CALL_EXPR or as the elements of a + VECTOR_CST. */ + for (; t; t = TREE_CHAIN (t)) + val = iterative_hash_expr (TREE_VALUE (t), val); + } + else + abort (); + + return val; +} /* Constructors for pointer, array and function types. (RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are constructed by language-dependent code, not here.) */ -/* Construct, lay out and return the type of pointers to TO_TYPE. - If such a type has already been constructed, reuse it. */ +/* Construct, lay out and return the type of pointers to TO_TYPE + with mode MODE. If such a type has already been constructed, + reuse it. */ tree -build_pointer_type (to_type) - tree to_type; +build_pointer_type_for_mode (tree to_type, enum machine_mode mode) { tree t = TYPE_POINTER_TO (to_type); /* First, if we already have a type for pointers to TO_TYPE, use it. */ - - if (t != 0) + if (t != 0 && mode == ptr_mode) return t; - /* We need a new one. */ t = make_node (POINTER_TYPE); TREE_TYPE (t) = to_type; + TYPE_MODE (t) = mode; /* Record this type as the pointer to TO_TYPE. */ + if (mode == ptr_mode) TYPE_POINTER_TO (to_type) = t; /* Lay out the type. This function has many callers that are concerned @@ -3479,25 +3651,34 @@ build_pointer_type (to_type) return t; } -/* Build the node for the type of references-to-TO_TYPE. */ +/* By default build pointers in ptr_mode. */ tree -build_reference_type (to_type) - tree to_type; +build_pointer_type (tree to_type) +{ + return build_pointer_type_for_mode (to_type, ptr_mode); +} + +/* Construct, lay out and return the type of references to TO_TYPE + with mode MODE. If such a type has already been constructed, + reuse it. */ + +tree +build_reference_type_for_mode (tree to_type, enum machine_mode mode) { tree t = TYPE_REFERENCE_TO (to_type); /* First, if we already have a type for pointers to TO_TYPE, use it. */ - - if (t) + if (t != 0 && mode == ptr_mode) return t; - /* We need a new one. */ t = make_node (REFERENCE_TYPE); TREE_TYPE (t) = to_type; + TYPE_MODE (t) = mode; /* Record this type as the pointer to TO_TYPE. */ + if (mode == ptr_mode) TYPE_REFERENCE_TO (to_type) = t; layout_type (t); @@ -3505,14 +3686,23 @@ build_reference_type (to_type) return t; } + +/* Build the node for the type of references-to-TO_TYPE by default + in ptr_mode. */ + +tree +build_reference_type (tree to_type) +{ + return build_reference_type_for_mode (to_type, ptr_mode); +} + /* Build a type that is compatible with t but has no cv quals anywhere in its type, thus const char *const *const * -> char ***. */ tree -build_type_no_quals (t) - tree t; +build_type_no_quals (tree t) { switch (TREE_CODE (t)) { @@ -3535,8 +3725,7 @@ build_type_no_quals (t) sizes that use more than one HOST_WIDE_INT. */ tree -build_index_type (maxval) - tree maxval; +build_index_type (tree maxval) { tree itype = make_node (INTEGER_TYPE); @@ -3562,8 +3751,7 @@ build_index_type (maxval) if TYPE==NULL_TREE, sizetype is used. */ tree -build_range_type (type, lowval, highval) - tree type, lowval, highval; +build_range_type (tree type, tree lowval, tree highval) { tree itype = make_node (INTEGER_TYPE); @@ -3593,49 +3781,17 @@ build_range_type (type, lowval, highval) of just highval (maxval). */ tree -build_index_2_type (lowval, highval) - tree lowval, highval; +build_index_2_type (tree lowval, tree highval) { return build_range_type (sizetype, lowval, highval); } -/* Return nonzero iff ITYPE1 and ITYPE2 are equal (in the LISP sense). - Needed because when index types are not hashed, equal index types - built at different times appear distinct, even though structurally, - they are not. */ - -int -index_type_equal (itype1, itype2) - tree itype1, itype2; -{ - if (TREE_CODE (itype1) != TREE_CODE (itype2)) - return 0; - - if (TREE_CODE (itype1) == INTEGER_TYPE) - { - if (TYPE_PRECISION (itype1) != TYPE_PRECISION (itype2) - || TYPE_MODE (itype1) != TYPE_MODE (itype2) - || simple_cst_equal (TYPE_SIZE (itype1), TYPE_SIZE (itype2)) != 1 - || TYPE_ALIGN (itype1) != TYPE_ALIGN (itype2)) - return 0; - - if (1 == simple_cst_equal (TYPE_MIN_VALUE (itype1), - TYPE_MIN_VALUE (itype2)) - && 1 == simple_cst_equal (TYPE_MAX_VALUE (itype1), - TYPE_MAX_VALUE (itype2))) - return 1; - } - - return 0; -} - /* Construct, lay out and return the type of arrays of elements with ELT_TYPE and number of elements specified by the range of values of INDEX_TYPE. If such a type has already been constructed, reuse it. */ tree -build_array_type (elt_type, index_type) - tree elt_type, index_type; +build_array_type (tree elt_type, tree index_type) { tree t; unsigned int hashcode; @@ -3672,8 +3828,7 @@ build_array_type (elt_type, index_type) the innermost dimension of ARRAY. */ tree -get_inner_array_type (array) - tree array; +get_inner_array_type (tree array) { tree type = TREE_TYPE (array); @@ -3691,8 +3846,7 @@ get_inner_array_type (array) If such a type has already been constructed, reuse it. */ tree -build_function_type (value_type, arg_types) - tree value_type, arg_types; +build_function_type (tree value_type, tree arg_types) { tree t; unsigned int hashcode; @@ -3717,18 +3871,18 @@ build_function_type (value_type, arg_types) return t; } -/* Build a function type. The RETURN_TYPE is the type retured by the +/* Build a function type. The RETURN_TYPE is the type returned by the function. If additional arguments are provided, they are additional argument types. The list of argument types must always be terminated by NULL_TREE. */ tree -build_function_type_list VPARAMS ((tree return_type, ...)) +build_function_type_list (tree return_type, ...) { tree t, args, last; + va_list p; - VA_OPEN (p, return_type); - VA_FIXEDARG (p, tree, return_type); + va_start (p, return_type); t = va_arg (p, tree); for (args = NULL_TREE; t != NULL_TREE; t = va_arg (p, tree)) @@ -3739,40 +3893,41 @@ build_function_type_list VPARAMS ((tree return_type, ...)) TREE_CHAIN (last) = void_list_node; args = build_function_type (return_type, args); - VA_CLOSE (p); + va_end (p); return args; } -/* Construct, lay out and return the type of methods belonging to class - BASETYPE and whose arguments and values are described by TYPE. - If that type exists already, reuse it. - TYPE must be a FUNCTION_TYPE node. */ +/* Build a METHOD_TYPE for a member of BASETYPE. The RETTYPE (a TYPE) + and ARGTYPES (a TREE_LIST) are the return type and arguments types + for the method. An implicit additional parameter (of type + pointer-to-BASETYPE) is added to the ARGTYPES. */ tree -build_method_type (basetype, type) - tree basetype, type; +build_method_type_directly (tree basetype, + tree rettype, + tree argtypes) { tree t; - unsigned int hashcode; + tree ptype; + int hashcode; /* Make a node of the sort we want. */ t = make_node (METHOD_TYPE); - if (TREE_CODE (type) != FUNCTION_TYPE) - abort (); - TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype); - TREE_TYPE (t) = TREE_TYPE (type); + TREE_TYPE (t) = rettype; + ptype = build_pointer_type (basetype); /* The actual arglist for this function includes a "hidden" argument which is "this". Put it into the list of argument types. */ + argtypes = tree_cons (NULL_TREE, ptype, argtypes); + TYPE_ARG_TYPES (t) = argtypes; - TYPE_ARG_TYPES (t) - = tree_cons (NULL_TREE, - build_pointer_type (basetype), TYPE_ARG_TYPES (type)); + /* If we already have such a type, use the old one and free this one. + Note that it also frees up the above cons cell if found. */ + hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + + type_hash_list (argtypes); - /* If we already have such a type, use the old one and free this one. */ - hashcode = TYPE_HASH (basetype) + TYPE_HASH (type); t = type_hash_canon (hashcode, t); if (!COMPLETE_TYPE_P (t)) @@ -3781,13 +3936,28 @@ build_method_type (basetype, type) return t; } +/* Construct, lay out and return the type of methods belonging to class + BASETYPE and whose arguments and values are described by TYPE. + If that type exists already, reuse it. + TYPE must be a FUNCTION_TYPE node. */ + +tree +build_method_type (tree basetype, tree type) +{ + if (TREE_CODE (type) != FUNCTION_TYPE) + abort (); + + return build_method_type_directly (basetype, + TREE_TYPE (type), + TYPE_ARG_TYPES (type)); +} + /* Construct, lay out and return the type of offsets to a value of type TYPE, within an object of type BASETYPE. If a suitable offset type exists already, reuse it. */ tree -build_offset_type (basetype, type) - tree basetype, type; +build_offset_type (tree basetype, tree type) { tree t; unsigned int hashcode; @@ -3811,8 +3981,7 @@ build_offset_type (basetype, type) /* Create a complex type whose components are COMPONENT_TYPE. */ tree -build_complex_type (component_type) - tree component_type; +build_complex_type (tree component_type) { tree t; unsigned int hashcode; @@ -3892,9 +4061,7 @@ build_complex_type (component_type) is different from (int) OP. */ tree -get_unwidened (op, for_type) - tree op; - tree for_type; +get_unwidened (tree op, tree for_type) { /* Set UNS initially if converting OP to FOR_TYPE is a zero-extension. */ tree type = TREE_TYPE (op); @@ -3954,7 +4121,8 @@ get_unwidened (op, for_type) { unsigned int innerprec = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1); - int unsignedp = TREE_UNSIGNED (TREE_OPERAND (op, 1)); + int unsignedp = (TREE_UNSIGNED (TREE_OPERAND (op, 1)) + || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1)))); type = (*lang_hooks.types.type_for_size) (innerprec, unsignedp); /* We can get this structure field in the narrowest type it fits in. @@ -3963,10 +4131,10 @@ get_unwidened (op, for_type) The resulting extension to its nominal type (a fullword type) must fit the same conditions as for other extensions. */ - if (innerprec < TYPE_PRECISION (TREE_TYPE (op)) + if (type != 0 + && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (op))) && (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1))) - && (! uns || final_prec <= innerprec || unsignedp) - && type != 0) + && (! uns || final_prec <= innerprec || unsignedp)) { win = build (COMPONENT_REF, type, TREE_OPERAND (op, 0), TREE_OPERAND (op, 1)); @@ -3984,9 +4152,7 @@ get_unwidened (op, for_type) or 0 if the value should be sign-extended. */ tree -get_narrower (op, unsignedp_ptr) - tree op; - int *unsignedp_ptr; +get_narrower (tree op, int *unsignedp_ptr) { int uns = 0; int first = 1; @@ -4040,8 +4206,9 @@ get_narrower (op, unsignedp_ptr) { unsigned HOST_WIDE_INT innerprec = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1); - tree type = (*lang_hooks.types.type_for_size) (innerprec, - TREE_UNSIGNED (op)); + int unsignedp = (TREE_UNSIGNED (TREE_OPERAND (op, 1)) + || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1)))); + tree type = (*lang_hooks.types.type_for_size) (innerprec, unsignedp); /* We can get this structure field in a narrower type that fits it, but the resulting extension to its nominal type (a fullword type) @@ -4072,32 +4239,60 @@ get_narrower (op, unsignedp_ptr) for type TYPE (an INTEGER_TYPE). */ int -int_fits_type_p (c, type) - tree c, type; -{ - /* If the bounds of the type are integers, we can check ourselves. - If not, but this type is a subtype, try checking against that. - Otherwise, use force_fit_type, which checks against the precision. */ - if (TYPE_MAX_VALUE (type) != NULL_TREE - && TYPE_MIN_VALUE (type) != NULL_TREE - && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST - && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST) +int_fits_type_p (tree c, tree type) +{ + tree type_low_bound = TYPE_MIN_VALUE (type); + tree type_high_bound = TYPE_MAX_VALUE (type); + int ok_for_low_bound, ok_for_high_bound; + + /* Perform some generic filtering first, which may allow making a decision + even if the bounds are not constant. First, negative integers never fit + in unsigned types, */ + if ((TREE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0) + /* Also, unsigned integers with top bit set never fit signed types. */ + || (! TREE_UNSIGNED (type) + && TREE_UNSIGNED (TREE_TYPE (c)) && tree_int_cst_msb (c))) + return 0; + + /* If at least one bound of the type is a constant integer, we can check + ourselves and maybe make a decision. If no such decision is possible, but + this type is a subtype, try checking against that. Otherwise, use + force_fit_type, which checks against the precision. + + Compute the status for each possibly constant bound, and return if we see + one does not match. Use ok_for_xxx_bound for this purpose, assigning -1 + for "unknown if constant fits", 0 for "constant known *not* to fit" and 1 + for "constant known to fit". */ + + ok_for_low_bound = -1; + ok_for_high_bound = -1; + + /* Check if C >= type_low_bound. */ + if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST) { - if (TREE_UNSIGNED (type)) - return (! INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c) - && ! INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type)) - /* Negative ints never fit unsigned types. */ - && ! (TREE_INT_CST_HIGH (c) < 0 - && ! TREE_UNSIGNED (TREE_TYPE (c)))); - else - return (! INT_CST_LT (TYPE_MAX_VALUE (type), c) - && ! INT_CST_LT (c, TYPE_MIN_VALUE (type)) - /* Unsigned ints with top bit set never fit signed types. */ - && ! (TREE_INT_CST_HIGH (c) < 0 - && TREE_UNSIGNED (TREE_TYPE (c)))); + ok_for_low_bound = ! tree_int_cst_lt (c, type_low_bound); + if (! ok_for_low_bound) + return 0; } + + /* Check if c <= type_high_bound. */ + if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST) + { + ok_for_high_bound = ! tree_int_cst_lt (type_high_bound, c); + if (! ok_for_high_bound) + return 0; + } + + /* If the constant fits both bounds, the result is known. */ + if (ok_for_low_bound == 1 && ok_for_high_bound == 1) + return 1; + + /* If we haven't been able to decide at this point, there nothing more we + can check ourselves here. Look at the base type if we have one. */ else if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0) return int_fits_type_p (c, TREE_TYPE (type)); + + /* Or to force_fit_type, if nothing else. */ else { c = copy_node (c); @@ -4111,56 +4306,68 @@ int_fits_type_p (c, type) modified types': in C99, a struct type is never variably modified because a VLA may not appear as a structure member. However, in GNU C code like: - + struct S { int i[f()]; }; is valid, and other languages may define similar constructs. */ bool -variably_modified_type_p (type) - tree type; +variably_modified_type_p (tree type) { + tree t; + if (type == error_mark_node) return false; - /* If TYPE itself has variable size, it is variably modified. + /* If TYPE itself has variable size, it is variably modified. We do not yet have a representation of the C99 '[*]' syntax. When a representation is chosen, this function should be modified to test for that case as well. */ - if (TYPE_SIZE (type) - && TYPE_SIZE (type) != error_mark_node - && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) - return true; - - /* If TYPE is a pointer or reference, it is variably modified if - the type pointed to is variably modified. */ - if ((TREE_CODE (type) == POINTER_TYPE - || TREE_CODE (type) == REFERENCE_TYPE) - && variably_modified_type_p (TREE_TYPE (type))) - return true; - - /* If TYPE is an array, it is variably modified if the array - elements are. (Note that the VLA case has already been checked - above.) */ - if (TREE_CODE (type) == ARRAY_TYPE - && variably_modified_type_p (TREE_TYPE (type))) + t = TYPE_SIZE (type); + if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST) return true; - /* If TYPE is a function type, it is variably modified if any of the - parameters or the return type are variably modified. */ - if (TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == METHOD_TYPE) + switch (TREE_CODE (type)) { - tree parm; + case POINTER_TYPE: + case REFERENCE_TYPE: + case ARRAY_TYPE: + /* If TYPE is a pointer or reference, it is variably modified if + the type pointed to is variably modified. Similarly for arrays; + note that VLAs are handled by the TYPE_SIZE check above. */ + return variably_modified_type_p (TREE_TYPE (type)); + + case FUNCTION_TYPE: + case METHOD_TYPE: + /* If TYPE is a function type, it is variably modified if any of the + parameters or the return type are variably modified. */ + { + tree parm; - if (variably_modified_type_p (TREE_TYPE (type))) - return true; - for (parm = TYPE_ARG_TYPES (type); - parm && parm != void_list_node; - parm = TREE_CHAIN (parm)) - if (variably_modified_type_p (TREE_VALUE (parm))) + if (variably_modified_type_p (TREE_TYPE (type))) return true; + for (parm = TYPE_ARG_TYPES (type); + parm && parm != void_list_node; + parm = TREE_CHAIN (parm)) + if (variably_modified_type_p (TREE_VALUE (parm))) + return true; + } + break; + + case INTEGER_TYPE: + /* Scalar types are variably modified if their end points + aren't constant. */ + t = TYPE_MIN_VALUE (type); + if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST) + return true; + t = TYPE_MAX_VALUE (type); + if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST) + return true; + return false; + + default: + break; } /* The current language may have other cases to check, but in general, @@ -4172,8 +4379,7 @@ variably_modified_type_p (type) NULL_TREE if there is no containing scope. */ tree -get_containing_scope (t) - tree t; +get_containing_scope (tree t) { return (TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t)); } @@ -4182,8 +4388,7 @@ get_containing_scope (t) a FUNCTION_DECL, or zero if none. */ tree -decl_function_context (decl) - tree decl; +decl_function_context (tree decl) { tree context; @@ -4222,32 +4427,35 @@ decl_function_context (decl) TYPE_DECLs and FUNCTION_DECLs are transparent to this function. */ tree -decl_type_context (decl) - tree decl; +decl_type_context (tree decl) { tree context = DECL_CONTEXT (decl); while (context) - { - if (TREE_CODE (context) == NAMESPACE_DECL) + switch (TREE_CODE (context)) + { + case NAMESPACE_DECL: + case TRANSLATION_UNIT_DECL: return NULL_TREE; - if (TREE_CODE (context) == RECORD_TYPE - || TREE_CODE (context) == UNION_TYPE - || TREE_CODE (context) == QUAL_UNION_TYPE) + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: return context; - - if (TREE_CODE (context) == TYPE_DECL - || TREE_CODE (context) == FUNCTION_DECL) + + case TYPE_DECL: + case FUNCTION_DECL: context = DECL_CONTEXT (context); - - else if (TREE_CODE (context) == BLOCK) + break; + + case BLOCK: context = BLOCK_SUPERCONTEXT (context); - - else - /* Unhandled CONTEXT!? */ + break; + + default: abort (); - } + } + return NULL_TREE; } @@ -4256,8 +4464,7 @@ decl_type_context (decl) determined. */ tree -get_callee_fndecl (call) - tree call; +get_callee_fndecl (tree call) { tree addr; @@ -4283,39 +4490,17 @@ get_callee_fndecl (call) if (TREE_CODE (addr) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL) return TREE_OPERAND (addr, 0); - - /* We couldn't figure out what was being called. */ - return NULL_TREE; -} - -/* Print debugging information about the obstack O, named STR. */ - -void -print_obstack_statistics (str, o) - const char *str; - struct obstack *o; -{ - struct _obstack_chunk *chunk = o->chunk; - int n_chunks = 1; - int n_alloc = 0; - - n_alloc += o->next_free - chunk->contents; - chunk = chunk->prev; - while (chunk) - { - n_chunks += 1; - n_alloc += chunk->limit - &chunk->contents[0]; - chunk = chunk->prev; - } - fprintf (stderr, "obstack %s: %u bytes, %d chunks\n", - str, n_alloc, n_chunks); + + /* We couldn't figure out what was being called. Maybe the front + end has some idea. */ + return (*lang_hooks.lang_get_callee_fndecl) (call); } /* Print debugging information about tree nodes generated during the compile, and any language-specific information. */ void -dump_tree_statistics () +dump_tree_statistics (void) { #ifdef GATHER_STATISTICS int i; @@ -4324,19 +4509,19 @@ dump_tree_statistics () fprintf (stderr, "\n??? tree nodes created\n\n"); #ifdef GATHER_STATISTICS - fprintf (stderr, "Kind Nodes Bytes\n"); - fprintf (stderr, "-------------------------------------\n"); + fprintf (stderr, "Kind Nodes Bytes\n"); + fprintf (stderr, "---------------------------------------\n"); total_nodes = total_bytes = 0; for (i = 0; i < (int) all_kinds; i++) { - fprintf (stderr, "%-20s %6d %9d\n", tree_node_kind_names[i], + fprintf (stderr, "%-20s %7d %10d\n", tree_node_kind_names[i], tree_node_counts[i], tree_node_sizes[i]); total_nodes += tree_node_counts[i]; total_bytes += tree_node_sizes[i]; } - fprintf (stderr, "-------------------------------------\n"); - fprintf (stderr, "%-20s %6d %9d\n", "Total", total_nodes, total_bytes); - fprintf (stderr, "-------------------------------------\n"); + fprintf (stderr, "---------------------------------------\n"); + fprintf (stderr, "%-20s %7d %10d\n", "Total", total_nodes, total_bytes); + fprintf (stderr, "---------------------------------------\n"); #else fprintf (stderr, "(No per-node statistics)\n"); #endif @@ -4346,85 +4531,34 @@ dump_tree_statistics () #define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s" -const char *flag_random_seed; - -/* Set up a default flag_random_seed value, if there wasn't one already. */ - -void -default_flag_random_seed () -{ - unsigned HOST_WIDE_INT value; - char *new_random_seed; - - if (flag_random_seed != NULL) - return; - - /* Get some more or less random data. */ -#ifdef HAVE_GETTIMEOFDAY - { - struct timeval tv; - - gettimeofday (&tv, NULL); - value = (((unsigned HOST_WIDE_INT) tv.tv_usec << 16) - ^ tv.tv_sec ^ getpid ()); - } -#else - value = getpid (); -#endif - - /* This slightly overestimates the space required. */ - new_random_seed = xmalloc (HOST_BITS_PER_WIDE_INT / 3 + 2); - sprintf (new_random_seed, HOST_WIDE_INT_PRINT_UNSIGNED, value); - flag_random_seed = new_random_seed; -} - -/* Appends 6 random characters to TEMPLATE to (hopefully) avoid name - clashes in cases where we can't reliably choose a unique name. - - Derived from mkstemp.c in libiberty. */ +/* Generate a crc32 of a string. */ -static void -append_random_chars (template) - char *template; +unsigned +crc32_string (unsigned chksum, const char *string) { - static const char letters[] - = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - unsigned HOST_WIDE_INT v; - size_t i; - - default_flag_random_seed (); - - /* This isn't a very good hash, but it does guarantee no collisions - when the random string is generated by the code above and the time - delta is small. */ - v = 0; - for (i = 0; i < strlen (flag_random_seed); i++) - v = (v << 4) ^ (v >> (HOST_BITS_PER_WIDE_INT - 4)) ^ flag_random_seed[i]; - - template += strlen (template); - - /* Fill in the random bits. */ - template[0] = letters[v % 62]; - v /= 62; - template[1] = letters[v % 62]; - v /= 62; - template[2] = letters[v % 62]; - v /= 62; - template[3] = letters[v % 62]; - v /= 62; - template[4] = letters[v % 62]; - v /= 62; - template[5] = letters[v % 62]; - - template[6] = '\0'; + do + { + unsigned value = *string << 24; + unsigned ix; + + for (ix = 8; ix--; value <<= 1) + { + unsigned feedback; + + feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0; + chksum <<= 1; + chksum ^= feedback; + } + } + while (*string++); + return chksum; } /* P is a string that will be used in a symbol. Mask out any characters that are not valid in that context. */ void -clean_symbol_name (p) - char *p; +clean_symbol_name (char *p) { for (; *p; p++) if (! (ISALNUM (*p) @@ -4443,8 +4577,7 @@ clean_symbol_name (p) linker or collect2. */ tree -get_file_function_name_long (type) - const char *type; +get_file_function_name_long (const char *type) { char *buf; const char *p; @@ -4456,7 +4589,7 @@ get_file_function_name_long (type) { /* We don't have anything that we know to be unique to this translation unit, so use what we do have and throw in some randomness. */ - + unsigned len; const char *name = weak_global_object_name; const char *file = main_input_filename; @@ -4465,15 +4598,18 @@ get_file_function_name_long (type) if (! file) file = input_filename; - q = (char *) alloca (7 + strlen (name) + strlen (file)); + len = strlen (file); + q = alloca (9 * 2 + len + 1); + memcpy (q, file, len + 1); + clean_symbol_name (q); + + sprintf (q + len, "_%08X_%08X", crc32_string (0, name), + crc32_string (0, flag_random_seed)); - sprintf (q, "%s%s", name, file); - append_random_chars (q); p = q; } - buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p) - + strlen (type)); + buf = alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p) + strlen (type)); /* Set up the name of the file-level functions we may need. Use a global object (which is already required to be unique over @@ -4481,10 +4617,6 @@ get_file_function_name_long (type) constraints). */ sprintf (buf, FILE_FUNCTION_FORMAT, type, p); - /* Don't need to pull weird characters out of global names. */ - if (p != first_global_object_name) - clean_symbol_name (buf + 11); - return get_identifier (buf); } @@ -4492,8 +4624,7 @@ get_file_function_name_long (type) If KIND=='D', return a suitable global clean-up (destructor) name. */ tree -get_file_function_name (kind) - int kind; +get_file_function_name (int kind) { char p[2]; @@ -4511,10 +4642,7 @@ get_file_function_name (kind) Otherwise, a TREE_LIST of the non-constant elements is emitted. */ tree -get_set_constructor_bits (init, buffer, bit_size) - tree init; - char *buffer; - int bit_size; +get_set_constructor_bits (tree init, char *buffer, int bit_size) { int i; tree vals; @@ -4569,17 +4697,14 @@ get_set_constructor_bits (init, buffer, bit_size) Otherwise, a TREE_LIST of the non-constant elements is emitted. */ tree -get_set_constructor_bytes (init, buffer, wd_size) - tree init; - unsigned char *buffer; - int wd_size; +get_set_constructor_bytes (tree init, unsigned char *buffer, int wd_size) { int i; int set_word_size = BITS_PER_UNIT; int bit_size = wd_size * set_word_size; int bit_pos = 0; unsigned char *bytep = buffer; - char *bit_buffer = (char *) alloca (bit_size); + char *bit_buffer = alloca (bit_size); tree non_const_bits = get_set_constructor_bits (init, bit_buffer, bit_size); for (i = 0; i < wd_size; i++) @@ -4606,12 +4731,8 @@ get_set_constructor_bytes (init, buffer, wd_size) FILE, LINE, and FUNCTION are of the caller. */ void -tree_check_failed (node, code, file, line, function) - const tree node; - enum tree_code code; - const char *file; - int line; - const char *function; +tree_check_failed (const tree node, enum tree_code code, const char *file, + int line, const char *function) { internal_error ("tree check: expected %s, have %s in %s, at %s:%d", tree_code_name[code], tree_code_name[TREE_CODE (node)], @@ -4622,12 +4743,8 @@ tree_check_failed (node, code, file, line, function) code, given in CL. */ void -tree_class_check_failed (node, cl, file, line, function) - const tree node; - int cl; - const char *file; - int line; - const char *function; +tree_class_check_failed (const tree node, int cl, const char *file, + int line, const char *function) { internal_error ("tree check: expected class '%c', have '%c' (%s) in %s, at %s:%d", @@ -4639,26 +4756,33 @@ tree_class_check_failed (node, cl, file, line, function) (dynamically sized) vector. */ void -tree_vec_elt_check_failed (idx, len, file, line, function) - int idx; - int len; - const char *file; - int line; - const char *function; +tree_vec_elt_check_failed (int idx, int len, const char *file, int line, + const char *function) { internal_error ("tree check: accessed elt %d of tree_vec with %d elts in %s, at %s:%d", idx + 1, len, function, trim_filename (file), line); } +/* Similar to above, except that the check is for the bounds of the operand + vector of an expression node. */ + +void +tree_operand_check_failed (int idx, enum tree_code code, const char *file, + int line, const char *function) +{ + internal_error + ("tree check: accessed operand %d of %s with %d operands in %s, at %s:%d", + idx + 1, tree_code_name[code], TREE_CODE_LENGTH (code), + function, trim_filename (file), line); +} #endif /* ENABLE_TREE_CHECKING */ /* For a new vector type node T, build the information necessary for debugging output. */ static void -finish_vector_type (t) - tree t; +finish_vector_type (tree t) { layout_type (t); @@ -4685,8 +4809,7 @@ finish_vector_type (t) this function to select one of the types as sizetype. */ void -build_common_tree_nodes (signed_char) - int signed_char; +build_common_tree_nodes (int signed_char) { error_mark_node = make_node (ERROR_MARK); TREE_TYPE (error_mark_node) = error_mark_node; @@ -4713,6 +4836,16 @@ build_common_tree_nodes (signed_char) long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE); long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE); + /* Define a boolean type. This type only represents boolean values but + may be larger than char depending on the value of BOOL_TYPE_SIZE. + Front ends which want to override this size (i.e. Java) can redefine + boolean_type_node before calling build_common_tree_nodes_2. */ + boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE); + TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE); + TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0); + TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node; + TYPE_PRECISION (boolean_type_node) = 1; + intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode)); intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode)); intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode)); @@ -4724,14 +4857,17 @@ build_common_tree_nodes (signed_char) unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode)); unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode)); unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode)); + + access_public_node = get_identifier ("public"); + access_protected_node = get_identifier ("protected"); + access_private_node = get_identifier ("private"); } /* Call this function after calling build_common_tree_nodes and set_sizetype. It will create several other common tree nodes. */ void -build_common_tree_nodes_2 (short_double) - int short_double; +build_common_tree_nodes_2 (int short_double) { /* Define these next since types below may used them. */ integer_zero_node = build_int_2 (0, 0); @@ -4744,6 +4880,9 @@ build_common_tree_nodes_2 (short_double) bitsize_one_node = bitsize_int (1); bitsize_unit_node = bitsize_int (BITS_PER_UNIT); + boolean_false_node = TYPE_MIN_VALUE (boolean_type_node); + boolean_true_node = TYPE_MAX_VALUE (boolean_type_node); + void_type_node = make_node (VOID_TYPE); layout_type (void_type_node); @@ -4775,6 +4914,11 @@ build_common_tree_nodes_2 (short_double) TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE; layout_type (long_double_type_node); + float_ptr_type_node = build_pointer_type (float_type_node); + double_ptr_type_node = build_pointer_type (double_type_node); + long_double_ptr_type_node = build_pointer_type (long_double_type_node); + integer_ptr_type_node = build_pointer_type (integer_type_node); + complex_integer_type_node = make_node (COMPLEX_TYPE); TREE_TYPE (complex_integer_type_node) = integer_type_node; layout_type (complex_integer_type_node); @@ -4792,10 +4936,9 @@ build_common_tree_nodes_2 (short_double) layout_type (complex_long_double_type_node); { - tree t; - BUILD_VA_LIST_TYPE (t); + tree t = (*targetm.build_builtin_va_list) (); - /* Many back-ends define record types without seting TYPE_NAME. + /* Many back-ends define record types without setting TYPE_NAME. If we copied the record type here, we'd keep the original record type without a name. This breaks name mangling. So, don't copy record types and let c_common_nodes_and_builtins() @@ -4838,16 +4981,14 @@ build_common_tree_nodes_2 (short_double) V2DF_type_node = make_vector (V2DFmode, double_type_node, 0); V16QI_type_node = make_vector (V16QImode, intQI_type_node, 0); V1DI_type_node = make_vector (V1DImode, intDI_type_node, 0); + V4DF_type_node = make_vector (V4DFmode, double_type_node, 0); } /* Returns a vector tree node given a vector mode, the inner type, and the signness. */ static tree -make_vector (mode, innertype, unsignedp) - enum machine_mode mode; - tree innertype; - int unsignedp; +make_vector (enum machine_mode mode, tree innertype, int unsignedp) { tree t; @@ -4864,8 +5005,7 @@ make_vector (mode, innertype, unsignedp) aggregate of zeros. Otherwise return FALSE. */ bool -initializer_zerop (init) - tree init; +initializer_zerop (tree init) { STRIP_NOPS (init); @@ -4883,9 +5023,14 @@ initializer_zerop (init) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init)))); case CONSTRUCTOR: { + /* Set is empty if it has no elements. */ + if ((TREE_CODE (TREE_TYPE (init)) == SET_TYPE) + && CONSTRUCTOR_ELTS (init)) + return false; + if (AGGREGATE_TYPE_P (TREE_TYPE (init))) { - tree aggr_init = TREE_OPERAND (init, 1); + tree aggr_init = CONSTRUCTOR_ELTS (init); while (aggr_init) { |