X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=3a0054c507e76d1d6a5397af6a3959e46748ea72;hb=05ac439abdc23f21dd7ceb8160de30879f977d39;hp=ef73afdbe6ca808f98f8d195720bdaeb61205ae5;hpb=4d28c5d1bd79990e131ac7994d9f3e8b4ea03b5d;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index ef73afdbe6c..3a0054c507e 100644 --- a/gcc/tree.c +++ b/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, 2003, 2004 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. @@ -48,6 +48,24 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tree-iterator.h" #include "basic-block.h" #include "tree-flow.h" +#include "params.h" + +/* Each tree code class has an associated string representation. + These must correspond to the tree_code_class entries. */ + +const char *const tree_code_class_strings[] = +{ + "exceptional", + "constant", + "type", + "declaration", + "reference", + "comparison", + "unary", + "binary", + "statement", + "expression", +}; /* obstack.[ch] explicitly declined to prototype this. */ extern int _obstack_allocated_p (struct obstack *h, void *obj); @@ -107,9 +125,16 @@ struct type_hash GTY(()) static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash))) htab_t type_hash_table; +/* Hash table and temporary node for larger integer const values. */ +static GTY (()) tree int_cst_node; +static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) + htab_t int_cst_hash_table; + 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 hashval_t int_cst_hash_hash (const void *); +static int int_cst_hash_eq (const void *, const void *); static void print_type_hash_statistics (void); static tree make_vector_type (tree, int, enum machine_mode); static int type_hash_marked_p (const void *); @@ -127,6 +152,9 @@ init_ttree (void) /* Initialize the hash table of types. */ type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash, type_hash_eq, 0); + int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash, + int_cst_hash_eq, NULL); + int_cst_node = make_node (INTEGER_CST); } @@ -141,57 +169,52 @@ decl_assembler_name (tree decl) return DECL_CHECK (decl)->decl.assembler_name; } -/* 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. */ +/* Compute the number of bytes occupied by a tree with code CODE. + This function cannot be used for TREE_VEC, PHI_NODE, or STRING_CST + codes, which are of variable length. */ size_t -tree_size (tree node) +tree_code_size (enum tree_code code) { - enum tree_code code = TREE_CODE (node); - switch (TREE_CODE_CLASS (code)) { - case 'd': /* A decl node */ + case tcc_declaration: /* A decl node */ return sizeof (struct tree_decl); - case 't': /* a type node */ + case tcc_type: /* a type node */ return sizeof (struct tree_type); - case 'r': /* a reference */ - case 'e': /* an expression */ - case 's': /* an expression with side effects */ - case '<': /* a comparison expression */ - case '1': /* a unary arithmetic expression */ - case '2': /* a binary arithmetic expression */ + case tcc_reference: /* a reference */ + case tcc_expression: /* an expression */ + case tcc_statement: /* an expression with side effects */ + case tcc_comparison: /* a comparison expression */ + case tcc_unary: /* a unary arithmetic expression */ + case tcc_binary: /* a binary arithmetic expression */ return (sizeof (struct tree_exp) - + TREE_CODE_LENGTH (code) * sizeof (char *) - sizeof (char *)); + + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *)); - case 'c': /* a constant */ + case tcc_constant: /* a constant */ 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); + case STRING_CST: gcc_unreachable (); default: return lang_hooks.tree_size (code); } - case 'x': /* something random, like an identifier. */ + case tcc_exceptional: /* something random, like an identifier. */ 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); - case PHI_NODE: return (sizeof (struct tree_phi_node) - + (PHI_ARG_CAPACITY (node) - 1) * - sizeof (struct phi_arg_d)); + case TREE_VEC: + case PHI_NODE: gcc_unreachable (); case SSA_NAME: return sizeof (struct tree_ssa_name); @@ -204,13 +227,38 @@ tree_size (tree node) } default: - abort (); + gcc_unreachable (); + } +} + +/* Compute the number of bytes occupied by NODE. This routine only + looks at TREE_CODE, except for PHI_NODE and TREE_VEC nodes. */ +size_t +tree_size (tree node) +{ + enum tree_code code = TREE_CODE (node); + switch (code) + { + case PHI_NODE: + return (sizeof (struct tree_phi_node) + + (PHI_ARG_CAPACITY (node) - 1) * sizeof (struct phi_arg_d)); + + case TREE_VEC: + return (sizeof (struct tree_vec) + + (TREE_VEC_LENGTH (node) - 1) * sizeof(char *)); + + case STRING_CST: + return sizeof (struct tree_string) + TREE_STRING_LENGTH (node) - 1; + + default: + return tree_code_size (code); } } -/* Return a newly allocated node of code CODE. - For decl and type nodes, some other fields are initialized. - The rest of the node is initialized to zero. +/* Return a newly allocated node of code CODE. For decl and type + nodes, some other fields are initialized. The rest of the node is + initialized to zero. This function cannot be used for PHI_NODE or + TREE_VEC nodes, which is enforced by asserts in tree_code_size. Achoo! I got a code in the node. */ @@ -218,70 +266,75 @@ tree make_node_stat (enum tree_code code MEM_STAT_DECL) { tree t; - int type = TREE_CODE_CLASS (code); - size_t length; + enum tree_code_class type = TREE_CODE_CLASS (code); + size_t length = tree_code_size (code); #ifdef GATHER_STATISTICS tree_node_kind kind; -#endif - struct tree_common ttmp; - - /* We can't allocate a TREE_VEC, PHI_NODE, or STRING_CST - without knowing how many elements it will have. */ - if (code == TREE_VEC || code == PHI_NODE) - abort (); - TREE_SET_CODE ((tree)&ttmp, code); - length = tree_size ((tree)&ttmp); - -#ifdef GATHER_STATISTICS switch (type) { - case 'd': /* A decl node */ + case tcc_declaration: /* A decl node */ kind = d_kind; break; - case 't': /* a type node */ + case tcc_type: /* a type node */ kind = t_kind; break; - case 's': /* an expression with side effects */ + case tcc_statement: /* an expression with side effects */ kind = s_kind; break; - case 'r': /* a reference */ + case tcc_reference: /* a reference */ kind = r_kind; break; - case 'e': /* an expression */ - case '<': /* a comparison expression */ - case '1': /* a unary arithmetic expression */ - case '2': /* a binary arithmetic expression */ + case tcc_expression: /* an expression */ + case tcc_comparison: /* a comparison expression */ + case tcc_unary: /* a unary arithmetic expression */ + case tcc_binary: /* a binary arithmetic expression */ kind = e_kind; break; - case 'c': /* a constant */ + case tcc_constant: /* a constant */ kind = c_kind; break; - case 'x': /* something random, like an identifier. */ - if (code == IDENTIFIER_NODE) - kind = id_kind; - else if (code == TREE_VEC) - kind = vec_kind; - else if (code == TREE_BINFO) - kind = binfo_kind; - else if (code == PHI_NODE) - kind = phi_kind; - else if (code == SSA_NAME) - kind = ssa_name_kind; - else if (code == BLOCK) - kind = b_kind; - else - kind = x_kind; - break; + case tcc_exceptional: /* something random, like an identifier. */ + switch (code) + { + case IDENTIFIER_NODE: + kind = id_kind; + break; + + case TREE_VEC:; + kind = vec_kind; + break; + + case TREE_BINFO: + kind = binfo_kind; + break; + + case PHI_NODE: + kind = phi_kind; + break; + + case SSA_NAME: + kind = ssa_name_kind; + break; + case BLOCK: + kind = b_kind; + break; + + default: + kind = x_kind; + break; + } + break; + default: - abort (); + gcc_unreachable (); } tree_node_counts[(int) kind]++; @@ -296,11 +349,11 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) switch (type) { - case 's': + case tcc_statement: TREE_SIDE_EFFECTS (t) = 1; break; - case 'd': + case tcc_declaration: if (code != FUNCTION_DECL) DECL_ALIGN (t) = 1; DECL_USER_ALIGN (t) = 0; @@ -312,7 +365,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) DECL_POINTER_ALIAS_SET (t) = -1; break; - case 't': + case tcc_type: TYPE_UID (t) = next_type_uid++; TYPE_ALIGN (t) = char_type_node ? TYPE_ALIGN (char_type_node) : 0; TYPE_USER_ALIGN (t) = 0; @@ -326,12 +379,12 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) TYPE_ALIAS_SET (t) = -1; break; - case 'c': + case tcc_constant: TREE_CONSTANT (t) = 1; TREE_INVARIANT (t) = 1; break; - case 'e': + case tcc_expression: switch (code) { case INIT_EXPR: @@ -350,6 +403,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) break; } break; + + default: + /* Other classes need no special treatment. */ + break; } return t; @@ -365,10 +422,7 @@ copy_node_stat (tree node MEM_STAT_DECL) enum tree_code code = TREE_CODE (node); size_t length; -#ifdef ENABLE_CHECKING - if (code == STATEMENT_LIST) - abort (); -#endif + gcc_assert (code != STATEMENT_LIST); length = tree_size (node); t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT); @@ -379,9 +433,9 @@ copy_node_stat (tree node MEM_STAT_DECL) TREE_VISITED (t) = 0; t->common.ann = 0; - if (TREE_CODE_CLASS (code) == 'd') + if (TREE_CODE_CLASS (code) == tcc_declaration) DECL_UID (t) = next_decl_uid++; - else if (TREE_CODE_CLASS (code) == 't') + else if (TREE_CODE_CLASS (code) == tcc_type) { TYPE_UID (t) = next_type_uid++; /* The following is so that the debug code for @@ -391,6 +445,13 @@ copy_node_stat (tree node MEM_STAT_DECL) but the optimizer should catch that. */ TYPE_SYMTAB_POINTER (t) = 0; TYPE_SYMTAB_ADDRESS (t) = 0; + + /* Do not copy the values cache. */ + if (TYPE_CACHED_VALUES_P(t)) + { + TYPE_CACHED_VALUES_P (t) = 0; + TYPE_CACHED_VALUES (t) = NULL_TREE; + } } return t; @@ -420,21 +481,269 @@ copy_list (tree list) } -/* 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'. */ +/* Create an INT_CST node with a LOW value sign extended. */ + +tree +build_int_cst (tree type, HOST_WIDE_INT low) +{ + return build_int_cst_wide (type, low, low < 0 ? -1 : 0); +} + +/* Create an INT_CST node with a LOW value zero extended. */ + +tree +build_int_cstu (tree type, unsigned HOST_WIDE_INT low) +{ + return build_int_cst_wide (type, low, 0); +} + +/* Create an INT_CST node with a LOW value in TYPE. The value is sign extended + if it is negative. This function is similar to build_int_cst, but + the extra bits outside of the type precision are cleared. Constants + with these extra bits may confuse the fold so that it detects overflows + even in cases when they do not occur, and in general should be avoided. + We cannot however make this a default behavior of build_int_cst without + more intrusive changes, since there are parts of gcc that rely on the extra + precision of the integer constants. */ tree -build_int_2 (unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) +build_int_cst_type (tree type, HOST_WIDE_INT low) { - tree t = make_node (INTEGER_CST); + unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low; + unsigned HOST_WIDE_INT hi; + unsigned bits; + bool signed_p; + bool negative; + + if (!type) + type = integer_type_node; + + bits = TYPE_PRECISION (type); + signed_p = !TYPE_UNSIGNED (type); + + if (bits >= HOST_BITS_PER_WIDE_INT) + negative = (low < 0); + else + { + /* If the sign bit is inside precision of LOW, use it to determine + the sign of the constant. */ + negative = ((val >> (bits - 1)) & 1) != 0; + + /* Mask out the bits outside of the precision of the constant. */ + if (signed_p && negative) + val = val | ((~(unsigned HOST_WIDE_INT) 0) << bits); + else + val = val & ~((~(unsigned HOST_WIDE_INT) 0) << bits); + } + + /* Determine the high bits. */ + hi = (negative ? ~(unsigned HOST_WIDE_INT) 0 : 0); + + /* For unsigned type we need to mask out the bits outside of the type + precision. */ + if (!signed_p) + { + if (bits <= HOST_BITS_PER_WIDE_INT) + hi = 0; + else + { + bits -= HOST_BITS_PER_WIDE_INT; + hi = hi & ~((~(unsigned HOST_WIDE_INT) 0) << bits); + } + } + + return build_int_cst_wide (type, val, hi); +} + +/* These are the hash table functions for the hash table of INTEGER_CST + nodes of a sizetype. */ + +/* Return the hash code code X, an INTEGER_CST. */ + +static hashval_t +int_cst_hash_hash (const void *x) +{ + tree t = (tree) x; + + return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t) + ^ htab_hash_pointer (TREE_TYPE (t))); +} + +/* Return nonzero if the value represented by *X (an INTEGER_CST tree node) + is the same as that given by *Y, which is the same. */ + +static int +int_cst_hash_eq (const void *x, const void *y) +{ + tree xt = (tree) x; + tree yt = (tree) y; + + return (TREE_TYPE (xt) == TREE_TYPE (yt) + && TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt) + && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt)); +} + +/* Create an INT_CST node of TYPE and value HI:LOW. If TYPE is NULL, + integer_type_node is used. The returned node is always shared. + For small integers we use a per-type vector cache, for larger ones + we use a single hash table. */ + +tree +build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) +{ + tree t; + int ix = -1; + int limit = 0; + + if (!type) + type = integer_type_node; + + switch (TREE_CODE (type)) + { + case POINTER_TYPE: + case REFERENCE_TYPE: + /* Cache NULL pointer. */ + if (!hi && !low) + { + limit = 1; + ix = 0; + } + break; + + case BOOLEAN_TYPE: + /* Cache false or true. */ + limit = 2; + if (!hi && low < 2) + ix = low; + break; + + case INTEGER_TYPE: + case CHAR_TYPE: + case OFFSET_TYPE: + if (TYPE_UNSIGNED (type)) + { + /* Cache 0..N */ + limit = INTEGER_SHARE_LIMIT; + if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT) + ix = low; + } + else + { + /* Cache -1..N */ + limit = INTEGER_SHARE_LIMIT + 1; + if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT) + ix = low + 1; + else if (hi == -1 && low == -(unsigned HOST_WIDE_INT)1) + ix = 0; + } + break; + default: + break; + } + + if (ix >= 0) + { + /* Look for it in the type's vector of small shared ints. */ + if (!TYPE_CACHED_VALUES_P (type)) + { + TYPE_CACHED_VALUES_P (type) = 1; + TYPE_CACHED_VALUES (type) = make_tree_vec (limit); + } + + t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix); + if (t) + { + /* Make sure no one is clobbering the shared constant. */ + gcc_assert (TREE_TYPE (t) == type); + gcc_assert (TREE_INT_CST_LOW (t) == low); + gcc_assert (TREE_INT_CST_HIGH (t) == hi); + } + else + { + /* Create a new shared int. */ + t = make_node (INTEGER_CST); + + TREE_INT_CST_LOW (t) = low; + TREE_INT_CST_HIGH (t) = hi; + TREE_TYPE (t) = type; + + TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t; + } + } + else + { + /* Use the cache of larger shared ints. */ + void **slot; + + TREE_INT_CST_LOW (int_cst_node) = low; + TREE_INT_CST_HIGH (int_cst_node) = hi; + TREE_TYPE (int_cst_node) = type; + + slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT); + t = *slot; + if (!t) + { + /* Insert this one into the hash table. */ + t = int_cst_node; + *slot = t; + /* Make a new node for next time round. */ + int_cst_node = make_node (INTEGER_CST); + } + } - TREE_INT_CST_LOW (t) = low; - TREE_INT_CST_HIGH (t) = hi; - TREE_TYPE (t) = integer_type_node; return t; } +/* Builds an integer constant in TYPE such that lowest BITS bits are ones + and the rest are zeros. */ + +tree +build_low_bits_mask (tree type, unsigned bits) +{ + unsigned HOST_WIDE_INT low; + HOST_WIDE_INT high; + unsigned HOST_WIDE_INT all_ones = ~(unsigned HOST_WIDE_INT) 0; + + gcc_assert (bits <= TYPE_PRECISION (type)); + + if (bits == TYPE_PRECISION (type) + && !TYPE_UNSIGNED (type)) + { + /* Sign extended all-ones mask. */ + low = all_ones; + high = -1; + } + else if (bits <= HOST_BITS_PER_WIDE_INT) + { + low = all_ones >> (HOST_BITS_PER_WIDE_INT - bits); + high = 0; + } + else + { + bits -= HOST_BITS_PER_WIDE_INT; + low = all_ones; + high = all_ones >> (HOST_BITS_PER_WIDE_INT - bits); + } + + return build_int_cst_wide (type, low, high); +} + +/* Checks that X is integer constant that can be expressed in (unsigned) + HOST_WIDE_INT without loss of precision. */ + +bool +cst_and_fits_in_hwi (tree x) +{ + if (TREE_CODE (x) != INTEGER_CST) + return false; + + if (TYPE_PRECISION (TREE_TYPE (x)) > HOST_BITS_PER_WIDE_INT) + return false; + + return (TREE_INT_CST_HIGH (x) == 0 + || TREE_INT_CST_HIGH (x) == -1); +} + /* Return a new VECTOR_CST node whose type is TYPE and whose values are in a list pointed by VALS. */ @@ -547,10 +856,23 @@ build_real_from_int_cst (tree type, tree i) tree build_string (int len, const char *str) { - tree s = make_node (STRING_CST); + tree s; + size_t length; + + length = len + sizeof (struct tree_string); +#ifdef GATHER_STATISTICS + tree_node_counts[(int) c_kind]++; + tree_node_sizes[(int) c_kind] += length; +#endif + + s = ggc_alloc_tree (length); + + memset (s, 0, sizeof (struct tree_common)); + TREE_SET_CODE (s, STRING_CST); TREE_STRING_LENGTH (s) = len; - TREE_STRING_POINTER (s) = ggc_alloc_string (str, len); + memcpy ((char *) TREE_STRING_POINTER (s), str, len); + ((char *) TREE_STRING_POINTER (s))[len] = '\0'; return s; } @@ -692,10 +1014,9 @@ integer_all_onesp (tree expr) shift_amount = prec - HOST_BITS_PER_WIDE_INT; - if (shift_amount > HOST_BITS_PER_WIDE_INT) - /* Can not handle precisions greater than twice the host int size. */ - abort (); - else if (shift_amount == HOST_BITS_PER_WIDE_INT) + /* Can not handle precisions greater than twice the host int size. */ + gcc_assert (shift_amount <= HOST_BITS_PER_WIDE_INT); + if (shift_amount == HOST_BITS_PER_WIDE_INT) /* Shifting by the host word size is undefined according to the ANSI standard, so we must handle this as a special case. */ high_value = -1; @@ -985,8 +1306,7 @@ list_length (tree t) #ifdef ENABLE_TREE_CHECKING if (len % 2) q = TREE_CHAIN (q); - if (p == q) - abort (); + gcc_assert (p != q); #endif len++; } @@ -1031,8 +1351,7 @@ chainon (tree op1, tree op2) { tree t2; for (t2 = op2; t2; t2 = TREE_CHAIN (t2)) - if (t2 == t1) - abort (); /* Circularity created. */ + gcc_assert (t2 != t1); } #endif @@ -1267,31 +1586,37 @@ array_type_nelts (tree type) : fold (build2 (MINUS_EXPR, TREE_TYPE (max), max, min))); } -/* Return true if arg is static -- a reference to an object in - static storage. This is not the same as the C meaning of `static'. */ +/* If arg is static -- a reference to an object in static storage -- then + return the object. This is not the same as the C meaning of `static'. + If arg isn't static, return NULL. */ -bool +tree staticp (tree arg) { switch (TREE_CODE (arg)) { case FUNCTION_DECL: - /* Nested functions aren't static, since taking their address - involves a trampoline. */ - return ((decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg)) - && ! DECL_NON_ADDR_CONST_P (arg)); + /* Nested functions are static, even though taking their address will + involve a trampoline as we unnest the nested function and create + the trampoline on the tree level. */ + return arg; case VAR_DECL: return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg)) && ! DECL_THREAD_LOCAL (arg) - && ! DECL_NON_ADDR_CONST_P (arg)); + && ! DECL_NON_ADDR_CONST_P (arg) + ? arg : NULL); + + case CONST_DECL: + return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg)) + ? arg : NULL); case CONSTRUCTOR: - return TREE_STATIC (arg); + return TREE_STATIC (arg) ? arg : NULL; case LABEL_DECL: case STRING_CST: - return true; + return arg; case COMPONENT_REF: /* If the thing being referenced is not a field, then it is @@ -1302,20 +1627,17 @@ staticp (tree arg) /* If we are referencing a bitfield, we can't evaluate an ADDR_EXPR at compile time and so it isn't a constant. */ if (DECL_BIT_FIELD (TREE_OPERAND (arg, 1))) - return false; + return NULL; return staticp (TREE_OPERAND (arg, 0)); case BIT_FIELD_REF: - return false; + return NULL; -#if 0 - /* This case is technically correct, but results in setting - TREE_CONSTANT on ADDR_EXPRs that cannot be evaluated at - compile time. */ + case MISALIGNED_INDIRECT_REF: + case ALIGN_INDIRECT_REF: case INDIRECT_REF: - return TREE_CONSTANT (TREE_OPERAND (arg, 0)); -#endif + return TREE_CONSTANT (TREE_OPERAND (arg, 0)) ? arg : NULL; case ARRAY_REF: case ARRAY_RANGE_REF: @@ -1330,7 +1652,7 @@ staticp (tree arg) >= (unsigned int) LAST_AND_UNUSED_TREE_CODE) return lang_hooks.staticp (arg); else - return false; + return NULL; } } @@ -1393,7 +1715,6 @@ save_expr (tree expr) value was computed on both sides of the jump. So make sure it isn't eliminated as dead. */ TREE_SIDE_EFFECTS (t) = 1; - TREE_READONLY (t) = 1; TREE_INVARIANT (t) = 1; return t; } @@ -1418,9 +1739,9 @@ skip_simple_arithmetic (tree expr) inner = expr; while (1) { - if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1') + if (UNARY_CLASS_P (inner)) inner = TREE_OPERAND (inner, 0); - else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2') + else if (BINARY_CLASS_P (inner)) { if (TREE_INVARIANT (TREE_OPERAND (inner, 1))) inner = TREE_OPERAND (inner, 0); @@ -1436,19 +1757,6 @@ skip_simple_arithmetic (tree expr) return inner; } -/* Returns the index of the first non-tree operand for CODE, or the number - of operands if all are trees. */ - -int -first_rtl_op (enum tree_code code) -{ - switch (code) - { - default: - return TREE_CODE_LENGTH (code); - } -} - /* Return which tree structure is used by T. */ enum tree_node_structure_enum @@ -1458,22 +1766,29 @@ tree_node_structure (tree t) switch (TREE_CODE_CLASS (code)) { - case 'd': return TS_DECL; - case 't': return TS_TYPE; - case 'r': case '<': case '1': case '2': case 'e': case 's': + case tcc_declaration: + return TS_DECL; + case tcc_type: + return TS_TYPE; + case tcc_reference: + case tcc_comparison: + case tcc_unary: + case tcc_binary: + case tcc_expression: + case tcc_statement: return TS_EXP; - default: /* 'c' and 'x' */ + default: /* tcc_constant and tcc_exceptional */ break; } switch (code) { - /* 'c' cases. */ + /* tcc_constant cases. */ case INTEGER_CST: return TS_INT_CST; case REAL_CST: return TS_REAL_CST; case COMPLEX_CST: return TS_COMPLEX; case VECTOR_CST: return TS_VECTOR; case STRING_CST: return TS_STRING; - /* 'x' cases. */ + /* tcc_exceptional cases. */ case ERROR_MARK: return TS_COMMON; case IDENTIFIER_NODE: return TS_IDENTIFIER; case TREE_LIST: return TS_LIST; @@ -1487,32 +1802,7 @@ tree_node_structure (tree t) case VALUE_HANDLE: return TS_VALUE_HANDLE; default: - abort (); - } -} - -/* Perform any modifications to EXPR required when it is unsaved. Does - not recurse into EXPR's subtrees. */ - -void -unsave_expr_1 (tree expr) -{ - switch (TREE_CODE (expr)) - { - case TARGET_EXPR: - /* Don't mess with a TARGET_EXPR that hasn't been expanded. - It's OK for this to happen if it was part of a subtree that - isn't immediately expanded, such as operand 2 of another - TARGET_EXPR. */ - if (TREE_OPERAND (expr, 1)) - break; - - TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3); - TREE_OPERAND (expr, 3) = NULL_TREE; - break; - - default: - break; + gcc_unreachable (); } } @@ -1533,22 +1823,23 @@ contains_placeholder_p (tree exp) switch (TREE_CODE_CLASS (code)) { - case 'r': + case tcc_reference: /* Don't look at any PLACEHOLDER_EXPRs that might be in index or bit 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)); - case 'x': + case tcc_exceptional: if (code == TREE_LIST) return (CONTAINS_PLACEHOLDER_P (TREE_VALUE (exp)) || CONTAINS_PLACEHOLDER_P (TREE_CHAIN (exp))); break; - case '1': - case '2': case '<': - case 'e': + case tcc_unary: + case tcc_binary: + case tcc_comparison: + case tcc_expression: switch (code) { case COMPOUND_EXPR: @@ -1564,7 +1855,7 @@ contains_placeholder_p (tree exp) break; } - switch (first_rtl_op (code)) + switch (TREE_CODE_LENGTH (code)) { case 1: return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0)); @@ -1581,12 +1872,12 @@ contains_placeholder_p (tree 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. */ +/* Return true 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) +static bool +type_contains_placeholder_1 (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. */ @@ -1594,7 +1885,7 @@ type_contains_placeholder_p (tree type) || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type)) || (TREE_TYPE (type) != 0 && type_contains_placeholder_p (TREE_TYPE (type)))) - return 1; + return true; /* Now do type-specific checks. Note that the last part of the check above greatly limits what we have to do below. */ @@ -1611,7 +1902,8 @@ type_contains_placeholder_p (tree type) case METHOD_TYPE: case FILE_TYPE: case FUNCTION_TYPE: - return 0; + case VECTOR_TYPE: + return false; case INTEGER_TYPE: case REAL_TYPE: @@ -1620,8 +1912,6 @@ type_contains_placeholder_p (tree type) || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type))); case ARRAY_TYPE: - case SET_TYPE: - case VECTOR_TYPE: /* We're already checked the component type (TREE_TYPE), so just check the index type. */ return type_contains_placeholder_p (TYPE_DOMAIN (type)); @@ -1630,33 +1920,7 @@ type_contains_placeholder_p (tree 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 @@ -1664,84 +1928,37 @@ type_contains_placeholder_p (tree type) || (TREE_CODE (type) == QUAL_UNION_TYPE && CONTAINS_PLACEHOLDER_P (DECL_QUALIFIER (field))) || type_contains_placeholder_p (TREE_TYPE (field)))) - { - ret = true; - break; - } + return true; - /* 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; + return false; } default: - abort (); + gcc_unreachable (); } } -/* Return 1 if EXP contains any expressions that produce cleanups for an - outer scope to deal with. Used by fold. */ - -int -has_cleanups (tree exp) +bool +type_contains_placeholder_p (tree type) { - int i, nops, cmp; - - if (! TREE_SIDE_EFFECTS (exp)) - return 0; - - switch (TREE_CODE (exp)) - { - case TARGET_EXPR: - case WITH_CLEANUP_EXPR: - return 1; - - case CLEANUP_POINT_EXPR: - return 0; - - case CALL_EXPR: - for (exp = TREE_OPERAND (exp, 1); exp; exp = TREE_CHAIN (exp)) - { - cmp = has_cleanups (TREE_VALUE (exp)); - if (cmp) - return cmp; - } - return 0; + bool result; - case DECL_EXPR: - return (DECL_INITIAL (DECL_EXPR_DECL (exp)) - && has_cleanups (DECL_INITIAL (DECL_EXPR_DECL (exp)))); + /* If the contains_placeholder_bits field has been initialized, + then we know the answer. */ + if (TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) > 0) + return TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) - 1; - default: - break; - } + /* Indicate that we've seen this type node, and the answer is false. + This is what we want to return if we run into recursion via fields. */ + TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) = 1; - /* This general rule works for most tree codes. All exceptions should be - handled above. If this is a language-specific tree code, we can't - trust what might be in the operand, so say we don't know - the situation. */ - if ((int) TREE_CODE (exp) >= (int) LAST_AND_UNUSED_TREE_CODE) - return -1; + /* Compute the real value. */ + result = type_contains_placeholder_1 (type); - nops = first_rtl_op (TREE_CODE (exp)); - for (i = 0; i < nops; i++) - if (TREE_OPERAND (exp, i) != 0) - { - int type = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i))); - if (type == 'e' || type == '<' || type == '1' || type == '2' - || type == 'r' || type == 's') - { - cmp = has_cleanups (TREE_OPERAND (exp, i)); - if (cmp) - return cmp; - } - } + /* Store the real value. */ + TYPE_CONTAINS_PLACEHOLDER_INTERNAL (type) = result + 1; - return 0; + return result; } /* Given a tree EXP, a FIELD_DECL F, and a replacement value R, @@ -1773,7 +1990,7 @@ substitute_in_expr (tree exp, tree f, tree r) /* If this expression is getting a value from a PLACEHOLDER_EXPR and it is the right field, replace it with R. */ for (inner = TREE_OPERAND (exp, 0); - TREE_CODE_CLASS (TREE_CODE (inner)) == 'r'; + REFERENCE_CLASS_P (inner); inner = TREE_OPERAND (inner, 0)) ; if (TREE_CODE (inner) == PLACEHOLDER_EXPR @@ -1794,17 +2011,17 @@ substitute_in_expr (tree exp, tree f, tree r) else switch (TREE_CODE_CLASS (code)) { - case 'c': - case 'd': + case tcc_constant: + case tcc_declaration: return exp; - case 'x': - case '1': - case '2': - case '<': - case 'e': - case 'r': - switch (first_rtl_op (code)) + case tcc_exceptional: + case tcc_unary: + case tcc_binary: + case tcc_comparison: + case tcc_expression: + case tcc_reference: + switch (TREE_CODE_LENGTH (code)) { case 0: return exp; @@ -1840,12 +2057,12 @@ substitute_in_expr (tree exp, tree f, tree r) break; default: - abort (); + gcc_unreachable (); } break; default: - abort (); + gcc_unreachable (); } TREE_READONLY (new) = TREE_READONLY (exp); @@ -1872,10 +2089,10 @@ substitute_placeholder_in_expr (tree exp, tree obj) elt = ((TREE_CODE (elt) == COMPOUND_EXPR || TREE_CODE (elt) == COND_EXPR) ? TREE_OPERAND (elt, 1) - : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r' - || TREE_CODE_CLASS (TREE_CODE (elt)) == '1' - || TREE_CODE_CLASS (TREE_CODE (elt)) == '2' - || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e') + : (REFERENCE_CLASS_P (elt) + || UNARY_CLASS_P (elt) + || BINARY_CLASS_P (elt) + || EXPRESSION_CLASS_P (elt)) ? TREE_OPERAND (elt, 0) : 0)) if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type) return elt; @@ -1884,10 +2101,10 @@ substitute_placeholder_in_expr (tree exp, tree obj) elt = ((TREE_CODE (elt) == COMPOUND_EXPR || TREE_CODE (elt) == COND_EXPR) ? TREE_OPERAND (elt, 1) - : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r' - || TREE_CODE_CLASS (TREE_CODE (elt)) == '1' - || TREE_CODE_CLASS (TREE_CODE (elt)) == '2' - || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e') + : (REFERENCE_CLASS_P (elt) + || UNARY_CLASS_P (elt) + || BINARY_CLASS_P (elt) + || EXPRESSION_CLASS_P (elt)) ? TREE_OPERAND (elt, 0) : 0)) if (POINTER_TYPE_P (TREE_TYPE (elt)) && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt))) @@ -1913,18 +2130,18 @@ substitute_placeholder_in_expr (tree exp, tree obj) else switch (TREE_CODE_CLASS (code)) { - case 'c': - case 'd': + case tcc_constant: + case tcc_declaration: return exp; - case 'x': - case '1': - case '2': - case '<': - case 'e': - case 'r': - case 's': - switch (first_rtl_op (code)) + case tcc_exceptional: + case tcc_unary: + case tcc_binary: + case tcc_comparison: + case tcc_expression: + case tcc_reference: + case tcc_statement: + switch (TREE_CODE_LENGTH (code)) { case 0: return exp; @@ -1970,12 +2187,12 @@ substitute_placeholder_in_expr (tree exp, tree obj) return fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3)); default: - abort (); + gcc_unreachable (); } break; default: - abort (); + gcc_unreachable (); } } @@ -2095,13 +2312,13 @@ stabilize_reference_1 (tree e) switch (TREE_CODE_CLASS (code)) { - case 'x': - case 't': - case 'd': - case '<': - case 's': - case 'e': - case 'r': + case tcc_exceptional: + case tcc_type: + case tcc_declaration: + case tcc_comparison: + case tcc_statement: + case tcc_expression: + case tcc_reference: /* If the expression has side-effects, then encase it in a SAVE_EXPR so that it will only be evaluated once. */ /* The reference (r) and comparison (<) classes could be handled as @@ -2110,12 +2327,12 @@ stabilize_reference_1 (tree e) return save_expr (e); return e; - case 'c': + case tcc_constant: /* Constants need no processing. In fact, we should never reach here. */ return e; - case '2': + case tcc_binary: /* Division is slow and tends to be compiled with jumps, especially the division by powers of 2 that is often found inside of an array reference. So do it just once. */ @@ -2129,13 +2346,13 @@ stabilize_reference_1 (tree e) stabilize_reference_1 (TREE_OPERAND (e, 1))); break; - case '1': + case tcc_unary: /* Recursively stabilize each operand. */ result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0))); break; default: - abort (); + gcc_unreachable (); } TREE_TYPE (result) = TREE_TYPE (e); @@ -2183,36 +2400,44 @@ do { tree _node = (NODE); \ && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE) { UPDATE_TITCSE (TREE_OPERAND (node, 1)); - UPDATE_TITCSE (array_ref_low_bound (node)); - UPDATE_TITCSE (array_ref_element_size (node)); + if (TREE_OPERAND (node, 2)) + UPDATE_TITCSE (TREE_OPERAND (node, 2)); + if (TREE_OPERAND (node, 3)) + UPDATE_TITCSE (TREE_OPERAND (node, 3)); } /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a FIELD_DECL, apparently. The G++ front end can put something else there, at least temporarily. */ else if (TREE_CODE (node) == COMPONENT_REF && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL) - UPDATE_TITCSE (component_ref_field_offset (node)); + { + if (TREE_OPERAND (node, 2)) + UPDATE_TITCSE (TREE_OPERAND (node, 2)); + } else if (TREE_CODE (node) == BIT_FIELD_REF) UPDATE_TITCSE (TREE_OPERAND (node, 2)); } /* Now see what's inside. If it's an INDIRECT_REF, copy our properties from - it. If it's a decl, it's invariant and constant if the decl is static. - It's also invariant if it's a decl in the current function. (Taking the - address of a volatile variable is not volatile.) If it's a constant, - the address is both invariant and constant. Otherwise it's neither. */ + the address, since &(*a)->b is a form of addition. If it's a decl, it's + invariant and constant if the decl is static. It's also invariant if it's + a decl in the current function. Taking the address of a volatile variable + is not volatile. If it's a constant, the address is both invariant and + constant. Otherwise it's neither. */ if (TREE_CODE (node) == INDIRECT_REF) - UPDATE_TITCSE (node); + UPDATE_TITCSE (TREE_OPERAND (node, 0)); else if (DECL_P (node)) { if (staticp (node)) ; - else if (decl_function_context (node) == current_function_decl) + else if (decl_function_context (node) == current_function_decl + /* Addresses of thread-local variables are invariant. */ + || (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node))) tc = false; else ti = tc = false; } - else if (TREE_CODE_CLASS (TREE_CODE (node)) == 'c') + else if (CONSTANT_CLASS_P (node)) ; else { @@ -2240,10 +2465,7 @@ build0_stat (enum tree_code code, tree tt MEM_STAT_DECL) { tree t; -#ifdef ENABLE_CHECKING - if (TREE_CODE_LENGTH (code) != 0) - abort (); -#endif + gcc_assert (TREE_CODE_LENGTH (code) == 0); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -2263,10 +2485,10 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) #ifdef GATHER_STATISTICS switch (TREE_CODE_CLASS (code)) { - case 's': /* an expression with side effects */ + case tcc_statement: /* an expression with side effects */ kind = s_kind; break; - case 'r': /* a reference */ + case tcc_reference: /* a reference */ kind = r_kind; break; default: @@ -2278,10 +2500,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) tree_node_sizes[(int) kind] += length; #endif -#ifdef ENABLE_CHECKING - if (TREE_CODE_LENGTH (code) != 1) - abort (); -#endif /* ENABLE_CHECKING */ + gcc_assert (TREE_CODE_LENGTH (code) == 1); t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT); @@ -2298,13 +2517,13 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) TREE_COMPLEXITY (t) = 0; TREE_OPERAND (t, 0) = node; TREE_BLOCK (t) = NULL_TREE; - if (node && !TYPE_P (node) && first_rtl_op (code) != 0) + if (node && !TYPE_P (node)) { TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (node); TREE_READONLY (t) = TREE_READONLY (node); } - if (TREE_CODE_CLASS (code) == 's') + if (TREE_CODE_CLASS (code) == tcc_statement) TREE_SIDE_EFFECTS (t) = 1; else switch (code) { @@ -2321,6 +2540,8 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) TREE_READONLY (t) = 0; break; + case MISALIGNED_INDIRECT_REF: + case ALIGN_INDIRECT_REF: case INDIRECT_REF: /* Whether a dereference is readonly has nothing to do with whether its operand is readonly. */ @@ -2333,12 +2554,15 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) break; default: - if (TREE_CODE_CLASS (code) == '1' && node && !TYPE_P (node) + if (TREE_CODE_CLASS (code) == tcc_unary + && node && !TYPE_P (node) && TREE_CONSTANT (node)) TREE_CONSTANT (t) = 1; - if (TREE_CODE_CLASS (code) == '1' && node && TREE_INVARIANT (node)) + if (TREE_CODE_CLASS (code) == tcc_unary + && node && TREE_INVARIANT (node)) TREE_INVARIANT (t) = 1; - if (TREE_CODE_CLASS (code) == 'r' && node && TREE_THIS_VOLATILE (node)) + if (TREE_CODE_CLASS (code) == tcc_reference + && node && TREE_THIS_VOLATILE (node)) TREE_THIS_VOLATILE (t) = 1; break; } @@ -2349,7 +2573,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) #define PROCESS_ARG(N) \ do { \ TREE_OPERAND (t, N) = arg##N; \ - if (arg##N &&!TYPE_P (arg##N) && fro > N) \ + if (arg##N &&!TYPE_P (arg##N)) \ { \ if (TREE_SIDE_EFFECTS (arg##N)) \ side_effects = 1; \ @@ -2367,12 +2591,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) { bool constant, read_only, side_effects, invariant; tree t; - int fro; -#ifdef ENABLE_CHECKING - if (TREE_CODE_LENGTH (code) != 2) - abort (); -#endif + gcc_assert (TREE_CODE_LENGTH (code) == 2); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -2381,12 +2601,11 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) result based on those same flags for the arguments. But if the arguments aren't really even `tree' expressions, we shouldn't be trying to do this. */ - fro = first_rtl_op (code); /* Expressions without side effects may be constant if their arguments are as well. */ - constant = (TREE_CODE_CLASS (code) == '<' - || TREE_CODE_CLASS (code) == '2'); + constant = (TREE_CODE_CLASS (code) == tcc_comparison + || TREE_CODE_CLASS (code) == tcc_binary); read_only = 1; side_effects = TREE_SIDE_EFFECTS (t); invariant = constant; @@ -2399,7 +2618,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) TREE_INVARIANT (t) = invariant; TREE_SIDE_EFFECTS (t) = side_effects; TREE_THIS_VOLATILE (t) - = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0); + = (TREE_CODE_CLASS (code) == tcc_reference + && arg0 && TREE_THIS_VOLATILE (arg0)); return t; } @@ -2410,18 +2630,12 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, { bool constant, read_only, side_effects, invariant; tree t; - int fro; -#ifdef ENABLE_CHECKING - if (TREE_CODE_LENGTH (code) != 3) - abort (); -#endif + gcc_assert (TREE_CODE_LENGTH (code) == 3); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; - fro = first_rtl_op (code); - side_effects = TREE_SIDE_EFFECTS (t); PROCESS_ARG(0); @@ -2450,7 +2664,8 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, TREE_SIDE_EFFECTS (t) = side_effects; TREE_THIS_VOLATILE (t) - = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0); + = (TREE_CODE_CLASS (code) == tcc_reference + && arg0 && TREE_THIS_VOLATILE (arg0)); return t; } @@ -2461,18 +2676,12 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1, { bool constant, read_only, side_effects, invariant; tree t; - int fro; -#ifdef ENABLE_CHECKING - if (TREE_CODE_LENGTH (code) != 4) - abort (); -#endif + gcc_assert (TREE_CODE_LENGTH (code) == 4); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; - fro = first_rtl_op (code); - side_effects = TREE_SIDE_EFFECTS (t); PROCESS_ARG(0); @@ -2482,7 +2691,8 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1, TREE_SIDE_EFFECTS (t) = side_effects; TREE_THIS_VOLATILE (t) - = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0); + = (TREE_CODE_CLASS (code) == tcc_reference + && arg0 && TREE_THIS_VOLATILE (arg0)); return t; } @@ -2525,7 +2735,7 @@ tree t = build4 (code, tt, arg0, arg1, arg2, arg3); break; default: - abort (); + gcc_unreachable (); } va_end (p); @@ -2686,6 +2896,74 @@ build_decl_attribute_variant (tree ddecl, tree attribute) return ddecl; } +/* Borrowed from hashtab.c iterative_hash implementation. */ +#define mix(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<< 8); \ + c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \ + a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \ + b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \ + a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \ + b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \ +} + + +/* Produce good hash value combining VAL and VAL2. */ +static inline hashval_t +iterative_hash_hashval_t (hashval_t val, hashval_t val2) +{ + /* the golden ratio; an arbitrary value. */ + hashval_t a = 0x9e3779b9; + + mix (a, val, val2); + return val2; +} + +/* Produce good hash value combining PTR and VAL2. */ +static inline hashval_t +iterative_hash_pointer (void *ptr, hashval_t val2) +{ + if (sizeof (ptr) == sizeof (hashval_t)) + return iterative_hash_hashval_t ((size_t) ptr, val2); + else + { + hashval_t a = (hashval_t) (size_t) ptr; + /* Avoid warnings about shifting of more than the width of the type on + hosts that won't execute this path. */ + int zero = 0; + hashval_t b = (hashval_t) ((size_t) ptr >> (sizeof (hashval_t) * 8 + zero)); + mix (a, b, val2); + return val2; + } +} + +/* Produce good hash value combining VAL and VAL2. */ +static inline hashval_t +iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2) +{ + if (sizeof (HOST_WIDE_INT) == sizeof (hashval_t)) + return iterative_hash_hashval_t (val, val2); + else + { + hashval_t a = (hashval_t) val; + /* Avoid warnings about shifting of more than the width of the type on + hosts that won't execute this path. */ + int zero = 0; + hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero)); + mix (a, b, val2); + if (sizeof (HOST_WIDE_INT) > 2 * sizeof (hashval_t)) + { + hashval_t a = (hashval_t) (val >> (sizeof (hashval_t) * 16 + zero)); + hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 24 + zero)); + mix (a, b, val2); + } + return val2; + } +} + /* Return a type like TTYPE except that its TYPE_ATTRIBUTE is ATTRIBUTE. @@ -2749,6 +3027,7 @@ build_type_attribute_variant (tree ttype, tree attribute) return ttype; } + /* Return nonzero if IDENT is a valid name for attribute ATTR, or zero if not. @@ -2757,29 +3036,29 @@ build_type_attribute_variant (tree ttype, tree attribute) `text'. One might then also require attribute lists to be stored in their canonicalized form. */ -int -is_attribute_p (const char *attr, tree ident) +static int +is_attribute_with_length_p (const char *attr, int attr_len, tree ident) { - int ident_len, attr_len; + int ident_len; const char *p; - if (TREE_CODE (ident) != IDENTIFIER_NODE) - return 0; - - if (strcmp (attr, IDENTIFIER_POINTER (ident)) == 0) - return 1; - + if (TREE_CODE (ident) != IDENTIFIER_NODE) + return 0; + p = IDENTIFIER_POINTER (ident); - ident_len = strlen (p); - attr_len = strlen (attr); + ident_len = IDENTIFIER_LENGTH (ident); + + if (ident_len == attr_len + && strcmp (attr, p) == 0) + return 1; /* If ATTR is `__text__', IDENT must be `text'; and vice versa. */ if (attr[0] == '_') { - if (attr[1] != '_' - || attr[attr_len - 2] != '_' - || attr[attr_len - 1] != '_') - abort (); + gcc_assert (attr[1] == '_'); + gcc_assert (attr[attr_len - 2] == '_'); + gcc_assert (attr[attr_len - 1] == '_'); + gcc_assert (attr[1] == '_'); if (ident_len == attr_len - 4 && strncmp (attr + 2, p, attr_len - 4) == 0) return 1; @@ -2796,6 +3075,17 @@ is_attribute_p (const char *attr, tree ident) return 0; } +/* Return nonzero if IDENT is a valid name for attribute ATTR, + or zero if not. + + We try both `text' and `__text__', ATTR may be either one. */ + +int +is_attribute_p (const char *attr, tree ident) +{ + return is_attribute_with_length_p (attr, strlen (attr), ident); +} + /* Given an attribute name and a list of attributes, return a pointer to the attribute's list element if the attribute is part of the list, or NULL_TREE if not found. If the attribute appears more than once, this only @@ -2806,12 +3096,12 @@ tree lookup_attribute (const char *attr_name, tree list) { tree l; + size_t attr_len = strlen (attr_name); for (l = list; l; l = TREE_CHAIN (l)) { - if (TREE_CODE (TREE_PURPOSE (l)) != IDENTIFIER_NODE) - abort (); - if (is_attribute_p (attr_name, TREE_PURPOSE (l))) + gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE); + if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l))) return l; } @@ -2887,7 +3177,7 @@ merge_decl_attributes (tree olddecl, tree newdecl) DECL_ATTRIBUTES (newdecl)); } -#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES +#if TARGET_DLLIMPORT_DECL_ATTRIBUTES /* Specialization of merge_decl_attributes for various Windows targets. @@ -2940,6 +3230,81 @@ merge_dllimport_decl_attributes (tree old, tree new) return a; } +/* Handle a "dllimport" or "dllexport" attribute; arguments as in + struct attribute_spec.handler. */ + +tree +handle_dll_attribute (tree * pnode, tree name, tree args, int flags, + bool *no_add_attrs) +{ + tree node = *pnode; + + /* These attributes may apply to structure and union types being created, + but otherwise should pass to the declaration involved. */ + if (!DECL_P (node)) + { + if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT + | (int) ATTR_FLAG_ARRAY_NEXT)) + { + *no_add_attrs = true; + return tree_cons (name, args, NULL_TREE); + } + if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) + { + warning ("%qs attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; + } + + /* Report error on dllimport ambiguities seen now before they cause + any damage. */ + if (is_attribute_p ("dllimport", name)) + { + /* Like MS, treat definition of dllimported variables and + non-inlined functions on declaration as syntax errors. We + allow the attribute for function definitions if declared + inline. */ + if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) + && !DECL_DECLARED_INLINE_P (node)) + { + error ("%Jfunction %qD definition is marked dllimport.", node, node); + *no_add_attrs = true; + } + + else if (TREE_CODE (node) == VAR_DECL) + { + if (DECL_INITIAL (node)) + { + error ("%Jvariable %qD definition is marked dllimport.", + node, node); + *no_add_attrs = true; + } + + /* `extern' needn't be specified with dllimport. + Specify `extern' now and hope for the best. Sigh. */ + DECL_EXTERNAL (node) = 1; + /* Also, implicitly give dllimport'd variables declared within + a function global scope, unless declared static. */ + if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) + TREE_PUBLIC (node) = 1; + } + } + + /* Report error if symbol is not accessible at global scope. */ + if (!TREE_PUBLIC (node) + && (TREE_CODE (node) == VAR_DECL + || TREE_CODE (node) == FUNCTION_DECL)) + { + error ("%Jexternal linkage required for symbol %qD because of " + "%qs attribute.", node, node, IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */ /* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask @@ -3002,29 +3367,45 @@ build_qualified_type (tree type, int type_quals) /* If not, build it. */ if (!t) { - t = build_type_copy (type); + t = build_variant_type_copy (type); set_type_quals (t, type_quals); } return t; } +/* Create a new distinct copy of TYPE. The new type is made its own + MAIN_VARIANT. */ + +tree +build_distinct_type_copy (tree type) +{ + tree t = copy_node (type); + + TYPE_POINTER_TO (t) = 0; + TYPE_REFERENCE_TO (t) = 0; + + /* Make it its own variant. */ + TYPE_MAIN_VARIANT (t) = t; + TYPE_NEXT_VARIANT (t) = 0; + + return t; +} + /* Create a new variant of TYPE, equivalent but distinct. This is so the caller can modify it. */ tree -build_type_copy (tree type) +build_variant_type_copy (tree type) { tree t, m = TYPE_MAIN_VARIANT (type); - t = copy_node (type); - - TYPE_POINTER_TO (t) = 0; - TYPE_REFERENCE_TO (t) = 0; - - /* Add this type to the chain of variants of TYPE. */ + t = build_distinct_type_copy (type); + + /* Add the new type to the chain of variants of TYPE. */ TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); TYPE_NEXT_VARIANT (m) = t; + TYPE_MAIN_VARIANT (t) = m; return t; } @@ -3072,11 +3453,13 @@ type_hash_eq (const void *va, const void *vb) { case VOID_TYPE: case COMPLEX_TYPE: - case VECTOR_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: return 1; + case VECTOR_TYPE: + return TYPE_VECTOR_SUBPARTS (a->type) == TYPE_VECTOR_SUBPARTS (b->type); + case ENUMERAL_TYPE: if (TYPE_VALUES (a->type) != TYPE_VALUES (b->type) && !(TYPE_VALUES (a->type) @@ -3114,7 +3497,6 @@ type_hash_eq (const void *va, const void *vb) TYPE_ARG_TYPES (b->type))))); case ARRAY_TYPE: - case SET_TYPE: return TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type); case RECORD_TYPE: @@ -3203,8 +3585,7 @@ type_hash_canon (unsigned int hashcode, tree type) /* The hash table only contains main variants, so ensure that's what we're being passed. */ - if (TYPE_MAIN_VARIANT (type) != type) - abort (); + gcc_assert (TYPE_MAIN_VARIANT (type) == type); if (!lang_hooks.types.hash_types) return type; @@ -3455,10 +3836,8 @@ host_integerp (tree t, int pos) HOST_WIDE_INT tree_low_cst (tree t, int pos) { - if (host_integerp (t, pos)) - return TREE_INT_CST_LOW (t); - else - abort (); + gcc_assert (host_integerp (t, pos)); + return TREE_INT_CST_LOW (t); } /* Return the most significant bit of the integer constant T. */ @@ -3630,12 +4009,12 @@ simple_cst_equal (tree t1, tree t2) switch (TREE_CODE_CLASS (code1)) { - case '1': - case '2': - case '<': - case 'e': - case 'r': - case 's': + case tcc_unary: + case tcc_binary: + case tcc_comparison: + case tcc_expression: + case tcc_reference: + case tcc_statement: cmp = 1; for (i = 0; i < TREE_CODE_LENGTH (code1); i++) { @@ -3692,7 +4071,7 @@ associative_tree_code (enum tree_code code) return false; } -/* Return true if CODE represents an commutative tree code. Otherwise +/* Return true if CODE represents a commutative tree code. Otherwise return false. */ bool commutative_tree_code (enum tree_code code) @@ -3737,97 +4116,104 @@ iterative_hash_expr (tree t, hashval_t val) char class; if (t == NULL_TREE) - return iterative_hash_object (t, val); + return iterative_hash_pointer (t, val); code = TREE_CODE (t); - class = TREE_CODE_CLASS (code); - if (class == 'd' - || TREE_CODE (t) == VALUE_HANDLE) - { - /* Decls we can just compare by pointer. */ - val = iterative_hash_object (t, val); - } - else if (class == 'c') + switch (code) { - /* Alas, constants aren't shared, so we can't rely on pointer - identity. */ - if (code == INTEGER_CST) + /* Alas, constants aren't shared, so we can't rely on pointer + identity. */ + case INTEGER_CST: + val = iterative_hash_host_wide_int (TREE_INT_CST_LOW (t), val); + return iterative_hash_host_wide_int (TREE_INT_CST_HIGH (t), val); + case REAL_CST: + { + unsigned int val2 = real_hash (TREE_REAL_CST_PTR (t)); + + return iterative_hash_hashval_t (val2, val); + } + case STRING_CST: + return iterative_hash (TREE_STRING_POINTER (t), + TREE_STRING_LENGTH (t), val); + case COMPLEX_CST: + val = iterative_hash_expr (TREE_REALPART (t), val); + return iterative_hash_expr (TREE_IMAGPART (t), val); + case VECTOR_CST: + return iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val); + + case SSA_NAME: + case VALUE_HANDLE: + /* we can just compare by pointer. */ + return iterative_hash_pointer (t, val); + + case 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); + return val; + case FUNCTION_DECL: + /* When referring to a built-in FUNCTION_DECL, use the + __builtin__ form. Otherwise nodes that compare equal + according to operand_equal_p might get different + hash codes. */ + if (DECL_BUILT_IN (t)) { - val = iterative_hash_object (TREE_INT_CST_LOW (t), val); - val = iterative_hash_object (TREE_INT_CST_HIGH (t), val); + val = iterative_hash_pointer (built_in_decls[DECL_FUNCTION_CODE (t)], + val); + return val; } - else if (code == REAL_CST) - { - unsigned int val2 = real_hash (TREE_REAL_CST_PTR (t)); + /* else FALL THROUGH */ + default: + class = TREE_CODE_CLASS (code); - val = iterative_hash (&val2, sizeof (unsigned int), val); - } - else if (code == STRING_CST) - val = iterative_hash (TREE_STRING_POINTER (t), - TREE_STRING_LENGTH (t), val); - else if (code == COMPLEX_CST) + if (class == tcc_declaration) { - val = iterative_hash_expr (TREE_REALPART (t), val); - val = iterative_hash_expr (TREE_IMAGPART (t), val); + /* Otherwise, we can just compare decls by pointer. */ + val = iterative_hash_pointer (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); - - /* Don't hash the type, that can lead to having nodes which - compare equal according to operand_equal_p, but which - have different hash codes. */ - if (code == NOP_EXPR - || code == CONVERT_EXPR - || code == NON_LVALUE_EXPR) { - /* Make sure to include signness in the hash computation. */ - val += TYPE_UNSIGNED (TREE_TYPE (t)); - val = iterative_hash_expr (TREE_OPERAND (t, 0), val); - } + gcc_assert (IS_EXPR_CODE_CLASS (class)); + + val = iterative_hash_object (code, val); + + /* Don't hash the type, that can lead to having nodes which + compare equal according to operand_equal_p, but which + have different hash codes. */ + if (code == NOP_EXPR + || code == CONVERT_EXPR + || code == NON_LVALUE_EXPR) + { + /* Make sure to include signness in the hash computation. */ + val += TYPE_UNSIGNED (TREE_TYPE (t)); + val = iterative_hash_expr (TREE_OPERAND (t, 0), val); + } - if (commutative_tree_code (code)) - { - /* 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 if (commutative_tree_code (code)) + { + /* 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_hashval_t (one, val); + val = iterative_hash_hashval_t (two, val); + } + else + for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; --i) + val = iterative_hash_expr (TREE_OPERAND (t, i), 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 if (code == SSA_NAME) - { - val = iterative_hash_object (SSA_NAME_VERSION (t), val); - val = iterative_hash_expr (SSA_NAME_VAR (t), val); + return val; + break; } - else - abort (); - - return val; } /* Constructors for pointer, array and function types. @@ -3976,7 +4362,7 @@ build_index_type (tree maxval) TREE_TYPE (itype) = sizetype; TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype); TYPE_MIN_VALUE (itype) = size_zero_node; - TYPE_MAX_VALUE (itype) = convert (sizetype, maxval); + TYPE_MAX_VALUE (itype) = fold_convert (sizetype, maxval); TYPE_MODE (itype) = TYPE_MODE (sizetype); TYPE_SIZE (itype) = TYPE_SIZE (sizetype); TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype); @@ -4071,9 +4457,12 @@ build_array_type (tree elt_type, tree index_type) t = make_node (ARRAY_TYPE); TREE_TYPE (t) = elt_type; TYPE_DOMAIN (t) = index_type; - + if (index_type == 0) - return t; + { + layout_type (t); + return t; + } hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode); hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); @@ -4149,9 +4538,14 @@ build_function_type_list (tree return_type, ...) for (args = NULL_TREE; t != NULL_TREE; t = va_arg (p, tree)) args = tree_cons (NULL_TREE, t, args); - last = args; - args = nreverse (args); - TREE_CHAIN (last) = void_list_node; + if (args == NULL_TREE) + args = void_list_node; + else + { + last = args; + args = nreverse (args); + TREE_CHAIN (last) = void_list_node; + } args = build_function_type (return_type, args); va_end (p); @@ -4204,8 +4598,7 @@ build_method_type_directly (tree basetype, tree build_method_type (tree basetype, tree type) { - if (TREE_CODE (type) != FUNCTION_TYPE) - abort (); + gcc_assert (TREE_CODE (type) == FUNCTION_TYPE); return build_method_type_directly (basetype, TREE_TYPE (type), @@ -4509,16 +4902,8 @@ 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 ((TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0) - /* Also, unsigned integers with top bit set never fit signed types. */ - || (! TYPE_UNSIGNED (type) - && TYPE_UNSIGNED (TREE_TYPE (c)) && tree_int_cst_msb (c))) - return 0; + bool ok_for_low_bound, ok_for_high_bound; + tree tmp; /* 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 @@ -4530,42 +4915,57 @@ int_fits_type_p (tree c, tree type) 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) { - ok_for_low_bound = ! tree_int_cst_lt (c, type_low_bound); - if (! ok_for_low_bound) + if (tree_int_cst_lt (c, type_low_bound)) return 0; + ok_for_low_bound = true; } + else + ok_for_low_bound = false; /* 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) + if (tree_int_cst_lt (type_high_bound, c)) return 0; + ok_for_high_bound = true; } + else + ok_for_high_bound = false; /* If the constant fits both bounds, the result is known. */ - if (ok_for_low_bound == 1 && ok_for_high_bound == 1) + if (ok_for_low_bound && ok_for_high_bound) + return 1; + + /* Perform some generic filtering which may allow making a decision + even if the bounds are not constant. First, negative integers + never fit in unsigned types, */ + if (TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0) + return 0; + + /* Second, narrower types always fit in wider ones. */ + if (TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (c))) return 1; + /* Third, unsigned integers with top bit set never fit signed types. */ + if (! TYPE_UNSIGNED (type) + && TYPE_UNSIGNED (TREE_TYPE (c)) + && tree_int_cst_msb (c)) + return 0; + /* 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) + 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); - TREE_TYPE (c) = type; - c = force_fit_type (c, -1, false, false); - return !TREE_OVERFLOW (c); - } + tmp = copy_node (c); + TREE_TYPE (tmp) = type; + tmp = force_fit_type (tmp, -1, false, false); + return TREE_INT_CST_HIGH (tmp) == TREE_INT_CST_HIGH (c) + && TREE_INT_CST_LOW (tmp) == TREE_INT_CST_LOW (c); } /* Subprogram of following function. Called by walk_tree. @@ -4581,7 +4981,8 @@ find_var_from_fn (tree *tp, int *walk_subtrees, void *data) if (TYPE_P (*tp)) *walk_subtrees = 0; - else if (DECL_P (*tp) && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn)) + else if (DECL_P (*tp) + && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn)) return *tp; return NULL_TREE; @@ -4628,7 +5029,6 @@ variably_modified_type_p (tree type, tree fn) case POINTER_TYPE: case REFERENCE_TYPE: case ARRAY_TYPE: - case SET_TYPE: case VECTOR_TYPE: if (variably_modified_type_p (TREE_TYPE (type), fn)) return true; @@ -4764,7 +5164,7 @@ decl_type_context (tree decl) break; default: - abort (); + gcc_unreachable (); } return NULL_TREE; @@ -4781,8 +5181,7 @@ get_callee_fndecl (tree call) /* It's invalid to call this function with anything but a CALL_EXPR. */ - if (TREE_CODE (call) != CALL_EXPR) - abort (); + gcc_assert (TREE_CODE (call) == CALL_EXPR); /* The first operand to the CALL is the address of the function called. */ @@ -4982,9 +5381,10 @@ get_set_constructor_bits (tree init, char *buffer, int bit_size) HOST_WIDE_INT hi_index = tree_low_cst (TREE_VALUE (vals), 0) - domain_min; - if (lo_index < 0 || lo_index >= bit_size - || hi_index < 0 || hi_index >= bit_size) - abort (); + gcc_assert (lo_index >= 0); + gcc_assert (lo_index < bit_size); + gcc_assert (hi_index >= 0); + gcc_assert (hi_index < bit_size); for (; lo_index <= hi_index; lo_index++) buffer[lo_index] = 1; } @@ -5042,8 +5442,9 @@ get_set_constructor_bytes (tree init, unsigned char *buffer, int wd_size) #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) /* Complain that the tree code of NODE does not match the expected 0 - terminated list of trailing codes. FILE, LINE, and FUNCTION are of - the caller. */ + terminated list of trailing codes. The trailing code list can be + empty, for a more vague error message. FILE, LINE, and FUNCTION + are of the caller. */ void tree_check_failed (const tree node, const char *file, @@ -5058,22 +5459,27 @@ tree_check_failed (const tree node, const char *file, while ((code = va_arg (args, int))) length += 4 + strlen (tree_code_name[code]); va_end (args); - va_start (args, function); - buffer = alloca (length); - length = 0; - while ((code = va_arg (args, int))) + if (length) { - if (length) + va_start (args, function); + length += strlen ("expected "); + buffer = alloca (length); + length = 0; + while ((code = va_arg (args, int))) { - strcpy (buffer + length, " or "); - length += 4; + const char *prefix = length ? " or " : "expected "; + + strcpy (buffer + length, prefix); + length += strlen (prefix); + strcpy (buffer + length, tree_code_name[code]); + length += strlen (tree_code_name[code]); } - strcpy (buffer + length, tree_code_name[code]); - length += strlen (tree_code_name[code]); + va_end (args); } - va_end (args); + else + buffer = (char *)"unexpected node"; - internal_error ("tree check: expected %s, have %s in %s, at %s:%d", + internal_error ("tree check: %s, have %s in %s, at %s:%d", buffer, tree_code_name[TREE_CODE (node)], function, trim_filename (file), line); } @@ -5119,12 +5525,13 @@ tree_not_check_failed (const tree node, const char *file, code, given in CL. */ void -tree_class_check_failed (const tree node, int cl, const char *file, - int line, const char *function) +tree_class_check_failed (const tree node, const enum tree_code_class cl, + const char *file, int line, const char *function) { internal_error - ("tree check: expected class '%c', have '%c' (%s) in %s, at %s:%d", - cl, TREE_CODE_CLASS (TREE_CODE (node)), + ("tree check: expected class %qs, have %qs (%s) in %s, at %s:%d", + TREE_CODE_CLASS_STRING (cl), + TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))), tree_code_name[TREE_CODE (node)], function, trim_filename (file), line); } @@ -5175,13 +5582,16 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) { tree t = make_node (VECTOR_TYPE); - TREE_TYPE (t) = innertype; + TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype); TYPE_VECTOR_SUBPARTS (t) = nunits; TYPE_MODE (t) = mode; + TYPE_READONLY (t) = TYPE_READONLY (innertype); + TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype); + layout_type (t); { - tree index = build_int_2 (nunits - 1, 0); + tree index = build_int_cst (NULL_TREE, nunits - 1); tree array = build_array_type (innertype, build_index_type (index)); tree rt = make_node (RECORD_TYPE); @@ -5196,6 +5606,16 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) TYPE_UID (rt) = TYPE_UID (t); } + /* Build our main variant, based on the main variant of the inner type. */ + if (TYPE_MAIN_VARIANT (innertype) != innertype) + { + tree innertype_main_variant = TYPE_MAIN_VARIANT (innertype); + unsigned int hash = TYPE_HASH (innertype_main_variant); + TYPE_MAIN_VARIANT (t) + = type_hash_canon (hash, make_vector_type (innertype_main_variant, + nunits, mode)); + } + return t; } @@ -5225,12 +5645,12 @@ make_or_reuse_type (unsigned size, int unsignedp) this function to select one of the types as sizetype. */ void -build_common_tree_nodes (int signed_char) +build_common_tree_nodes (bool signed_char, bool signed_sizetype) { error_mark_node = make_node (ERROR_MARK); TREE_TYPE (error_mark_node) = error_mark_node; - initialize_sizetypes (); + initialize_sizetypes (signed_sizetype); /* Define both `signed char' and `unsigned char'. */ signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); @@ -5258,8 +5678,7 @@ build_common_tree_nodes (int signed_char) 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_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1); TYPE_PRECISION (boolean_type_node) = 1; /* Fill in the rest of the sized types. Reuse existing type nodes @@ -5288,9 +5707,9 @@ void 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); - integer_one_node = build_int_2 (1, 0); - integer_minus_one_node = build_int_2 (-1, -1); + integer_zero_node = build_int_cst (NULL_TREE, 0); + integer_one_node = build_int_cst (NULL_TREE, 1); + integer_minus_one_node = build_int_cst (NULL_TREE, -1); size_zero_node = size_int (0); size_one_node = size_int (1); @@ -5309,8 +5728,7 @@ build_common_tree_nodes_2 (int short_double) TYPE_ALIGN (void_type_node) = BITS_PER_UNIT; TYPE_USER_ALIGN (void_type_node) = 0; - null_pointer_node = build_int_2 (0, 0); - TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node); + null_pointer_node = build_int_cst (build_pointer_type (void_type_node), 0); layout_type (TREE_TYPE (null_pointer_node)); ptr_type_node = build_pointer_type (void_type_node); @@ -5363,12 +5781,172 @@ build_common_tree_nodes_2 (int short_double) don't copy record types and let c_common_nodes_and_builtins() declare the type to be __builtin_va_list. */ if (TREE_CODE (t) != RECORD_TYPE) - t = build_type_copy (t); + t = build_variant_type_copy (t); va_list_type_node = t; } } +/* A subroutine of build_common_builtin_nodes. Define a builtin function. */ + +static void +local_define_builtin (const char *name, tree type, enum built_in_function code, + const char *library_name, int ecf_flags) +{ + tree decl; + + decl = lang_hooks.builtin_function (name, type, code, BUILT_IN_NORMAL, + library_name, NULL_TREE); + if (ecf_flags & ECF_CONST) + TREE_READONLY (decl) = 1; + if (ecf_flags & ECF_PURE) + DECL_IS_PURE (decl) = 1; + if (ecf_flags & ECF_NORETURN) + TREE_THIS_VOLATILE (decl) = 1; + if (ecf_flags & ECF_NOTHROW) + TREE_NOTHROW (decl) = 1; + if (ecf_flags & ECF_MALLOC) + DECL_IS_MALLOC (decl) = 1; + + built_in_decls[code] = decl; + implicit_built_in_decls[code] = decl; +} + +/* Call this function after instantiating all builtins that the language + front end cares about. This will build the rest of the builtins that + are relied upon by the tree optimizers and the middle-end. */ + +void +build_common_builtin_nodes (void) +{ + tree tmp, ftype; + + if (built_in_decls[BUILT_IN_MEMCPY] == NULL + || built_in_decls[BUILT_IN_MEMMOVE] == NULL) + { + tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); + tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp); + tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); + ftype = build_function_type (ptr_type_node, tmp); + + if (built_in_decls[BUILT_IN_MEMCPY] == NULL) + local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY, + "memcpy", ECF_NOTHROW); + if (built_in_decls[BUILT_IN_MEMMOVE] == NULL) + local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE, + "memmove", ECF_NOTHROW); + } + + if (built_in_decls[BUILT_IN_MEMCMP] == NULL) + { + tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); + tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp); + tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp); + ftype = build_function_type (ptr_type_node, tmp); + local_define_builtin ("__builtin_memcmp", ftype, BUILT_IN_MEMCMP, + "memcmp", ECF_PURE | ECF_NOTHROW); + } + + if (built_in_decls[BUILT_IN_MEMSET] == NULL) + { + tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); + tmp = tree_cons (NULL_TREE, integer_type_node, tmp); + tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); + ftype = build_function_type (ptr_type_node, tmp); + local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET, + "memset", ECF_NOTHROW); + } + + if (built_in_decls[BUILT_IN_ALLOCA] == NULL) + { + tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); + ftype = build_function_type (ptr_type_node, tmp); + local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA, + "alloca", ECF_NOTHROW | ECF_MALLOC); + } + + tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); + tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); + ftype = build_function_type (void_type_node, tmp); + local_define_builtin ("__builtin_init_trampoline", ftype, + BUILT_IN_INIT_TRAMPOLINE, + "__builtin_init_trampoline", ECF_NOTHROW); + + tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + ftype = build_function_type (ptr_type_node, tmp); + local_define_builtin ("__builtin_adjust_trampoline", ftype, + BUILT_IN_ADJUST_TRAMPOLINE, + "__builtin_adjust_trampoline", + ECF_CONST | ECF_NOTHROW); + + tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); + ftype = build_function_type (void_type_node, tmp); + local_define_builtin ("__builtin_nonlocal_goto", ftype, + BUILT_IN_NONLOCAL_GOTO, + "__builtin_nonlocal_goto", + ECF_NORETURN | ECF_NOTHROW); + + ftype = build_function_type (ptr_type_node, void_list_node); + local_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE, + "__builtin_stack_save", ECF_NOTHROW); + + tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + ftype = build_function_type (void_type_node, tmp); + local_define_builtin ("__builtin_stack_restore", ftype, + BUILT_IN_STACK_RESTORE, + "__builtin_stack_restore", ECF_NOTHROW); + + ftype = build_function_type (void_type_node, void_list_node); + local_define_builtin ("__builtin_profile_func_enter", ftype, + BUILT_IN_PROFILE_FUNC_ENTER, "profile_func_enter", 0); + local_define_builtin ("__builtin_profile_func_exit", ftype, + BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit", 0); + + /* Complex multiplication and division. These are handled as builtins + rather than optabs because emit_library_call_value doesn't support + complex. Further, we can do slightly better with folding these + beasties if the real and complex parts of the arguments are separate. */ + { + enum machine_mode mode; + + for (mode = MIN_MODE_COMPLEX_FLOAT; mode <= MAX_MODE_COMPLEX_FLOAT; ++mode) + { + char mode_name_buf[4], *q; + const char *p; + enum built_in_function mcode, dcode; + tree type, inner_type; + + type = lang_hooks.types.type_for_mode (mode, 0); + if (type == NULL) + continue; + inner_type = TREE_TYPE (type); + + tmp = tree_cons (NULL_TREE, inner_type, void_list_node); + tmp = tree_cons (NULL_TREE, inner_type, tmp); + tmp = tree_cons (NULL_TREE, inner_type, tmp); + tmp = tree_cons (NULL_TREE, inner_type, tmp); + ftype = build_function_type (type, tmp); + + mcode = BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT; + dcode = BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT; + + for (p = GET_MODE_NAME (mode), q = mode_name_buf; *p; p++, q++) + *q = TOLOWER (*p); + *q = '\0'; + + built_in_names[mcode] = concat ("__mul", mode_name_buf, "3", NULL); + local_define_builtin (built_in_names[mcode], ftype, mcode, + built_in_names[mcode], ECF_CONST | ECF_NOTHROW); + + built_in_names[dcode] = concat ("__div", mode_name_buf, "3", NULL); + local_define_builtin (built_in_names[dcode], ftype, dcode, + built_in_names[dcode], ECF_CONST | ECF_NOTHROW); + } + } +} + /* HACK. GROSS. This is absolutely disgusting. I wish there was a better way. @@ -5401,10 +5979,15 @@ reconstruct_complex_type (tree type, tree bottom) } else if (TREE_CODE (type) == METHOD_TYPE) { + tree argtypes; inner = reconstruct_complex_type (TREE_TYPE (type), bottom); + /* The build_method_type_directly() routine prepends 'this' to argument list, + so we must compensate by getting rid of it. */ + argtypes = TYPE_ARG_TYPES (type); outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type), inner, TYPE_ARG_TYPES (type)); + TYPE_ARG_TYPES (outer) = argtypes; } else return bottom; @@ -5422,21 +6005,25 @@ build_vector_type_for_mode (tree innertype, enum machine_mode mode) { int nunits; - if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT - || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) - nunits = GET_MODE_NUNITS (mode); - - else if (GET_MODE_CLASS (mode) == MODE_INT) + switch (GET_MODE_CLASS (mode)) { + case MODE_VECTOR_INT: + case MODE_VECTOR_FLOAT: + nunits = GET_MODE_NUNITS (mode); + break; + + case MODE_INT: /* Check that there are no leftover bits. */ - if (GET_MODE_BITSIZE (mode) % TREE_INT_CST_LOW (TYPE_SIZE (innertype))) - abort (); + gcc_assert (GET_MODE_BITSIZE (mode) + % TREE_INT_CST_LOW (TYPE_SIZE (innertype)) == 0); nunits = GET_MODE_BITSIZE (mode) / TREE_INT_CST_LOW (TYPE_SIZE (innertype)); + break; + + default: + gcc_unreachable (); } - else - abort (); return make_vector_type (innertype, nunits, mode); } @@ -5488,10 +6075,6 @@ initializer_zerop (tree init) if (elt == NULL_TREE) return true; - /* A set is empty only if it has no elements. */ - if (TREE_CODE (TREE_TYPE (init)) == SET_TYPE) - return false; - for (; elt ; elt = TREE_CHAIN (elt)) if (! initializer_zerop (TREE_VALUE (elt))) return false; @@ -5549,15 +6132,22 @@ in_array_bounds_p (tree ref) return true; } +/* Return true if T (assumed to be a DECL) is a global variable. */ + +bool +is_global_var (tree t) +{ + return (TREE_STATIC (t) || DECL_EXTERNAL (t)); +} + /* Return true if T (assumed to be a DECL) must be assigned a memory location. */ bool needs_to_live_in_memory (tree t) { - return (DECL_NEEDS_TO_LIVE_IN_MEMORY_INTERNAL (t) - || TREE_STATIC (t) - || DECL_EXTERNAL (t) + return (TREE_ADDRESSABLE (t) + || is_global_var (t) || (TREE_CODE (t) == RESULT_DECL && aggregate_value_p (t, current_function_decl))); } @@ -5615,8 +6205,7 @@ int_cst_value (tree x) unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x); bool negative = ((val >> (bits - 1)) & 1) != 0; - if (bits > HOST_BITS_PER_WIDE_INT) - abort (); + gcc_assert (bits <= HOST_BITS_PER_WIDE_INT); if (negative) val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1; @@ -5635,11 +6224,8 @@ tree_fold_gcd (tree a, tree b) tree a_mod_b; tree type = TREE_TYPE (a); -#if defined ENABLE_CHECKING - if (TREE_CODE (a) != INTEGER_CST - || TREE_CODE (b) != INTEGER_CST) - abort (); -#endif + gcc_assert (TREE_CODE (a) == INTEGER_CST); + gcc_assert (TREE_CODE (b) == INTEGER_CST); if (integer_zerop (a)) return b; @@ -5657,7 +6243,7 @@ tree_fold_gcd (tree a, tree b) while (1) { - a_mod_b = fold (build2 (CEIL_MOD_EXPR, type, a, b)); + a_mod_b = fold (build2 (FLOOR_MOD_EXPR, type, a, b)); if (!TREE_INT_CST_LOW (a_mod_b) && !TREE_INT_CST_HIGH (a_mod_b)) @@ -5668,4 +6254,146 @@ tree_fold_gcd (tree a, tree b) } } +/* Returns unsigned variant of TYPE. */ + +tree +unsigned_type_for (tree type) +{ + return lang_hooks.types.unsigned_type (type); +} + +/* Returns signed variant of TYPE. */ + +tree +signed_type_for (tree type) +{ + return lang_hooks.types.signed_type (type); +} + +/* Returns the largest value obtainable by casting something in INNER type to + OUTER type. */ + +tree +upper_bound_in_type (tree outer, tree inner) +{ + unsigned HOST_WIDE_INT lo, hi; + unsigned bits = TYPE_PRECISION (inner); + + if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner)) + { + /* Zero extending in these cases. */ + if (bits <= HOST_BITS_PER_WIDE_INT) + { + hi = 0; + lo = (~(unsigned HOST_WIDE_INT) 0) + >> (HOST_BITS_PER_WIDE_INT - bits); + } + else + { + hi = (~(unsigned HOST_WIDE_INT) 0) + >> (2 * HOST_BITS_PER_WIDE_INT - bits); + lo = ~(unsigned HOST_WIDE_INT) 0; + } + } + else + { + /* Sign extending in these cases. */ + if (bits <= HOST_BITS_PER_WIDE_INT) + { + hi = 0; + lo = (~(unsigned HOST_WIDE_INT) 0) + >> (HOST_BITS_PER_WIDE_INT - bits) >> 1; + } + else + { + hi = (~(unsigned HOST_WIDE_INT) 0) + >> (2 * HOST_BITS_PER_WIDE_INT - bits) >> 1; + lo = ~(unsigned HOST_WIDE_INT) 0; + } + } + + return fold_convert (outer, + build_int_cst_wide (inner, lo, hi)); +} + +/* Returns the smallest value obtainable by casting something in INNER type to + OUTER type. */ + +tree +lower_bound_in_type (tree outer, tree inner) +{ + unsigned HOST_WIDE_INT lo, hi; + unsigned bits = TYPE_PRECISION (inner); + + if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner)) + lo = hi = 0; + else if (bits <= HOST_BITS_PER_WIDE_INT) + { + hi = ~(unsigned HOST_WIDE_INT) 0; + lo = (~(unsigned HOST_WIDE_INT) 0) << (bits - 1); + } + else + { + hi = (~(unsigned HOST_WIDE_INT) 0) << (bits - HOST_BITS_PER_WIDE_INT - 1); + lo = 0; + } + + return fold_convert (outer, + build_int_cst_wide (inner, lo, hi)); +} + +/* Return nonzero if two operands that are suitable for PHI nodes are + necessarily equal. Specifically, both ARG0 and ARG1 must be either + SSA_NAME or invariant. Note that this is strictly an optimization. + That is, callers of this function can directly call operand_equal_p + and get the same result, only slower. */ + +int +operand_equal_for_phi_arg_p (tree arg0, tree arg1) +{ + if (arg0 == arg1) + return 1; + if (TREE_CODE (arg0) == SSA_NAME || TREE_CODE (arg1) == SSA_NAME) + return 0; + return operand_equal_p (arg0, arg1, 0); +} + +/* Returns number of zeros at the end of binary representation of X. + + ??? Use ffs if available? */ + +tree +num_ending_zeros (tree x) +{ + unsigned HOST_WIDE_INT fr, nfr; + unsigned num, abits; + tree type = TREE_TYPE (x); + + if (TREE_INT_CST_LOW (x) == 0) + { + num = HOST_BITS_PER_WIDE_INT; + fr = TREE_INT_CST_HIGH (x); + } + else + { + num = 0; + fr = TREE_INT_CST_LOW (x); + } + + for (abits = HOST_BITS_PER_WIDE_INT / 2; abits; abits /= 2) + { + nfr = fr >> abits; + if (nfr << abits == fr) + { + num += abits; + fr = nfr; + } + } + + if (num > TYPE_PRECISION (type)) + num = TYPE_PRECISION (type); + + return build_int_cst_type (type, num); +} + #include "gt-tree.h"