X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Ftree.c;h=c45e807b43d96dd46932a43540a1a65d3c8d8bf1;hp=bcb8a0c1130dcd4de102053905c93c4529d04867;hb=d62a642a79aa9558d852f37bb0d922734ad707e2;hpb=fb1e4f4abf01d3559f37568d2624b734410d3b3e diff --git a/gcc/tree.c b/gcc/tree.c index bcb8a0c1130..c45e807b43d 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1,6 +1,6 @@ /* Language-independent node constructors for parse phase of GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -45,12 +45,21 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "target.h" #include "langhooks.h" +#include "tree-inline.h" #include "tree-iterator.h" #include "basic-block.h" #include "tree-flow.h" #include "params.h" #include "pointer-set.h" #include "fixed-value.h" +#include "tree-pass.h" +#include "langhooks-def.h" +#include "diagnostic.h" +#include "cgraph.h" +#include "timevar.h" +#include "except.h" +#include "debug.h" +#include "intl.h" /* Tree code classes. */ @@ -144,6 +153,9 @@ static const char * const tree_node_kind_names[] = { static GTY(()) int next_decl_uid; /* Unique id for next type created. */ static GTY(()) int next_type_uid = 1; +/* Unique id for next debug decl created. Use negative numbers, + to catch erroneous uses. */ +static GTY(()) int next_debug_decl_uid; /* Since we cannot rehash a type after it is in the table, we have to keep the hash code. */ @@ -184,19 +196,16 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) /* General tree->tree mapping structure for use in hash tables. */ -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 debug_expr_for_decl; -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_priority_map_marked_p"), +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; - static void set_type_quals (tree, int); static int type_hash_eq (const void *, const void *); static hashval_t type_hash_hash (const void *); @@ -256,7 +265,265 @@ const char * const omp_clause_code_name[] = "collapse", "untied" }; - + + +/* Return the tree node structure used by tree code CODE. */ + +static inline enum tree_node_structure_enum +tree_node_structure_for_code (enum tree_code code) +{ + switch (TREE_CODE_CLASS (code)) + { + case tcc_declaration: + { + switch (code) + { + case FIELD_DECL: + return TS_FIELD_DECL; + case PARM_DECL: + return TS_PARM_DECL; + case VAR_DECL: + return TS_VAR_DECL; + case LABEL_DECL: + return TS_LABEL_DECL; + case RESULT_DECL: + return TS_RESULT_DECL; + case DEBUG_EXPR_DECL: + return TS_DECL_WRTL; + case CONST_DECL: + return TS_CONST_DECL; + case TYPE_DECL: + return TS_TYPE_DECL; + case FUNCTION_DECL: + return TS_FUNCTION_DECL; + default: + return TS_DECL_NON_COMMON; + } + } + case tcc_type: + return TS_TYPE; + case tcc_reference: + case tcc_comparison: + case tcc_unary: + case tcc_binary: + case tcc_expression: + case tcc_statement: + case tcc_vl_exp: + return TS_EXP; + default: /* tcc_constant and tcc_exceptional */ + break; + } + switch (code) + { + /* tcc_constant cases. */ + case INTEGER_CST: return TS_INT_CST; + case REAL_CST: return TS_REAL_CST; + case FIXED_CST: return TS_FIXED_CST; + case COMPLEX_CST: return TS_COMPLEX; + case VECTOR_CST: return TS_VECTOR; + case STRING_CST: return TS_STRING; + /* tcc_exceptional cases. */ + case ERROR_MARK: return TS_COMMON; + case IDENTIFIER_NODE: return TS_IDENTIFIER; + case TREE_LIST: return TS_LIST; + case TREE_VEC: return TS_VEC; + case SSA_NAME: return TS_SSA_NAME; + case PLACEHOLDER_EXPR: return TS_COMMON; + case STATEMENT_LIST: return TS_STATEMENT_LIST; + case BLOCK: return TS_BLOCK; + case CONSTRUCTOR: return TS_CONSTRUCTOR; + case TREE_BINFO: return TS_BINFO; + case OMP_CLAUSE: return TS_OMP_CLAUSE; + case OPTIMIZATION_NODE: return TS_OPTIMIZATION; + case TARGET_OPTION_NODE: return TS_TARGET_OPTION; + + default: + gcc_unreachable (); + } +} + + +/* Initialize tree_contains_struct to describe the hierarchy of tree + nodes. */ + +static void +initialize_tree_contains_struct (void) +{ + unsigned i; + +#define MARK_TS_BASE(C) \ + do { \ + tree_contains_struct[C][TS_BASE] = 1; \ + } while (0) + +#define MARK_TS_COMMON(C) \ + do { \ + MARK_TS_BASE (C); \ + tree_contains_struct[C][TS_COMMON] = 1; \ + } while (0) + +#define MARK_TS_DECL_MINIMAL(C) \ + do { \ + MARK_TS_COMMON (C); \ + tree_contains_struct[C][TS_DECL_MINIMAL] = 1; \ + } while (0) + +#define MARK_TS_DECL_COMMON(C) \ + do { \ + MARK_TS_DECL_MINIMAL (C); \ + tree_contains_struct[C][TS_DECL_COMMON] = 1; \ + } while (0) + +#define MARK_TS_DECL_WRTL(C) \ + do { \ + MARK_TS_DECL_COMMON (C); \ + tree_contains_struct[C][TS_DECL_WRTL] = 1; \ + } while (0) + +#define MARK_TS_DECL_WITH_VIS(C) \ + do { \ + MARK_TS_DECL_WRTL (C); \ + tree_contains_struct[C][TS_DECL_WITH_VIS] = 1; \ + } while (0) + +#define MARK_TS_DECL_NON_COMMON(C) \ + do { \ + MARK_TS_DECL_WITH_VIS (C); \ + tree_contains_struct[C][TS_DECL_NON_COMMON] = 1; \ + } while (0) + + for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++) + { + enum tree_code code; + enum tree_node_structure_enum ts_code; + + code = (enum tree_code) i; + ts_code = tree_node_structure_for_code (code); + + /* Mark the TS structure itself. */ + tree_contains_struct[code][ts_code] = 1; + + /* Mark all the structures that TS is derived from. */ + switch (ts_code) + { + case TS_COMMON: + MARK_TS_BASE (code); + break; + + case TS_INT_CST: + case TS_REAL_CST: + case TS_FIXED_CST: + case TS_VECTOR: + case TS_STRING: + case TS_COMPLEX: + case TS_IDENTIFIER: + case TS_DECL_MINIMAL: + case TS_TYPE: + case TS_LIST: + case TS_VEC: + case TS_EXP: + case TS_SSA_NAME: + case TS_BLOCK: + case TS_BINFO: + case TS_STATEMENT_LIST: + case TS_CONSTRUCTOR: + case TS_OMP_CLAUSE: + case TS_OPTIMIZATION: + case TS_TARGET_OPTION: + MARK_TS_COMMON (code); + break; + + case TS_DECL_COMMON: + MARK_TS_DECL_MINIMAL (code); + break; + + case TS_DECL_WRTL: + MARK_TS_DECL_COMMON (code); + break; + + case TS_DECL_NON_COMMON: + MARK_TS_DECL_WITH_VIS (code); + break; + + case TS_DECL_WITH_VIS: + case TS_PARM_DECL: + case TS_LABEL_DECL: + case TS_RESULT_DECL: + case TS_CONST_DECL: + MARK_TS_DECL_WRTL (code); + break; + + case TS_FIELD_DECL: + MARK_TS_DECL_COMMON (code); + break; + + case TS_VAR_DECL: + MARK_TS_DECL_WITH_VIS (code); + break; + + case TS_TYPE_DECL: + case TS_FUNCTION_DECL: + MARK_TS_DECL_NON_COMMON (code); + break; + + default: + gcc_unreachable (); + } + } + + /* Basic consistency checks for attributes used in fold. */ + gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON]); + gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON]); + gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON]); + gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_WRTL]); + gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WRTL]); + gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_WRTL]); + gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_WRTL]); + gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL]); + gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_WRTL]); + gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS]); + gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS]); + gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS]); + gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_WITH_VIS]); + gcc_assert (tree_contains_struct[VAR_DECL][TS_VAR_DECL]); + gcc_assert (tree_contains_struct[FIELD_DECL][TS_FIELD_DECL]); + gcc_assert (tree_contains_struct[PARM_DECL][TS_PARM_DECL]); + gcc_assert (tree_contains_struct[LABEL_DECL][TS_LABEL_DECL]); + gcc_assert (tree_contains_struct[RESULT_DECL][TS_RESULT_DECL]); + gcc_assert (tree_contains_struct[CONST_DECL][TS_CONST_DECL]); + gcc_assert (tree_contains_struct[TYPE_DECL][TS_TYPE_DECL]); + gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]); + gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]); + +#undef MARK_TS_BASE +#undef MARK_TS_COMMON +#undef MARK_TS_DECL_MINIMAL +#undef MARK_TS_DECL_COMMON +#undef MARK_TS_DECL_WRTL +#undef MARK_TS_DECL_WITH_VIS +#undef MARK_TS_DECL_NON_COMMON +} + + /* Init tree.c. */ void @@ -273,12 +540,10 @@ init_ttree (void) tree_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); int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash, int_cst_hash_eq, NULL); - + int_cst_node = make_node (INTEGER_CST); cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash, @@ -287,55 +552,8 @@ init_ttree (void) cl_optimization_node = make_node (OPTIMIZATION_NODE); cl_target_option_node = make_node (TARGET_OPTION_NODE); - tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON] = 1; - tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON] = 1; - tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON] = 1; - - - tree_contains_struct[CONST_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[VAR_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[PARM_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[RESULT_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[TYPE_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[LABEL_DECL][TS_DECL_COMMON] = 1; - tree_contains_struct[FIELD_DECL][TS_DECL_COMMON] = 1; - - - tree_contains_struct[CONST_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[VAR_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[PARM_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[RESULT_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL] = 1; - tree_contains_struct[LABEL_DECL][TS_DECL_WRTL] = 1; - - tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL] = 1; - 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[VAR_DECL][TS_DECL_WITH_VIS] = 1; - tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1; - tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS] = 1; - tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_WITH_VIS] = 1; - - tree_contains_struct[VAR_DECL][TS_VAR_DECL] = 1; - tree_contains_struct[FIELD_DECL][TS_FIELD_DECL] = 1; - tree_contains_struct[PARM_DECL][TS_PARM_DECL] = 1; - tree_contains_struct[LABEL_DECL][TS_LABEL_DECL] = 1; - tree_contains_struct[RESULT_DECL][TS_RESULT_DECL] = 1; - tree_contains_struct[CONST_DECL][TS_CONST_DECL] = 1; - tree_contains_struct[TYPE_DECL][TS_TYPE_DECL] = 1; - tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL] = 1; - tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON] = 1; - + /* Initialize the tree_contains_struct array. */ + initialize_tree_contains_struct (); lang_hooks.init_ts (); } @@ -366,7 +584,7 @@ decl_assembler_name_equal (tree decl, const_tree asmname) decl_str = IDENTIFIER_POINTER (decl_asmname); asmname_str = IDENTIFIER_POINTER (asmname); - + /* 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 @@ -455,6 +673,8 @@ tree_code_size (enum tree_code code) return sizeof (struct tree_type_decl); case FUNCTION_DECL: return sizeof (struct tree_function_decl); + case DEBUG_EXPR_DECL: + return sizeof (struct tree_decl_with_rtl); default: return sizeof (struct tree_decl_non_common); } @@ -624,7 +844,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) break; } break; - + default: gcc_unreachable (); } @@ -658,11 +878,17 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) } else DECL_ALIGN (t) = 1; - /* 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++; + if (TREE_CODE (t) == DEBUG_EXPR_DECL) + DECL_UID (t) = --next_debug_decl_uid; + else + { + DECL_UID (t) = next_decl_uid++; + SET_DECL_PT_UID (t, -1); + } + if (TREE_CODE (t) == LABEL_DECL) + LABEL_DECL_UID (t) = -1; break; @@ -732,11 +958,19 @@ copy_node_stat (tree node MEM_STAT_DECL) TREE_CHAIN (t) = 0; TREE_ASM_WRITTEN (t) = 0; TREE_VISITED (t) = 0; - t->base.ann = 0; + if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL) + *DECL_VAR_ANN_PTR (t) = 0; if (TREE_CODE_CLASS (code) == tcc_declaration) { - DECL_UID (t) = next_decl_uid++; + if (code == DEBUG_EXPR_DECL) + DECL_UID (t) = --next_debug_decl_uid; + else + { + DECL_UID (t) = next_decl_uid++; + if (DECL_PT_UID_SET_P (node)) + SET_DECL_PT_UID (t, DECL_PT_UID (node)); + } if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL) && DECL_HAS_VALUE_EXPR_P (node)) { @@ -748,11 +982,6 @@ copy_node_stat (tree node MEM_STAT_DECL) SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node)); DECL_HAS_INIT_PRIORITY_P (t) = 1; } - if (TREE_CODE (node) == VAR_DECL && DECL_BASED_ON_RESTRICT_P (node)) - { - SET_DECL_RESTRICT_BASE (t, DECL_GET_RESTRICT_BASE (node)); - DECL_BASED_ON_RESTRICT_P (t) = 1; - } } else if (TREE_CODE_CLASS (code) == tcc_type) { @@ -764,7 +993,7 @@ copy_node_stat (tree node MEM_STAT_DECL) but the optimizer should catch that. */ TYPE_SYMTAB_POINTER (t) = 0; TYPE_SYMTAB_ADDRESS (t) = 0; - + /* Do not copy the values cache. */ if (TYPE_CACHED_VALUES_P(t)) { @@ -853,6 +1082,30 @@ build_int_cst_wide_type (tree type, return build_int_cst_wide (type, low, high); } +/* Constructs tree in type TYPE from with value given by CST. Signedness + of CST is assumed to be the same as the signedness of TYPE. */ + +tree +double_int_to_tree (tree type, double_int cst) +{ + cst = double_int_ext (cst, TYPE_PRECISION (type), TYPE_UNSIGNED (type)); + + return build_int_cst_wide (type, cst.low, cst.high); +} + +/* Returns true if CST fits into range of TYPE. Signedness of CST is assumed + to be the same as the signedness of TYPE. */ + +bool +double_int_fits_to_tree_p (const_tree type, double_int cst) +{ + double_int ext = double_int_ext (cst, + TYPE_PRECISION (type), + TYPE_UNSIGNED (type)); + + return double_int_equal_p (cst, ext); +} + /* These are the hash table functions for the hash table of INTEGER_CST nodes of a sizetype. */ @@ -965,7 +1218,7 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) TREE_INT_CST_LOW (t) = low; TREE_INT_CST_HIGH (t) = hi; TREE_TYPE (t) = type; - + TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t; } } @@ -999,32 +1252,18 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) tree build_low_bits_mask (tree type, unsigned bits) { - unsigned HOST_WIDE_INT low; - HOST_WIDE_INT high; - unsigned HOST_WIDE_INT all_ones = ~(unsigned HOST_WIDE_INT) 0; + double_int mask; gcc_assert (bits <= TYPE_PRECISION (type)); if (bits == TYPE_PRECISION (type) && !TYPE_UNSIGNED (type)) - { - /* Sign extended all-ones mask. */ - low = all_ones; - high = -1; - } - else if (bits <= HOST_BITS_PER_WIDE_INT) - { - low = all_ones >> (HOST_BITS_PER_WIDE_INT - bits); - high = 0; - } + /* Sign extended all-ones mask. */ + mask = double_int_minus_one; else - { - bits -= HOST_BITS_PER_WIDE_INT; - low = all_ones; - high = all_ones >> (HOST_BITS_PER_WIDE_INT - bits); - } + mask = double_int_mask (bits); - return build_int_cst_wide (type, low, high); + return build_int_cst_wide (type, mask.low, mask.high); } /* Checks that X is integer constant that can be expressed in (unsigned) @@ -1234,7 +1473,7 @@ build_string (int len, const char *str) #ifdef GATHER_STATISTICS tree_node_counts[(int) c_kind]++; tree_node_sizes[(int) c_kind] += length; -#endif +#endif s = ggc_alloc_tree (length); @@ -1463,8 +1702,7 @@ integer_pow2p (const_tree expr) if (TREE_CODE (expr) != INTEGER_CST) return 0; - prec = (POINTER_TYPE_P (TREE_TYPE (expr)) - ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr))); + prec = TYPE_PRECISION (TREE_TYPE (expr)); high = TREE_INT_CST_HIGH (expr); low = TREE_INT_CST_LOW (expr); @@ -1528,9 +1766,7 @@ tree_log2 (const_tree expr) if (TREE_CODE (expr) == COMPLEX_CST) return tree_log2 (TREE_REALPART (expr)); - prec = (POINTER_TYPE_P (TREE_TYPE (expr)) - ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr))); - + prec = TYPE_PRECISION (TREE_TYPE (expr)); high = TREE_INT_CST_HIGH (expr); low = TREE_INT_CST_LOW (expr); @@ -1566,9 +1802,7 @@ tree_floor_log2 (const_tree expr) if (TREE_CODE (expr) == COMPLEX_CST) return tree_log2 (TREE_REALPART (expr)); - prec = (POINTER_TYPE_P (TREE_TYPE (expr)) - ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr))); - + prec = TYPE_PRECISION (TREE_TYPE (expr)); high = TREE_INT_CST_HIGH (expr); low = TREE_INT_CST_LOW (expr); @@ -1591,7 +1825,8 @@ tree_floor_log2 (const_tree expr) : floor_log2 (low)); } -/* Return 1 if EXPR is the real constant zero. */ +/* Return 1 if EXPR is the real constant zero. Trailing zeroes matter for + decimal float constants, so don't return 1 for them. */ int real_zerop (const_tree expr) @@ -1599,13 +1834,16 @@ real_zerop (const_tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)) + && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0) + && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))))) || (TREE_CODE (expr) == COMPLEX_CST && real_zerop (TREE_REALPART (expr)) && real_zerop (TREE_IMAGPART (expr)))); } -/* Return 1 if EXPR is the real constant one in real or complex form. */ +/* Return 1 if EXPR is the real constant one in real or complex form. + Trailing zeroes matter for decimal float constants, so don't return + 1 for them. */ int real_onep (const_tree expr) @@ -1613,13 +1851,15 @@ real_onep (const_tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)) + && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1) + && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))))) || (TREE_CODE (expr) == COMPLEX_CST && real_onep (TREE_REALPART (expr)) && real_zerop (TREE_IMAGPART (expr)))); } -/* Return 1 if EXPR is the real constant two. */ +/* Return 1 if EXPR is the real constant two. Trailing zeroes matter + for decimal float constants, so don't return 1 for them. */ int real_twop (const_tree expr) @@ -1627,13 +1867,15 @@ real_twop (const_tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)) + && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2) + && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))))) || (TREE_CODE (expr) == COMPLEX_CST && real_twop (TREE_REALPART (expr)) && real_zerop (TREE_IMAGPART (expr)))); } -/* Return 1 if EXPR is the real constant minus one. */ +/* Return 1 if EXPR is the real constant minus one. Trailing zeroes + matter for decimal float constants, so don't return 1 for them. */ int real_minus_onep (const_tree expr) @@ -1641,7 +1883,8 @@ real_minus_onep (const_tree expr) STRIP_NOPS (expr); return ((TREE_CODE (expr) == REAL_CST - && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)) + && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1) + && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))))) || (TREE_CODE (expr) == COMPLEX_CST && real_minus_onep (TREE_REALPART (expr)) && real_zerop (TREE_IMAGPART (expr)))); @@ -1689,6 +1932,17 @@ purpose_member (const_tree elem, tree list) return NULL_TREE; } +/* Returns element number IDX (zero-origin) of chain CHAIN, or + NULL_TREE. */ + +tree +chain_index (int idx, tree chain) +{ + for (; chain && idx > 0; --idx) + chain = TREE_CHAIN (chain); + return chain; +} + /* Return nonzero if ELEM is part of the chain CHAIN. */ int @@ -1746,6 +2000,18 @@ fields_length (const_tree type) return count; } +/* Returns the first FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or + UNION_TYPE TYPE, or NULL_TREE if none. */ + +tree +first_field (const_tree type) +{ + tree t = TYPE_FIELDS (type); + while (t && TREE_CODE (t) != FIELD_DECL) + t = TREE_CHAIN (t); + return t; +} + /* Concatenate two chains of nodes (chained through TREE_CHAIN) by modifying the last node in chain 1 to point to chain 2. This is the Lisp primitive `nconc'. */ @@ -1787,18 +2053,6 @@ tree_last (tree chain) return chain; } -/* Return the node in a chain of nodes whose value is x, NULL if not found. */ - -tree -tree_find_value (tree chain, tree x) -{ - tree list; - for (list = chain; list; list = TREE_CHAIN (list)) - if (TREE_VALUE (list) == x) - return list; - return NULL; -} - /* Reverse the order of elements in the chain T, and return the new head of the chain (old last element). */ @@ -1827,6 +2081,23 @@ build_tree_list_stat (tree parm, tree value MEM_STAT_DECL) return t; } +/* Build a chain of TREE_LIST nodes from a vector. */ + +tree +build_tree_list_vec_stat (const VEC(tree,gc) *vec MEM_STAT_DECL) +{ + tree ret = NULL_TREE; + tree *pp = &ret; + unsigned int i; + tree t; + for (i = 0; VEC_iterate (tree, vec, i, t); ++i) + { + *pp = build_tree_list_stat (NULL, t PASS_MEM_STAT); + pp = &TREE_CHAIN (*pp); + } + return ret; +} + /* Return a newly created TREE_LIST node whose purpose and value fields are PURPOSE and VALUE and whose TREE_CHAIN is CHAIN. */ @@ -1870,6 +2141,22 @@ ctor_to_list (tree ctor) return list; } + +/* Return the values of the elements of a CONSTRUCTOR as a vector of + trees. */ + +VEC(tree,gc) * +ctor_to_vec (tree ctor) +{ + VEC(tree, gc) *vec = VEC_alloc (tree, gc, CONSTRUCTOR_NELTS (ctor)); + unsigned int ix; + tree val; + + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), ix, val) + VEC_quick_push (tree, vec, val); + + return vec; +} /* Return the size nominally occupied by an object of type TYPE when it resides in memory. The value is measured in units of bytes, @@ -1952,6 +2239,18 @@ max_int_size_in_bytes (const_tree type) return size; } + +/* Returns a tree for the size of EXP in bytes. */ + +tree +tree_expr_size (const_tree exp) +{ + if (DECL_P (exp) + && DECL_SIZE_UNIT (exp) != 0) + return DECL_SIZE_UNIT (exp); + else + return size_in_bytes (TREE_TYPE (exp)); +} /* Return the bit position of FIELD, in bits from the start of the record. This is a tree of type bitsizetype. */ @@ -2319,6 +2618,7 @@ save_expr (tree expr) return t; t = build1 (SAVE_EXPR, TREE_TYPE (expr), t); + SET_EXPR_LOCATION (t, EXPR_LOCATION (expr)); /* This expression might be placed ahead of a jump to ensure that the value was computed on both sides of the jump. So make sure it isn't @@ -2365,79 +2665,44 @@ skip_simple_arithmetic (tree expr) return inner; } + /* Return which tree structure is used by T. */ enum tree_node_structure_enum tree_node_structure (const_tree t) { const enum tree_code code = TREE_CODE (t); + return tree_node_structure_for_code (code); +} - switch (TREE_CODE_CLASS (code)) - { - case tcc_declaration: +/* Set various status flags when building a CALL_EXPR object T. */ + +static void +process_call_operands (tree t) +{ + bool side_effects = TREE_SIDE_EFFECTS (t); + bool read_only = false; + int i = call_expr_flags (t); + + /* Calls have side-effects, except those to const or pure functions. */ + if ((i & ECF_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE))) + side_effects = true; + /* Propagate TREE_READONLY of arguments for const functions. */ + if (i & ECF_CONST) + read_only = true; + + if (!side_effects || read_only) + for (i = 1; i < TREE_OPERAND_LENGTH (t); i++) { - switch (code) - { - case FIELD_DECL: - return TS_FIELD_DECL; - case PARM_DECL: - return TS_PARM_DECL; - case VAR_DECL: - return TS_VAR_DECL; - case LABEL_DECL: - return TS_LABEL_DECL; - case RESULT_DECL: - return TS_RESULT_DECL; - case CONST_DECL: - return TS_CONST_DECL; - case TYPE_DECL: - return TS_TYPE_DECL; - case FUNCTION_DECL: - return TS_FUNCTION_DECL; - default: - return TS_DECL_NON_COMMON; - } + tree op = TREE_OPERAND (t, i); + if (op && TREE_SIDE_EFFECTS (op)) + side_effects = true; + if (op && !TREE_READONLY (op) && !CONSTANT_CLASS_P (op)) + read_only = false; } - case tcc_type: - return TS_TYPE; - case tcc_reference: - case tcc_comparison: - case tcc_unary: - case tcc_binary: - case tcc_expression: - case tcc_statement: - case tcc_vl_exp: - return TS_EXP; - default: /* tcc_constant and tcc_exceptional */ - break; - } - switch (code) - { - /* tcc_constant cases. */ - case INTEGER_CST: return TS_INT_CST; - case REAL_CST: return TS_REAL_CST; - case FIXED_CST: return TS_FIXED_CST; - case COMPLEX_CST: return TS_COMPLEX; - case VECTOR_CST: return TS_VECTOR; - case STRING_CST: return TS_STRING; - /* tcc_exceptional cases. */ - case ERROR_MARK: return TS_COMMON; - case IDENTIFIER_NODE: return TS_IDENTIFIER; - case TREE_LIST: return TS_LIST; - case TREE_VEC: return TS_VEC; - case SSA_NAME: return TS_SSA_NAME; - case PLACEHOLDER_EXPR: return TS_COMMON; - case STATEMENT_LIST: return TS_STATEMENT_LIST; - case BLOCK: return TS_BLOCK; - case CONSTRUCTOR: return TS_CONSTRUCTOR; - case TREE_BINFO: return TS_BINFO; - case OMP_CLAUSE: return TS_OMP_CLAUSE; - case OPTIMIZATION_NODE: return TS_OPTIMIZATION; - case TARGET_OPTION_NODE: return TS_TARGET_OPTION; - default: - gcc_unreachable (); - } + TREE_SIDE_EFFECTS (t) = side_effects; + TREE_READONLY (t) = read_only; } /* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size @@ -2615,18 +2880,109 @@ type_contains_placeholder_p (tree type) return result; } +/* Push tree EXP onto vector QUEUE if it is not already present. */ + +static void +push_without_duplicates (tree exp, VEC (tree, heap) **queue) +{ + unsigned int i; + tree iter; + + for (i = 0; VEC_iterate (tree, *queue, i, iter); i++) + if (simple_cst_equal (iter, exp) == 1) + break; + + if (!iter) + VEC_safe_push (tree, heap, *queue, exp); +} + +/* Given a tree EXP, find all occurences of references to fields + in a PLACEHOLDER_EXPR and place them in vector REFS without + duplicates. Also record VAR_DECLs and CONST_DECLs. Note that + we assume here that EXP contains only arithmetic expressions + or CALL_EXPRs with PLACEHOLDER_EXPRs occurring only in their + argument list. */ + +void +find_placeholder_in_expr (tree exp, VEC (tree, heap) **refs) +{ + enum tree_code code = TREE_CODE (exp); + tree inner; + int i; + + /* We handle TREE_LIST and COMPONENT_REF separately. */ + if (code == TREE_LIST) + { + FIND_PLACEHOLDER_IN_EXPR (TREE_CHAIN (exp), refs); + FIND_PLACEHOLDER_IN_EXPR (TREE_VALUE (exp), refs); + } + else if (code == COMPONENT_REF) + { + for (inner = TREE_OPERAND (exp, 0); + REFERENCE_CLASS_P (inner); + inner = TREE_OPERAND (inner, 0)) + ; + + if (TREE_CODE (inner) == PLACEHOLDER_EXPR) + push_without_duplicates (exp, refs); + else + FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), refs); + } + else + switch (TREE_CODE_CLASS (code)) + { + case tcc_constant: + break; + + case tcc_declaration: + /* Variables allocated to static storage can stay. */ + if (!TREE_STATIC (exp)) + push_without_duplicates (exp, refs); + break; + + case tcc_expression: + /* This is the pattern built in ada/make_aligning_type. */ + if (code == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (exp, 0)) == PLACEHOLDER_EXPR) + { + push_without_duplicates (exp, refs); + break; + } + + /* Fall through... */ + + case tcc_exceptional: + case tcc_unary: + case tcc_binary: + case tcc_comparison: + case tcc_reference: + for (i = 0; i < TREE_CODE_LENGTH (code); i++) + FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, i), refs); + break; + + case tcc_vl_exp: + for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++) + FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, i), refs); + break; + + default: + gcc_unreachable (); + } +} + /* Given a tree EXP, a FIELD_DECL F, and a replacement value R, return a tree with all occurrences of references to F in a - PLACEHOLDER_EXPR replaced by R. Note that we assume here that EXP - contains only arithmetic expressions or a CALL_EXPR with a - PLACEHOLDER_EXPR occurring only in its arglist. */ + PLACEHOLDER_EXPR replaced by R. Also handle VAR_DECLs and + CONST_DECLs. Note that we assume here that EXP contains only + arithmetic expressions or CALL_EXPRs with PLACEHOLDER_EXPRs + occurring only in their argument list. */ tree substitute_in_expr (tree exp, tree f, tree r) { enum tree_code code = TREE_CODE (exp); tree op0, op1, op2, op3; - tree new_tree, inner; + tree new_tree; /* We handle TREE_LIST and COMPONENT_REF separately. */ if (code == TREE_LIST) @@ -2639,40 +2995,55 @@ substitute_in_expr (tree exp, tree f, tree r) return tree_cons (TREE_PURPOSE (exp), op1, op0); } else if (code == COMPONENT_REF) - { - /* If this expression is getting a value from a PLACEHOLDER_EXPR - and it is the right field, replace it with R. */ - for (inner = TREE_OPERAND (exp, 0); - REFERENCE_CLASS_P (inner); - inner = TREE_OPERAND (inner, 0)) - ; - if (TREE_CODE (inner) == PLACEHOLDER_EXPR - && TREE_OPERAND (exp, 1) == f) - return r; - - /* If this expression hasn't been completed let, leave it alone. */ - if (TREE_CODE (inner) == PLACEHOLDER_EXPR && TREE_TYPE (inner) == 0) - return exp; - - op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r); - if (op0 == TREE_OPERAND (exp, 0)) - return exp; - - new_tree = fold_build3 (COMPONENT_REF, TREE_TYPE (exp), - op0, TREE_OPERAND (exp, 1), NULL_TREE); + { + tree inner; + + /* If this expression is getting a value from a PLACEHOLDER_EXPR + and it is the right field, replace it with R. */ + for (inner = TREE_OPERAND (exp, 0); + REFERENCE_CLASS_P (inner); + inner = TREE_OPERAND (inner, 0)) + ; + + /* The field. */ + op1 = TREE_OPERAND (exp, 1); + + if (TREE_CODE (inner) == PLACEHOLDER_EXPR && op1 == f) + return r; + + /* If this expression hasn't been completed let, leave it alone. */ + if (TREE_CODE (inner) == PLACEHOLDER_EXPR && !TREE_TYPE (inner)) + return exp; + + op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r); + if (op0 == TREE_OPERAND (exp, 0)) + return exp; + + new_tree + = fold_build3 (COMPONENT_REF, TREE_TYPE (exp), op0, op1, NULL_TREE); } else switch (TREE_CODE_CLASS (code)) { case tcc_constant: - case tcc_declaration: return exp; + case tcc_declaration: + if (exp == f) + return r; + else + return exp; + + case tcc_expression: + if (exp == f) + return r; + + /* Fall through... */ + case tcc_exceptional: case tcc_unary: case tcc_binary: case tcc_comparison: - case tcc_expression: case tcc_reference: switch (TREE_CODE_LENGTH (code)) { @@ -2720,7 +3091,8 @@ substitute_in_expr (tree exp, tree f, tree r) && op3 == TREE_OPERAND (exp, 3)) return exp; - new_tree = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3)); + new_tree + = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3)); break; default: @@ -2730,23 +3102,39 @@ substitute_in_expr (tree exp, tree f, tree r) case tcc_vl_exp: { - tree copy = NULL_TREE; int i; + new_tree = NULL_TREE; + + /* If we are trying to replace F with a constant, inline back + functions which do nothing else than computing a value from + the arguments they are passed. This makes it possible to + fold partially or entirely the replacement expression. */ + if (CONSTANT_CLASS_P (r) && code == CALL_EXPR) + { + tree t = maybe_inline_call_in_expr (exp); + if (t) + return SUBSTITUTE_IN_EXPR (t, f, r); + } + for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++) { tree op = TREE_OPERAND (exp, i); tree new_op = SUBSTITUTE_IN_EXPR (op, f, r); if (new_op != op) { - if (!copy) - copy = copy_node (exp); - TREE_OPERAND (copy, i) = new_op; + if (!new_tree) + new_tree = copy_node (exp); + TREE_OPERAND (new_tree, i) = new_op; } } - if (copy) - new_tree = fold (copy); + if (new_tree) + { + new_tree = fold (new_tree); + if (TREE_CODE (new_tree) == CALL_EXPR) + process_call_operands (new_tree); + } else return exp; } @@ -2756,7 +3144,7 @@ substitute_in_expr (tree exp, tree f, tree r) gcc_unreachable (); } - TREE_READONLY (new_tree) = TREE_READONLY (exp); + TREE_READONLY (new_tree) |= TREE_READONLY (exp); return new_tree; } @@ -2768,6 +3156,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) { enum tree_code code = TREE_CODE (exp); tree op0, op1, op2, op3; + tree new_tree; /* If this is a PLACEHOLDER_EXPR, see if we find a corresponding type in the chain of OBJ. */ @@ -2843,8 +3232,9 @@ substitute_placeholder_in_expr (tree exp, tree obj) op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj); if (op0 == TREE_OPERAND (exp, 0)) return exp; - else - return fold_build1 (code, TREE_TYPE (exp), op0); + + new_tree = fold_build1 (code, TREE_TYPE (exp), op0); + break; case 2: op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj); @@ -2852,8 +3242,9 @@ substitute_placeholder_in_expr (tree exp, tree obj) if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)) return exp; - else - return fold_build2 (code, TREE_TYPE (exp), op0, op1); + + new_tree = fold_build2 (code, TREE_TYPE (exp), op0, op1); + break; case 3: op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj); @@ -2863,8 +3254,9 @@ substitute_placeholder_in_expr (tree exp, tree obj) if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1) && op2 == TREE_OPERAND (exp, 2)) return exp; - else - return fold_build3 (code, TREE_TYPE (exp), op0, op1, op2); + + new_tree = fold_build3 (code, TREE_TYPE (exp), op0, op1, op2); + break; case 4: op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj); @@ -2876,8 +3268,10 @@ substitute_placeholder_in_expr (tree exp, tree obj) && op2 == TREE_OPERAND (exp, 2) && op3 == TREE_OPERAND (exp, 3)) return exp; - else - return fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3)); + + new_tree + = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3)); + break; default: gcc_unreachable (); @@ -2886,30 +3280,39 @@ substitute_placeholder_in_expr (tree exp, tree obj) case tcc_vl_exp: { - tree copy = NULL_TREE; int i; + new_tree = NULL_TREE; + for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++) { tree op = TREE_OPERAND (exp, i); tree new_op = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj); if (new_op != op) { - if (!copy) - copy = copy_node (exp); - TREE_OPERAND (copy, i) = new_op; + if (!new_tree) + new_tree = copy_node (exp); + TREE_OPERAND (new_tree, i) = new_op; } } - if (copy) - return fold (copy); + if (new_tree) + { + new_tree = fold (new_tree); + if (TREE_CODE (new_tree) == CALL_EXPR) + process_call_operands (new_tree); + } else return exp; } + break; default: gcc_unreachable (); } + + TREE_READONLY (new_tree) |= TREE_READONLY (exp); + return new_tree; } /* Stabilize a reference so that we can use it any number of times @@ -3257,18 +3660,19 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) return t; } -#define PROCESS_ARG(N) \ - do { \ - TREE_OPERAND (t, N) = arg##N; \ - if (arg##N &&!TYPE_P (arg##N)) \ - { \ - if (TREE_SIDE_EFFECTS (arg##N)) \ - side_effects = 1; \ - if (!TREE_READONLY (arg##N)) \ - read_only = 0; \ - if (!TREE_CONSTANT (arg##N)) \ - constant = 0; \ - } \ +#define PROCESS_ARG(N) \ + do { \ + TREE_OPERAND (t, N) = arg##N; \ + if (arg##N &&!TYPE_P (arg##N)) \ + { \ + if (TREE_SIDE_EFFECTS (arg##N)) \ + side_effects = 1; \ + if (!TREE_READONLY (arg##N) \ + && !CONSTANT_CLASS_P (arg##N)) \ + (void) (read_only = 0); \ + if (!TREE_CONSTANT (arg##N)) \ + (void) (constant = 0); \ + } \ } while (0) tree @@ -3335,6 +3739,8 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; + read_only = 1; + /* As a special exception, if COND_EXPR has NULL branches, we assume that it is a gimple statement and always consider it to have side effects. */ @@ -3350,6 +3756,9 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, PROCESS_ARG(1); PROCESS_ARG(2); + if (code == COND_EXPR) + TREE_READONLY (t) = read_only; + TREE_SIDE_EFFECTS (t) = side_effects; TREE_THIS_VOLATILE (t) = (TREE_CODE_CLASS (code) == tcc_reference @@ -3432,10 +3841,14 @@ build6_stat (enum tree_code code, tree tt, tree arg0, tree arg1, PROCESS_ARG(2); PROCESS_ARG(3); PROCESS_ARG(4); + if (code == TARGET_MEM_REF) + side_effects = 0; PROCESS_ARG(5); TREE_SIDE_EFFECTS (t) = side_effects; - TREE_THIS_VOLATILE (t) = 0; + TREE_THIS_VOLATILE (t) + = (code == TARGET_MEM_REF + && arg5 && TREE_THIS_VOLATILE (arg5)); return t; } @@ -3483,19 +3896,40 @@ build_nt_call_list (tree fn, tree arglist) CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist); return t; } + +/* Similar to build_nt, but for creating a CALL_EXPR object with a + tree VEC. */ + +tree +build_nt_call_vec (tree fn, VEC(tree,gc) *args) +{ + tree ret, t; + unsigned int ix; + + ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3); + CALL_EXPR_FN (ret) = fn; + CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE; + for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix) + CALL_EXPR_ARG (ret, ix) = t; + return ret; +} /* 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. + LOC is the location of the decl. + layout_decl is used to set up the decl's storage layout. Other slots are initialized to 0 or null pointers. */ tree -build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL) +build_decl_stat (location_t loc, enum tree_code code, tree name, + tree type MEM_STAT_DECL) { tree t; t = make_node_stat (code PASS_MEM_STAT); + DECL_SOURCE_LOCATION (t) = loc; /* if (type == error_mark_node) type = integer_type_node; */ @@ -3517,7 +3951,7 @@ tree build_fn_decl (const char *name, tree type) { tree id = get_identifier (name); - tree decl = build_decl (FUNCTION_DECL, id, type); + tree decl = build_decl (input_location, FUNCTION_DECL, id, type); DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; @@ -3548,9 +3982,9 @@ expanded_location expand_location (source_location loc) { expanded_location xloc; - if (loc == 0) + if (loc <= BUILTINS_LOCATION) { - xloc.file = NULL; + xloc.file = loc == UNKNOWN_LOCATION ? NULL : _(""); xloc.line = 0; xloc.column = 0; xloc.sysp = 0; @@ -3567,18 +4001,6 @@ expand_location (source_location loc) } -/* Source location accessor functions. */ - - -void -set_expr_locus (tree node, source_location *loc) -{ - if (loc == NULL) - EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION; - else - EXPR_CHECK (node)->exp.locus = *loc; -} - /* Like SET_EXPR_LOCATION, but make sure the tree can have a location. LOC is the location to use in tree T. */ @@ -3626,26 +4048,8 @@ iterative_hash_hashval_t (hashval_t val, hashval_t val2) return val2; } -/* Produce good hash value combining PTR and VAL2. */ -static inline hashval_t -iterative_hash_pointer (const void *ptr, hashval_t val2) -{ - if (sizeof (ptr) == sizeof (hashval_t)) - return iterative_hash_hashval_t ((size_t) ptr, val2); - else - { - hashval_t a = (hashval_t) (size_t) ptr; - /* Avoid warnings about shifting of more than the width of the type on - hosts that won't execute this path. */ - int zero = 0; - hashval_t b = (hashval_t) ((size_t) ptr >> (sizeof (hashval_t) * 8 + zero)); - mix (a, b, val2); - return val2; - } -} - /* Produce good hash value combining VAL and VAL2. */ -static inline hashval_t +hashval_t iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2) { if (sizeof (HOST_WIDE_INT) == sizeof (hashval_t)) @@ -3673,7 +4077,7 @@ iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2) Record such modified types already made so we don't make duplicates. */ -static tree +tree build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) { if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute)) @@ -3757,18 +4161,913 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) } -/* Return a type like TTYPE except that its TYPE_ATTRIBUTE - is ATTRIBUTE. +/* 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)); +} + + +/* Reset the expression *EXPR_P, a size or position. + + ??? We could reset all non-constant sizes or positions. But it's cheap + enough to not do so and refrain from adding workarounds to dwarf2out.c. + + We need to reset self-referential sizes or positions because they cannot + be gimplified and thus can contain a CALL_EXPR after the gimplification + is finished, which will run afoul of LTO streaming. And they need to be + reset to something essentially dummy but not constant, so as to preserve + the properties of the object they are attached to. */ + +static inline void +free_lang_data_in_one_sizepos (tree *expr_p) +{ + tree expr = *expr_p; + if (CONTAINS_PLACEHOLDER_P (expr)) + *expr_p = build0 (PLACEHOLDER_EXPR, TREE_TYPE (expr)); +} + + +/* Reset all the fields in a binfo node BINFO. We only keep + BINFO_VIRTUALS, which is used by gimple_fold_obj_type_ref. */ + +static void +free_lang_data_in_binfo (tree binfo) +{ + unsigned i; + tree t; + + gcc_assert (TREE_CODE (binfo) == TREE_BINFO); + + BINFO_VTABLE (binfo) = NULL_TREE; + BINFO_BASE_ACCESSES (binfo) = NULL; + BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE; + BINFO_SUBVTT_INDEX (binfo) = NULL_TREE; + + for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (binfo), i, t); i++) + free_lang_data_in_binfo (t); +} + + +/* Reset all language specific information still present in TYPE. */ + +static void +free_lang_data_in_type (tree type) +{ + gcc_assert (TYPE_P (type)); + + /* Give the FE a chance to remove its own data first. */ + lang_hooks.free_lang_data (type); + + TREE_LANG_FLAG_0 (type) = 0; + TREE_LANG_FLAG_1 (type) = 0; + TREE_LANG_FLAG_2 (type) = 0; + TREE_LANG_FLAG_3 (type) = 0; + TREE_LANG_FLAG_4 (type) = 0; + TREE_LANG_FLAG_5 (type) = 0; + TREE_LANG_FLAG_6 (type) = 0; + + if (TREE_CODE (type) == FUNCTION_TYPE) + { + /* Remove the const and volatile qualifiers from arguments. The + C++ front end removes them, but the C front end does not, + leading to false ODR violation errors when merging two + instances of the same function signature compiled by + different front ends. */ + tree p; + + for (p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p)) + { + tree arg_type = TREE_VALUE (p); + + if (TYPE_READONLY (arg_type) || TYPE_VOLATILE (arg_type)) + { + int quals = TYPE_QUALS (arg_type) + & ~TYPE_QUAL_CONST + & ~TYPE_QUAL_VOLATILE; + TREE_VALUE (p) = build_qualified_type (arg_type, quals); + free_lang_data_in_type (TREE_VALUE (p)); + } + } + } + + /* Remove members that are not actually FIELD_DECLs from the field + list of an aggregate. These occur in C++. */ + if (RECORD_OR_UNION_TYPE_P (type)) + { + tree prev, member; + + /* Note that TYPE_FIELDS can be shared across distinct + TREE_TYPEs. Therefore, if the first field of TYPE_FIELDS is + to be removed, we cannot set its TREE_CHAIN to NULL. + Otherwise, we would not be able to find all the other fields + in the other instances of this TREE_TYPE. + + This was causing an ICE in testsuite/g++.dg/lto/20080915.C. */ + prev = NULL_TREE; + member = TYPE_FIELDS (type); + while (member) + { + if (TREE_CODE (member) == FIELD_DECL) + { + if (prev) + TREE_CHAIN (prev) = member; + else + TYPE_FIELDS (type) = member; + prev = member; + } + + member = TREE_CHAIN (member); + } + + if (prev) + TREE_CHAIN (prev) = NULL_TREE; + else + TYPE_FIELDS (type) = NULL_TREE; + + TYPE_METHODS (type) = NULL_TREE; + if (TYPE_BINFO (type)) + free_lang_data_in_binfo (TYPE_BINFO (type)); + } + else + { + /* For non-aggregate types, clear out the language slot (which + overloads TYPE_BINFO). */ + TYPE_LANG_SLOT_1 (type) = NULL_TREE; + + if (INTEGRAL_TYPE_P (type) + || SCALAR_FLOAT_TYPE_P (type) + || FIXED_POINT_TYPE_P (type)) + { + free_lang_data_in_one_sizepos (&TYPE_MIN_VALUE (type)); + free_lang_data_in_one_sizepos (&TYPE_MAX_VALUE (type)); + } + } + + free_lang_data_in_one_sizepos (&TYPE_SIZE (type)); + free_lang_data_in_one_sizepos (&TYPE_SIZE_UNIT (type)); + + if (debug_info_level < DINFO_LEVEL_TERSE + || (TYPE_CONTEXT (type) + && TREE_CODE (TYPE_CONTEXT (type)) != FUNCTION_DECL + && TREE_CODE (TYPE_CONTEXT (type)) != NAMESPACE_DECL)) + TYPE_CONTEXT (type) = NULL_TREE; + + if (debug_info_level < DINFO_LEVEL_TERSE) + TYPE_STUB_DECL (type) = NULL_TREE; +} + + +/* Return true if DECL may need an assembler name to be set. */ + +static inline bool +need_assembler_name_p (tree decl) +{ + /* Only FUNCTION_DECLs and VAR_DECLs are considered. */ + if (TREE_CODE (decl) != FUNCTION_DECL + && TREE_CODE (decl) != VAR_DECL) + return false; + + /* If DECL already has its assembler name set, it does not need a + new one. */ + if (!HAS_DECL_ASSEMBLER_NAME_P (decl) + || DECL_ASSEMBLER_NAME_SET_P (decl)) + return false; + + /* Abstract decls do not need an assembler name. */ + if (DECL_ABSTRACT (decl)) + return false; + + /* For VAR_DECLs, only static, public and external symbols need an + assembler name. */ + if (TREE_CODE (decl) == VAR_DECL + && !TREE_STATIC (decl) + && !TREE_PUBLIC (decl) + && !DECL_EXTERNAL (decl)) + return false; + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + /* Do not set assembler name on builtins. Allow RTL expansion to + decide whether to expand inline or via a regular call. */ + if (DECL_BUILT_IN (decl) + && DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND) + return false; + + /* Functions represented in the callgraph need an assembler name. */ + if (cgraph_get_node (decl) != NULL) + return true; + + /* Unused and not public functions don't need an assembler name. */ + if (!TREE_USED (decl) && !TREE_PUBLIC (decl)) + return false; + } + + return true; +} + + +/* Remove all the non-variable decls from BLOCK. LOCALS is the set of + variables in DECL_STRUCT_FUNCTION (FN)->local_decls. Every decl + in BLOCK that is not in LOCALS is removed. */ + +static void +free_lang_data_in_block (tree fn, tree block, struct pointer_set_t *locals) +{ + tree *tp, t; + + tp = &BLOCK_VARS (block); + while (*tp) + { + if (!pointer_set_contains (locals, *tp)) + *tp = TREE_CHAIN (*tp); + else + tp = &TREE_CHAIN (*tp); + } + + for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t)) + free_lang_data_in_block (fn, t, locals); +} + + +/* Reset all language specific information still present in symbol + DECL. */ + +static void +free_lang_data_in_decl (tree decl) +{ + gcc_assert (DECL_P (decl)); + + /* Give the FE a chance to remove its own data first. */ + lang_hooks.free_lang_data (decl); + + TREE_LANG_FLAG_0 (decl) = 0; + TREE_LANG_FLAG_1 (decl) = 0; + TREE_LANG_FLAG_2 (decl) = 0; + TREE_LANG_FLAG_3 (decl) = 0; + TREE_LANG_FLAG_4 (decl) = 0; + TREE_LANG_FLAG_5 (decl) = 0; + TREE_LANG_FLAG_6 (decl) = 0; + + /* Identifiers need not have a type. */ + if (DECL_NAME (decl)) + TREE_TYPE (DECL_NAME (decl)) = NULL_TREE; + + /* Ignore any intervening types, because we are going to clear their + TYPE_CONTEXT fields. */ + if (TREE_CODE (decl) != FIELD_DECL + && TREE_CODE (decl) != FUNCTION_DECL) + DECL_CONTEXT (decl) = decl_function_context (decl); + + if (DECL_CONTEXT (decl) + && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL) + DECL_CONTEXT (decl) = NULL_TREE; + + if (TREE_CODE (decl) == VAR_DECL) + { + tree context = DECL_CONTEXT (decl); + + if (context) + { + enum tree_code code = TREE_CODE (context); + if (code == FUNCTION_DECL && DECL_ABSTRACT (context)) + { + /* Do not clear the decl context here, that will promote + all vars to global ones. */ + DECL_INITIAL (decl) = NULL_TREE; + } + + if (TREE_STATIC (decl)) + DECL_CONTEXT (decl) = NULL_TREE; + } + } + + free_lang_data_in_one_sizepos (&DECL_SIZE (decl)); + free_lang_data_in_one_sizepos (&DECL_SIZE_UNIT (decl)); + if (TREE_CODE (decl) == FIELD_DECL) + free_lang_data_in_one_sizepos (&DECL_FIELD_OFFSET (decl)); + + /* DECL_FCONTEXT is only used for debug info generation. */ + if (TREE_CODE (decl) == FIELD_DECL + && debug_info_level < DINFO_LEVEL_TERSE) + DECL_FCONTEXT (decl) = NULL_TREE; + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + if (gimple_has_body_p (decl)) + { + tree t; + struct pointer_set_t *locals; + + /* If DECL has a gimple body, then the context for its + arguments must be DECL. Otherwise, it doesn't really + matter, as we will not be emitting any code for DECL. In + general, there may be other instances of DECL created by + the front end and since PARM_DECLs are generally shared, + their DECL_CONTEXT changes as the replicas of DECL are + created. The only time where DECL_CONTEXT is important + is for the FUNCTION_DECLs that have a gimple body (since + the PARM_DECL will be used in the function's body). */ + for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t)) + DECL_CONTEXT (t) = decl; + + /* Collect all the symbols declared in DECL. */ + locals = pointer_set_create (); + t = DECL_STRUCT_FUNCTION (decl)->local_decls; + for (; t; t = TREE_CHAIN (t)) + { + pointer_set_insert (locals, TREE_VALUE (t)); + + /* All the local symbols should have DECL as their + context. */ + DECL_CONTEXT (TREE_VALUE (t)) = decl; + } + + /* Get rid of any decl not in local_decls. */ + free_lang_data_in_block (decl, DECL_INITIAL (decl), locals); + + pointer_set_destroy (locals); + } + + /* DECL_SAVED_TREE holds the GENERIC representation for DECL. + At this point, it is not needed anymore. */ + DECL_SAVED_TREE (decl) = NULL_TREE; + } + else if (TREE_CODE (decl) == VAR_DECL) + { + tree expr = DECL_DEBUG_EXPR (decl); + if (expr + && TREE_CODE (expr) == VAR_DECL + && !TREE_STATIC (expr) && !DECL_EXTERNAL (expr)) + SET_DECL_DEBUG_EXPR (decl, NULL_TREE); + + if (DECL_EXTERNAL (decl) + && (!TREE_STATIC (decl) || !TREE_READONLY (decl))) + DECL_INITIAL (decl) = NULL_TREE; + } + else if (TREE_CODE (decl) == TYPE_DECL) + { + DECL_INITIAL (decl) = NULL_TREE; + + /* DECL_CONTEXT is overloaded as DECL_FIELD_CONTEXT for + FIELD_DECLs, which should be preserved. Otherwise, + we shouldn't be concerned with source-level lexical + nesting beyond this point. */ + DECL_CONTEXT (decl) = NULL_TREE; + } +} + + +/* Data used when collecting DECLs and TYPEs for language data removal. */ + +struct free_lang_data_d +{ + /* Worklist to avoid excessive recursion. */ + VEC(tree,heap) *worklist; + + /* Set of traversed objects. Used to avoid duplicate visits. */ + struct pointer_set_t *pset; + + /* Array of symbols to process with free_lang_data_in_decl. */ + VEC(tree,heap) *decls; + + /* Array of types to process with free_lang_data_in_type. */ + VEC(tree,heap) *types; +}; + + +/* Save all language fields needed to generate proper debug information + for DECL. This saves most fields cleared out by free_lang_data_in_decl. */ + +static void +save_debug_info_for_decl (tree t) +{ + /*struct saved_debug_info_d *sdi;*/ + + gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && DECL_P (t)); + + /* FIXME. Partial implementation for saving debug info removed. */ +} + + +/* Save all language fields needed to generate proper debug information + for TYPE. This saves most fields cleared out by free_lang_data_in_type. */ + +static void +save_debug_info_for_type (tree t) +{ + /*struct saved_debug_info_d *sdi;*/ + + gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && TYPE_P (t)); + + /* FIXME. Partial implementation for saving debug info removed. */ +} + + +/* Add type or decl T to one of the list of tree nodes that need their + language data removed. The lists are held inside FLD. */ + +static void +add_tree_to_fld_list (tree t, struct free_lang_data_d *fld) +{ + if (DECL_P (t)) + { + VEC_safe_push (tree, heap, fld->decls, t); + if (debug_info_level > DINFO_LEVEL_TERSE) + save_debug_info_for_decl (t); + } + else if (TYPE_P (t)) + { + VEC_safe_push (tree, heap, fld->types, t); + if (debug_info_level > DINFO_LEVEL_TERSE) + save_debug_info_for_type (t); + } + else + gcc_unreachable (); +} + +/* Push tree node T into FLD->WORKLIST. */ + +static inline void +fld_worklist_push (tree t, struct free_lang_data_d *fld) +{ + if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t)) + VEC_safe_push (tree, heap, fld->worklist, (t)); +} + + +/* Operand callback helper for free_lang_data_in_node. *TP is the + subtree operand being considered. */ + +static tree +find_decls_types_r (tree *tp, int *ws, void *data) +{ + tree t = *tp; + struct free_lang_data_d *fld = (struct free_lang_data_d *) data; + + if (TREE_CODE (t) == TREE_LIST) + return NULL_TREE; + + /* Language specific nodes will be removed, so there is no need + to gather anything under them. */ + if (is_lang_specific (t)) + { + *ws = 0; + return NULL_TREE; + } + + if (DECL_P (t)) + { + /* Note that walk_tree does not traverse every possible field in + decls, so we have to do our own traversals here. */ + add_tree_to_fld_list (t, fld); + + fld_worklist_push (DECL_NAME (t), fld); + fld_worklist_push (DECL_CONTEXT (t), fld); + fld_worklist_push (DECL_SIZE (t), fld); + fld_worklist_push (DECL_SIZE_UNIT (t), fld); + + /* We are going to remove everything under DECL_INITIAL for + TYPE_DECLs. No point walking them. */ + if (TREE_CODE (t) != TYPE_DECL) + fld_worklist_push (DECL_INITIAL (t), fld); + + fld_worklist_push (DECL_ATTRIBUTES (t), fld); + fld_worklist_push (DECL_ABSTRACT_ORIGIN (t), fld); + + if (TREE_CODE (t) == FUNCTION_DECL) + { + fld_worklist_push (DECL_ARGUMENTS (t), fld); + fld_worklist_push (DECL_RESULT (t), fld); + } + else if (TREE_CODE (t) == TYPE_DECL) + { + fld_worklist_push (DECL_ARGUMENT_FLD (t), fld); + fld_worklist_push (DECL_VINDEX (t), fld); + } + else if (TREE_CODE (t) == FIELD_DECL) + { + fld_worklist_push (DECL_FIELD_OFFSET (t), fld); + fld_worklist_push (DECL_BIT_FIELD_TYPE (t), fld); + fld_worklist_push (DECL_QUALIFIER (t), fld); + fld_worklist_push (DECL_FIELD_BIT_OFFSET (t), fld); + fld_worklist_push (DECL_FCONTEXT (t), fld); + } + else if (TREE_CODE (t) == VAR_DECL) + { + fld_worklist_push (DECL_SECTION_NAME (t), fld); + fld_worklist_push (DECL_COMDAT_GROUP (t), fld); + } + + if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) + && DECL_HAS_VALUE_EXPR_P (t)) + fld_worklist_push (DECL_VALUE_EXPR (t), fld); + + if (TREE_CODE (t) != FIELD_DECL) + fld_worklist_push (TREE_CHAIN (t), fld); + *ws = 0; + } + else if (TYPE_P (t)) + { + /* Note that walk_tree does not traverse every possible field in + types, so we have to do our own traversals here. */ + add_tree_to_fld_list (t, fld); + + if (!RECORD_OR_UNION_TYPE_P (t)) + fld_worklist_push (TYPE_CACHED_VALUES (t), fld); + fld_worklist_push (TYPE_SIZE (t), fld); + fld_worklist_push (TYPE_SIZE_UNIT (t), fld); + fld_worklist_push (TYPE_ATTRIBUTES (t), fld); + fld_worklist_push (TYPE_POINTER_TO (t), fld); + fld_worklist_push (TYPE_REFERENCE_TO (t), fld); + fld_worklist_push (TYPE_NAME (t), fld); + fld_worklist_push (TYPE_MINVAL (t), fld); + if (!RECORD_OR_UNION_TYPE_P (t)) + fld_worklist_push (TYPE_MAXVAL (t), fld); + fld_worklist_push (TYPE_MAIN_VARIANT (t), fld); + fld_worklist_push (TYPE_NEXT_VARIANT (t), fld); + fld_worklist_push (TYPE_CONTEXT (t), fld); + fld_worklist_push (TYPE_CANONICAL (t), fld); + + if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t)) + { + unsigned i; + tree tem; + for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (TYPE_BINFO (t)), + i, tem); ++i) + fld_worklist_push (TREE_TYPE (tem), fld); + tem = BINFO_VIRTUALS (TYPE_BINFO (t)); + if (tem + /* The Java FE overloads BINFO_VIRTUALS for its own purpose. */ + && TREE_CODE (tem) == TREE_LIST) + do + { + fld_worklist_push (TREE_VALUE (tem), fld); + tem = TREE_CHAIN (tem); + } + while (tem); + } + if (RECORD_OR_UNION_TYPE_P (t)) + { + tree tem; + /* Push all TYPE_FIELDS - there can be interleaving interesting + and non-interesting things. */ + tem = TYPE_FIELDS (t); + while (tem) + { + if (TREE_CODE (tem) == FIELD_DECL) + fld_worklist_push (tem, fld); + tem = TREE_CHAIN (tem); + } + } + + fld_worklist_push (TREE_CHAIN (t), fld); + *ws = 0; + } + + fld_worklist_push (TREE_TYPE (t), fld); + + return NULL_TREE; +} + + +/* Find decls and types in T. */ + +static void +find_decls_types (tree t, struct free_lang_data_d *fld) +{ + while (1) + { + if (!pointer_set_contains (fld->pset, t)) + walk_tree (&t, find_decls_types_r, fld, fld->pset); + if (VEC_empty (tree, fld->worklist)) + break; + t = VEC_pop (tree, fld->worklist); + } +} + +/* Translate all the types in LIST with the corresponding runtime + types. */ + +static tree +get_eh_types_for_runtime (tree list) +{ + tree head, prev; + + if (list == NULL_TREE) + return NULL_TREE; + + head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list))); + prev = head; + list = TREE_CHAIN (list); + while (list) + { + tree n = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list))); + TREE_CHAIN (prev) = n; + prev = TREE_CHAIN (prev); + list = TREE_CHAIN (list); + } + + return head; +} + + +/* Find decls and types referenced in EH region R and store them in + FLD->DECLS and FLD->TYPES. */ + +static void +find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld) +{ + switch (r->type) + { + case ERT_CLEANUP: + break; + + case ERT_TRY: + { + eh_catch c; + + /* The types referenced in each catch must first be changed to the + EH types used at runtime. This removes references to FE types + in the region. */ + for (c = r->u.eh_try.first_catch; c ; c = c->next_catch) + { + c->type_list = get_eh_types_for_runtime (c->type_list); + walk_tree (&c->type_list, find_decls_types_r, fld, fld->pset); + } + } + break; + + case ERT_ALLOWED_EXCEPTIONS: + r->u.allowed.type_list + = get_eh_types_for_runtime (r->u.allowed.type_list); + walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, fld->pset); + break; + + case ERT_MUST_NOT_THROW: + walk_tree (&r->u.must_not_throw.failure_decl, + find_decls_types_r, fld, fld->pset); + break; + } +} + + +/* Find decls and types referenced in cgraph node N and store them in + FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will + look for *every* kind of DECL and TYPE node reachable from N, + including those embedded inside types and decls (i.e,, TYPE_DECLs, + NAMESPACE_DECLs, etc). */ + +static void +find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) +{ + basic_block bb; + struct function *fn; + tree t; + + find_decls_types (n->decl, fld); + + if (!gimple_has_body_p (n->decl)) + return; + + gcc_assert (current_function_decl == NULL_TREE && cfun == NULL); + + fn = DECL_STRUCT_FUNCTION (n->decl); + + /* Traverse locals. */ + for (t = fn->local_decls; t; t = TREE_CHAIN (t)) + find_decls_types (TREE_VALUE (t), fld); + + /* Traverse EH regions in FN. */ + { + eh_region r; + FOR_ALL_EH_REGION_FN (r, fn) + find_decls_types_in_eh_region (r, fld); + } + + /* Traverse every statement in FN. */ + FOR_EACH_BB_FN (bb, fn) + { + gimple_stmt_iterator si; + unsigned i; + + for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si)) + { + gimple phi = gsi_stmt (si); + + for (i = 0; i < gimple_phi_num_args (phi); i++) + { + tree *arg_p = gimple_phi_arg_def_ptr (phi, i); + find_decls_types (*arg_p, fld); + } + } + + for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) + { + gimple stmt = gsi_stmt (si); + + for (i = 0; i < gimple_num_ops (stmt); i++) + { + tree arg = gimple_op (stmt, i); + find_decls_types (arg, fld); + } + } + } +} + + +/* Find decls and types referenced in varpool node N and store them in + FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will + look for *every* kind of DECL and TYPE node reachable from N, + including those embedded inside types and decls (i.e,, TYPE_DECLs, + NAMESPACE_DECLs, etc). */ + +static void +find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld) +{ + find_decls_types (v->decl, fld); +} + +/* If T needs an assembler name, have one created for it. */ + +void +assign_assembler_name_if_neeeded (tree t) +{ + if (need_assembler_name_p (t)) + { + /* When setting DECL_ASSEMBLER_NAME, the C++ mangler may emit + diagnostics that use input_location to show locus + information. The problem here is that, at this point, + input_location is generally anchored to the end of the file + (since the parser is long gone), so we don't have a good + position to pin it to. + + To alleviate this problem, this uses the location of T's + declaration. Examples of this are + testsuite/g++.dg/template/cond2.C and + testsuite/g++.dg/template/pr35240.C. */ + location_t saved_location = input_location; + input_location = DECL_SOURCE_LOCATION (t); + + decl_assembler_name (t); + + input_location = saved_location; + } +} + + +/* Free language specific information for every operand and expression + in every node of the call graph. This process operates in three stages: + + 1- Every callgraph node and varpool node is traversed looking for + decls and types embedded in them. This is a more exhaustive + search than that done by find_referenced_vars, because it will + also collect individual fields, decls embedded in types, etc. + + 2- All the decls found are sent to free_lang_data_in_decl. + + 3- All the types found are sent to free_lang_data_in_type. + + The ordering between decls and types is important because + free_lang_data_in_decl sets assembler names, which includes + mangling. So types cannot be freed up until assembler names have + been set up. */ + +static void +free_lang_data_in_cgraph (void) +{ + struct cgraph_node *n; + struct varpool_node *v; + struct free_lang_data_d fld; + tree t; + unsigned i; + alias_pair *p; + + /* Initialize sets and arrays to store referenced decls and types. */ + fld.pset = pointer_set_create (); + fld.worklist = NULL; + fld.decls = VEC_alloc (tree, heap, 100); + fld.types = VEC_alloc (tree, heap, 100); + + /* Find decls and types in the body of every function in the callgraph. */ + for (n = cgraph_nodes; n; n = n->next) + find_decls_types_in_node (n, &fld); + + for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++) + find_decls_types (p->decl, &fld); + + /* Find decls and types in every varpool symbol. */ + for (v = varpool_nodes_queue; v; v = v->next_needed) + find_decls_types_in_var (v, &fld); + + /* Set the assembler name on every decl found. We need to do this + now because free_lang_data_in_decl will invalidate data needed + for mangling. This breaks mangling on interdependent decls. */ + for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++) + assign_assembler_name_if_neeeded (t); + + /* Traverse every decl found freeing its language data. */ + for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++) + free_lang_data_in_decl (t); + + /* Traverse every type found freeing its language data. */ + for (i = 0; VEC_iterate (tree, fld.types, i, t); i++) + free_lang_data_in_type (t); + + pointer_set_destroy (fld.pset); + VEC_free (tree, heap, fld.worklist); + VEC_free (tree, heap, fld.decls); + VEC_free (tree, heap, fld.types); +} + + +/* Free resources that are used by FE but are not needed once they are done. */ + +static unsigned +free_lang_data (void) +{ + unsigned i; + + /* If we are the LTO frontend we have freed lang-specific data already. */ + if (in_lto_p + || !flag_generate_lto) + return 0; + + /* Allocate and assign alias sets to the standard integer types + while the slots are still in the way the frontends generated them. */ + for (i = 0; i < itk_none; ++i) + if (integer_types[i]) + TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i]); + + /* Traverse the IL resetting language specific information for + operands, expressions, etc. */ + free_lang_data_in_cgraph (); + + /* Create gimple variants for common types. */ + ptrdiff_type_node = integer_type_node; + fileptr_type_node = ptr_type_node; + if (TREE_CODE (boolean_type_node) != BOOLEAN_TYPE + || (TYPE_MODE (boolean_type_node) + != mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0)) + || TYPE_PRECISION (boolean_type_node) != 1 + || !TYPE_UNSIGNED (boolean_type_node)) + { + boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE); + TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE); + TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1); + TYPE_PRECISION (boolean_type_node) = 1; + boolean_false_node = TYPE_MIN_VALUE (boolean_type_node); + boolean_true_node = TYPE_MAX_VALUE (boolean_type_node); + } + + /* Unify char_type_node with its properly signed variant. */ + if (TYPE_UNSIGNED (char_type_node)) + unsigned_char_type_node = char_type_node; + else + signed_char_type_node = char_type_node; + + /* Reset some langhooks. Do not reset types_compatible_p, it may + still be used indirectly via the get_alias_set langhook. */ + lang_hooks.callgraph.analyze_expr = NULL; + lang_hooks.dwarf_name = lhd_dwarf_name; + lang_hooks.decl_printable_name = gimple_decl_printable_name; + lang_hooks.set_decl_assembler_name = lhd_set_decl_assembler_name; + lang_hooks.fold_obj_type_ref = gimple_fold_obj_type_ref; - Record such modified types already made so we don't make duplicates. */ + /* Reset diagnostic machinery. */ + diagnostic_starter (global_dc) = default_diagnostic_starter; + diagnostic_finalizer (global_dc) = default_diagnostic_finalizer; + diagnostic_format_decoder (global_dc) = default_tree_printer; -tree -build_type_attribute_variant (tree ttype, tree attribute) -{ - return build_type_attribute_qual_variant (ttype, attribute, - TYPE_QUALS (ttype)); + return 0; } + +struct simple_ipa_opt_pass pass_ipa_free_lang_data = +{ + { + SIMPLE_IPA_PASS, + "*free_lang_data", /* name */ + NULL, /* gate */ + free_lang_data, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_IPA_FREE_LANG_DATA, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_ggc_collect /* todo_flags_finish */ + } +}; + /* Return nonzero if IDENT is a valid name for attribute ATTR, or zero if not. @@ -3785,10 +5084,10 @@ is_attribute_with_length_p (const char *attr, int attr_len, const_tree ident) if (TREE_CODE (ident) != IDENTIFIER_NODE) return 0; - + p = IDENTIFIER_POINTER (ident); ident_len = IDENTIFIER_LENGTH (ident); - + if (ident_len == attr_len && strcmp (attr, p) == 0) return 1; @@ -3970,12 +5269,12 @@ merge_dllimport_decl_attributes (tree old, tree new_tree) marked dllimport and a definition appears later, then the object is not dllimport'd. We also remove a `new' dllimport if the old list contains dllexport: dllexport always overrides dllimport, regardless - of the order of declaration. */ + of the order of declaration. */ if (!VAR_OR_FUNCTION_DECL_P (new_tree)) delete_dllimport_p = 0; else if (DECL_DLLIMPORT_P (new_tree) && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old))) - { + { DECL_DLLIMPORT_P (new_tree) = 0; warning (OPT_Wattributes, "%q+D already declared with dllexport attribute: " "dllimport ignored", new_tree); @@ -4001,7 +5300,7 @@ merge_dllimport_decl_attributes (tree old, tree new_tree) } /* Let an inline definition silently override the external reference, - but otherwise warn about attribute inconsistency. */ + but otherwise warn about attribute inconsistency. */ else if (TREE_CODE (new_tree) == VAR_DECL || !DECL_DECLARED_INLINE_P (new_tree)) warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: " @@ -4012,11 +5311,11 @@ merge_dllimport_decl_attributes (tree old, tree new_tree) a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree)); - if (delete_dllimport_p) + if (delete_dllimport_p) { tree prev, t; - const size_t attr_len = strlen ("dllimport"); - + const size_t attr_len = strlen ("dllimport"); + /* Scan the list for dllimport and delete it. */ for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t)) { @@ -4043,6 +5342,7 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, bool *no_add_attrs) { tree node = *pnode; + bool is_dllimport; /* These attributes may apply to structure and union types being created, but otherwise should pass to the declaration involved. */ @@ -4063,8 +5363,8 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, } else { - warning (OPT_Wattributes, "%qs attribute ignored", - IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qE attribute ignored", + name); *no_add_attrs = true; return NULL_TREE; } @@ -4075,8 +5375,8 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, && TREE_CODE (node) != TYPE_DECL) { *no_add_attrs = true; - warning (OPT_Wattributes, "%qs attribute ignored", - IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qE attribute ignored", + name); return NULL_TREE; } @@ -4085,16 +5385,18 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE) { *no_add_attrs = true; - warning (OPT_Wattributes, "%qs attribute ignored", - IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qE attribute ignored", + name); return NULL_TREE; } + is_dllimport = is_attribute_p ("dllimport", name); + /* Report error on dllimport ambiguities seen now before they cause any damage. */ - else if (is_attribute_p ("dllimport", name)) + if (is_dllimport) { - /* Honor any target-specific overrides. */ + /* Honor any target-specific overrides. */ if (!targetm.valid_dllimport_attribute_p (node)) *no_add_attrs = true; @@ -4102,7 +5404,7 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, && DECL_DECLARED_INLINE_P (node)) { warning (OPT_Wattributes, "inline function %q+D declared as " - " dllimport: attribute ignored", node); + " dllimport: attribute ignored", node); *no_add_attrs = true; } /* Like MS, treat definition of dllimported variables and @@ -4134,6 +5436,10 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, if (*no_add_attrs == false) DECL_DLLIMPORT_P (node) = 1; } + else if (TREE_CODE (node) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (node)) + /* An exported function, even if inline, must be emitted. */ + DECL_EXTERNAL (node) = 0; /* Report error if symbol is not accessible at global scope. */ if (!TREE_PUBLIC (node) @@ -4141,7 +5447,7 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, || TREE_CODE (node) == FUNCTION_DECL)) { error ("external linkage required for symbol %q+D because of " - "%qs attribute", node, IDENTIFIER_POINTER (name)); + "%qE attribute", node, name); *no_add_attrs = true; } @@ -4154,9 +5460,9 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, { if (DECL_VISIBILITY_SPECIFIED (node) && DECL_VISIBILITY (node) != VISIBILITY_DEFAULT) - error ("%qs implies default visibility, but %qD has already " - "been declared with a different visibility", - IDENTIFIER_POINTER (name), node); + error ("%qE implies default visibility, but %qD has already " + "been declared with a different visibility", + name, node); DECL_VISIBILITY (node) = VISIBILITY_DEFAULT; DECL_VISIBILITY_SPECIFIED (node) = 1; } @@ -4175,6 +5481,7 @@ set_type_quals (tree type, int type_quals) TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0; TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0; TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0; + TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals); } /* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */ @@ -4240,7 +5547,7 @@ build_qualified_type (tree type, int type_quals) else /* T is its own canonical type. */ TYPE_CANONICAL (t) = t; - + } return t; @@ -4255,7 +5562,7 @@ tree build_distinct_type_copy (tree type) { tree t = copy_node (type); - + TYPE_POINTER_TO (t) = 0; TYPE_REFERENCE_TO (t) = 0; @@ -4293,7 +5600,7 @@ build_variant_type_copy (tree 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); TYPE_NEXT_VARIANT (m) = t; @@ -4400,7 +5707,7 @@ decl_init_priority_insert (tree decl, priority_type priority) gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); h = decl_priority_info (decl); h->init = priority; -} +} /* Set the finalization priority for DECL to PRIORITY. */ @@ -4412,36 +5719,6 @@ decl_fini_priority_insert (tree decl, priority_type priority) gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); h = decl_priority_info (decl); h->fini = priority; -} - -/* Look up a restrict qualified base decl for FROM. */ - -tree -decl_restrict_base_lookup (tree from) -{ - struct tree_map *h; - struct tree_map in; - - in.base.from = from; - h = (struct tree_map *) htab_find_with_hash (restrict_base_for_decl, &in, - htab_hash_pointer (from)); - return h ? h->to : NULL_TREE; -} - -/* Record the restrict qualified base TO for FROM. */ - -void -decl_restrict_base_insert (tree from, tree to) -{ - struct tree_map *h; - void **loc; - - h = GGC_NEW (struct tree_map); - h->hash = htab_hash_pointer (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; } /* Print out the statistics for the DECL_DEBUG_EXPR hash table. */ @@ -4466,23 +5743,9 @@ print_value_expr_statistics (void) htab_collisions (value_expr_for_decl)); } -/* Print out statistics for the RESTRICT_BASE_FOR_DECL hash table, but - don't print anything if the table is empty. */ - -static void -print_restrict_base_statistics (void) -{ - if (htab_elements (restrict_base_for_decl) != 0) - fprintf (stderr, - "RESTRICT_BASE hash: size %ld, %ld elements, %f collisions\n", - (long) htab_size (restrict_base_for_decl), - (long) htab_elements (restrict_base_for_decl), - htab_collisions (restrict_base_for_decl)); -} - /* Lookup a debug expression for FROM, and return it if we find one. */ -tree +tree decl_debug_expr_lookup (tree from) { struct tree_map *h, in; @@ -4509,11 +5772,11 @@ decl_debug_expr_insert (tree from, tree to) h->to = to; loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT); *(struct tree_map **) loc = h; -} +} /* Lookup a value expression for FROM, and return it if we find one. */ -tree +tree decl_value_expr_lookup (tree from) { struct tree_map *h, in; @@ -4580,7 +5843,7 @@ type_hash_eq (const void *va, const void *vb) TYPE_ATTRIBUTES (b->type)) || TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type) || TYPE_MODE (a->type) != TYPE_MODE (b->type) - || (TREE_CODE (a->type) != COMPLEX_TYPE + || (TREE_CODE (a->type) != COMPLEX_TYPE && TYPE_NAME (a->type) != TYPE_NAME (b->type))) return 0; @@ -4974,6 +6237,9 @@ tree_int_cst_compare (const_tree t1, const_tree t2) int host_integerp (const_tree t, int pos) { + if (t == NULL_TREE) + return 0; + return (TREE_CODE (t) == INTEGER_CST && ((TREE_INT_CST_HIGH (t) == 0 && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0) @@ -5330,7 +6596,7 @@ iterative_hash_expr (const_tree t, hashval_t val) char tclass; if (t == NULL_TREE) - return iterative_hash_pointer (t, val); + return iterative_hash_hashval_t (0, val); code = TREE_CODE (t); @@ -5361,11 +6627,12 @@ iterative_hash_expr (const_tree t, hashval_t val) return iterative_hash_expr (TREE_IMAGPART (t), val); case VECTOR_CST: return iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val); - case SSA_NAME: - /* we can just compare by pointer. */ - return iterative_hash_pointer (t, val); - + /* We can just compare by pointer. */ + return iterative_hash_host_wide_int (SSA_NAME_VERSION (t), val); + case PLACEHOLDER_EXPR: + /* The node itself doesn't matter. */ + return val; case TREE_LIST: /* A list of expressions, for a CALL_EXPR or as the elements of a VECTOR_CST. */ @@ -5384,17 +6651,18 @@ iterative_hash_expr (const_tree t, hashval_t val) return val; } case FUNCTION_DECL: - /* When referring to a built-in FUNCTION_DECL, use the - __builtin__ form. Otherwise nodes that compare equal - according to operand_equal_p might get different - hash codes. */ - if (DECL_BUILT_IN (t)) + /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form. + Otherwise nodes that compare equal according to operand_equal_p might + get different hash codes. However, don't do this for machine specific + or front end builtins, since the function code is overloaded in those + cases. */ + if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL + && built_in_decls[DECL_FUNCTION_CODE (t)]) { - val = iterative_hash_pointer (built_in_decls[DECL_FUNCTION_CODE (t)], - val); - return val; + t = built_in_decls[DECL_FUNCTION_CODE (t)]; + code = TREE_CODE (t); } - /* else FALL THROUGH */ + /* FALL THROUGH */ default: tclass = TREE_CODE_CLASS (code); @@ -5406,7 +6674,7 @@ iterative_hash_expr (const_tree t, hashval_t val) else { gcc_assert (IS_EXPR_CODE_CLASS (tclass)); - + val = iterative_hash_object (code, val); /* Don't hash the type, that can lead to having nodes which @@ -5536,7 +6804,10 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode, tree build_pointer_type (tree to_type) { - return build_pointer_type_for_mode (to_type, ptr_mode, false); + addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC + : TYPE_ADDR_SPACE (to_type); + enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as); + return build_pointer_type_for_mode (to_type, pointer_mode, false); } /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE. */ @@ -5584,7 +6855,7 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode, if (TYPE_STRUCTURAL_EQUALITY_P (to_type)) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (TYPE_CANONICAL (to_type) != to_type) - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = build_reference_type_for_mode (TYPE_CANONICAL (to_type), mode, can_alias_all); @@ -5600,7 +6871,10 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode, tree build_reference_type (tree to_type) { - return build_reference_type_for_mode (to_type, ptr_mode, false); + addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC + : TYPE_ADDR_SPACE (to_type); + enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as); + return build_reference_type_for_mode (to_type, pointer_mode, false); } /* Build a type that is compatible with t but has no cv quals anywhere @@ -5662,6 +6936,10 @@ build_index_type (tree maxval) } } +#define MAX_INT_CACHED_PREC \ + (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64) +static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2]; + /* Builds a signed or unsigned integer type of precision PRECISION. Used for C bitfields whose precision does not match that of built-in target types. */ @@ -5669,8 +6947,19 @@ tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, int unsignedp) { - tree itype = make_node (INTEGER_TYPE); + tree itype, ret; + + if (unsignedp) + unsignedp = MAX_INT_CACHED_PREC + 1; + + if (precision <= MAX_INT_CACHED_PREC) + { + itype = nonstandard_integer_type_cache[precision + unsignedp]; + if (itype) + return itype; + } + itype = make_node (INTEGER_TYPE); TYPE_PRECISION (itype) = precision; if (unsignedp) @@ -5678,10 +6967,13 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, else fixup_signed_type (itype); + ret = itype; if (host_integerp (TYPE_MAX_VALUE (itype), 1)) - return type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype); + ret = type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype); + if (precision <= MAX_INT_CACHED_PREC && lang_hooks.types.hash_types) + nonstandard_integer_type_cache[precision + unsignedp] = ret; - return itype; + return ret; } /* Create a range of some discrete type TYPE (an INTEGER_TYPE, @@ -5715,6 +7007,57 @@ build_range_type (tree type, tree lowval, tree highval) return itype; } +/* Return true if the debug information for TYPE, a subtype, should be emitted + as a subrange type. If so, set LOWVAL to the low bound and HIGHVAL to the + high bound, respectively. Sometimes doing so unnecessarily obfuscates the + debug info and doesn't reflect the source code. */ + +bool +subrange_type_for_debug_p (const_tree type, tree *lowval, tree *highval) +{ + tree base_type = TREE_TYPE (type), low, high; + + /* Subrange types have a base type which is an integral type. */ + if (!INTEGRAL_TYPE_P (base_type)) + return false; + + /* Get the real bounds of the subtype. */ + if (lang_hooks.types.get_subrange_bounds) + lang_hooks.types.get_subrange_bounds (type, &low, &high); + else + { + low = TYPE_MIN_VALUE (type); + high = TYPE_MAX_VALUE (type); + } + + /* If the type and its base type have the same representation and the same + name, then the type is not a subrange but a copy of the base type. */ + if ((TREE_CODE (base_type) == INTEGER_TYPE + || TREE_CODE (base_type) == BOOLEAN_TYPE) + && int_size_in_bytes (type) == int_size_in_bytes (base_type) + && tree_int_cst_equal (low, TYPE_MIN_VALUE (base_type)) + && tree_int_cst_equal (high, TYPE_MAX_VALUE (base_type))) + { + tree type_name = TYPE_NAME (type); + tree base_type_name = TYPE_NAME (base_type); + + if (type_name && TREE_CODE (type_name) == TYPE_DECL) + type_name = DECL_NAME (type_name); + + if (base_type_name && TREE_CODE (base_type_name) == TYPE_DECL) + base_type_name = DECL_NAME (base_type_name); + + if (type_name == base_type_name) + return false; + } + + if (lowval) + *lowval = low; + if (highval) + *highval = high; + return true; +} + /* Just like build_index_type, but takes lowval and highval instead of just highval (maxval). */ @@ -5743,44 +7086,30 @@ build_array_type (tree elt_type, tree index_type) t = make_node (ARRAY_TYPE); TREE_TYPE (t) = elt_type; TYPE_DOMAIN (t) = index_type; - - if (index_type == 0) - { - 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); - } + TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (elt_type); + layout_type (t); - return t; - } + /* If the element type is incomplete at this point we get marked for + structural equality. Do not record these types in the canonical + type hashtable. */ + if (TYPE_STRUCTURAL_EQUALITY_P (t)) + return t; hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode); - hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); + if (index_type) + hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); t = type_hash_canon (hashcode, t); - 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)) + || (index_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) + || (index_type && TYPE_CANONICAL (index_type) != index_type)) + TYPE_CANONICAL (t) = build_array_type (TYPE_CANONICAL (elt_type), - TYPE_CANONICAL (index_type)); + index_type ? TYPE_CANONICAL (index_type) : NULL); } return t; @@ -5799,7 +7128,7 @@ strip_array_types (tree type) } /* Computes the canonical argument types from the argument type list - ARGTYPES. + ARGTYPES. Upon return, *ANY_STRUCTURAL_P will be true iff either it was true on entry to this function, or if any of the ARGTYPES are @@ -5813,14 +7142,14 @@ strip_array_types (tree type) canonical argument list is unneeded (i.e., *ANY_STRUCTURAL_P is true) or would not differ from ARGTYPES. */ -static tree -maybe_canonicalize_argtypes(tree argtypes, +static tree +maybe_canonicalize_argtypes(tree argtypes, bool *any_structural_p, bool *any_noncanonical_p) { tree arg; bool any_noncanonical_argtypes_p = false; - + for (arg = argtypes; arg && !(*any_structural_p); arg = TREE_CHAIN (arg)) { if (!TREE_VALUE (arg) || TREE_VALUE (arg) == error_mark_node) @@ -5904,7 +7233,7 @@ build_function_type (tree value_type, tree arg_types) /* Set up the canonical type. */ any_structural_p = TYPE_STRUCTURAL_EQUALITY_P (value_type); any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type; - canon_argtypes = maybe_canonicalize_argtypes (arg_types, + canon_argtypes = maybe_canonicalize_argtypes (arg_types, &any_structural_p, &any_noncanonical_p); if (any_structural_p) @@ -5912,7 +7241,7 @@ build_function_type (tree value_type, tree arg_types) else if (any_noncanonical_p) TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type), canon_argtypes); - + if (!COMPLETE_TYPE_P (t)) layout_type (t); return t; @@ -5941,7 +7270,6 @@ build_function_type_skip_args (tree orig_type, bitmap args_to_skip) else new_reversed = void_list_node; } - gcc_assert (new_reversed); /* Use copy_node to preserve as much as possible from original type (debug info, attribute lists etc.) @@ -5979,8 +7307,8 @@ build_function_type_skip_args (tree orig_type, bitmap args_to_skip) return new_type; } -/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP. - +/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP. + Arguments from DECL_ARGUMENTS list can't be removed now, since they are linked by TREE_CHAIN directly. It is caller responsibility to eliminate them when they are being duplicated (i.e. copy_arguments_for_versioning). */ @@ -6118,7 +7446,7 @@ build_method_type_directly (tree basetype, if (any_structural_p) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (any_noncanonical_p) - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = build_method_type_directly (TYPE_CANONICAL (basetype), TYPE_CANONICAL (rettype), canon_argtypes); @@ -6174,7 +7502,7 @@ build_offset_type (tree basetype, tree type) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)) != basetype || TYPE_CANONICAL (type) != type) - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = build_offset_type (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)), TYPE_CANONICAL (type)); } @@ -6211,7 +7539,7 @@ build_complex_type (tree component_type) if (TYPE_STRUCTURAL_EQUALITY_P (component_type)) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (TYPE_CANONICAL (component_type) != component_type) - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = build_complex_type (TYPE_CANONICAL (component_type)); } @@ -6245,7 +7573,8 @@ build_complex_type (tree component_type) name = 0; if (name != 0) - TYPE_NAME (t) = build_decl (TYPE_DECL, get_identifier (name), t); + TYPE_NAME (t) = build_decl (UNKNOWN_LOCATION, TYPE_DECL, + get_identifier (name), t); } return build_qualified_type (t, TYPE_QUALS (component_type)); @@ -6384,6 +7713,14 @@ get_unwidened (tree op, tree for_type) } } + /* If we finally reach a constant see if it fits in for_type and + in that case convert it. */ + if (for_type + && TREE_CODE (win) == INTEGER_CST + && TREE_TYPE (win) != for_type + && int_fits_type_p (win, for_type)) + win = fold_convert (for_type, win); + return win; } @@ -6639,7 +7976,7 @@ get_type_static_bounds (const_tree type, mpz_t min, mpz_t max) } } - if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type) + if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type) && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST) mpz_set_double_int (max, tree_to_double_int (TYPE_MAX_VALUE (type)), TYPE_UNSIGNED (type)); @@ -6660,7 +7997,8 @@ bool auto_var_in_fn_p (const_tree var, const_tree fn) { return (DECL_P (var) && DECL_CONTEXT (var) == fn - && (((TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL) + && ((((TREE_CODE (var) == VAR_DECL && ! DECL_EXTERNAL (var)) + || TREE_CODE (var) == PARM_DECL) && ! TREE_STATIC (var)) || TREE_CODE (var) == LABEL_DECL || TREE_CODE (var) == RESULT_DECL)); @@ -6938,7 +8276,6 @@ dump_tree_statistics (void) print_type_hash_statistics (); print_debug_expr_statistics (); print_value_expr_statistics (); - print_restrict_base_statistics (); lang_hooks.print_statistics (); } @@ -7089,7 +8426,7 @@ tree_check_failed (const_tree node, const char *file, while ((code = va_arg (args, int))) { const char *prefix = length ? " or " : "expected "; - + strcpy (tmp + length, prefix); length += strlen (prefix); strcpy (tmp + length, tree_code_name[code]); @@ -7166,7 +8503,7 @@ tree_range_check_failed (const_tree node, const char *file, int line, { char *buffer; unsigned length = 0; - enum tree_code c; + unsigned int c; for (c = c1; c <= c2; ++c) length += 4 + strlen (tree_code_name[c]); @@ -7227,7 +8564,7 @@ omp_clause_range_check_failed (const_tree node, const char *file, int line, { char *buffer; unsigned length = 0; - enum omp_clause_code c; + unsigned int c; for (c = c1; c <= c2; ++c) length += 4 + strlen (omp_clause_code_name[c]); @@ -7266,9 +8603,9 @@ static const char *ts_enum_names[] = { whether CODE contains the tree structure identified by EN. */ void -tree_contains_struct_check_failed (const_tree node, +tree_contains_struct_check_failed (const_tree node, const enum tree_node_structure_enum en, - const char *file, int line, + const char *file, int line, const char *function) { internal_error @@ -7329,37 +8666,28 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) 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); SET_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) + TYPE_CANONICAL (t) = make_vector_type (TYPE_CANONICAL (innertype), nunits, VOIDmode); layout_type (t); { tree index = build_int_cst (NULL_TREE, nunits - 1); - tree array = build_array_type (innertype, build_index_type (index)); + tree array = build_array_type (TYPE_MAIN_VARIANT (innertype), + build_index_type (index)); tree rt = make_node (RECORD_TYPE); - TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array); + TYPE_FIELDS (rt) = build_decl (UNKNOWN_LOCATION, FIELD_DECL, + get_identifier ("f"), array); DECL_CONTEXT (TYPE_FIELDS (rt)) = rt; layout_type (rt); TYPE_DEBUG_REPRESENTATION_TYPE (t) = rt; @@ -7371,9 +8699,20 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) } hashcode = iterative_hash_host_wide_int (VECTOR_TYPE, hashcode); + hashcode = iterative_hash_host_wide_int (nunits, hashcode); hashcode = iterative_hash_host_wide_int (mode, hashcode); - hashcode = iterative_hash_object (TYPE_HASH (innertype), hashcode); - return type_hash_canon (hashcode, t); + hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (t)), hashcode); + t = type_hash_canon (hashcode, t); + + /* We have built a main variant, based on the main variant of the + inner type. Use it to build the variant we return. */ + if ((TYPE_ATTRIBUTES (innertype) || TYPE_QUALS (innertype)) + && TREE_TYPE (t) != innertype) + return build_type_attribute_qual_variant (t, + TYPE_ATTRIBUTES (innertype), + TYPE_QUALS (innertype)); + + return t; } static tree @@ -7476,12 +8815,12 @@ make_or_reuse_accum_type (unsigned size, int unsignedp, int satp) this function to select one of the types as sizetype. */ void -build_common_tree_nodes (bool signed_char, bool signed_sizetype) +build_common_tree_nodes (bool signed_char) { error_mark_node = make_node (ERROR_MARK); TREE_TYPE (error_mark_node) = error_mark_node; - initialize_sizetypes (signed_sizetype); + initialize_sizetypes (); /* Define both `signed char' and `unsigned char'. */ signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); @@ -7596,7 +8935,7 @@ build_common_tree_nodes_2 (int short_double) /* Decimal float types. */ dfloat32_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE; + TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE; layout_type (dfloat32_type_node); SET_TYPE_MODE (dfloat32_type_node, SDmode); dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node); @@ -7608,7 +8947,7 @@ build_common_tree_nodes_2 (int short_double) 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; + TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE; layout_type (dfloat128_type_node); SET_TYPE_MODE (dfloat128_type_node, TDmode); dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node); @@ -7681,7 +9020,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; } } @@ -7720,7 +9059,7 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, void build_common_builtin_nodes (void) { - tree tmp, ftype; + tree tmp, tmp2, ftype; if (built_in_decls[BUILT_IN_MEMCPY] == NULL || built_in_decls[BUILT_IN_MEMMOVE] == NULL) @@ -7763,7 +9102,8 @@ build_common_builtin_nodes (void) tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); ftype = build_function_type (ptr_type_node, tmp); local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA, - "alloca", ECF_NOTHROW | ECF_MALLOC); + "alloca", + ECF_MALLOC | (flag_stack_check ? 0 : ECF_NOTHROW)); } tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); @@ -7825,12 +9165,53 @@ build_common_builtin_nodes (void) local_define_builtin ("__builtin_profile_func_exit", ftype, BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit", 0); + /* If there's a possibility that we might use the ARM EABI, build the + alternate __cxa_end_cleanup node used to resume from C++ and Java. */ + if (targetm.arm_eabi_unwinder) + { + ftype = build_function_type (void_type_node, void_list_node); + local_define_builtin ("__builtin_cxa_end_cleanup", ftype, + BUILT_IN_CXA_END_CLEANUP, + "__cxa_end_cleanup", ECF_NORETURN); + } + + tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + ftype = build_function_type (void_type_node, tmp); + local_define_builtin ("__builtin_unwind_resume", ftype, + BUILT_IN_UNWIND_RESUME, + (USING_SJLJ_EXCEPTIONS + ? "_Unwind_SjLj_Resume" : "_Unwind_Resume"), + ECF_NORETURN); + + /* The exception object and filter values from the runtime. The argument + must be zero before exception lowering, i.e. from the front end. After + exception lowering, it will be the region number for the exception + landing pad. These functions are PURE instead of CONST to prevent + them from being hoisted past the exception edge that will initialize + its value in the landing pad. */ + tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node); + ftype = build_function_type (ptr_type_node, tmp); + local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER, + "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW); + + tmp2 = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0); + ftype = build_function_type (tmp2, tmp); + local_define_builtin ("__builtin_eh_filter", ftype, BUILT_IN_EH_FILTER, + "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW); + + tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node); + tmp = tree_cons (NULL_TREE, integer_type_node, tmp); + ftype = build_function_type (void_type_node, tmp); + local_define_builtin ("__builtin_eh_copy_values", ftype, + BUILT_IN_EH_COPY_VALUES, + "__builtin_eh_copy_values", ECF_NOTHROW); + /* Complex multiplication and division. These are handled as builtins rather than optabs because emit_library_call_value doesn't support - complex. Further, we can do slightly better with folding these + complex. Further, we can do slightly better with folding these beasties if the real and complex parts of the arguments are separate. */ { - enum machine_mode mode; + int mode; for (mode = MIN_MODE_COMPLEX_FLOAT; mode <= MAX_MODE_COMPLEX_FLOAT; ++mode) { @@ -7839,7 +9220,7 @@ build_common_builtin_nodes (void) enum built_in_function mcode, dcode; tree type, inner_type; - type = lang_hooks.types.type_for_mode (mode, 0); + type = lang_hooks.types.type_for_mode ((enum machine_mode) mode, 0); if (type == NULL) continue; inner_type = TREE_TYPE (type); @@ -7850,8 +9231,10 @@ build_common_builtin_nodes (void) tmp = tree_cons (NULL_TREE, inner_type, tmp); ftype = build_function_type (type, tmp); - mcode = BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT; - dcode = BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT; + mcode = ((enum built_in_function) + (BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT)); + dcode = ((enum built_in_function) + (BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT)); for (p = GET_MODE_NAME (mode), q = mode_name_buf; *p; p++, q++) *q = TOLOWER (*p); @@ -7882,7 +9265,7 @@ tree reconstruct_complex_type (tree type, tree bottom) { tree inner, outer; - + if (TREE_CODE (type) == POINTER_TYPE) { inner = reconstruct_complex_type (TREE_TYPE (type), bottom); @@ -7910,8 +9293,8 @@ reconstruct_complex_type (tree type, tree bottom) inner = reconstruct_complex_type (TREE_TYPE (type), bottom); /* The build_method_type_directly() routine prepends 'this' to argument list, so we must compensate by getting rid of it. */ - outer - = build_method_type_directly + outer + = build_method_type_directly (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))), inner, TREE_CHAIN (TYPE_ARG_TYPES (type))); @@ -7924,7 +9307,8 @@ reconstruct_complex_type (tree type, tree bottom) else return bottom; - return build_qualified_type (outer, TYPE_QUALS (type)); + return build_type_attribute_qual_variant (outer, TYPE_ATTRIBUTES (type), + TYPE_QUALS (type)); } /* Returns a vector tree node given a mode (integer, vector, or BLKmode) and @@ -7984,16 +9368,6 @@ build_opaque_vector_type (tree innertype, int nunits) } -/* Build RESX_EXPR with given REGION_NUMBER. */ -tree -build_resx (int region_number) -{ - tree t; - t = build1 (RESX_EXPR, void_type_node, - build_int_cst (NULL_TREE, region_number)); - return t; -} - /* Given an initializer INIT, return TRUE if INIT is zero or some aggregate of zeros. Otherwise return FALSE. */ bool @@ -8040,24 +9414,40 @@ initializer_zerop (const_tree init) return true; } + case STRING_CST: + { + int i; + + /* We need to loop through all elements to handle cases like + "\0" and "\0foobar". */ + for (i = 0; i < TREE_STRING_LENGTH (init); ++i) + if (TREE_STRING_POINTER (init)[i] != '\0') + return false; + + return true; + } + default: return false; } } -/* Build an empty statement. */ +/* Build an empty statement at location LOC. */ tree -build_empty_stmt (void) +build_empty_stmt (location_t loc) { - return build1 (NOP_EXPR, void_type_node, size_zero_node); + tree t = build1 (NOP_EXPR, void_type_node, size_zero_node); + SET_EXPR_LOCATION (t, loc); + return t; } -/* Build an OpenMP clause with code CODE. */ +/* Build an OpenMP clause with code CODE. LOC is the location of the + clause. */ tree -build_omp_clause (enum omp_clause_code code) +build_omp_clause (location_t loc, enum omp_clause_code code) { tree t; int size, length; @@ -8069,48 +9459,14 @@ build_omp_clause (enum omp_clause_code code) memset (t, 0, size); TREE_SET_CODE (t, OMP_CLAUSE); OMP_CLAUSE_SET_CODE (t, code); + OMP_CLAUSE_LOCATION (t) = loc; #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_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE))) - side_effects = 1; - } - TREE_SIDE_EFFECTS (t) = side_effects; + return t; } /* Build a tcc_vl_exp object with code CODE and room for LEN operands. LEN @@ -8206,7 +9562,8 @@ build_call_valist (tree return_type, tree fn, int nargs, va_list args) which are specified as a tree array ARGS. */ tree -build_call_array (tree return_type, tree fn, int nargs, tree *args) +build_call_array_loc (location_t loc, tree return_type, tree fn, + int nargs, const tree *args) { tree t; int i; @@ -8218,9 +9575,28 @@ build_call_array (tree return_type, tree fn, int nargs, tree *args) for (i = 0; i < nargs; i++) CALL_EXPR_ARG (t, i) = args[i]; process_call_operands (t); + SET_EXPR_LOCATION (t, loc); return t; } +/* Like build_call_array, but takes a VEC. */ + +tree +build_call_vec (tree return_type, tree fn, VEC(tree,gc) *args) +{ + tree ret, t; + unsigned int ix; + + ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3); + TREE_TYPE (ret) = return_type; + CALL_EXPR_FN (ret) = fn; + CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE; + for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix) + CALL_EXPR_ARG (ret, ix) = t; + process_call_operands (ret); + return ret; +} + /* Returns true if it is possible to prove that the index of an array access REF (an ARRAY_REF expression) falls into the @@ -8366,6 +9742,36 @@ int_cst_value (const_tree x) return val; } +/* Return value of a constant X and sign-extend it. */ + +HOST_WIDEST_INT +widest_int_cst_value (const_tree x) +{ + unsigned bits = TYPE_PRECISION (TREE_TYPE (x)); + unsigned HOST_WIDEST_INT val = TREE_INT_CST_LOW (x); + +#if HOST_BITS_PER_WIDEST_INT > HOST_BITS_PER_WIDE_INT + gcc_assert (HOST_BITS_PER_WIDEST_INT >= 2 * HOST_BITS_PER_WIDE_INT); + val |= (((unsigned HOST_WIDEST_INT) TREE_INT_CST_HIGH (x)) + << HOST_BITS_PER_WIDE_INT); +#else + /* Make sure the sign-extended value will fit in a HOST_WIDE_INT. */ + gcc_assert (TREE_INT_CST_HIGH (x) == 0 + || TREE_INT_CST_HIGH (x) == -1); +#endif + + if (bits < HOST_BITS_PER_WIDEST_INT) + { + bool negative = ((val >> (bits - 1)) & 1) != 0; + if (negative) + val |= (~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1; + else + val &= ~((~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1); + } + + return val; +} + /* If TYPE is an integral type, return an equivalent type which is unsigned iff UNSIGNEDP is true. If TYPE is not an integral type, return TYPE itself. */ @@ -8375,11 +9781,19 @@ signed_or_unsigned_type_for (int unsignedp, tree type) { tree t = type; if (POINTER_TYPE_P (type)) - t = size_type_node; + { + /* If the pointer points to the normal address space, use the + size_type_node. Otherwise use an appropriate size for the pointer + based on the named address space it points to. */ + if (!TYPE_ADDR_SPACE (TREE_TYPE (t))) + t = size_type_node; + else + return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp); + } if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp) return t; - + return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp); } @@ -8525,7 +9939,7 @@ operand_equal_for_phi_arg_p (const_tree arg0, const_tree arg1) } /* Returns number of zeros at the end of binary representation of X. - + ??? Use ffs if available? */ tree @@ -8853,10 +10267,6 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len)); } - case CHANGE_DYNAMIC_TYPE_EXPR: - WALK_SUBTREE (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*tp)); - WALK_SUBTREE_TAIL (CHANGE_DYNAMIC_TYPE_LOCATION (*tp)); - 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 @@ -8867,7 +10277,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, 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) { @@ -8887,9 +10297,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, return result; /* 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) + if (RECORD_OR_UNION_TYPE_P (*type_p)) { tree field; @@ -9000,13 +10408,15 @@ call_expr_arglist (tree exp) } -/* Create a nameless artificial label and put it in the current function - context. Returns the newly created label. */ +/* Create a nameless artificial label and put it in the current + function context. The label has a location of LOC. Returns the + newly created label. */ tree -create_artificial_label (void) +create_artificial_label (location_t loc) { - tree lab = build_decl (LABEL_DECL, NULL_TREE, void_type_node); + tree lab = build_decl (loc, + LABEL_DECL, NULL_TREE, void_type_node); DECL_ARTIFICIAL (lab) = 1; DECL_IGNORED_P (lab) = 1; @@ -9116,32 +10526,12 @@ block_nonartificial_location (tree block) location_t tree_nonartificial_location (tree exp) { - tree block = TREE_BLOCK (exp); - - while (block - && TREE_CODE (block) == BLOCK - && BLOCK_ABSTRACT_ORIGIN (block)) - { - tree ao = BLOCK_ABSTRACT_ORIGIN (block); - - do - { - if (TREE_CODE (ao) == FUNCTION_DECL - && DECL_DECLARED_INLINE_P (ao) - && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao))) - return BLOCK_SOURCE_LOCATION (block); - else if (TREE_CODE (ao) == BLOCK - && BLOCK_SUPERCONTEXT (ao) != ao) - ao = BLOCK_SUPERCONTEXT (ao); - else - break; - } - while (ao); - - block = BLOCK_SUPERCONTEXT (block); - } + location_t *loc = block_nonartificial_location (TREE_BLOCK (exp)); - return EXPR_LOCATION (exp); + if (loc) + return *loc; + else + return EXPR_LOCATION (exp); } @@ -9318,4 +10708,107 @@ block_ultimate_origin (const_tree block) } } +/* Return true if T1 and T2 are equivalent lists. */ + +bool +list_equal_p (const_tree t1, const_tree t2) +{ + for (; t1 && t2; t1 = TREE_CHAIN (t1) , t2 = TREE_CHAIN (t2)) + if (TREE_VALUE (t1) != TREE_VALUE (t2)) + return false; + return !t1 && !t2; +} + +/* Return true iff conversion in EXP generates no instruction. Mark + it inline so that we fully inline into the stripping functions even + though we have two uses of this function. */ + +static inline bool +tree_nop_conversion (const_tree exp) +{ + tree outer_type, inner_type; + + if (!CONVERT_EXPR_P (exp) + && TREE_CODE (exp) != NON_LVALUE_EXPR) + return false; + if (TREE_OPERAND (exp, 0) == error_mark_node) + return false; + + outer_type = TREE_TYPE (exp); + inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); + + if (!inner_type) + return false; + + /* Use precision rather then machine mode when we can, which gives + the correct answer even for submode (bit-field) types. */ + if ((INTEGRAL_TYPE_P (outer_type) + || POINTER_TYPE_P (outer_type) + || TREE_CODE (outer_type) == OFFSET_TYPE) + && (INTEGRAL_TYPE_P (inner_type) + || POINTER_TYPE_P (inner_type) + || TREE_CODE (inner_type) == OFFSET_TYPE)) + return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type); + + /* Otherwise fall back on comparing machine modes (e.g. for + aggregate types, floats). */ + return TYPE_MODE (outer_type) == TYPE_MODE (inner_type); +} + +/* Return true iff conversion in EXP generates no instruction. Don't + consider conversions changing the signedness. */ + +static bool +tree_sign_nop_conversion (const_tree exp) +{ + tree outer_type, inner_type; + + if (!tree_nop_conversion (exp)) + return false; + + outer_type = TREE_TYPE (exp); + inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); + + return (TYPE_UNSIGNED (outer_type) == TYPE_UNSIGNED (inner_type) + && POINTER_TYPE_P (outer_type) == POINTER_TYPE_P (inner_type)); +} + +/* Strip conversions from EXP according to tree_nop_conversion and + return the resulting expression. */ + +tree +tree_strip_nop_conversions (tree exp) +{ + while (tree_nop_conversion (exp)) + exp = TREE_OPERAND (exp, 0); + return exp; +} + +/* Strip conversions from EXP according to tree_sign_nop_conversion + and return the resulting expression. */ + +tree +tree_strip_sign_nop_conversions (tree exp) +{ + while (tree_sign_nop_conversion (exp)) + exp = TREE_OPERAND (exp, 0); + return exp; +} + +static GTY(()) tree gcc_eh_personality_decl; + +/* Return the GCC personality function decl. */ + +tree +lhd_gcc_personality (void) +{ + if (!gcc_eh_personality_decl) + gcc_eh_personality_decl + = build_personality_function (USING_SJLJ_EXCEPTIONS + ? "__gcc_personality_sj0" + : "__gcc_personality_v0"); + + return gcc_eh_personality_decl; +} + #include "gt-tree.h"