X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=f941892815d6483069eef76128df2e263d0b7d96;hb=3a8843c6da5f76535c016db4d0c8da620a7cde3e;hp=4edccd5c2322a8e63c7c7b08d76458b538e2e49a;hpb=c046db8f6a9acb6e4c828b9a6942d517bd3c5a30;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index 4edccd5c232..f941892815d 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1,6 +1,7 @@ /* 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, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. This file is part of GCC. @@ -65,7 +66,9 @@ const char *const tree_code_class_strings[] = "unary", "binary", "statement", + "vl_exp", "expression", + "gimple_stmt" }; /* obstack.[ch] explicitly declined to prototype this. */ @@ -96,7 +99,9 @@ static const char * const tree_node_kind_names[] = { "constructors", "random kinds", "lang_decl kinds", - "lang_type kinds" + "lang_type kinds", + "omp clauses", + "gimple statements" }; #endif /* GATHER_STATISTICS */ @@ -141,20 +146,13 @@ static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t value_expr_for_decl; -static GTY ((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map))) +static GTY ((if_marked ("tree_priority_map_marked_p"), + param_is (struct tree_priority_map))) htab_t init_priority_for_decl; static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t restrict_base_for_decl; -struct tree_int_map GTY(()) -{ - tree from; - unsigned short to; -}; -static unsigned int tree_int_map_hash (const void *); -static int tree_int_map_eq (const void *, const void *); -static int tree_int_map_marked_p (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 *); @@ -163,7 +161,6 @@ static int int_cst_hash_eq (const void *, const void *); static void print_type_hash_statistics (void); static void print_debug_expr_statistics (void); static void print_value_expr_statistics (void); -static tree make_vector_type (tree, int, enum machine_mode); static int type_hash_marked_p (const void *); static unsigned int type_hash_list (tree, hashval_t); static unsigned int attribute_hash_list (tree, hashval_t); @@ -172,13 +169,49 @@ tree global_trees[TI_MAX]; tree integer_types[itk_none]; unsigned char tree_contains_struct[256][64]; + +/* Number of operands for each OpenMP clause. */ +unsigned const char omp_clause_num_ops[] = +{ + 0, /* OMP_CLAUSE_ERROR */ + 1, /* OMP_CLAUSE_PRIVATE */ + 1, /* OMP_CLAUSE_SHARED */ + 1, /* OMP_CLAUSE_FIRSTPRIVATE */ + 1, /* OMP_CLAUSE_LASTPRIVATE */ + 4, /* OMP_CLAUSE_REDUCTION */ + 1, /* OMP_CLAUSE_COPYIN */ + 1, /* OMP_CLAUSE_COPYPRIVATE */ + 1, /* OMP_CLAUSE_IF */ + 1, /* OMP_CLAUSE_NUM_THREADS */ + 1, /* OMP_CLAUSE_SCHEDULE */ + 0, /* OMP_CLAUSE_NOWAIT */ + 0, /* OMP_CLAUSE_ORDERED */ + 0 /* OMP_CLAUSE_DEFAULT */ +}; + +const char * const omp_clause_code_name[] = +{ + "error_clause", + "private", + "shared", + "firstprivate", + "lastprivate", + "reduction", + "copyin", + "copyprivate", + "if", + "num_threads", + "schedule", + "nowait", + "ordered", + "default" +}; /* Init tree.c. */ void 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); @@ -188,8 +221,8 @@ init_ttree (void) value_expr_for_decl = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0); - init_priority_for_decl = htab_create_ggc (512, tree_int_map_hash, - tree_int_map_eq, 0); + init_priority_for_decl = htab_create_ggc (512, tree_priority_map_hash, + tree_priority_map_eq, 0); restrict_base_for_decl = htab_create_ggc (256, tree_map_hash, tree_map_eq, 0); @@ -230,6 +263,18 @@ init_ttree (void) tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[STRUCT_FIELD_TAG][TS_DECL_MINIMAL] = 1; + tree_contains_struct[NAME_MEMORY_TAG][TS_DECL_MINIMAL] = 1; + tree_contains_struct[SYMBOL_MEMORY_TAG][TS_DECL_MINIMAL] = 1; + tree_contains_struct[MEMORY_PARTITION_TAG][TS_DECL_MINIMAL] = 1; + + tree_contains_struct[STRUCT_FIELD_TAG][TS_MEMORY_TAG] = 1; + tree_contains_struct[NAME_MEMORY_TAG][TS_MEMORY_TAG] = 1; + tree_contains_struct[SYMBOL_MEMORY_TAG][TS_MEMORY_TAG] = 1; + tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_TAG] = 1; + + tree_contains_struct[STRUCT_FIELD_TAG][TS_STRUCT_FIELD_TAG] = 1; + tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_PARTITION_TAG] = 1; tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1; tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1; @@ -260,9 +305,43 @@ decl_assembler_name (tree decl) return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name; } +/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */ + +bool +decl_assembler_name_equal (tree decl, tree asmname) +{ + tree decl_asmname = DECL_ASSEMBLER_NAME (decl); + + if (decl_asmname == asmname) + return true; + + /* If the target assembler name was set by the user, things are trickier. + We have a leading '*' to begin with. After that, it's arguable what + is the correct thing to do with -fleading-underscore. Arguably, we've + historically been doing the wrong thing in assemble_alias by always + printing the leading underscore. Since we're not changing that, make + sure user_label_prefix follows the '*' before matching. */ + if (IDENTIFIER_POINTER (decl_asmname)[0] == '*') + { + const char *decl_str = IDENTIFIER_POINTER (decl_asmname) + 1; + size_t ulp_len = strlen (user_label_prefix); + + if (ulp_len == 0) + ; + else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0) + decl_str += ulp_len; + else + return false; + + return strcmp (decl_str, IDENTIFIER_POINTER (asmname)) == 0; + } + + return false; +} + /* 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. */ + This function cannot be used for nodes that have variable sizes, + including TREE_VEC, PHI_NODE, STRING_CST, and CALL_EXPR. */ size_t tree_code_size (enum tree_code code) { @@ -288,6 +367,13 @@ tree_code_size (enum tree_code code) return sizeof (struct tree_type_decl); case FUNCTION_DECL: return sizeof (struct tree_function_decl); + case NAME_MEMORY_TAG: + case SYMBOL_MEMORY_TAG: + return sizeof (struct tree_memory_tag); + case STRUCT_FIELD_TAG: + return sizeof (struct tree_struct_field_tag); + case MEMORY_PARTITION_TAG: + return sizeof (struct tree_memory_partition_tag); default: return sizeof (struct tree_decl_non_common); } @@ -303,6 +389,10 @@ tree_code_size (enum tree_code code) case tcc_unary: /* a unary arithmetic expression */ case tcc_binary: /* a binary arithmetic expression */ return (sizeof (struct tree_exp) + + (TREE_CODE_LENGTH (code) - 1) * sizeof (tree)); + + case tcc_gimple_stmt: + return (sizeof (struct gimple_stmt) + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *)); case tcc_constant: /* a constant */ @@ -327,6 +417,7 @@ tree_code_size (enum tree_code code) case PLACEHOLDER_EXPR: return sizeof (struct tree_common); case TREE_VEC: + case OMP_CLAUSE: case PHI_NODE: gcc_unreachable (); case SSA_NAME: return sizeof (struct tree_ssa_name); @@ -346,7 +437,7 @@ tree_code_size (enum tree_code code) } /* Compute the number of bytes occupied by NODE. This routine only - looks at TREE_CODE, except for PHI_NODE and TREE_VEC nodes. */ + looks at TREE_CODE, except for those nodes that have variable sizes. */ size_t tree_size (tree node) { @@ -363,20 +454,30 @@ tree_size (tree node) case TREE_VEC: return (sizeof (struct tree_vec) - + (TREE_VEC_LENGTH (node) - 1) * sizeof(char *)); + + (TREE_VEC_LENGTH (node) - 1) * sizeof (tree)); case STRING_CST: - return sizeof (struct tree_string) + TREE_STRING_LENGTH (node) - 1; + return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; + + case OMP_CLAUSE: + return (sizeof (struct tree_omp_clause) + + (omp_clause_num_ops[OMP_CLAUSE_CODE (node)] - 1) + * sizeof (tree)); default: - return tree_code_size (code); + if (TREE_CODE_CLASS (code) == tcc_vl_exp) + return (sizeof (struct tree_exp) + + (VL_EXP_OPERAND_LENGTH (node) - 1) * sizeof (tree)); + else + 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. This function cannot be used for PHI_NODE or - TREE_VEC nodes, which is enforced by asserts in tree_code_size. + initialized to zero. This function cannot be used for PHI_NODE, + TREE_VEC or OMP_CLAUSE nodes, which is enforced by asserts in + tree_code_size. Achoo! I got a code in the node. */ @@ -418,6 +519,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = c_kind; break; + case tcc_gimple_stmt: + kind = gimple_stmt_kind; + break; + case tcc_exceptional: /* something random, like an identifier. */ switch (code) { @@ -479,13 +584,16 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) break; case tcc_declaration: - if (code != FUNCTION_DECL) - DECL_ALIGN (t) = 1; - DECL_USER_ALIGN (t) = 0; if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) DECL_IN_SYSTEM_HEADER (t) = in_system_header; - /* We have not yet computed the alias set for this declaration. */ - DECL_POINTER_ALIAS_SET (t) = -1; + if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) + { + if (code != FUNCTION_DECL) + DECL_ALIGN (t) = 1; + DECL_USER_ALIGN (t) = 0; + /* We have not yet computed the alias set for this declaration. */ + DECL_POINTER_ALIAS_SET (t) = -1; + } DECL_SOURCE_LOCATION (t) = input_location; DECL_UID (t) = next_decl_uid++; @@ -496,6 +604,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) TYPE_ALIGN (t) = BITS_PER_UNIT; TYPE_USER_ALIGN (t) = 0; TYPE_MAIN_VARIANT (t) = t; + TYPE_CANONICAL (t) = t; /* Default to no attributes for type, but let target change that. */ TYPE_ATTRIBUTES (t) = NULL_TREE; @@ -530,6 +639,17 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) } break; + case tcc_gimple_stmt: + switch (code) + { + case GIMPLE_MODIFY_STMT: + TREE_SIDE_EFFECTS (t) = 1; + break; + + default: + break; + } + default: /* Other classes need no special treatment. */ break; @@ -554,10 +674,11 @@ copy_node_stat (tree node MEM_STAT_DECL) t = ggc_alloc_zone_pass_stat (length, &tree_zone); memcpy (t, node, length); - TREE_CHAIN (t) = 0; + if (!GIMPLE_TUPLE_P (node)) + TREE_CHAIN (t) = 0; TREE_ASM_WRITTEN (t) = 0; TREE_VISITED (t) = 0; - t->common.ann = 0; + t->base.ann = 0; if (TREE_CODE_CLASS (code) == tcc_declaration) { @@ -630,6 +751,10 @@ copy_list (tree list) tree build_int_cst (tree type, HOST_WIDE_INT low) { + /* Support legacy code. */ + if (!type) + type = integer_type_node; + return build_int_cst_wide (type, low, low < 0 ? -1 : 0); } @@ -653,53 +778,25 @@ build_int_cstu (tree type, unsigned HOST_WIDE_INT low) tree build_int_cst_type (tree type, HOST_WIDE_INT low) { - unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low; - unsigned HOST_WIDE_INT hi, mask; - unsigned bits; - bool signed_p; - bool negative; - - if (!type) - type = integer_type_node; - - bits = TYPE_PRECISION (type); - signed_p = !TYPE_UNSIGNED (type); + unsigned HOST_WIDE_INT low1; + HOST_WIDE_INT hi; - 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; + gcc_assert (type); - /* Mask out the bits outside of the precision of the constant. */ - mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1; - - if (signed_p && negative) - val |= ~mask; - else - val &= mask; - } + fit_double_type (low, low < 0 ? -1 : 0, &low1, &hi, type); - /* Determine the high bits. */ - hi = (negative ? ~(unsigned HOST_WIDE_INT) 0 : 0); + return build_int_cst_wide (type, low1, hi); +} - /* 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; - mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1; - hi &= mask; - } - } +/* Create an INT_CST node of TYPE and value HI:LOW. The value is truncated + and sign extended according to the value range of TYPE. */ - return build_int_cst_wide (type, val, hi); +tree +build_int_cst_wide_type (tree type, + unsigned HOST_WIDE_INT low, HOST_WIDE_INT high) +{ + fit_double_type (low, high, &low, &high, type); + return build_int_cst_wide (type, low, high); } /* These are the hash table functions for the hash table of INTEGER_CST @@ -730,10 +827,9 @@ int_cst_hash_eq (const void *x, const void *y) && 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. */ +/* Create an INT_CST node of TYPE and value HI:LOW. + 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) @@ -742,8 +838,7 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) int ix = -1; int limit = 0; - if (!type) - type = integer_type_node; + gcc_assert (type); switch (TREE_CODE (type)) { @@ -765,7 +860,6 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) break; case INTEGER_TYPE: - case CHAR_TYPE: case OFFSET_TYPE: if (TYPE_UNSIGNED (type)) { @@ -784,8 +878,12 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) ix = 0; } break; - default: + + case ENUMERAL_TYPE: break; + + default: + gcc_unreachable (); } if (ix >= 0) @@ -898,7 +996,7 @@ tree build_vector (tree type, tree vals) { tree v = make_node (VECTOR_CST); - int over1 = 0, over2 = 0; + int over = 0; tree link; TREE_VECTOR_CST_ELTS (v) = vals; @@ -909,13 +1007,14 @@ build_vector (tree type, tree vals) { tree value = TREE_VALUE (link); - over1 |= TREE_OVERFLOW (value); - over2 |= TREE_CONSTANT_OVERFLOW (value); - } + /* Don't crash if we get an address constant. */ + if (!CONSTANT_CLASS_P (value)) + continue; - TREE_OVERFLOW (v) = over1; - TREE_CONSTANT_OVERFLOW (v) = over2; + over |= TREE_OVERFLOW (value); + } + TREE_OVERFLOW (v) = over; return v; } @@ -952,13 +1051,16 @@ build_constructor_single (tree type, tree index, tree value) { VEC(constructor_elt,gc) *v; constructor_elt *elt; + tree t; v = VEC_alloc (constructor_elt, gc, 1); elt = VEC_quick_push (constructor_elt, v, NULL); elt->index = index; elt->value = value; - return build_constructor (type, v); + t = build_constructor (type, v); + TREE_CONSTANT (t) = TREE_CONSTANT (value); + return t; } @@ -967,8 +1069,9 @@ build_constructor_single (tree type, tree index, tree value) tree build_constructor_from_list (tree type, tree vals) { - tree t; + tree t, val; VEC(constructor_elt,gc) *v = NULL; + bool constant_p = true; if (vals) { @@ -976,12 +1079,17 @@ build_constructor_from_list (tree type, tree vals) for (t = vals; t; t = TREE_CHAIN (t)) { constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL); + val = TREE_VALUE (t); elt->index = TREE_PURPOSE (t); - elt->value = TREE_VALUE (t); + elt->value = val; + if (!TREE_CONSTANT (val)) + constant_p = false; } } - return build_constructor (type, v); + t = build_constructor (type, v); + TREE_CONSTANT (t) = constant_p; + return t; } @@ -1003,7 +1111,7 @@ build_real (tree type, REAL_VALUE_TYPE d) TREE_TYPE (v) = type; TREE_REAL_CST_PTR (v) = dp; - TREE_OVERFLOW (v) = TREE_CONSTANT_OVERFLOW (v) = overflow; + TREE_OVERFLOW (v) = overflow; return v; } @@ -1037,7 +1145,6 @@ build_real_from_int_cst (tree type, tree i) v = build_real (type, real_value_from_int_cst (type, i)); TREE_OVERFLOW (v) |= overflow; - TREE_CONSTANT_OVERFLOW (v) |= overflow; return v; } @@ -1050,8 +1157,9 @@ build_string (int len, const char *str) { tree s; size_t length; - - length = len + sizeof (struct tree_string); + + /* Do not waste bytes provided by padding of struct tree_string. */ + length = len + offsetof (struct tree_string, str) + 1; #ifdef GATHER_STATISTICS tree_node_counts[(int) c_kind]++; @@ -1085,11 +1193,50 @@ build_complex (tree type, tree real, tree imag) TREE_IMAGPART (t) = imag; TREE_TYPE (t) = type ? type : build_complex_type (TREE_TYPE (real)); TREE_OVERFLOW (t) = TREE_OVERFLOW (real) | TREE_OVERFLOW (imag); - TREE_CONSTANT_OVERFLOW (t) - = TREE_CONSTANT_OVERFLOW (real) | TREE_CONSTANT_OVERFLOW (imag); return t; } +/* Return a constant of arithmetic type TYPE which is the + multiplicative identity of the set TYPE. */ + +tree +build_one_cst (tree type) +{ + switch (TREE_CODE (type)) + { + case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: + case POINTER_TYPE: case REFERENCE_TYPE: + case OFFSET_TYPE: + return build_int_cst (type, 1); + + case REAL_TYPE: + return build_real (type, dconst1); + + case VECTOR_TYPE: + { + tree scalar, cst; + int i; + + scalar = build_one_cst (TREE_TYPE (type)); + + /* Create 'vect_cst_ = {cst,cst,...,cst}' */ + cst = NULL_TREE; + for (i = TYPE_VECTOR_SUBPARTS (type); --i >= 0; ) + cst = tree_cons (NULL_TREE, scalar, cst); + + return build_vector (type, cst); + } + + case COMPLEX_TYPE: + return build_complex (type, + build_one_cst (TREE_TYPE (type)), + fold_convert (TREE_TYPE (type), integer_zero_node)); + + default: + gcc_unreachable (); + } +} + /* Build a BINFO with LEN language slots. */ tree @@ -1148,7 +1295,6 @@ integer_zerop (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 @@ -1165,7 +1311,6 @@ integer_onep (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == INTEGER_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && TREE_INT_CST_LOW (expr) == 1 && TREE_INT_CST_HIGH (expr) == 0) || (TREE_CODE (expr) == COMPLEX_CST @@ -1189,14 +1334,15 @@ integer_all_onesp (tree expr) && integer_zerop (TREE_IMAGPART (expr))) return 1; - else if (TREE_CODE (expr) != INTEGER_CST - || TREE_CONSTANT_OVERFLOW (expr)) + else if (TREE_CODE (expr) != INTEGER_CST) return 0; uns = TYPE_UNSIGNED (TREE_TYPE (expr)); + if (TREE_INT_CST_LOW (expr) == ~(unsigned HOST_WIDE_INT) 0 + && TREE_INT_CST_HIGH (expr) == -1) + return 1; if (!uns) - return (TREE_INT_CST_LOW (expr) == ~(unsigned HOST_WIDE_INT) 0 - && TREE_INT_CST_HIGH (expr) == -1); + return 0; /* Note that using TYPE_PRECISION here is wrong. We care about the actual bits, not the (arbitrary) range of the type. */ @@ -1240,7 +1386,7 @@ integer_pow2p (tree expr) && integer_zerop (TREE_IMAGPART (expr))) return 1; - if (TREE_CODE (expr) != INTEGER_CST || TREE_CONSTANT_OVERFLOW (expr)) + if (TREE_CODE (expr) != INTEGER_CST) return 0; prec = (POINTER_TYPE_P (TREE_TYPE (expr)) @@ -1278,7 +1424,6 @@ 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 @@ -1371,7 +1516,6 @@ real_zerop (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)) || (TREE_CODE (expr) == COMPLEX_CST && real_zerop (TREE_REALPART (expr)) @@ -1386,7 +1530,6 @@ real_onep (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)) || (TREE_CODE (expr) == COMPLEX_CST && real_onep (TREE_REALPART (expr)) @@ -1401,7 +1544,6 @@ real_twop (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)) || (TREE_CODE (expr) == COMPLEX_CST && real_twop (TREE_REALPART (expr)) @@ -1416,7 +1558,6 @@ real_minus_onep (tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && ! TREE_CONSTANT_OVERFLOW (expr) && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)) || (TREE_CODE (expr) == COMPLEX_CST && real_minus_onep (TREE_REALPART (expr)) @@ -1641,9 +1782,6 @@ size_in_bytes (tree type) return size_zero_node; } - if (TREE_CODE (t) == INTEGER_CST) - t = force_fit_type (t, 0, false, false); - return t; } @@ -1662,7 +1800,6 @@ int_size_in_bytes (tree type) t = TYPE_SIZE_UNIT (type); if (t == 0 || TREE_CODE (t) != INTEGER_CST - || TREE_OVERFLOW (t) || TREE_INT_CST_HIGH (t) != 0 /* If the result would appear negative, it's too big to represent. */ || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0) @@ -1670,6 +1807,39 @@ int_size_in_bytes (tree type) return TREE_INT_CST_LOW (t); } + +/* Return the maximum size of TYPE (in bytes) as a wide integer + or return -1 if the size can vary or is larger than an integer. */ + +HOST_WIDE_INT +max_int_size_in_bytes (tree type) +{ + HOST_WIDE_INT size = -1; + tree size_tree; + + /* If this is an array type, check for a possible MAX_SIZE attached. */ + + if (TREE_CODE (type) == ARRAY_TYPE) + { + size_tree = TYPE_ARRAY_MAX_SIZE (type); + + if (size_tree && host_integerp (size_tree, 1)) + size = tree_low_cst (size_tree, 1); + } + + /* If we still haven't been able to get a size, see if the language + can compute a maximum size. */ + + if (size == -1) + { + size_tree = lang_hooks.types.max_size (type); + + if (size_tree && host_integerp (size_tree, 1)) + size = tree_low_cst (size_tree, 1); + } + + return size; +} /* Return the bit position of FIELD, in bits from the start of the record. This is a tree of type bitsizetype. */ @@ -1727,6 +1897,10 @@ expr_align (tree t) align1 = TYPE_ALIGN (TREE_TYPE (t)); return MAX (align0, align1); + case GIMPLE_MODIFY_STMT: + /* We should never ask for the alignment of a gimple statement. */ + gcc_unreachable (); + case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR: case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR: case CLEANUP_POINT_EXPR: @@ -1979,6 +2153,11 @@ tree_node_structure (tree t) return TS_TYPE_DECL; case FUNCTION_DECL: return TS_FUNCTION_DECL; + case SYMBOL_MEMORY_TAG: + case NAME_MEMORY_TAG: + case STRUCT_FIELD_TAG: + case MEMORY_PARTITION_TAG: + return TS_MEMORY_TAG; default: return TS_DECL_NON_COMMON; } @@ -1991,7 +2170,10 @@ tree_node_structure (tree t) case tcc_binary: case tcc_expression: case tcc_statement: + case tcc_vl_exp: return TS_EXP; + case tcc_gimple_stmt: + return TS_GIMPLE_STATEMENT; default: /* tcc_constant and tcc_exceptional */ break; } @@ -2004,6 +2186,8 @@ tree_node_structure (tree t) case VECTOR_CST: return TS_VECTOR; case STRING_CST: return TS_STRING; /* tcc_exceptional cases. */ + /* FIXME tuples: eventually this should be TS_BASE. For now, nothing + returns TS_BASE. */ case ERROR_MARK: return TS_COMMON; case IDENTIFIER_NODE: return TS_IDENTIFIER; case TREE_LIST: return TS_LIST; @@ -2016,6 +2200,7 @@ tree_node_structure (tree t) case CONSTRUCTOR: return TS_CONSTRUCTOR; case TREE_BINFO: return TS_BINFO; case VALUE_HANDLE: return TS_VALUE_HANDLE; + case OMP_CLAUSE: return TS_OMP_CLAUSE; default: gcc_unreachable (); @@ -2067,9 +2252,6 @@ contains_placeholder_p (tree exp) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2))); - case CALL_EXPR: - return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)); - default: break; } @@ -2085,6 +2267,22 @@ contains_placeholder_p (tree exp) return 0; } + case tcc_vl_exp: + switch (code) + { + case CALL_EXPR: + { + tree arg; + call_expr_arg_iterator iter; + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + if (CONTAINS_PLACEHOLDER_P (arg)) + return 1; + return 0; + } + default: + return 0; + } + default: return 0; } @@ -2114,7 +2312,6 @@ type_contains_placeholder_1 (tree type) case COMPLEX_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: - case CHAR_TYPE: case POINTER_TYPE: case OFFSET_TYPE: case REFERENCE_TYPE: @@ -2293,6 +2490,27 @@ substitute_in_expr (tree exp, tree f, tree r) } break; + case tcc_vl_exp: + { + tree copy = NULL_TREE; + int i; + int n = TREE_OPERAND_LENGTH (exp); + for (i = 1; i < n; i++) + { + tree op = TREE_OPERAND (exp, i); + tree newop = SUBSTITUTE_IN_EXPR (op, f, r); + if (newop != op) + { + copy = copy_node (exp); + TREE_OPERAND (copy, i) = newop; + } + } + if (copy) + new = fold (copy); + else + return exp; + } + default: gcc_unreachable (); } @@ -2324,6 +2542,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) : (REFERENCE_CLASS_P (elt) || UNARY_CLASS_P (elt) || BINARY_CLASS_P (elt) + || VL_EXP_CLASS_P (elt) || EXPRESSION_CLASS_P (elt)) ? TREE_OPERAND (elt, 0) : 0)) if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type) @@ -2336,6 +2555,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) : (REFERENCE_CLASS_P (elt) || UNARY_CLASS_P (elt) || BINARY_CLASS_P (elt) + || VL_EXP_CLASS_P (elt) || EXPRESSION_CLASS_P (elt)) ? TREE_OPERAND (elt, 0) : 0)) if (POINTER_TYPE_P (TREE_TYPE (elt)) @@ -2423,6 +2643,28 @@ substitute_placeholder_in_expr (tree exp, tree obj) } break; + case tcc_vl_exp: + { + tree copy = NULL_TREE; + int i; + int n = TREE_OPERAND_LENGTH (exp); + for (i = 1; i < n; i++) + { + tree op = TREE_OPERAND (exp, i); + tree newop = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj); + if (newop != op) + { + if (!copy) + copy = copy_node (exp); + TREE_OPERAND (copy, i) = newop; + } + } + if (copy) + return fold (copy); + else + return exp; + } + default: gcc_unreachable (); } @@ -2454,9 +2696,6 @@ stabilize_reference (tree ref) case CONVERT_EXPR: case FLOAT_EXPR: case FIX_TRUNC_EXPR: - case FIX_FLOOR_EXPR: - case FIX_ROUND_EXPR: - case FIX_CEIL_EXPR: result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0))); break; @@ -2551,6 +2790,7 @@ stabilize_reference_1 (tree e) case tcc_statement: case tcc_expression: case tcc_reference: + case tcc_vl_exp: /* 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 @@ -2602,7 +2842,7 @@ stabilize_reference_1 (tree e) TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR. */ void -recompute_tree_invarant_for_addr_expr (tree t) +recompute_tree_invariant_for_addr_expr (tree t) { tree node; bool tc = true, ti = true, se = false; @@ -2691,9 +2931,7 @@ do { tree _node = (NODE); \ Constants, decls, types and misc nodes cannot be. We define 5 non-variadic functions, from 0 to 4 arguments. This is - enough for all extant tree codes. These functions can be called - directly (preferably!), but can also be obtained via GCC preprocessor - magic within the build macro. */ + enough for all extant tree codes. */ tree build0_stat (enum tree_code code, tree tt MEM_STAT_DECL) @@ -2749,7 +2987,6 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) #else SET_EXPR_LOCUS (t, NULL); #endif - TREE_COMPLEXITY (t) = 0; TREE_OPERAND (t, 0) = node; TREE_BLOCK (t) = NULL_TREE; if (node && !TYPE_P (node)) @@ -2779,15 +3016,15 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) case ADDR_EXPR: if (node) - recompute_tree_invarant_for_addr_expr (t); + recompute_tree_invariant_for_addr_expr (t); break; default: - if (TREE_CODE_CLASS (code) == tcc_unary + if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR) && node && !TYPE_P (node) && TREE_CONSTANT (node)) TREE_CONSTANT (t) = 1; - if (TREE_CODE_CLASS (code) == tcc_unary + if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR) && node && TREE_INVARIANT (node)) TREE_INVARIANT (t) = 1; if (TREE_CODE_CLASS (code) == tcc_reference @@ -2823,6 +3060,15 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) gcc_assert (TREE_CODE_LENGTH (code) == 2); +#if 1 + /* FIXME tuples: Statement's aren't expressions! */ + if (code == GIMPLE_MODIFY_STMT) + return build_gimple_modify_stmt_stat (arg0, arg1 PASS_MEM_STAT); +#else + /* Must use build_gimple_modify_stmt to construct GIMPLE_MODIFY_STMTs. */ + gcc_assert (code != GIMPLE_MODIFY_STMT); +#endif + t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -2853,6 +3099,22 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) return t; } + +/* Build a GIMPLE_MODIFY_STMT node. This tree code doesn't have a + type, so we can't use build2 (a.k.a. build2_stat). */ + +tree +build_gimple_modify_stmt_stat (tree arg0, tree arg1 MEM_STAT_DECL) +{ + tree t; + + t = make_node_stat (GIMPLE_MODIFY_STMT PASS_MEM_STAT); + /* ?? We don't care about setting flags for tuples... */ + GIMPLE_STMT_OPERAND (t, 0) = arg0; + GIMPLE_STMT_OPERAND (t, 1) = arg1; + return t; +} + tree build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree arg2 MEM_STAT_DECL) @@ -2861,6 +3123,7 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree t; gcc_assert (TREE_CODE_LENGTH (code) == 3); + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -2871,26 +3134,6 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, PROCESS_ARG(1); PROCESS_ARG(2); - if (code == CALL_EXPR && !side_effects) - { - tree node; - int i; - - /* Calls have side-effects, except those to const or - pure functions. */ - i = call_expr_flags (t); - if (!(i & (ECF_CONST | ECF_PURE))) - side_effects = 1; - - /* And even those have side-effects if their arguments do. */ - else for (node = arg1; node; node = TREE_CHAIN (node)) - if (TREE_SIDE_EFFECTS (TREE_VALUE (node))) - { - side_effects = 1; - break; - } - } - TREE_SIDE_EFFECTS (t) = side_effects; TREE_THIS_VOLATILE (t) = (TREE_CODE_CLASS (code) == tcc_reference @@ -2927,14 +3170,13 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1, } tree -build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1, - tree arg2, tree arg3, tree arg4, tree arg5, - tree arg6 MEM_STAT_DECL) +build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1, + tree arg2, tree arg3, tree arg4 MEM_STAT_DECL) { bool constant, read_only, side_effects, invariant; tree t; - gcc_assert (code == TARGET_MEM_REF); + gcc_assert (TREE_CODE_LENGTH (code) == 5); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -2946,66 +3188,40 @@ build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1, PROCESS_ARG(2); PROCESS_ARG(3); PROCESS_ARG(4); - PROCESS_ARG(5); - PROCESS_ARG(6); TREE_SIDE_EFFECTS (t) = side_effects; - TREE_THIS_VOLATILE (t) = 0; + TREE_THIS_VOLATILE (t) + = (TREE_CODE_CLASS (code) == tcc_reference + && arg0 && TREE_THIS_VOLATILE (arg0)); return t; } -/* Backup definition for non-gcc build compilers. */ - tree -(build) (enum tree_code code, tree tt, ...) +build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1, + tree arg2, tree arg3, tree arg4, tree arg5, + tree arg6 MEM_STAT_DECL) { - tree t, arg0, arg1, arg2, arg3, arg4, arg5, arg6; - int length = TREE_CODE_LENGTH (code); - va_list p; + bool constant, read_only, side_effects, invariant; + tree t; - va_start (p, tt); - switch (length) - { - case 0: - t = build0 (code, tt); - break; - case 1: - arg0 = va_arg (p, tree); - t = build1 (code, tt, arg0); - break; - case 2: - arg0 = va_arg (p, tree); - arg1 = va_arg (p, tree); - t = build2 (code, tt, arg0, arg1); - break; - case 3: - arg0 = va_arg (p, tree); - arg1 = va_arg (p, tree); - arg2 = va_arg (p, tree); - t = build3 (code, tt, arg0, arg1, arg2); - break; - case 4: - arg0 = va_arg (p, tree); - arg1 = va_arg (p, tree); - arg2 = va_arg (p, tree); - arg3 = va_arg (p, tree); - t = build4 (code, tt, arg0, arg1, arg2, arg3); - break; - case 7: - arg0 = va_arg (p, tree); - arg1 = va_arg (p, tree); - arg2 = va_arg (p, tree); - arg3 = va_arg (p, tree); - arg4 = va_arg (p, tree); - arg5 = va_arg (p, tree); - arg6 = va_arg (p, tree); - t = build7 (code, tt, arg0, arg1, arg2, arg3, arg4, arg5, arg6); - break; - default: - gcc_unreachable (); - } - va_end (p); + gcc_assert (code == TARGET_MEM_REF); + + t = make_node_stat (code PASS_MEM_STAT); + TREE_TYPE (t) = tt; + + side_effects = TREE_SIDE_EFFECTS (t); + + PROCESS_ARG(0); + PROCESS_ARG(1); + PROCESS_ARG(2); + PROCESS_ARG(3); + PROCESS_ARG(4); + PROCESS_ARG(5); + PROCESS_ARG(6); + + TREE_SIDE_EFFECTS (t) = side_effects; + TREE_THIS_VOLATILE (t) = 0; return t; } @@ -3023,6 +3239,8 @@ build_nt (enum tree_code code, ...) int i; va_list p; + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); + va_start (p, code); t = make_node (code); @@ -3034,6 +3252,23 @@ build_nt (enum tree_code code, ...) va_end (p); return t; } + +/* Similar to build_nt, but for creating a CALL_EXPR object with + ARGLIST passed as a list. */ + +tree +build_nt_call_list (tree fn, tree arglist) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3); + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++) + CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist); + return t; +} /* Create a DECL_... node of code CODE, name NAME and data type TYPE. We do NOT enter this node in any sort of symbol table. @@ -3061,14 +3296,6 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL) else if (code == FUNCTION_DECL) DECL_MODE (t) = FUNCTION_MODE; - if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) - { - /* Set default visibility to whatever the user supplied with - visibility_specified depending on #pragma GCC visibility. */ - DECL_VISIBILITY (t) = default_visibility; - DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma; - } - return t; } @@ -3107,7 +3334,7 @@ build_block (tree vars, tree subblocks, tree supercontext, tree chain) #if 1 /* ! defined(USE_MAPPED_LOCATION) */ /* ??? gengtype doesn't handle conditionals */ -static GTY(()) location_t *last_annotated_node; +static GTY(()) source_locus last_annotated_node; #endif #ifdef USE_MAPPED_LOCATION @@ -3116,7 +3343,12 @@ expanded_location expand_location (source_location loc) { expanded_location xloc; - if (loc == 0) { xloc.file = NULL; xloc.line = 0; xloc.column = 0; } + if (loc == 0) + { + xloc.file = NULL; + xloc.line = 0; + xloc.column = 0; + } else { const struct line_map *map = linemap_lookup (&line_table, loc); @@ -3172,17 +3404,141 @@ annotate_with_locus (tree node, location_t locus) } #endif -/* Return a declaration like DDECL except that its DECL_ATTRIBUTES - is ATTRIBUTE. */ +/* Source location accessor functions. */ -tree -build_decl_attribute_variant (tree ddecl, tree attribute) + +/* The source location of this expression. Non-tree_exp nodes such as + decls and constants can be shared among multiple locations, so + return nothing. */ +location_t +expr_location (tree node) { - DECL_ATTRIBUTES (ddecl) = attribute; - return ddecl; +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + return GIMPLE_STMT_LOCUS (node); + return EXPR_P (node) ? node->exp.locus : UNKNOWN_LOCATION; +#else + if (GIMPLE_STMT_P (node)) + return EXPR_HAS_LOCATION (node) + ? *GIMPLE_STMT_LOCUS (node) : UNKNOWN_LOCATION; + return EXPR_HAS_LOCATION (node) ? *node->exp.locus : UNKNOWN_LOCATION; +#endif } -/* Borrowed from hashtab.c iterative_hash implementation. */ +void +set_expr_location (tree node, location_t locus) +{ +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + GIMPLE_STMT_LOCUS (node) = locus; + else + EXPR_CHECK (node)->exp.locus = locus; +#else + annotate_with_locus (node, locus); +#endif +} + +bool +expr_has_location (tree node) +{ +#ifdef USE_MAPPED_LOCATION + return expr_location (node) != UNKNOWN_LOCATION; +#else + return expr_locus (node) != NULL; +#endif +} + +#ifdef USE_MAPPED_LOCATION +source_location * +#else +source_locus +#endif +expr_locus (tree node) +{ +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + return &GIMPLE_STMT_LOCUS (node); + return EXPR_P (node) ? &node->exp.locus : (location_t *) NULL; +#else + if (GIMPLE_STMT_P (node)) + return GIMPLE_STMT_LOCUS (node); + /* ?? The cast below was originally "(location_t *)" in the macro, + but that makes no sense. ?? */ + return EXPR_P (node) ? node->exp.locus : (source_locus) NULL; +#endif +} + +void +set_expr_locus (tree node, +#ifdef USE_MAPPED_LOCATION + source_location *loc +#else + source_locus loc +#endif + ) +{ +#ifdef USE_MAPPED_LOCATION + if (loc == NULL) + { + if (GIMPLE_STMT_P (node)) + GIMPLE_STMT_LOCUS (node) = UNKNOWN_LOCATION; + else + EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION; + } + else + { + if (GIMPLE_STMT_P (node)) + GIMPLE_STMT_LOCUS (node) = *loc; + else + EXPR_CHECK (node)->exp.locus = *loc; + } +#else + if (GIMPLE_STMT_P (node)) + GIMPLE_STMT_LOCUS (node) = loc; + else + EXPR_CHECK (node)->exp.locus = loc; +#endif +} + +const char ** +expr_filename (tree node) +{ +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + return &LOCATION_FILE (GIMPLE_STMT_LOCUS (node)); + return &LOCATION_FILE (EXPR_CHECK (node)->exp.locus); +#else + if (GIMPLE_STMT_P (node)) + return &GIMPLE_STMT_LOCUS (node)->file; + return &(EXPR_CHECK (node)->exp.locus->file); +#endif +} + +int * +expr_lineno (tree node) +{ +#ifdef USE_MAPPED_LOCATION + if (GIMPLE_STMT_P (node)) + return &LOCATION_LINE (GIMPLE_STMT_LOCUS (node)); + return &LOCATION_LINE (EXPR_CHECK (node)->exp.locus); +#else + if (GIMPLE_STMT_P (node)) + return &GIMPLE_STMT_LOCUS (node)->line; + return &EXPR_CHECK (node)->exp.locus->line; +#endif +} + +/* Return a declaration like DDECL except that its DECL_ATTRIBUTES + is ATTRIBUTE. */ + +tree +build_decl_attribute_variant (tree ddecl, tree attribute) +{ + DECL_ATTRIBUTES (ddecl) = attribute; + return ddecl; +} + +/* Borrowed from hashtab.c iterative_hash implementation. */ #define mix(a,b,c) \ { \ a -= b; a -= c; a ^= (c>>13); \ @@ -3251,12 +3607,12 @@ iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2) } /* Return a type like TTYPE except that its TYPE_ATTRIBUTE - is ATTRIBUTE. + is ATTRIBUTE and its qualifiers are QUALS. Record such modified types already made so we don't make duplicates. */ -tree -build_type_attribute_variant (tree ttype, tree attribute) +static tree +build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) { if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute)) { @@ -3270,6 +3626,12 @@ build_type_attribute_variant (tree ttype, tree attribute) TYPE_REFERENCE_TO (ntype) = 0; TYPE_ATTRIBUTES (ntype) = attribute; + if (TYPE_STRUCTURAL_EQUALITY_P (ttype)) + SET_TYPE_STRUCTURAL_EQUALITY (ntype); + else + TYPE_CANONICAL (ntype) + = build_qualified_type (TYPE_CANONICAL (ttype), quals); + /* Create a new main variant of TYPE. */ TYPE_MAIN_VARIANT (ntype) = ntype; TYPE_NEXT_VARIANT (ntype) = 0; @@ -3307,13 +3669,32 @@ build_type_attribute_variant (tree ttype, tree attribute) } ntype = type_hash_canon (hashcode, ntype); - ttype = build_qualified_type (ntype, TYPE_QUALS (ttype)); + + /* If the target-dependent attributes make NTYPE different from + its canonical type, we will need to use structural equality + checks for this qualified type. */ + if (!targetm.comp_type_attributes (ntype, ttype)) + SET_TYPE_STRUCTURAL_EQUALITY (ntype); + + ttype = build_qualified_type (ntype, quals); } return ttype; } +/* Return a type like TTYPE except that its TYPE_ATTRIBUTE + is ATTRIBUTE. + + Record such modified types already made so we don't make duplicates. */ + +tree +build_type_attribute_variant (tree ttype, tree attribute) +{ + return build_type_attribute_qual_variant (ttype, attribute, + TYPE_QUALS (ttype)); +} + /* Return nonzero if IDENT is a valid name for attribute ATTR, or zero if not. @@ -3344,7 +3725,6 @@ is_attribute_with_length_p (const char *attr, int attr_len, tree ident) 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; @@ -3394,6 +3774,28 @@ lookup_attribute (const char *attr_name, tree list) return NULL_TREE; } +/* Remove any instances of attribute ATTR_NAME in LIST and return the + modified list. */ + +tree +remove_attribute (const char *attr_name, tree list) +{ + tree *p; + size_t attr_len = strlen (attr_name); + + for (p = &list; *p; ) + { + tree l = *p; + gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE); + if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l))) + *p = TREE_CHAIN (l); + else + p = &TREE_CHAIN (l); + } + + return list; +} + /* Return an attribute list that is the union of a1 and a2. */ tree @@ -3428,7 +3830,17 @@ merge_attributes (tree a1, tree a2) a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), TREE_CHAIN (a))) { - if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1) + if (TREE_VALUE (a) != NULL + && TREE_CODE (TREE_VALUE (a)) == TREE_LIST + && TREE_VALUE (a2) != NULL + && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST) + { + if (simple_cst_list_equal (TREE_VALUE (a), + TREE_VALUE (a2)) == 1) + break; + } + else if (simple_cst_equal (TREE_VALUE (a), + TREE_VALUE (a2)) == 1) break; } if (a == NULL_TREE) @@ -3580,9 +3992,18 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, return NULL_TREE; } + if (TREE_CODE (node) != FUNCTION_DECL + && TREE_CODE (node) != VAR_DECL) + { + *no_add_attrs = true; + warning (OPT_Wattributes, "%qs attribute ignored", + IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + /* Report error on dllimport ambiguities seen now before they cause any damage. */ - if (is_attribute_p ("dllimport", name)) + else if (is_attribute_p ("dllimport", name)) { /* Honor any target-specific overrides. */ if (!targetm.valid_dllimport_attribute_p (node)) @@ -3703,26 +4124,27 @@ build_qualified_type (tree type, int type_quals) t = build_variant_type_copy (type); set_type_quals (t, type_quals); - /* If it's a pointer type, the new variant points to the same type. */ - if (TREE_CODE (type) == POINTER_TYPE) - { - TYPE_NEXT_PTR_TO (t) = TYPE_NEXT_PTR_TO (type); - TYPE_NEXT_PTR_TO (type) = t; - } - - /* Same for a reference type. */ - else if (TREE_CODE (type) == REFERENCE_TYPE) - { - TYPE_NEXT_REF_TO (t) = TYPE_NEXT_REF_TO (type); - TYPE_NEXT_REF_TO (type) = t; - } + if (TYPE_STRUCTURAL_EQUALITY_P (type)) + /* Propagate structural equality. */ + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (type) != type) + /* Build the underlying canonical type, since it is different + from TYPE. */ + TYPE_CANONICAL (t) = build_qualified_type (TYPE_CANONICAL (type), + type_quals); + else + /* T is its own canonical type. */ + TYPE_CANONICAL (t) = t; + } return t; } /* Create a new distinct copy of TYPE. The new type is made its own - MAIN_VARIANT. */ + MAIN_VARIANT. If TYPE requires structural equality checks, the + resulting type requires structural equality checks; otherwise, its + TYPE_CANONICAL points to itself. */ tree build_distinct_type_copy (tree type) @@ -3732,6 +4154,13 @@ build_distinct_type_copy (tree type) TYPE_POINTER_TO (t) = 0; TYPE_REFERENCE_TO (t) = 0; + /* Set the canonical type either to a new equivalence class, or + propagate the need for structural equality checks. */ + if (TYPE_STRUCTURAL_EQUALITY_P (type)) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else + TYPE_CANONICAL (t) = t; + /* Make it its own variant. */ TYPE_MAIN_VARIANT (t) = t; TYPE_NEXT_VARIANT (t) = 0; @@ -3739,8 +4168,11 @@ build_distinct_type_copy (tree type) return t; } -/* Create a new variant of TYPE, equivalent but distinct. - This is so the caller can modify it. */ +/* Create a new variant of TYPE, equivalent but distinct. This is so + the caller can modify it. TYPE_CANONICAL for the return type will + be equivalent to TYPE_CANONICAL of TYPE, indicating that the types + are considered equal by the language itself (or that both types + require structural equality checks). */ tree build_variant_type_copy (tree type) @@ -3748,6 +4180,10 @@ build_variant_type_copy (tree type) tree t, m = TYPE_MAIN_VARIANT (type); t = build_distinct_type_copy (type); + + /* Since we're building a variant, assume that it is a non-semantic + variant. This also propagates TYPE_STRUCTURAL_EQUALITY_P. */ + TYPE_CANONICAL (t) = TYPE_CANONICAL (type); /* Add the new type to the chain of variants of TYPE. */ TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); @@ -3760,18 +4196,18 @@ build_variant_type_copy (tree type) /* Return true if the from tree in both tree maps are equal. */ int -tree_map_eq (const void *va, const void *vb) +tree_map_base_eq (const void *va, const void *vb) { - const struct tree_map *a = va, *b = vb; + const struct tree_map_base *a = va, *b = vb; return (a->from == b->from); } /* Hash a from tree in a tree_map. */ unsigned int -tree_map_hash (const void *item) +tree_map_base_hash (const void *item) { - return (((const struct tree_map *) item)->hash); + return htab_hash_pointer (((const struct tree_map_base *)item)->from); } /* Return true if this tree map structure is marked for garbage collection @@ -3779,70 +4215,97 @@ tree_map_hash (const void *item) structure goes away when the from tree goes away. */ int -tree_map_marked_p (const void *p) +tree_map_base_marked_p (const void *p) { - tree from = ((struct tree_map *) p)->from; + return ggc_marked_p (((struct tree_map_base *) p)->from); +} - return ggc_marked_p (from); +unsigned int +tree_map_hash (const void *item) +{ + return (((const struct tree_map *) item)->hash); } -/* Return true if the trees in the tree_int_map *'s VA and VB are equal. */ +/* Return the initialization priority for DECL. */ -static int -tree_int_map_eq (const void *va, const void *vb) +priority_type +decl_init_priority_lookup (tree decl) { - const struct tree_int_map *a = va, *b = vb; - return (a->from == b->from); + struct tree_priority_map *h; + struct tree_map_base in; + + gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); + gcc_assert (TREE_CODE (decl) == VAR_DECL + ? DECL_HAS_INIT_PRIORITY_P (decl) + : DECL_STATIC_CONSTRUCTOR (decl)); + in.from = decl; + h = htab_find (init_priority_for_decl, &in); + return h ? h->init : DEFAULT_INIT_PRIORITY; } -/* Hash a from tree in the tree_int_map * ITEM. */ +/* Return the finalization priority for DECL. */ -static unsigned int -tree_int_map_hash (const void *item) +priority_type +decl_fini_priority_lookup (tree decl) { - return htab_hash_pointer (((const struct tree_int_map *)item)->from); + struct tree_priority_map *h; + struct tree_map_base in; + + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); + gcc_assert (DECL_STATIC_DESTRUCTOR (decl)); + in.from = decl; + h = htab_find (init_priority_for_decl, &in); + return h ? h->fini : DEFAULT_INIT_PRIORITY; } -/* Return true if this tree int map structure is marked for garbage collection - purposes. We simply return true if the from tree_int_map *P's from tree is marked, so that this - structure goes away when the from tree goes away. */ +/* Return the initialization and finalization priority information for + DECL. If there is no previous priority information, a freshly + allocated structure is returned. */ -static int -tree_int_map_marked_p (const void *p) +static struct tree_priority_map * +decl_priority_info (tree decl) { - tree from = ((struct tree_int_map *) p)->from; + struct tree_priority_map in; + struct tree_priority_map *h; + void **loc; + + in.base.from = decl; + loc = htab_find_slot (init_priority_for_decl, &in, INSERT); + h = *loc; + if (!h) + { + h = GGC_CNEW (struct tree_priority_map); + *loc = h; + h->base.from = decl; + h->init = DEFAULT_INIT_PRIORITY; + h->fini = DEFAULT_INIT_PRIORITY; + } - return ggc_marked_p (from); + return h; } -/* Lookup an init priority for FROM, and return it if we find one. */ -unsigned short -decl_init_priority_lookup (tree from) +/* Set the initialization priority for DECL to PRIORITY. */ + +void +decl_init_priority_insert (tree decl, priority_type priority) { - struct tree_int_map *h, in; - in.from = from; + struct tree_priority_map *h; - h = htab_find_with_hash (init_priority_for_decl, - &in, htab_hash_pointer (from)); - if (h) - return h->to; - return 0; -} + gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); + h = decl_priority_info (decl); + h->init = priority; +} -/* Insert a mapping FROM->TO in the init priority hashtable. */ +/* Set the finalization priority for DECL to PRIORITY. */ void -decl_init_priority_insert (tree from, unsigned short to) +decl_fini_priority_insert (tree decl, priority_type priority) { - struct tree_int_map *h; - void **loc; + struct tree_priority_map *h; - h = ggc_alloc (sizeof (struct tree_int_map)); - h->from = from; - h->to = to; - loc = htab_find_slot_with_hash (init_priority_for_decl, h, - htab_hash_pointer (from), INSERT); - *(struct tree_int_map **) loc = h; + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); + h = decl_priority_info (decl); + h->fini = priority; } /* Look up a restrict qualified base decl for FROM. */ @@ -3853,7 +4316,7 @@ decl_restrict_base_lookup (tree from) struct tree_map *h; struct tree_map in; - in.from = from; + in.base.from = from; h = htab_find_with_hash (restrict_base_for_decl, &in, htab_hash_pointer (from)); return h ? h->to : NULL_TREE; @@ -3869,7 +4332,7 @@ decl_restrict_base_insert (tree from, tree to) h = ggc_alloc (sizeof (struct tree_map)); h->hash = htab_hash_pointer (from); - h->from = from; + h->base.from = from; h->to = to; loc = htab_find_slot_with_hash (restrict_base_for_decl, h, h->hash, INSERT); *(struct tree_map **) loc = h; @@ -3917,7 +4380,7 @@ tree decl_debug_expr_lookup (tree from) { struct tree_map *h, in; - in.from = from; + in.base.from = from; h = htab_find_with_hash (debug_expr_for_decl, &in, htab_hash_pointer (from)); if (h) @@ -3935,7 +4398,7 @@ decl_debug_expr_insert (tree from, tree to) h = ggc_alloc (sizeof (struct tree_map)); h->hash = htab_hash_pointer (from); - h->from = from; + h->base.from = from; h->to = to; loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT); *(struct tree_map **) loc = h; @@ -3947,7 +4410,7 @@ tree decl_value_expr_lookup (tree from) { struct tree_map *h, in; - in.from = from; + in.base.from = from; h = htab_find_with_hash (value_expr_for_decl, &in, htab_hash_pointer (from)); if (h) @@ -3965,7 +4428,7 @@ decl_value_expr_insert (tree from, tree to) h = ggc_alloc (sizeof (struct tree_map)); h->hash = htab_hash_pointer (from); - h->from = from; + h->base.from = from; h->to = to; loc = htab_find_slot_with_hash (value_expr_for_decl, h, h->hash, INSERT); *(struct tree_map **) loc = h; @@ -4036,7 +4499,6 @@ type_hash_eq (const void *va, const void *vb) case INTEGER_TYPE: case REAL_TYPE: case BOOLEAN_TYPE: - case CHAR_TYPE: return ((TYPE_MAX_VALUE (a->type) == TYPE_MAX_VALUE (b->type) || tree_int_cst_equal (TYPE_MAX_VALUE (a->type), TYPE_MAX_VALUE (b->type))) @@ -4254,15 +4716,21 @@ attribute_list_contained (tree l1, tree l2) attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), TREE_CHAIN (attr))) { - if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1) + if (TREE_VALUE (t2) != NULL + && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST + && TREE_VALUE (attr) != NULL + && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST) + { + if (simple_cst_list_equal (TREE_VALUE (t2), + TREE_VALUE (attr)) == 1) + break; + } + else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1) break; } if (attr == 0) return 0; - - if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) != 1) - return 0; } return 1; @@ -4381,7 +4849,6 @@ int host_integerp (tree t, int pos) { return (TREE_CODE (t) == INTEGER_CST - && ! TREE_OVERFLOW (t) && ((TREE_INT_CST_HIGH (t) == 0 && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0) || (! pos && TREE_INT_CST_HIGH (t) == -1 @@ -4525,11 +4992,26 @@ simple_cst_equal (tree t1, tree t2) return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); case CALL_EXPR: - cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); + cmp = simple_cst_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)); if (cmp <= 0) return cmp; - return - simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)); + if (call_expr_nargs (t1) != call_expr_nargs (t2)) + return 0; + { + tree arg1, arg2; + call_expr_arg_iterator iter1, iter2; + for (arg1 = first_call_expr_arg (t1, &iter1), + arg2 = first_call_expr_arg (t2, &iter2); + arg1 && arg2; + arg1 = next_call_expr_arg (&iter1), + arg2 = next_call_expr_arg (&iter2)) + { + cmp = simple_cst_equal (arg1, arg2); + if (cmp <= 0) + return cmp; + } + return arg1 == arg2; + } case TARGET_EXPR: /* Special case: if either target is an unallocated VAR_DECL, @@ -4755,8 +5237,8 @@ iterative_hash_expr (tree t, hashval_t val) if (class == tcc_declaration) { - /* Otherwise, we can just compare decls by pointer. */ - val = iterative_hash_pointer (t, val); + /* DECL's have a unique ID */ + val = iterative_hash_host_wide_int (DECL_UID (t), val); } else { @@ -4793,7 +5275,7 @@ iterative_hash_expr (tree t, hashval_t val) val = iterative_hash_hashval_t (two, val); } else - for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; --i) + for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i) val = iterative_hash_expr (TREE_OPERAND (t, i), val); } return val; @@ -4831,12 +5313,10 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode, && TREE_CODE (TYPE_POINTER_TO (to_type)) != POINTER_TYPE) return TYPE_POINTER_TO (to_type); - /* First, if we already have an unqualified type for pointers to TO_TYPE - and it's the proper mode, use it. */ + /* First, if we already have a type for pointers to TO_TYPE and it's + the proper mode, use it. */ for (t = TYPE_POINTER_TO (to_type); t; t = TYPE_NEXT_PTR_TO (t)) - if (TYPE_MODE (t) == mode - && !TYPE_QUALS (t) - && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all) + if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all) return t; t = make_node (POINTER_TYPE); @@ -4847,6 +5327,13 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode, TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (to_type); TYPE_POINTER_TO (to_type) = t; + if (TYPE_STRUCTURAL_EQUALITY_P (to_type)) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (to_type) != to_type) + TYPE_CANONICAL (t) + = build_pointer_type_for_mode (TYPE_CANONICAL (to_type), + mode, can_alias_all); + /* Lay out the type. This function has many callers that are concerned with expression-construction, and this simplifies them all. */ layout_type (t); @@ -4882,12 +5369,10 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode, && TREE_CODE (TYPE_REFERENCE_TO (to_type)) != REFERENCE_TYPE) return TYPE_REFERENCE_TO (to_type); - /* First, if we already have an unqualified type for references to TO_TYPE - and it's the proper mode, use it. */ + /* First, if we already have a type for pointers to TO_TYPE and it's + the proper mode, use it. */ for (t = TYPE_REFERENCE_TO (to_type); t; t = TYPE_NEXT_REF_TO (t)) - if (TYPE_MODE (t) == mode - && !TYPE_QUALS (t) - && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all) + if (TYPE_MODE (t) == mode && TYPE_REF_CAN_ALIAS_ALL (t) == can_alias_all) return t; t = make_node (REFERENCE_TYPE); @@ -4898,6 +5383,13 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode, TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (to_type); TYPE_REFERENCE_TO (to_type) = t; + if (TYPE_STRUCTURAL_EQUALITY_P (to_type)) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (to_type) != to_type) + TYPE_CANONICAL (t) + = build_reference_type_for_mode (TYPE_CANONICAL (to_type), + mode, can_alias_all); + layout_type (t); return t; @@ -4964,7 +5456,12 @@ build_index_type (tree maxval) if (host_integerp (maxval, 1)) return type_hash_canon (tree_low_cst (maxval, 1), itype); else - return itype; + { + /* Since we cannot hash this type, we need to compare it using + structural equality checks. */ + SET_TYPE_STRUCTURAL_EQUALITY (itype); + return itype; + } } /* Builds a signed or unsigned integer type of precision PRECISION. @@ -4990,9 +5487,8 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, } /* Create a range of some discrete type TYPE (an INTEGER_TYPE, - ENUMERAL_TYPE, BOOLEAN_TYPE, or CHAR_TYPE), with - low bound LOWVAL and high bound HIGHVAL. - if TYPE==NULL_TREE, sizetype is used. */ + ENUMERAL_TYPE or BOOLEAN_TYPE), with low bound LOWVAL and + high bound HIGHVAL. If TYPE is NULL, sizetype is used. */ tree build_range_type (tree type, tree lowval, tree highval) @@ -5003,8 +5499,8 @@ build_range_type (tree type, tree lowval, tree highval) if (type == NULL_TREE) type = sizetype; - TYPE_MIN_VALUE (itype) = convert (type, lowval); - TYPE_MAX_VALUE (itype) = highval ? convert (type, highval) : NULL; + TYPE_MIN_VALUE (itype) = fold_convert (type, lowval); + TYPE_MAX_VALUE (itype) = highval ? fold_convert (type, highval) : NULL; TYPE_PRECISION (itype) = TYPE_PRECISION (type); TYPE_MODE (itype) = TYPE_MODE (type); @@ -5052,7 +5548,21 @@ build_array_type (tree elt_type, tree index_type) if (index_type == 0) { - layout_type (t); + tree save = t; + hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode); + t = type_hash_canon (hashcode, t); + if (save == t) + layout_type (t); + + if (TYPE_CANONICAL (t) == t) + { + if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (elt_type) != elt_type) + TYPE_CANONICAL (t) + = build_array_type (TYPE_CANONICAL (elt_type), index_type); + } + return t; } @@ -5062,6 +5572,19 @@ build_array_type (tree elt_type, tree index_type) if (!COMPLETE_TYPE_P (t)) layout_type (t); + + if (TYPE_CANONICAL (t) == t) + { + if (TYPE_STRUCTURAL_EQUALITY_P (elt_type) + || TYPE_STRUCTURAL_EQUALITY_P (index_type)) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (elt_type) != elt_type + || TYPE_CANONICAL (index_type) != index_type) + TYPE_CANONICAL (t) + = build_array_type (TYPE_CANONICAL (elt_type), + TYPE_CANONICAL (index_type)); + } + return t; } @@ -5103,6 +5626,9 @@ build_function_type (tree value_type, tree arg_types) TREE_TYPE (t) = value_type; TYPE_ARG_TYPES (t) = arg_types; + /* We don't have canonicalization of function types, yet. */ + SET_TYPE_STRUCTURAL_EQUALITY (t); + /* If we already have such a type, use the old one. */ hashcode = iterative_hash_object (TYPE_HASH (value_type), hashcode); hashcode = type_hash_list (arg_types, hashcode); @@ -5170,6 +5696,9 @@ build_method_type_directly (tree basetype, argtypes = tree_cons (NULL_TREE, ptype, argtypes); TYPE_ARG_TYPES (t) = argtypes; + /* We don't have canonicalization of method types yet. */ + SET_TYPE_STRUCTURAL_EQUALITY (t); + /* If we already have such a type, use the old one. */ hashcode = iterative_hash_object (TYPE_HASH (basetype), hashcode); hashcode = iterative_hash_object (TYPE_HASH (rettype), hashcode); @@ -5221,6 +5750,18 @@ build_offset_type (tree basetype, tree type) if (!COMPLETE_TYPE_P (t)) layout_type (t); + if (TYPE_CANONICAL (t) == t) + { + if (TYPE_STRUCTURAL_EQUALITY_P (basetype) + || TYPE_STRUCTURAL_EQUALITY_P (type)) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (basetype) != basetype + || TYPE_CANONICAL (type) != type) + TYPE_CANONICAL (t) + = build_offset_type (TYPE_CANONICAL (basetype), + TYPE_CANONICAL (type)); + } + return t; } @@ -5244,6 +5785,15 @@ build_complex_type (tree component_type) if (!COMPLETE_TYPE_P (t)) layout_type (t); + if (TYPE_CANONICAL (t) == t) + { + if (TYPE_STRUCTURAL_EQUALITY_P (component_type)) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (component_type) != component_type) + TYPE_CANONICAL (t) + = build_complex_type (TYPE_CANONICAL (component_type)); + } + /* If we are writing Dwarf2 output we need to create a name, since complex is a fundamental type. */ if ((write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) @@ -5486,12 +6036,10 @@ get_narrower (tree op, int *unsignedp_ptr) { if (first) uns = DECL_UNSIGNED (TREE_OPERAND (op, 1)); - win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0), - TREE_OPERAND (op, 1), NULL_TREE); - TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op); - TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op); + win = fold_convert (type, op); } } + *unsignedp_ptr = uns; return win; } @@ -5505,12 +6053,13 @@ int_fits_type_p (tree c, tree type) tree type_low_bound = TYPE_MIN_VALUE (type); tree type_high_bound = TYPE_MAX_VALUE (type); bool ok_for_low_bound, ok_for_high_bound; - tree tmp; + unsigned HOST_WIDE_INT low; + HOST_WIDE_INT high; /* 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. + fit_double_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 @@ -5558,16 +6107,17 @@ int_fits_type_p (tree c, tree type) 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. */ - if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0) + can check ourselves here. Look at the base type if we have one and it + has the same precision. */ + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_TYPE (type) != 0 + && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type))) return int_fits_type_p (c, TREE_TYPE (type)); - /* Or to force_fit_type, if nothing else. */ - 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); + /* Or to fit_double_type, if nothing else. */ + low = TREE_INT_CST_LOW (c); + high = TREE_INT_CST_HIGH (c); + return !fit_double_type (low, high, &low, &high, type); } /* Subprogram of following function. Called by walk_tree. @@ -5591,8 +6141,10 @@ find_var_from_fn (tree *tp, int *walk_subtrees, void *data) } /* Returns true if T is, contains, or refers to a type with variable - size. If FN is nonzero, only return true if a modifier of the type - or position of FN is a variable or parameter inside FN. + size. For METHOD_TYPEs and FUNCTION_TYPEs we exclude the + arguments, but not the return type. If FN is nonzero, only return + true if a modifier of the type or position of FN is a variable or + parameter inside FN. This concept is more general than that of C99 'variably modified types': in C99, a struct type is never variably modified because a VLA may not @@ -5618,19 +6170,14 @@ variably_modified_type_p (tree type, tree fn) if (type == error_mark_node) return false; - /* 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 itself has variable size, it is variably modified. */ RETURN_TRUE_IF_VAR (TYPE_SIZE (type)); - RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT(type)); + RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (type)); switch (TREE_CODE (type)) { case POINTER_TYPE: case REFERENCE_TYPE: - case ARRAY_TYPE: case VECTOR_TYPE: if (variably_modified_type_p (TREE_TYPE (type), fn)) return true; @@ -5638,23 +6185,16 @@ variably_modified_type_p (tree type, tree fn) 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. */ + /* If TYPE is a function type, it is variably modified if the + return type is variably modified. */ if (variably_modified_type_p (TREE_TYPE (type), fn)) return true; - - for (t = TYPE_ARG_TYPES (type); - t && t != void_list_node; - t = TREE_CHAIN (t)) - if (variably_modified_type_p (TREE_VALUE (t), fn)) - return true; break; case INTEGER_TYPE: case REAL_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: - case CHAR_TYPE: /* Scalar types are variably modified if their end points aren't constant. */ RETURN_TRUE_IF_VAR (TYPE_MIN_VALUE (type)); @@ -5664,7 +6204,7 @@ variably_modified_type_p (tree type, tree fn) case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - /* We can't see if any of the field are variably-modified by the + /* We can't see if any of the fields are variably-modified by the definition we normally use, since that would produce infinite recursion via pointers. */ /* This is variably modified if some field's type is. */ @@ -5680,6 +6220,13 @@ variably_modified_type_p (tree type, tree fn) } break; + case ARRAY_TYPE: + /* Do not call ourselves to avoid infinite recursion. This is + variably modified if the element type is. */ + RETURN_TRUE_IF_VAR (TYPE_SIZE (TREE_TYPE (type))); + RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (TREE_TYPE (type))); + break; + default: break; } @@ -5781,13 +6328,16 @@ get_callee_fndecl (tree call) { tree addr; + if (call == error_mark_node) + return call; + /* It's invalid to call this function with anything but a CALL_EXPR. */ gcc_assert (TREE_CODE (call) == CALL_EXPR); /* The first operand to the CALL is the address of the function called. */ - addr = TREE_OPERAND (call, 0); + addr = CALL_EXPR_FN (call); STRIP_NOPS (addr); @@ -5889,22 +6439,48 @@ clean_symbol_name (char *p) *p = '_'; } -/* Generate a name for a function unique to this translation unit. +/* Generate a name for a special-purpose function function. + The generated name may need to be unique across the whole link. TYPE is some string to identify the purpose of this function to the - linker or collect2. */ + linker or collect2; it must start with an uppercase letter, + one of: + I - for constructors + D - for destructors + N - for C++ anonymous namespaces + F - for DWARF unwind frame information. */ tree -get_file_function_name_long (const char *type) +get_file_function_name (const char *type) { char *buf; const char *p; char *q; + /* If we already have a name we know to be unique, just use that. */ if (first_global_object_name) p = first_global_object_name; + /* If the target is handling the constructors/destructors, they + will be local to this file and the name is only necessary for + debugging purposes. */ + else if ((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors) + { + const char *file = main_input_filename; + if (! file) + file = input_filename; + /* Just use the file's basename, because the full pathname + might be quite long. */ + p = strrchr (file, '/'); + if (p) + p++; + else + p = file; + p = q = ASTRDUP (p); + clean_symbol_name (q); + } else { - /* We don't have anything that we know to be unique to this translation + /* Otherwise, the name must be unique across the entire link. + 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; @@ -5936,20 +6512,6 @@ get_file_function_name_long (const char *type) return get_identifier (buf); } - -/* If KIND=='I', return a suitable global initializer (constructor) name. - If KIND=='D', return a suitable global clean-up (destructor) name. */ - -tree -get_file_function_name (int kind) -{ - char p[2]; - - p[0] = kind; - p[1] = 0; - - return get_file_function_name_long (p); -} #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) @@ -6046,6 +6608,103 @@ tree_class_check_failed (const tree node, const enum tree_code_class cl, TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))), tree_code_name[TREE_CODE (node)], function, trim_filename (file), line); } + +/* Similar to tree_check_failed, except that instead of specifying a + dozen codes, use the knowledge that they're all sequential. */ + +void +tree_range_check_failed (const tree node, const char *file, int line, + const char *function, enum tree_code c1, + enum tree_code c2) +{ + char *buffer; + unsigned length = 0; + enum tree_code c; + + for (c = c1; c <= c2; ++c) + length += 4 + strlen (tree_code_name[c]); + + length += strlen ("expected "); + buffer = alloca (length); + length = 0; + + for (c = c1; c <= c2; ++c) + { + const char *prefix = length ? " or " : "expected "; + + strcpy (buffer + length, prefix); + length += strlen (prefix); + strcpy (buffer + length, tree_code_name[c]); + length += strlen (tree_code_name[c]); + } + + internal_error ("tree check: %s, have %s in %s, at %s:%d", + buffer, tree_code_name[TREE_CODE (node)], + function, trim_filename (file), line); +} + + +/* Similar to tree_check_failed, except that we check that a tree does + not have the specified code, given in CL. */ + +void +tree_not_class_check_failed (const tree node, const enum tree_code_class cl, + const char *file, int line, const char *function) +{ + internal_error + ("tree check: did not expect 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); +} + + +/* Similar to tree_check_failed but applied to OMP_CLAUSE codes. */ + +void +omp_clause_check_failed (const tree node, const char *file, int line, + const char *function, enum omp_clause_code code) +{ + internal_error ("tree check: expected omp_clause %s, have %s in %s, at %s:%d", + omp_clause_code_name[code], tree_code_name[TREE_CODE (node)], + function, trim_filename (file), line); +} + + +/* Similar to tree_range_check_failed but applied to OMP_CLAUSE codes. */ + +void +omp_clause_range_check_failed (const tree node, const char *file, int line, + const char *function, enum omp_clause_code c1, + enum omp_clause_code c2) +{ + char *buffer; + unsigned length = 0; + enum omp_clause_code c; + + for (c = c1; c <= c2; ++c) + length += 4 + strlen (omp_clause_code_name[c]); + + length += strlen ("expected "); + buffer = alloca (length); + length = 0; + + for (c = c1; c <= c2; ++c) + { + const char *prefix = length ? " or " : "expected "; + + strcpy (buffer + length, prefix); + length += strlen (prefix); + strcpy (buffer + length, omp_clause_code_name[c]); + length += strlen (omp_clause_code_name[c]); + } + + internal_error ("tree check: %s, have %s in %s, at %s:%d", + buffer, omp_clause_code_name[TREE_CODE (node)], + function, trim_filename (file), line); +} + + #undef DEFTREESTRUCT #define DEFTREESTRUCT(VAL, NAME) NAME, @@ -6097,17 +6756,32 @@ phi_node_elt_check_failed (int idx, int len, const char *file, int line, } /* Similar to above, except that the check is for the bounds of the operand - vector of an expression node. */ + vector of an expression node EXP. */ void -tree_operand_check_failed (int idx, enum tree_code code, const char *file, +tree_operand_check_failed (int idx, tree exp, const char *file, int line, const char *function) { + int code = TREE_CODE (exp); 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), + idx + 1, tree_code_name[code], TREE_OPERAND_LENGTH (exp), function, trim_filename (file), line); } + +/* Similar to above, except that the check is for the number of + operands of an OMP_CLAUSE node. */ + +void +omp_clause_operand_check_failed (int idx, tree t, const char *file, + int line, const char *function) +{ + internal_error + ("tree check: accessed operand %d of omp_clause %s with %d operands " + "in %s, at %s:%d", idx + 1, omp_clause_code_name[OMP_CLAUSE_CODE (t)], + omp_clause_num_ops [OMP_CLAUSE_CODE (t)], function, + trim_filename (file), line); +} #endif /* ENABLE_TREE_CHECKING */ /* Create a new vector type node holding SUBPARTS units of type INNERTYPE, @@ -6117,14 +6791,32 @@ tree_operand_check_failed (int idx, enum tree_code code, const char *file, static tree make_vector_type (tree innertype, int nunits, enum machine_mode mode) { - tree t = make_node (VECTOR_TYPE); + tree t; + hashval_t hashcode = 0; + /* Build a main variant, based on the main variant of the inner type, then + use it to build the variant we return. */ + if ((TYPE_ATTRIBUTES (innertype) || TYPE_QUALS (innertype)) + && TYPE_MAIN_VARIANT (innertype) != innertype) + return build_type_attribute_qual_variant ( + make_vector_type (TYPE_MAIN_VARIANT (innertype), nunits, mode), + TYPE_ATTRIBUTES (innertype), + TYPE_QUALS (innertype)); + + t = make_node (VECTOR_TYPE); TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype); SET_TYPE_VECTOR_SUBPARTS (t, nunits); TYPE_MODE (t) = mode; TYPE_READONLY (t) = TYPE_READONLY (innertype); TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype); + if (TYPE_STRUCTURAL_EQUALITY_P (innertype)) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (innertype) != innertype + || mode != VOIDmode) + TYPE_CANONICAL (t) + = make_vector_type (TYPE_CANONICAL (innertype), nunits, VOIDmode); + layout_type (t); { @@ -6143,17 +6835,10 @@ 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; + hashcode = iterative_hash_host_wide_int (VECTOR_TYPE, hashcode); + hashcode = iterative_hash_host_wide_int (mode, hashcode); + hashcode = iterative_hash_object (TYPE_HASH (innertype), hashcode); + return type_hash_canon (hashcode, t); } static tree @@ -6191,7 +6876,9 @@ build_common_tree_nodes (bool signed_char, bool signed_sizetype) /* Define both `signed char' and `unsigned char'. */ signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); + TYPE_STRING_FLAG (signed_char_type_node) = 1; unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE); + TYPE_STRING_FLAG (unsigned_char_type_node) = 1; /* Define `char', which is like either `signed char' or `unsigned char' but not the same as either. */ @@ -6199,6 +6886,7 @@ build_common_tree_nodes (bool signed_char, bool signed_sizetype) = (signed_char ? make_signed_type (CHAR_TYPE_SIZE) : make_unsigned_type (CHAR_TYPE_SIZE)); + TYPE_STRING_FLAG (char_type_node) = 1; short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); @@ -6293,6 +6981,29 @@ build_common_tree_nodes_2 (int short_double) long_double_ptr_type_node = build_pointer_type (long_double_type_node); integer_ptr_type_node = build_pointer_type (integer_type_node); + /* Fixed size integer types. */ + uint32_type_node = build_nonstandard_integer_type (32, true); + uint64_type_node = build_nonstandard_integer_type (64, true); + + /* Decimal float types. */ + dfloat32_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE; + layout_type (dfloat32_type_node); + TYPE_MODE (dfloat32_type_node) = SDmode; + dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node); + + dfloat64_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE; + layout_type (dfloat64_type_node); + TYPE_MODE (dfloat64_type_node) = DDmode; + dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node); + + dfloat128_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE; + layout_type (dfloat128_type_node); + TYPE_MODE (dfloat128_type_node) = TDmode; + dfloat128_ptr_type_node = build_pointer_type (dfloat128_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); @@ -6319,7 +7030,7 @@ build_common_tree_nodes_2 (int short_double) declare the type to be __builtin_va_list. */ if (TREE_CODE (t) != RECORD_TYPE) t = build_variant_type_copy (t); - + va_list_type_node = t; } } @@ -6332,8 +7043,8 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, { tree decl; - decl = lang_hooks.builtin_function (name, type, code, BUILT_IN_NORMAL, - library_name, NULL_TREE); + decl = add_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) @@ -6425,6 +7136,26 @@ build_common_builtin_nodes (void) "__builtin_nonlocal_goto", ECF_NORETURN | 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_setjmp_setup", ftype, + BUILT_IN_SETJMP_SETUP, + "__builtin_setjmp_setup", 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_setjmp_dispatcher", ftype, + BUILT_IN_SETJMP_DISPATCHER, + "__builtin_setjmp_dispatcher", + ECF_PURE | 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_setjmp_receiver", ftype, + BUILT_IN_SETJMP_RECEIVER, + "__builtin_setjmp_receiver", 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); @@ -6574,6 +7305,7 @@ build_vector_type (tree innertype, int nunits) return make_vector_type (innertype, nunits, VOIDmode); } + /* Build RESX_EXPR with given REGION_NUMBER. */ tree build_resx (int region_number) @@ -6632,16 +7364,6 @@ initializer_zerop (tree init) } } -void -add_var_to_bind_expr (tree bind_expr, tree var) -{ - BIND_EXPR_VARS (bind_expr) - = chainon (BIND_EXPR_VARS (bind_expr), var); - if (BIND_EXPR_BLOCK (bind_expr)) - BLOCK_VARS (BIND_EXPR_BLOCK (bind_expr)) - = BIND_EXPR_VARS (bind_expr); -} - /* Build an empty statement. */ tree @@ -6651,6 +7373,174 @@ build_empty_stmt (void) } +/* Build an OpenMP clause with code CODE. */ + +tree +build_omp_clause (enum omp_clause_code code) +{ + tree t; + int size, length; + + length = omp_clause_num_ops[code]; + size = (sizeof (struct tree_omp_clause) + (length - 1) * sizeof (tree)); + + t = ggc_alloc (size); + memset (t, 0, size); + TREE_SET_CODE (t, OMP_CLAUSE); + OMP_CLAUSE_SET_CODE (t, code); + +#ifdef GATHER_STATISTICS + tree_node_counts[(int) omp_clause_kind]++; + tree_node_sizes[(int) omp_clause_kind] += size; +#endif + + return t; +} + +/* Set various status flags when building a CALL_EXPR object T. */ + +static void +process_call_operands (tree t) +{ + bool side_effects; + + side_effects = TREE_SIDE_EFFECTS (t); + if (!side_effects) + { + int i, n; + n = TREE_OPERAND_LENGTH (t); + for (i = 1; i < n; i++) + { + tree op = TREE_OPERAND (t, i); + if (op && TREE_SIDE_EFFECTS (op)) + { + side_effects = 1; + break; + } + } + } + if (!side_effects) + { + int i; + + /* Calls have side-effects, except those to const or + pure functions. */ + i = call_expr_flags (t); + if (!(i & (ECF_CONST | ECF_PURE))) + side_effects = 1; + } + TREE_SIDE_EFFECTS (t) = side_effects; +} + +/* Build a tcc_vl_exp object with code CODE and room for LEN operands. LEN + includes the implicit operand count in TREE_OPERAND 0, and so must be >= 1. + Except for the CODE and operand count field, other storage for the + object is initialized to zeros. */ + +tree +build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL) +{ + tree t; + int length = (len - 1) * sizeof (tree) + sizeof (struct tree_exp); + + gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp); + gcc_assert (len >= 1); + +#ifdef GATHER_STATISTICS + tree_node_counts[(int) e_kind]++; + tree_node_sizes[(int) e_kind] += length; +#endif + + t = ggc_alloc_zone_pass_stat (length, &tree_zone); + + memset (t, 0, length); + + TREE_SET_CODE (t, code); + + /* Can't use TREE_OPERAND to store the length because if checking is + enabled, it will try to check the length before we store it. :-P */ + t->exp.operands[0] = build_int_cst (sizetype, len); + + return t; +} + + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE + and FN and a null static chain slot. ARGLIST is a TREE_LIST of the + arguments. */ + +tree +build_call_list (tree return_type, tree fn, tree arglist) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++) + CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist); + process_call_operands (t); + return t; +} + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and + FN and a null static chain slot. NARGS is the number of call arguments + which are specified as "..." arguments. */ + +tree +build_call_nary (tree return_type, tree fn, int nargs, ...) +{ + tree ret; + va_list args; + va_start (args, nargs); + ret = build_call_valist (return_type, fn, nargs, args); + va_end (args); + return ret; +} + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and + FN and a null static chain slot. NARGS is the number of call arguments + which are specified as a va_list ARGS. */ + +tree +build_call_valist (tree return_type, tree fn, int nargs, va_list args) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, nargs + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; i < nargs; i++) + CALL_EXPR_ARG (t, i) = va_arg (args, tree); + process_call_operands (t); + return t; +} + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and + FN and a null static chain slot. NARGS is the number of call arguments + which are specified as a tree array ARGS. */ + +tree +build_call_array (tree return_type, tree fn, int nargs, tree *args) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, nargs + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; i < nargs; i++) + CALL_EXPR_ARG (t, i) = args[i]; + process_call_operands (t); + return t; +} + + /* Returns true if it is possible to prove that the index of an array access REF (an ARRAY_REF expression) falls into the array bounds. */ @@ -6679,12 +7569,48 @@ in_array_bounds_p (tree ref) return true; } +/* Returns true if it is possible to prove that the range of + an array access REF (an ARRAY_RANGE_REF expression) falls + into the array bounds. */ + +bool +range_in_array_bounds_p (tree ref) +{ + tree domain_type = TYPE_DOMAIN (TREE_TYPE (ref)); + tree range_min, range_max, min, max; + + range_min = TYPE_MIN_VALUE (domain_type); + range_max = TYPE_MAX_VALUE (domain_type); + if (!range_min + || !range_max + || TREE_CODE (range_min) != INTEGER_CST + || TREE_CODE (range_max) != INTEGER_CST) + return false; + + min = array_ref_low_bound (ref); + max = array_ref_up_bound (ref); + if (!min + || !max + || TREE_CODE (min) != INTEGER_CST + || TREE_CODE (max) != INTEGER_CST) + return false; + + if (tree_int_cst_lt (range_min, min) + || tree_int_cst_lt (max, range_max)) + return false; + + 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)); + if (MTAG_P (t)) + return (TREE_STATIC (t) || MTAG_GLOBAL (t)); + else + return (TREE_STATIC (t) || DECL_EXTERNAL (t)); } /* Return true if T (assumed to be a DECL) must be assigned a memory @@ -6693,6 +7619,9 @@ is_global_var (tree t) bool needs_to_live_in_memory (tree t) { + if (TREE_CODE (t) == SSA_NAME) + t = SSA_NAME_VAR (t); + return (TREE_ADDRESSABLE (t) || is_global_var (t) || (TREE_CODE (t) == RESULT_DECL @@ -6762,50 +7691,14 @@ int_cst_value (tree x) return val; } -/* Returns the greatest common divisor of A and B, which must be - INTEGER_CSTs. */ - -tree -tree_fold_gcd (tree a, tree b) -{ - tree a_mod_b; - tree type = TREE_TYPE (a); - - gcc_assert (TREE_CODE (a) == INTEGER_CST); - gcc_assert (TREE_CODE (b) == INTEGER_CST); - - if (integer_zerop (a)) - return b; - - if (integer_zerop (b)) - return a; - - if (tree_int_cst_sgn (a) == -1) - a = fold_build2 (MULT_EXPR, type, a, - convert (type, integer_minus_one_node)); - - if (tree_int_cst_sgn (b) == -1) - b = fold_build2 (MULT_EXPR, type, b, - convert (type, integer_minus_one_node)); - - while (1) - { - 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)) - return b; - - a = b; - b = a_mod_b; - } -} /* Returns unsigned variant of TYPE. */ tree unsigned_type_for (tree type) { + if (POINTER_TYPE_P (type)) + return lang_hooks.types.unsigned_type (size_type_node); return lang_hooks.types.unsigned_type (type); } @@ -6814,6 +7707,8 @@ unsigned_type_for (tree type) tree signed_type_for (tree type) { + if (POINTER_TYPE_P (type)) + return lang_hooks.types.signed_type (size_type_node); return lang_hooks.types.signed_type (type); } @@ -7055,15 +7950,6 @@ walk_type_fields (tree type, walk_tree_fn func, void *data, WALK_SUBTREE (TYPE_DOMAIN (type)); break; - case BOOLEAN_TYPE: - case ENUMERAL_TYPE: - case INTEGER_TYPE: - case CHAR_TYPE: - case REAL_TYPE: - WALK_SUBTREE (TYPE_MIN_VALUE (type)); - WALK_SUBTREE (TYPE_MAX_VALUE (type)); - break; - case OFFSET_TYPE: WALK_SUBTREE (TREE_TYPE (type)); WALK_SUBTREE (TYPE_OFFSET_BASETYPE (type)); @@ -7121,202 +8007,237 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) interesting below this point in the tree. */ if (!walk_subtrees) { + /* But we still need to check our siblings. */ if (code == TREE_LIST) - /* But we still need to check our siblings. */ WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); + else if (code == OMP_CLAUSE) + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); else return NULL_TREE; } result = lang_hooks.tree_inlining.walk_subtrees (tp, &walk_subtrees, func, data, pset); - if (result || ! walk_subtrees) + if (result || !walk_subtrees) return result; - /* If this is a DECL_EXPR, walk into various fields of the type that it's - defining. We only want to walk into these fields of a type in this - case. Note that decls get walked as part of the processing of a - BIND_EXPR. - - ??? Precisely which fields of types that we are supposed to walk in - this case vs. the normal case aren't well defined. */ - if (code == DECL_EXPR - && TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL - && TREE_CODE (TREE_TYPE (DECL_EXPR_DECL (*tp))) != ERROR_MARK) + switch (code) { - tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); + case ERROR_MARK: + case IDENTIFIER_NODE: + case INTEGER_CST: + case REAL_CST: + case VECTOR_CST: + case STRING_CST: + case BLOCK: + case PLACEHOLDER_EXPR: + case SSA_NAME: + case FIELD_DECL: + case RESULT_DECL: + /* None of these have subtrees other than those already walked + above. */ + break; - /* Call the function for the type. See if it returns anything or - doesn't want us to continue. If we are to continue, walk both - the normal fields and those for the declaration case. */ - result = (*func) (type_p, &walk_subtrees, data); - if (result || !walk_subtrees) - return NULL_TREE; + case TREE_LIST: + WALK_SUBTREE (TREE_VALUE (*tp)); + WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); + break; - result = walk_type_fields (*type_p, func, data, pset); - if (result) - return result; + case TREE_VEC: + { + int len = TREE_VEC_LENGTH (*tp); - WALK_SUBTREE (TYPE_SIZE (*type_p)); - WALK_SUBTREE (TYPE_SIZE_UNIT (*type_p)); + if (len == 0) + break; - /* If this is a record type, also walk the fields. */ - if (TREE_CODE (*type_p) == RECORD_TYPE - || TREE_CODE (*type_p) == UNION_TYPE - || TREE_CODE (*type_p) == QUAL_UNION_TYPE) - { - tree field; + /* Walk all elements but the first. */ + while (--len) + WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); - for (field = TYPE_FIELDS (*type_p); field; - field = TREE_CHAIN (field)) - { - /* We'd like to look at the type of the field, but we can easily - get infinite recursion. So assume it's pointed to elsewhere - in the tree. Also, ignore things that aren't fields. */ - if (TREE_CODE (field) != FIELD_DECL) - continue; - - WALK_SUBTREE (DECL_FIELD_OFFSET (field)); - WALK_SUBTREE (DECL_SIZE (field)); - WALK_SUBTREE (DECL_SIZE_UNIT (field)); - if (TREE_CODE (*type_p) == QUAL_UNION_TYPE) - WALK_SUBTREE (DECL_QUALIFIER (field)); - } - } - } + /* Now walk the first one as a tail call. */ + WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); + } - else if (code != SAVE_EXPR - && code != BIND_EXPR - && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))) - { - int i, len; + case COMPLEX_CST: + WALK_SUBTREE (TREE_REALPART (*tp)); + WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); - /* Walk over all the sub-trees of this operand. */ - len = TREE_CODE_LENGTH (code); - /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. - But, we only want to walk once. */ - if (code == TARGET_EXPR - && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) - --len; + case CONSTRUCTOR: + { + unsigned HOST_WIDE_INT idx; + constructor_elt *ce; - /* Go through the subtrees. We need to do this in forward order so - that the scope of a FOR_EXPR is handled properly. */ -#ifdef DEBUG_WALK_TREE - for (i = 0; i < len; ++i) - WALK_SUBTREE (TREE_OPERAND (*tp, i)); -#else - for (i = 0; i < len - 1; ++i) - WALK_SUBTREE (TREE_OPERAND (*tp, i)); + for (idx = 0; + VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (*tp), idx, ce); + idx++) + WALK_SUBTREE (ce->value); + } + break; - if (len) - { - /* The common case is that we may tail recurse here. */ - if (code != BIND_EXPR - && !TREE_CHAIN (*tp)) - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1)); - else - WALK_SUBTREE (TREE_OPERAND (*tp, len - 1)); - } -#endif - } + case SAVE_EXPR: + WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); - /* If this is a type, walk the needed fields in the type. */ - else if (TYPE_P (*tp)) - { - result = walk_type_fields (*tp, func, data, pset); - if (result) - return result; - } - else - { - /* Not one of the easy cases. We must explicitly go through the - children. */ - switch (code) - { - case ERROR_MARK: - case IDENTIFIER_NODE: - case INTEGER_CST: - case REAL_CST: - case VECTOR_CST: - case STRING_CST: - case BLOCK: - case PLACEHOLDER_EXPR: - case SSA_NAME: - case FIELD_DECL: - case RESULT_DECL: - /* None of these have subtrees other than those already walked - above. */ - break; + case BIND_EXPR: + { + tree decl; + for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl)) + { + /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk + into declarations that are just mentioned, rather than + declared; they don't really belong to this part of the tree. + And, we can see cycles: the initializer for a declaration + can refer to the declaration itself. */ + WALK_SUBTREE (DECL_INITIAL (decl)); + WALK_SUBTREE (DECL_SIZE (decl)); + WALK_SUBTREE (DECL_SIZE_UNIT (decl)); + } + WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp)); + } - case TREE_LIST: - WALK_SUBTREE (TREE_VALUE (*tp)); - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); - break; + case STATEMENT_LIST: + { + tree_stmt_iterator i; + for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i)) + WALK_SUBTREE (*tsi_stmt_ptr (i)); + } + break; - case TREE_VEC: + case OMP_CLAUSE: + switch (OMP_CLAUSE_CODE (*tp)) + { + case OMP_CLAUSE_PRIVATE: + case OMP_CLAUSE_SHARED: + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_LASTPRIVATE: + case OMP_CLAUSE_COPYIN: + case OMP_CLAUSE_COPYPRIVATE: + case OMP_CLAUSE_IF: + case OMP_CLAUSE_NUM_THREADS: + case OMP_CLAUSE_SCHEDULE: + WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0)); + /* FALLTHRU */ + + case OMP_CLAUSE_NOWAIT: + case OMP_CLAUSE_ORDERED: + case OMP_CLAUSE_DEFAULT: + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + + case OMP_CLAUSE_REDUCTION: { - int len = TREE_VEC_LENGTH (*tp); + int i; + for (i = 0; i < 4; i++) + WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + } - if (len == 0) - break; + default: + gcc_unreachable (); + } + break; - /* Walk all elements but the first. */ - while (--len) - WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); + case TARGET_EXPR: + { + int i, len; + + /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. + But, we only want to walk once. */ + len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3; + for (i = 0; i < len; ++i) + WALK_SUBTREE (TREE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len)); + } - /* Now walk the first one as a tail call. */ - WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); - } + case DECL_EXPR: + /* If this is a TYPE_DECL, walk into the fields of the type that it's + defining. We only want to walk into these fields of a type in this + case and not in the general case of a mere reference to the type. - case COMPLEX_CST: - WALK_SUBTREE (TREE_REALPART (*tp)); - WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); + The criterion is as follows: if the field can be an expression, it + must be walked only here. This should be in keeping with the fields + that are directly gimplified in gimplify_type_sizes in order for the + mark/copy-if-shared/unmark machinery of the gimplifier to work with + variable-sized types. + + Note that DECLs get walked as part of processing the BIND_EXPR. */ + if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL) + { + tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); + if (TREE_CODE (*type_p) == ERROR_MARK) + return NULL_TREE; + + /* Call the function for the type. See if it returns anything or + doesn't want us to continue. If we are to continue, walk both + the normal fields and those for the declaration case. */ + result = (*func) (type_p, &walk_subtrees, data); + if (result || !walk_subtrees) + return result; - case CONSTRUCTOR: - { - unsigned HOST_WIDE_INT idx; - constructor_elt *ce; + result = walk_type_fields (*type_p, func, data, pset); + if (result) + return result; - for (idx = 0; - VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (*tp), idx, ce); - idx++) - WALK_SUBTREE (ce->value); - } - break; + /* If this is a record type, also walk the fields. */ + if (TREE_CODE (*type_p) == RECORD_TYPE + || TREE_CODE (*type_p) == UNION_TYPE + || TREE_CODE (*type_p) == QUAL_UNION_TYPE) + { + tree field; - case SAVE_EXPR: - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); + for (field = TYPE_FIELDS (*type_p); field; + field = TREE_CHAIN (field)) + { + /* We'd like to look at the type of the field, but we can + easily get infinite recursion. So assume it's pointed + to elsewhere in the tree. Also, ignore things that + aren't fields. */ + if (TREE_CODE (field) != FIELD_DECL) + continue; + + WALK_SUBTREE (DECL_FIELD_OFFSET (field)); + WALK_SUBTREE (DECL_SIZE (field)); + WALK_SUBTREE (DECL_SIZE_UNIT (field)); + if (TREE_CODE (*type_p) == QUAL_UNION_TYPE) + WALK_SUBTREE (DECL_QUALIFIER (field)); + } + } - case BIND_EXPR: - { - tree decl; - for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl)) - { - /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk - into declarations that are just mentioned, rather than - declared; they don't really belong to this part of the tree. - And, we can see cycles: the initializer for a declaration - can refer to the declaration itself. */ - WALK_SUBTREE (DECL_INITIAL (decl)); - WALK_SUBTREE (DECL_SIZE (decl)); - WALK_SUBTREE (DECL_SIZE_UNIT (decl)); - } - WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp)); - } + /* Same for scalar types. */ + else if (TREE_CODE (*type_p) == BOOLEAN_TYPE + || TREE_CODE (*type_p) == ENUMERAL_TYPE + || TREE_CODE (*type_p) == INTEGER_TYPE + || TREE_CODE (*type_p) == REAL_TYPE) + { + WALK_SUBTREE (TYPE_MIN_VALUE (*type_p)); + WALK_SUBTREE (TYPE_MAX_VALUE (*type_p)); + } - case STATEMENT_LIST: - { - tree_stmt_iterator i; - for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i)) - WALK_SUBTREE (*tsi_stmt_ptr (i)); - } - break; + WALK_SUBTREE (TYPE_SIZE (*type_p)); + WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p)); + } + /* FALLTHRU */ - default: - /* ??? This could be a language-defined node. We really should make - a hook for it, but right now just ignore it. */ - break; + default: + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) + || IS_GIMPLE_STMT_CODE_CLASS (TREE_CODE_CLASS (code))) + { + int i, len; + + /* Walk over all the sub-trees of this operand. */ + len = TREE_OPERAND_LENGTH (*tp); + + /* Go through the subtrees. We need to do this in forward order so + that the scope of a FOR_EXPR is handled properly. */ + if (len) + { + for (i = 0; i < len - 1; ++i) + WALK_SUBTREE (GENERIC_TREE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (GENERIC_TREE_OPERAND (*tp, len - 1)); + } } + /* If this is a type, walk the needed fields in the type. */ + else if (TYPE_P (*tp)) + return walk_type_fields (*tp, func, data, pset); + break; } /* We didn't find what we were looking for. */ @@ -7340,4 +8261,74 @@ walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data) return result; } + +/* Return true if STMT is an empty statement or contains nothing but + empty statements. */ + +bool +empty_body_p (tree stmt) +{ + tree_stmt_iterator i; + tree body; + + if (IS_EMPTY_STMT (stmt)) + return true; + else if (TREE_CODE (stmt) == BIND_EXPR) + body = BIND_EXPR_BODY (stmt); + else if (TREE_CODE (stmt) == STATEMENT_LIST) + body = stmt; + else + return false; + + for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i)) + if (!empty_body_p (tsi_stmt (i))) + return false; + + return true; +} + +tree * +tree_block (tree t) +{ + char const c = TREE_CODE_CLASS (TREE_CODE (t)); + + if (IS_EXPR_CODE_CLASS (c)) + return &t->exp.block; + else if (IS_GIMPLE_STMT_CODE_CLASS (c)) + return &GIMPLE_STMT_BLOCK (t); + gcc_unreachable (); + return NULL; +} + +tree * +generic_tree_operand (tree node, int i) +{ + if (GIMPLE_STMT_P (node)) + return &GIMPLE_STMT_OPERAND (node, i); + return &TREE_OPERAND (node, i); +} + +tree * +generic_tree_type (tree node) +{ + if (GIMPLE_STMT_P (node)) + return &void_type_node; + return &TREE_TYPE (node); +} + +/* Build and return a TREE_LIST of arguments in the CALL_EXPR exp. + FIXME: don't use this function. It exists for compatibility with + the old representation of CALL_EXPRs where a list was used to hold the + arguments. Places that currently extract the arglist from a CALL_EXPR + ought to be rewritten to use the CALL_EXPR itself. */ +tree +call_expr_arglist (tree exp) +{ + tree arglist = NULL_TREE; + int i; + for (i = call_expr_nargs (exp) - 1; i >= 0; i--) + arglist = tree_cons (NULL_TREE, CALL_EXPR_ARG (exp, i), arglist); + return arglist; +} + #include "gt-tree.h"