X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=8bf2b7718afa065674a5a4fb168a4dd019cf8b0c;hb=9fed75026cca1c2bf8cbf67920c15fe52489d1c9;hp=6824c14d16cffb218a6702a7928bbd4216841328;hpb=426a138f1f231a55f4670be9c4bca30dbb0e3b61;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index 6824c14d16c..8bf2b7718af 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1,13 +1,13 @@ /* 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 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* This file contains the low level primitives for operating on tree nodes, including allocation, list operations, interning of identifiers, @@ -51,6 +50,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tree-flow.h" #include "params.h" #include "pointer-set.h" +#include "fixed-value.h" /* Each tree code class has an associated string representation. These must correspond to the tree_code_class entries. */ @@ -66,7 +66,9 @@ const char *const tree_code_class_strings[] = "unary", "binary", "statement", + "vl_exp", "expression", + "gimple_stmt" }; /* obstack.[ch] explicitly declined to prototype this. */ @@ -144,20 +146,13 @@ static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t value_expr_for_decl; -static GTY ((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map))) +static GTY ((if_marked ("tree_priority_map_marked_p"), + param_is (struct tree_priority_map))) htab_t init_priority_for_decl; static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t restrict_base_for_decl; -struct tree_int_map GTY(()) -{ - tree from; - unsigned short to; -}; -static unsigned int tree_int_map_hash (const void *); -static int tree_int_map_eq (const void *, const void *); -static int tree_int_map_marked_p (const void *); static void set_type_quals (tree, int); static int type_hash_eq (const void *, const void *); static hashval_t type_hash_hash (const void *); @@ -167,13 +162,13 @@ static void print_type_hash_statistics (void); static void print_debug_expr_statistics (void); static void print_value_expr_statistics (void); static int type_hash_marked_p (const void *); -static unsigned int type_hash_list (tree, hashval_t); -static unsigned int attribute_hash_list (tree, hashval_t); +static unsigned int type_hash_list (const_tree, hashval_t); +static unsigned int attribute_hash_list (const_tree, hashval_t); tree global_trees[TI_MAX]; tree integer_types[itk_none]; -unsigned char tree_contains_struct[256][64]; +unsigned char tree_contains_struct[MAX_TREE_CODES][64]; /* Number of operands for each OpenMP clause. */ unsigned const char omp_clause_num_ops[] = @@ -182,7 +177,7 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_PRIVATE */ 1, /* OMP_CLAUSE_SHARED */ 1, /* OMP_CLAUSE_FIRSTPRIVATE */ - 1, /* OMP_CLAUSE_LASTPRIVATE */ + 2, /* OMP_CLAUSE_LASTPRIVATE */ 4, /* OMP_CLAUSE_REDUCTION */ 1, /* OMP_CLAUSE_COPYIN */ 1, /* OMP_CLAUSE_COPYPRIVATE */ @@ -191,7 +186,9 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_SCHEDULE */ 0, /* OMP_CLAUSE_NOWAIT */ 0, /* OMP_CLAUSE_ORDERED */ - 0 /* OMP_CLAUSE_DEFAULT */ + 0, /* OMP_CLAUSE_DEFAULT */ + 3, /* OMP_CLAUSE_COLLAPSE */ + 0 /* OMP_CLAUSE_UNTIED */ }; const char * const omp_clause_code_name[] = @@ -209,7 +206,9 @@ const char * const omp_clause_code_name[] = "schedule", "nowait", "ordered", - "default" + "default", + "collapse", + "untied" }; /* Init tree.c. */ @@ -226,8 +225,8 @@ init_ttree (void) value_expr_for_decl = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0); - init_priority_for_decl = htab_create_ggc (512, tree_int_map_hash, - tree_int_map_eq, 0); + init_priority_for_decl = htab_create_ggc (512, tree_priority_map_hash, + tree_priority_map_eq, 0); restrict_base_for_decl = htab_create_ggc (256, tree_map_hash, tree_map_eq, 0); @@ -268,17 +267,14 @@ init_ttree (void) tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL] = 1; - tree_contains_struct[STRUCT_FIELD_TAG][TS_DECL_MINIMAL] = 1; tree_contains_struct[NAME_MEMORY_TAG][TS_DECL_MINIMAL] = 1; tree_contains_struct[SYMBOL_MEMORY_TAG][TS_DECL_MINIMAL] = 1; tree_contains_struct[MEMORY_PARTITION_TAG][TS_DECL_MINIMAL] = 1; - tree_contains_struct[STRUCT_FIELD_TAG][TS_MEMORY_TAG] = 1; tree_contains_struct[NAME_MEMORY_TAG][TS_MEMORY_TAG] = 1; tree_contains_struct[SYMBOL_MEMORY_TAG][TS_MEMORY_TAG] = 1; tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_TAG] = 1; - tree_contains_struct[STRUCT_FIELD_TAG][TS_STRUCT_FIELD_TAG] = 1; tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_PARTITION_TAG] = 1; tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1; @@ -345,8 +341,8 @@ decl_assembler_name_equal (tree decl, tree asmname) } /* Compute the number of bytes occupied by a tree with code CODE. - This function cannot be used for TREE_VEC, PHI_NODE, or STRING_CST - codes, which are of variable length. */ + This function cannot be used for nodes that have variable sizes, + including TREE_VEC, PHI_NODE, STRING_CST, and CALL_EXPR. */ size_t tree_code_size (enum tree_code code) { @@ -375,8 +371,6 @@ tree_code_size (enum tree_code code) case NAME_MEMORY_TAG: case SYMBOL_MEMORY_TAG: return sizeof (struct tree_memory_tag); - case STRUCT_FIELD_TAG: - return sizeof (struct tree_struct_field_tag); case MEMORY_PARTITION_TAG: return sizeof (struct tree_memory_partition_tag); default: @@ -394,7 +388,7 @@ tree_code_size (enum tree_code code) case tcc_unary: /* a unary arithmetic expression */ case tcc_binary: /* a binary arithmetic expression */ return (sizeof (struct tree_exp) - + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *)); + + (TREE_CODE_LENGTH (code) - 1) * sizeof (tree)); case tcc_gimple_stmt: return (sizeof (struct gimple_stmt) @@ -405,6 +399,7 @@ tree_code_size (enum tree_code code) { case INTEGER_CST: return sizeof (struct tree_int_cst); case REAL_CST: return sizeof (struct tree_real_cst); + case FIXED_CST: return sizeof (struct tree_fixed_cst); case COMPLEX_CST: return sizeof (struct tree_complex); case VECTOR_CST: return sizeof (struct tree_vector); case STRING_CST: gcc_unreachable (); @@ -442,11 +437,11 @@ tree_code_size (enum tree_code code) } /* Compute the number of bytes occupied by NODE. This routine only - looks at TREE_CODE, except for PHI_NODE and TREE_VEC nodes. */ + looks at TREE_CODE, except for those nodes that have variable sizes. */ size_t -tree_size (tree node) +tree_size (const_tree node) { - enum tree_code code = TREE_CODE (node); + const enum tree_code code = TREE_CODE (node); switch (code) { case PHI_NODE: @@ -459,7 +454,7 @@ tree_size (tree node) case TREE_VEC: return (sizeof (struct tree_vec) - + (TREE_VEC_LENGTH (node) - 1) * sizeof(char *)); + + (TREE_VEC_LENGTH (node) - 1) * sizeof (tree)); case STRING_CST: return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; @@ -470,7 +465,11 @@ tree_size (tree node) * sizeof (tree)); default: - return tree_code_size (code); + if (TREE_CODE_CLASS (code) == tcc_vl_exp) + return (sizeof (struct tree_exp) + + (VL_EXP_OPERAND_LENGTH (node) - 1) * sizeof (tree)); + else + return tree_code_size (code); } } @@ -589,9 +588,13 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) DECL_IN_SYSTEM_HEADER (t) = in_system_header; if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { - if (code != FUNCTION_DECL) + if (code == FUNCTION_DECL) + { + DECL_ALIGN (t) = FUNCTION_BOUNDARY; + DECL_MODE (t) = FUNCTION_MODE; + } + else DECL_ALIGN (t) = 1; - DECL_USER_ALIGN (t) = 0; /* We have not yet computed the alias set for this declaration. */ DECL_POINTER_ALIAS_SET (t) = -1; } @@ -617,7 +620,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) case tcc_constant: TREE_CONSTANT (t) = 1; - TREE_INVARIANT (t) = 1; break; case tcc_expression: @@ -808,7 +810,7 @@ build_int_cst_wide_type (tree type, static hashval_t int_cst_hash_hash (const void *x) { - tree t = (tree) x; + const_tree const t = (const_tree) x; return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t) ^ htab_hash_pointer (TREE_TYPE (t))); @@ -820,8 +822,8 @@ int_cst_hash_hash (const void *x) static int int_cst_hash_eq (const void *x, const void *y) { - tree xt = (tree) x; - tree yt = (tree) y; + const_tree const xt = (const_tree) x; + const_tree const yt = (const_tree) y; return (TREE_TYPE (xt) == TREE_TYPE (yt) && TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt) @@ -978,7 +980,7 @@ build_low_bits_mask (tree type, unsigned bits) HOST_WIDE_INT without loss of precision. */ bool -cst_and_fits_in_hwi (tree x) +cst_and_fits_in_hwi (const_tree x) { if (TREE_CODE (x) != INTEGER_CST) return false; @@ -1093,6 +1095,22 @@ build_constructor_from_list (tree type, tree vals) return t; } +/* Return a new FIXED_CST node whose type is TYPE and value is F. */ + +tree +build_fixed (tree type, FIXED_VALUE_TYPE f) +{ + tree v; + FIXED_VALUE_TYPE *fp; + + v = make_node (FIXED_CST); + fp = ggc_alloc (sizeof (FIXED_VALUE_TYPE)); + memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE)); + + TREE_TYPE (v) = type; + TREE_FIXED_CST_PTR (v) = fp; + return v; +} /* Return a new REAL_CST node whose type is TYPE and value is D. */ @@ -1120,7 +1138,7 @@ build_real (tree type, REAL_VALUE_TYPE d) and whose value is the integer value of the INTEGER_CST node I. */ REAL_VALUE_TYPE -real_value_from_int_cst (tree type, tree i) +real_value_from_int_cst (const_tree type, const_tree i) { REAL_VALUE_TYPE d; @@ -1138,7 +1156,7 @@ real_value_from_int_cst (tree type, tree i) representing the same value as a floating-point constant of type TYPE. */ tree -build_real_from_int_cst (tree type, tree i) +build_real_from_int_cst (tree type, const_tree i) { tree v; int overflow = TREE_OVERFLOW (i); @@ -1172,10 +1190,9 @@ build_string (int len, const char *str) memset (s, 0, sizeof (struct tree_common)); TREE_SET_CODE (s, STRING_CST); TREE_CONSTANT (s) = 1; - TREE_INVARIANT (s) = 1; TREE_STRING_LENGTH (s) = len; - memcpy ((char *) TREE_STRING_POINTER (s), str, len); - ((char *) TREE_STRING_POINTER (s))[len] = '\0'; + memcpy (s->string.str, str, len); + s->string.str[len] = '\0'; return s; } @@ -1213,6 +1230,11 @@ build_one_cst (tree type) case REAL_TYPE: return build_real (type, dconst1); + case FIXED_POINT_TYPE: + /* We can only generate 1 for accum types. */ + gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type))); + return build_fixed (type, FCONST1(TYPE_MODE (type))); + case VECTOR_TYPE: { tree scalar, cst; @@ -1291,7 +1313,7 @@ make_tree_vec_stat (int len MEM_STAT_DECL) of zero. */ int -integer_zerop (tree expr) +integer_zerop (const_tree expr) { STRIP_NOPS (expr); @@ -1307,7 +1329,7 @@ integer_zerop (tree expr) complex constant. */ int -integer_onep (tree expr) +integer_onep (const_tree expr) { STRIP_NOPS (expr); @@ -1323,7 +1345,7 @@ integer_onep (tree expr) it contains. Likewise for the corresponding complex constant. */ int -integer_all_onesp (tree expr) +integer_all_onesp (const_tree expr) { int prec; int uns; @@ -1375,7 +1397,7 @@ integer_all_onesp (tree expr) one bit on). */ int -integer_pow2p (tree expr) +integer_pow2p (const_tree expr) { int prec; HOST_WIDE_INT high, low; @@ -1420,7 +1442,7 @@ integer_pow2p (tree expr) complex constant other than zero. */ int -integer_nonzerop (tree expr) +integer_nonzerop (const_tree expr) { STRIP_NOPS (expr); @@ -1432,11 +1454,20 @@ integer_nonzerop (tree expr) || integer_nonzerop (TREE_IMAGPART (expr))))); } +/* Return 1 if EXPR is the fixed-point constant zero. */ + +int +fixed_zerop (const_tree expr) +{ + return (TREE_CODE (expr) == FIXED_CST + && double_int_zero_p (TREE_FIXED_CST (expr).data)); +} + /* Return the power of two represented by a tree node known to be a power of two. */ int -tree_log2 (tree expr) +tree_log2 (const_tree expr) { int prec; HOST_WIDE_INT high, low; @@ -1474,7 +1505,7 @@ tree_log2 (tree expr) than or equal to EXPR. */ int -tree_floor_log2 (tree expr) +tree_floor_log2 (const_tree expr) { int prec; HOST_WIDE_INT high, low; @@ -1512,7 +1543,7 @@ tree_floor_log2 (tree expr) /* Return 1 if EXPR is the real constant zero. */ int -real_zerop (tree expr) +real_zerop (const_tree expr) { STRIP_NOPS (expr); @@ -1526,7 +1557,7 @@ real_zerop (tree expr) /* Return 1 if EXPR is the real constant one in real or complex form. */ int -real_onep (tree expr) +real_onep (const_tree expr) { STRIP_NOPS (expr); @@ -1540,7 +1571,7 @@ real_onep (tree expr) /* Return 1 if EXPR is the real constant two. */ int -real_twop (tree expr) +real_twop (const_tree expr) { STRIP_NOPS (expr); @@ -1554,7 +1585,7 @@ real_twop (tree expr) /* Return 1 if EXPR is the real constant minus one. */ int -real_minus_onep (tree expr) +real_minus_onep (const_tree expr) { STRIP_NOPS (expr); @@ -1568,11 +1599,10 @@ real_minus_onep (tree expr) /* Nonzero if EXP is a constant or a cast of a constant. */ int -really_constant_p (tree exp) +really_constant_p (const_tree exp) { /* This is not quite the same as STRIP_NOPS. It does more. */ - while (TREE_CODE (exp) == NOP_EXPR - || TREE_CODE (exp) == CONVERT_EXPR + while (CONVERT_EXPR_P (exp) || TREE_CODE (exp) == NON_LVALUE_EXPR) exp = TREE_OPERAND (exp, 0); return TREE_CONSTANT (exp); @@ -1597,7 +1627,7 @@ value_member (tree elem, tree list) Return 0 if ELEM is not in LIST. */ tree -purpose_member (tree elem, tree list) +purpose_member (const_tree elem, tree list) { while (list) { @@ -1611,7 +1641,7 @@ purpose_member (tree elem, tree list) /* Return nonzero if ELEM is part of the chain CHAIN. */ int -chain_member (tree elem, tree chain) +chain_member (const_tree elem, const_tree chain) { while (chain) { @@ -1628,11 +1658,11 @@ chain_member (tree elem, tree chain) This is the Lisp primitive `length'. */ int -list_length (tree t) +list_length (const_tree t) { - tree p = t; + const_tree p = t; #ifdef ENABLE_TREE_CHECKING - tree q = t; + const_tree q = t; #endif int len = 0; @@ -1653,7 +1683,7 @@ list_length (tree t) /* Returns the number of FIELD_DECLs in TYPE. */ int -fields_length (tree type) +fields_length (const_tree type) { tree t = TYPE_FIELDS (type); int count = 0; @@ -1767,7 +1797,7 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL) make_unsigned_type). */ tree -size_in_bytes (tree type) +size_in_bytes (const_tree type) { tree t; @@ -1790,7 +1820,7 @@ size_in_bytes (tree type) or return -1 if the size can vary or is larger than an integer. */ HOST_WIDE_INT -int_size_in_bytes (tree type) +int_size_in_bytes (const_tree type) { tree t; @@ -1813,7 +1843,7 @@ int_size_in_bytes (tree type) or return -1 if the size can vary or is larger than an integer. */ HOST_WIDE_INT -max_int_size_in_bytes (tree type) +max_int_size_in_bytes (const_tree type) { HOST_WIDE_INT size = -1; tree size_tree; @@ -1846,7 +1876,7 @@ max_int_size_in_bytes (tree type) This is a tree of type bitsizetype. */ tree -bit_position (tree field) +bit_position (const_tree field) { return bit_from_pos (DECL_FIELD_OFFSET (field), DECL_FIELD_BIT_OFFSET (field)); @@ -1857,7 +1887,7 @@ bit_position (tree field) option of returning -1 like int_size_in_byte can. */ HOST_WIDE_INT -int_bit_position (tree field) +int_bit_position (const_tree field) { return tree_low_cst (bit_position (field), 0); } @@ -1866,7 +1896,7 @@ int_bit_position (tree field) This is a tree of type sizetype. */ tree -byte_position (tree field) +byte_position (const_tree field) { return byte_from_pos (DECL_FIELD_OFFSET (field), DECL_FIELD_BIT_OFFSET (field)); @@ -1877,7 +1907,7 @@ byte_position (tree field) option of returning -1 like int_size_in_byte can. */ HOST_WIDE_INT -int_byte_position (tree field) +int_byte_position (const_tree field) { return tree_low_cst (byte_position (field), 0); } @@ -1885,27 +1915,24 @@ int_byte_position (tree field) /* Return the strictest alignment, in bits, that T is known to have. */ unsigned int -expr_align (tree t) +expr_align (const_tree t) { unsigned int align0, align1; switch (TREE_CODE (t)) { - case NOP_EXPR: case CONVERT_EXPR: case NON_LVALUE_EXPR: + CASE_CONVERT: case NON_LVALUE_EXPR: /* If we have conversions, we know that the alignment of the object must meet each of the alignments of the types. */ align0 = expr_align (TREE_OPERAND (t, 0)); align1 = TYPE_ALIGN (TREE_TYPE (t)); return MAX (align0, align1); - case MODIFY_EXPR: - /* FIXME tuples: It is unclear to me if this function, which - is only called from ADA, is called on gimple or non gimple - trees. Let's assume it's from gimple trees unless we hit - this abort. */ + case GIMPLE_MODIFY_STMT: + /* We should never ask for the alignment of a gimple statement. */ gcc_unreachable (); - case SAVE_EXPR: case COMPOUND_EXPR: case GIMPLE_MODIFY_STMT: + case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR: case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR: case CLEANUP_POINT_EXPR: /* These don't change the alignment of an object. */ @@ -1918,14 +1945,13 @@ expr_align (tree t) align1 = expr_align (TREE_OPERAND (t, 2)); return MIN (align0, align1); + /* FIXME: LABEL_DECL and CONST_DECL never have DECL_ALIGN set + meaningfully, it's always 1. */ case LABEL_DECL: case CONST_DECL: case VAR_DECL: case PARM_DECL: case RESULT_DECL: - if (DECL_ALIGN (t) != 0) - return DECL_ALIGN (t); - break; - case FUNCTION_DECL: - return FUNCTION_BOUNDARY; + gcc_assert (DECL_ALIGN (t) != 0); + return DECL_ALIGN (t); default: break; @@ -1939,7 +1965,7 @@ expr_align (tree t) ARRAY_TYPE) minus one. This counts only elements of the top array. */ tree -array_type_nelts (tree type) +array_type_nelts (const_tree type) { tree index_type, min, max; @@ -2026,7 +2052,111 @@ staticp (tree arg) return NULL; } } + + + +/* Return whether OP is a DECL whose address is function-invariant. */ + +bool +decl_address_invariant_p (const_tree op) +{ + /* The conditions below are slightly less strict than the one in + staticp. */ + + switch (TREE_CODE (op)) + { + case PARM_DECL: + case RESULT_DECL: + case LABEL_DECL: + case FUNCTION_DECL: + return true; + + case VAR_DECL: + if (((TREE_STATIC (op) || DECL_EXTERNAL (op)) + && !DECL_DLLIMPORT_P (op)) + || DECL_THREAD_LOCAL_P (op) + || DECL_CONTEXT (op) == current_function_decl + || decl_function_context (op) == current_function_decl) + return true; + break; + + case CONST_DECL: + if ((TREE_STATIC (op) || DECL_EXTERNAL (op)) + || decl_function_context (op) == current_function_decl) + return true; + break; + + default: + break; + } + + return false; +} + + +/* Return true if T is function-invariant (internal function, does + not handle arithmetic; that's handled in skip_simple_arithmetic and + tree_invariant_p). */ + +static bool tree_invariant_p (tree t); + +static bool +tree_invariant_p_1 (tree t) +{ + tree op; + + if (TREE_CONSTANT (t) + || (TREE_READONLY (t) && !TREE_SIDE_EFFECTS (t))) + return true; + + switch (TREE_CODE (t)) + { + case SAVE_EXPR: + return true; + + case ADDR_EXPR: + op = TREE_OPERAND (t, 0); + while (handled_component_p (op)) + { + switch (TREE_CODE (op)) + { + case ARRAY_REF: + case ARRAY_RANGE_REF: + if (!tree_invariant_p (TREE_OPERAND (op, 1)) + || TREE_OPERAND (op, 2) != NULL_TREE + || TREE_OPERAND (op, 3) != NULL_TREE) + return false; + break; + + case COMPONENT_REF: + if (TREE_OPERAND (op, 2) != NULL_TREE) + return false; + break; + + default:; + } + op = TREE_OPERAND (op, 0); + } + + return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op); + + default: + break; + } + + return false; +} + +/* Return true if T is function-invariant. */ + +static bool +tree_invariant_p (tree t) +{ + tree inner = skip_simple_arithmetic (t); + return tree_invariant_p_1 (inner); +} + /* Wrap a SAVE_EXPR around EXPR, if appropriate. Do this to any expression which may be used in more than one place, but must be evaluated only once. @@ -2061,11 +2191,10 @@ save_expr (tree expr) Since it is no problem to reevaluate literals, we just return the literal node. */ inner = skip_simple_arithmetic (t); + if (TREE_CODE (inner) == ERROR_MARK) + return inner; - if (TREE_INVARIANT (inner) - || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner)) - || TREE_CODE (inner) == SAVE_EXPR - || TREE_CODE (inner) == ERROR_MARK) + if (tree_invariant_p_1 (inner)) return t; /* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since @@ -2086,7 +2215,6 @@ save_expr (tree expr) value was computed on both sides of the jump. So make sure it isn't eliminated as dead. */ TREE_SIDE_EFFECTS (t) = 1; - TREE_INVARIANT (t) = 1; return t; } @@ -2114,9 +2242,9 @@ skip_simple_arithmetic (tree expr) inner = TREE_OPERAND (inner, 0); else if (BINARY_CLASS_P (inner)) { - if (TREE_INVARIANT (TREE_OPERAND (inner, 1))) + if (tree_invariant_p (TREE_OPERAND (inner, 1))) inner = TREE_OPERAND (inner, 0); - else if (TREE_INVARIANT (TREE_OPERAND (inner, 0))) + else if (tree_invariant_p (TREE_OPERAND (inner, 0))) inner = TREE_OPERAND (inner, 1); else break; @@ -2131,9 +2259,9 @@ skip_simple_arithmetic (tree expr) /* Return which tree structure is used by T. */ enum tree_node_structure_enum -tree_node_structure (tree t) +tree_node_structure (const_tree t) { - enum tree_code code = TREE_CODE (t); + const enum tree_code code = TREE_CODE (t); switch (TREE_CODE_CLASS (code)) { @@ -2159,7 +2287,6 @@ tree_node_structure (tree t) return TS_FUNCTION_DECL; case SYMBOL_MEMORY_TAG: case NAME_MEMORY_TAG: - case STRUCT_FIELD_TAG: case MEMORY_PARTITION_TAG: return TS_MEMORY_TAG; default: @@ -2174,6 +2301,7 @@ tree_node_structure (tree t) case tcc_binary: case tcc_expression: case tcc_statement: + case tcc_vl_exp: return TS_EXP; case tcc_gimple_stmt: return TS_GIMPLE_STATEMENT; @@ -2185,6 +2313,7 @@ tree_node_structure (tree t) /* 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; @@ -2214,7 +2343,7 @@ tree_node_structure (tree t) or offset that depends on a field within a record. */ bool -contains_placeholder_p (tree exp) +contains_placeholder_p (const_tree exp) { enum tree_code code; @@ -2255,9 +2384,6 @@ contains_placeholder_p (tree exp) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2))); - case CALL_EXPR: - return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)); - default: break; } @@ -2273,6 +2399,22 @@ contains_placeholder_p (tree exp) return 0; } + case tcc_vl_exp: + switch (code) + { + case CALL_EXPR: + { + const_tree arg; + const_call_expr_arg_iterator iter; + FOR_EACH_CONST_CALL_EXPR_ARG (arg, iter, exp) + if (CONTAINS_PLACEHOLDER_P (arg)) + return 1; + return 0; + } + default: + return 0; + } + default: return 0; } @@ -2284,7 +2426,7 @@ contains_placeholder_p (tree exp) (for QUAL_UNION_TYPE) and field positions. */ static bool -type_contains_placeholder_1 (tree type) +type_contains_placeholder_1 (const_tree type) { /* If the size contains a placeholder or the parent type (component type in the case of arrays) type involves a placeholder, this type does. */ @@ -2312,6 +2454,7 @@ type_contains_placeholder_1 (tree type) case INTEGER_TYPE: case REAL_TYPE: + case FIXED_POINT_TYPE: /* Here we just check the bounds. */ return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type)) || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type))); @@ -2377,8 +2520,7 @@ 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, inner; /* We handle TREE_LIST and COMPONENT_REF separately. */ if (code == TREE_LIST) @@ -2480,6 +2622,30 @@ substitute_in_expr (tree exp, tree f, tree r) } break; + case tcc_vl_exp: + { + tree copy = NULL_TREE; + int i; + + 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 (copy) + new = fold (copy); + else + return exp; + } + break; + default: gcc_unreachable (); } @@ -2511,6 +2677,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) : (REFERENCE_CLASS_P (elt) || UNARY_CLASS_P (elt) || BINARY_CLASS_P (elt) + || VL_EXP_CLASS_P (elt) || EXPRESSION_CLASS_P (elt)) ? TREE_OPERAND (elt, 0) : 0)) if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type) @@ -2523,6 +2690,7 @@ substitute_placeholder_in_expr (tree exp, tree obj) : (REFERENCE_CLASS_P (elt) || UNARY_CLASS_P (elt) || BINARY_CLASS_P (elt) + || VL_EXP_CLASS_P (elt) || EXPRESSION_CLASS_P (elt)) ? TREE_OPERAND (elt, 0) : 0)) if (POINTER_TYPE_P (TREE_TYPE (elt)) @@ -2610,6 +2778,29 @@ substitute_placeholder_in_expr (tree exp, tree obj) } break; + case tcc_vl_exp: + { + tree copy = NULL_TREE; + int i; + + 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 (copy) + return fold (copy); + else + return exp; + } + default: gcc_unreachable (); } @@ -2637,8 +2828,7 @@ stabilize_reference (tree ref) /* No action is needed in this case. */ return ref; - case NOP_EXPR: - case CONVERT_EXPR: + CASE_CONVERT: case FLOAT_EXPR: case FIX_TRUNC_EXPR: result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0))); @@ -2723,7 +2913,7 @@ stabilize_reference_1 (tree e) ignore things that are actual constant or that already have been handled by this function. */ - if (TREE_INVARIANT (e)) + if (tree_invariant_p (e)) return e; switch (TREE_CODE_CLASS (code)) @@ -2735,6 +2925,7 @@ stabilize_reference_1 (tree e) case tcc_statement: case tcc_expression: case tcc_reference: + case tcc_vl_exp: /* If the expression has side-effects, then encase it in a SAVE_EXPR so that it will only be evaluated once. */ /* The reference (r) and comparison (<) classes could be handled as @@ -2775,7 +2966,6 @@ stabilize_reference_1 (tree e) TREE_READONLY (result) = TREE_READONLY (e); TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e); TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e); - TREE_INVARIANT (result) = 1; return result; } @@ -2783,13 +2973,13 @@ stabilize_reference_1 (tree e) /* Low-level constructors for expressions. */ /* A helper function for build1 and constant folders. Set TREE_CONSTANT, - TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR. */ + and TREE_SIDE_EFFECTS for an ADDR_EXPR. */ void recompute_tree_invariant_for_addr_expr (tree t) { tree node; - bool tc = true, ti = true, se = false; + bool tc = true, se = false; /* We started out assuming this address is both invariant and constant, but does not have side effects. Now go down any handled components and see if @@ -2799,9 +2989,8 @@ recompute_tree_invariant_for_addr_expr (tree t) ??? Note that this code makes no attempt to deal with the case where taking the address of something causes a copy due to misalignment. */ -#define UPDATE_TITCSE(NODE) \ +#define UPDATE_FLAGS(NODE) \ do { tree _node = (NODE); \ - if (_node && !TREE_INVARIANT (_node)) ti = false; \ if (_node && !TREE_CONSTANT (_node)) tc = false; \ if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0) @@ -2815,11 +3004,11 @@ do { tree _node = (NODE); \ || TREE_CODE (node) == ARRAY_RANGE_REF) && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE) { - UPDATE_TITCSE (TREE_OPERAND (node, 1)); + UPDATE_FLAGS (TREE_OPERAND (node, 1)); if (TREE_OPERAND (node, 2)) - UPDATE_TITCSE (TREE_OPERAND (node, 2)); + UPDATE_FLAGS (TREE_OPERAND (node, 2)); if (TREE_OPERAND (node, 3)) - UPDATE_TITCSE (TREE_OPERAND (node, 3)); + UPDATE_FLAGS (TREE_OPERAND (node, 3)); } /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a FIELD_DECL, apparently. The G++ front end can put something else @@ -2828,46 +3017,35 @@ do { tree _node = (NODE); \ && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL) { if (TREE_OPERAND (node, 2)) - UPDATE_TITCSE (TREE_OPERAND (node, 2)); + UPDATE_FLAGS (TREE_OPERAND (node, 2)); } else if (TREE_CODE (node) == BIT_FIELD_REF) - UPDATE_TITCSE (TREE_OPERAND (node, 2)); + UPDATE_FLAGS (TREE_OPERAND (node, 2)); } - node = lang_hooks.expr_to_decl (node, &tc, &ti, &se); + node = lang_hooks.expr_to_decl (node, &tc, &se); /* Now see what's inside. If it's an INDIRECT_REF, copy our properties from - the address, since &(*a)->b is a form of addition. If it's a decl, it's - invariant and constant if the decl is static. It's also invariant if it's - a decl in the current function. Taking the address of a volatile variable - is not volatile. If it's a constant, the address is both invariant and - constant. Otherwise it's neither. */ + the address, since &(*a)->b is a form of addition. If it's a constant, the + address is constant too. If it's a decl, its address is constant if the + decl is static. Everything else is not constant and, furthermore, + taking the address of a volatile variable is not volatile. */ if (TREE_CODE (node) == INDIRECT_REF) - UPDATE_TITCSE (TREE_OPERAND (node, 0)); - else if (DECL_P (node)) - { - if (staticp (node)) - ; - else if (decl_function_context (node) == current_function_decl - /* Addresses of thread-local variables are invariant. */ - || (TREE_CODE (node) == VAR_DECL - && DECL_THREAD_LOCAL_P (node))) - tc = false; - else - ti = tc = false; - } + UPDATE_FLAGS (TREE_OPERAND (node, 0)); else if (CONSTANT_CLASS_P (node)) ; + else if (DECL_P (node)) + tc &= (staticp (node) != NULL_TREE); else { - ti = tc = false; + tc = false; se |= TREE_SIDE_EFFECTS (node); } + TREE_CONSTANT (t) = tc; - TREE_INVARIANT (t) = ti; TREE_SIDE_EFFECTS (t) = se; -#undef UPDATE_TITCSE +#undef UPDATE_FLAGS } /* Build an expression of code CODE, data type TYPE, and operands as @@ -2926,12 +3104,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) TREE_SET_CODE (t, code); TREE_TYPE (t) = type; -#ifdef USE_MAPPED_LOCATION SET_EXPR_LOCATION (t, UNKNOWN_LOCATION); -#else - SET_EXPR_LOCUS (t, NULL); -#endif - TREE_COMPLEXITY (t) = 0; TREE_OPERAND (t, 0) = node; TREE_BLOCK (t) = NULL_TREE; if (node && !TYPE_P (node)) @@ -2969,9 +3142,6 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) && node && !TYPE_P (node) && TREE_CONSTANT (node)) TREE_CONSTANT (t) = 1; - if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR) - && node && TREE_INVARIANT (node)) - TREE_INVARIANT (t) = 1; if (TREE_CODE_CLASS (code) == tcc_reference && node && TREE_THIS_VOLATILE (node)) TREE_THIS_VOLATILE (t) = 1; @@ -2992,29 +3162,34 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL) read_only = 0; \ if (!TREE_CONSTANT (arg##N)) \ constant = 0; \ - if (!TREE_INVARIANT (arg##N)) \ - invariant = 0; \ } \ } while (0) tree build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) { - bool constant, read_only, side_effects, invariant; + bool constant, read_only, side_effects; tree t; gcc_assert (TREE_CODE_LENGTH (code) == 2); - if (code == MODIFY_EXPR && cfun && cfun->gimplified) - { - /* We should be talking GIMPLE_MODIFY_STMT by now. */ - gcc_unreachable (); - } +#if 1 + /* FIXME tuples: Statement's aren't expressions! */ + if (code == GIMPLE_MODIFY_STMT) + return build_gimple_modify_stmt_stat (arg0, arg1 PASS_MEM_STAT); +#else + /* Must use build_gimple_modify_stmt to construct GIMPLE_MODIFY_STMTs. */ + gcc_assert (code != GIMPLE_MODIFY_STMT); +#endif - /* FIXME tuples: For now let's be lazy; later we must rewrite all - build2 calls to build2_gimple calls. */ - if (TREE_CODE_CLASS (code) == tcc_gimple_stmt) - return build2_gimple (code, arg0, arg1); + if ((code == MINUS_EXPR || code == PLUS_EXPR || code == MULT_EXPR) + && arg0 && arg1 && tt && POINTER_TYPE_P (tt)) + gcc_assert (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST); + + if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt) + gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0)) + && INTEGRAL_TYPE_P (TREE_TYPE (arg1)) + && useless_type_conversion_p (sizetype, TREE_TYPE (arg1))); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; @@ -3030,14 +3205,12 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) || TREE_CODE_CLASS (code) == tcc_binary); read_only = 1; side_effects = TREE_SIDE_EFFECTS (t); - invariant = constant; PROCESS_ARG(0); PROCESS_ARG(1); TREE_READONLY (t) = read_only; TREE_CONSTANT (t) = constant; - TREE_INVARIANT (t) = invariant; TREE_SIDE_EFFECTS (t) = side_effects; TREE_THIS_VOLATILE (t) = (TREE_CODE_CLASS (code) == tcc_reference @@ -3047,31 +3220,18 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) } -/* Similar as build2_stat, but for GIMPLE tuples. For convenience's sake, - arguments and return type are trees. */ +/* Build a GIMPLE_MODIFY_STMT node. This tree code doesn't have a + type, so we can't use build2 (a.k.a. build2_stat). */ tree -build2_gimple_stat (enum tree_code code, tree arg0, tree arg1 MEM_STAT_DECL) +build_gimple_modify_stmt_stat (tree arg0, tree arg1 MEM_STAT_DECL) { - bool side_effects; tree t; - gcc_assert (TREE_CODE_LENGTH (code) == 2); - - t = make_node_stat (code PASS_MEM_STAT); - - side_effects = TREE_SIDE_EFFECTS (t); - + t = make_node_stat (GIMPLE_MODIFY_STMT PASS_MEM_STAT); /* ?? We don't care about setting flags for tuples... */ GIMPLE_STMT_OPERAND (t, 0) = arg0; GIMPLE_STMT_OPERAND (t, 1) = arg1; - - /* ...except perhaps side_effects and volatility. ?? */ - TREE_SIDE_EFFECTS (t) = side_effects; - TREE_THIS_VOLATILE (t) = (TREE_CODE_CLASS (code) == tcc_reference - && arg0 && TREE_THIS_VOLATILE (arg0)); - - return t; } @@ -3079,40 +3239,30 @@ tree build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree arg2 MEM_STAT_DECL) { - bool constant, read_only, side_effects, invariant; + bool constant, read_only, side_effects; tree t; gcc_assert (TREE_CODE_LENGTH (code) == 3); + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); t = make_node_stat (code PASS_MEM_STAT); TREE_TYPE (t) = tt; - side_effects = TREE_SIDE_EFFECTS (t); + /* 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. */ + if (code == COND_EXPR + && tt == void_type_node + && arg1 == NULL_TREE + && arg2 == NULL_TREE) + side_effects = true; + else + side_effects = TREE_SIDE_EFFECTS (t); PROCESS_ARG(0); PROCESS_ARG(1); PROCESS_ARG(2); - if (code == CALL_EXPR && !side_effects) - { - tree node; - int i; - - /* Calls have side-effects, except those to const or - pure functions. */ - i = call_expr_flags (t); - if (!(i & (ECF_CONST | ECF_PURE))) - side_effects = 1; - - /* And even those have side-effects if their arguments do. */ - else for (node = arg1; node; node = TREE_CHAIN (node)) - if (TREE_SIDE_EFFECTS (TREE_VALUE (node))) - { - side_effects = 1; - break; - } - } - TREE_SIDE_EFFECTS (t) = side_effects; TREE_THIS_VOLATILE (t) = (TREE_CODE_CLASS (code) == tcc_reference @@ -3125,7 +3275,7 @@ tree build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree arg2, tree arg3 MEM_STAT_DECL) { - bool constant, read_only, side_effects, invariant; + bool constant, read_only, side_effects; tree t; gcc_assert (TREE_CODE_LENGTH (code) == 4); @@ -3152,7 +3302,7 @@ tree build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree arg2, tree arg3, tree arg4 MEM_STAT_DECL) { - bool constant, read_only, side_effects, invariant; + bool constant, read_only, side_effects; tree t; gcc_assert (TREE_CODE_LENGTH (code) == 5); @@ -3181,7 +3331,7 @@ build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1, tree arg2, tree arg3, tree arg4, tree arg5, tree arg6 MEM_STAT_DECL) { - bool constant, read_only, side_effects, invariant; + bool constant, read_only, side_effects; tree t; gcc_assert (code == TARGET_MEM_REF); @@ -3218,6 +3368,8 @@ build_nt (enum tree_code code, ...) int i; va_list p; + gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); + va_start (p, code); t = make_node (code); @@ -3229,6 +3381,23 @@ build_nt (enum tree_code code, ...) va_end (p); return t; } + +/* Similar to build_nt, but for creating a CALL_EXPR object with + ARGLIST passed as a list. */ + +tree +build_nt_call_list (tree fn, tree arglist) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3); + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++) + CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist); + return t; +} /* Create a DECL_... node of code CODE, name NAME and data type TYPE. We do NOT enter this node in any sort of symbol table. @@ -3253,8 +3422,6 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL) if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL) layout_decl (t, 0); - else if (code == FUNCTION_DECL) - DECL_MODE (t) = FUNCTION_MODE; return t; } @@ -3292,13 +3459,6 @@ build_block (tree vars, tree subblocks, tree supercontext, tree chain) return block; } -#if 1 /* ! defined(USE_MAPPED_LOCATION) */ -/* ??? gengtype doesn't handle conditionals */ -static GTY(()) source_locus last_annotated_node; -#endif - -#ifdef USE_MAPPED_LOCATION - expanded_location expand_location (source_location loc) { @@ -3311,7 +3471,7 @@ expand_location (source_location loc) } else { - const struct line_map *map = linemap_lookup (&line_table, loc); + const struct line_map *map = linemap_lookup (line_table, loc); xloc.file = map->to_file; xloc.line = SOURCE_LINE (map, loc); xloc.column = SOURCE_COLUMN (map, loc); @@ -3319,50 +3479,6 @@ expand_location (source_location loc) return xloc; } -#else - -/* Record the exact location where an expression or an identifier were - encountered. */ - -void -annotate_with_file_line (tree node, const char *file, int line) -{ - /* Roughly one percent of the calls to this function are to annotate - a node with the same information already attached to that node! - Just return instead of wasting memory. */ - if (EXPR_LOCUS (node) - && EXPR_LINENO (node) == line - && (EXPR_FILENAME (node) == file - || !strcmp (EXPR_FILENAME (node), file))) - { - last_annotated_node = EXPR_LOCUS (node); - return; - } - - /* In heavily macroized code (such as GCC itself) this single - entry cache can reduce the number of allocations by more - than half. */ - if (last_annotated_node - && last_annotated_node->line == line - && (last_annotated_node->file == file - || !strcmp (last_annotated_node->file, file))) - { - SET_EXPR_LOCUS (node, last_annotated_node); - return; - } - - SET_EXPR_LOCUS (node, ggc_alloc (sizeof (location_t))); - EXPR_LINENO (node) = line; - EXPR_FILENAME (node) = file; - last_annotated_node = EXPR_LOCUS (node); -} - -void -annotate_with_locus (tree node, location_t locus) -{ - annotate_with_file_line (node, locus.file, locus.line); -} -#endif /* Source location accessor functions. */ @@ -3371,73 +3487,41 @@ annotate_with_locus (tree node, location_t locus) decls and constants can be shared among multiple locations, so return nothing. */ location_t -expr_location (tree node) +expr_location (const_tree node) { -#ifdef USE_MAPPED_LOCATION if (GIMPLE_STMT_P (node)) return GIMPLE_STMT_LOCUS (node); return EXPR_P (node) ? node->exp.locus : UNKNOWN_LOCATION; -#else - if (GIMPLE_STMT_P (node)) - return EXPR_HAS_LOCATION (node) - ? *GIMPLE_STMT_LOCUS (node) : UNKNOWN_LOCATION; - return EXPR_HAS_LOCATION (node) ? *node->exp.locus : UNKNOWN_LOCATION; -#endif } void set_expr_location (tree node, location_t locus) { -#ifdef USE_MAPPED_LOCATION if (GIMPLE_STMT_P (node)) GIMPLE_STMT_LOCUS (node) = locus; else EXPR_CHECK (node)->exp.locus = locus; -#else - annotate_with_locus (node, locus); -#endif } bool -expr_has_location (tree node) +expr_has_location (const_tree node) { -#ifdef USE_MAPPED_LOCATION return expr_location (node) != UNKNOWN_LOCATION; -#else - return expr_locus (node) != NULL; -#endif } -#ifdef USE_MAPPED_LOCATION source_location * -#else -source_locus -#endif -expr_locus (tree node) +expr_locus (const_tree node) { -#ifdef USE_MAPPED_LOCATION - if (GIMPLE_STMT_P (node)) - return &GIMPLE_STMT_LOCUS (node); - return EXPR_P (node) ? &node->exp.locus : (location_t *) NULL; -#else if (GIMPLE_STMT_P (node)) - return GIMPLE_STMT_LOCUS (node); - /* ?? The cast below was originally "(location_t *)" in the macro, - but that makes no sense. ?? */ - return EXPR_P (node) ? node->exp.locus : (source_locus) NULL; -#endif + return CONST_CAST (source_location *, &GIMPLE_STMT_LOCUS (node)); + return (EXPR_P (node) + ? CONST_CAST (source_location *, &node->exp.locus) + : (source_location *) NULL); } void -set_expr_locus (tree node, -#ifdef USE_MAPPED_LOCATION - source_location *loc -#else - source_locus loc -#endif - ) +set_expr_locus (tree node, source_location *loc) { -#ifdef USE_MAPPED_LOCATION if (loc == NULL) { if (GIMPLE_STMT_P (node)) @@ -3452,41 +3536,26 @@ set_expr_locus (tree node, else EXPR_CHECK (node)->exp.locus = *loc; } -#else - if (GIMPLE_STMT_P (node)) - GIMPLE_STMT_LOCUS (node) = loc; - else - EXPR_CHECK (node)->exp.locus = loc; -#endif } -const char ** -expr_filename (tree node) +/* Return the file name of the location of NODE. */ +const char * +expr_filename (const_tree node) { -#ifdef USE_MAPPED_LOCATION if (GIMPLE_STMT_P (node)) - return &LOCATION_FILE (GIMPLE_STMT_LOCUS (node)); - return &LOCATION_FILE (EXPR_CHECK (node)->exp.locus); -#else - if (GIMPLE_STMT_P (node)) - return &GIMPLE_STMT_LOCUS (node)->file; - return &(EXPR_CHECK (node)->exp.locus->file); -#endif + return LOCATION_FILE (GIMPLE_STMT_LOCUS (node)); + return LOCATION_FILE (EXPR_CHECK (node)->exp.locus); } -int * -expr_lineno (tree node) +/* Return the line number of the location of NODE. */ +int +expr_lineno (const_tree node) { -#ifdef USE_MAPPED_LOCATION if (GIMPLE_STMT_P (node)) - return &LOCATION_LINE (GIMPLE_STMT_LOCUS (node)); - return &LOCATION_LINE (EXPR_CHECK (node)->exp.locus); -#else - if (GIMPLE_STMT_P (node)) - return &GIMPLE_STMT_LOCUS (node)->line; - return &EXPR_CHECK (node)->exp.locus->line; -#endif + return LOCATION_LINE (GIMPLE_STMT_LOCUS (node)); + return LOCATION_LINE (EXPR_CHECK (node)->exp.locus); } + /* Return a declaration like DDECL except that its DECL_ATTRIBUTES is ATTRIBUTE. */ @@ -3526,7 +3595,7 @@ iterative_hash_hashval_t (hashval_t val, hashval_t val2) /* Produce good hash value combining PTR and VAL2. */ static inline hashval_t -iterative_hash_pointer (void *ptr, hashval_t val2) +iterative_hash_pointer (const void *ptr, hashval_t val2) { if (sizeof (ptr) == sizeof (hashval_t)) return iterative_hash_hashval_t ((size_t) ptr, val2); @@ -3580,21 +3649,26 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) tree ntype; enum tree_code code = TREE_CODE (ttype); - ntype = copy_node (ttype); - - TYPE_POINTER_TO (ntype) = 0; - TYPE_REFERENCE_TO (ntype) = 0; - TYPE_ATTRIBUTES (ntype) = attribute; + /* Building a distinct copy of a tagged type is inappropriate; it + causes breakage in code that expects there to be a one-to-one + relationship between a struct and its fields. + build_duplicate_type is another solution (as used in + handle_transparent_union_attribute), but that doesn't play well + with the stronger C++ type identity model. */ + if (TREE_CODE (ttype) == RECORD_TYPE + || TREE_CODE (ttype) == UNION_TYPE + || TREE_CODE (ttype) == QUAL_UNION_TYPE + || TREE_CODE (ttype) == ENUMERAL_TYPE) + { + warning (OPT_Wattributes, + "ignoring attributes applied to %qT after definition", + TYPE_MAIN_VARIANT (ttype)); + return build_qualified_type (ttype, quals); + } - if (TYPE_STRUCTURAL_EQUALITY_P (ttype)) - SET_TYPE_STRUCTURAL_EQUALITY (ntype); - else - TYPE_CANONICAL (ntype) - = build_qualified_type (TYPE_CANONICAL (ttype), quals); + ntype = build_distinct_type_copy (ttype); - /* Create a new main variant of TYPE. */ - TYPE_MAIN_VARIANT (ntype) = ntype; - TYPE_NEXT_VARIANT (ntype) = 0; + TYPE_ATTRIBUTES (ntype) = attribute; set_type_quals (ntype, TYPE_UNQUALIFIED); hashcode = iterative_hash_object (code, hashcode); @@ -3609,8 +3683,9 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode); break; case ARRAY_TYPE: - hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)), - hashcode); + if (TYPE_DOMAIN (ntype)) + hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)), + hashcode); break; case INTEGER_TYPE: hashcode = iterative_hash_object @@ -3619,6 +3694,7 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode); break; case REAL_TYPE: + case FIXED_POINT_TYPE: { unsigned int precision = TYPE_PRECISION (ntype); hashcode = iterative_hash_object (precision, hashcode); @@ -3633,11 +3709,17 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) /* If the target-dependent attributes make NTYPE different from its canonical type, we will need to use structural equality checks for this qualified type. */ - if (!targetm.comp_type_attributes (ntype, ttype)) + ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED); + if (TYPE_STRUCTURAL_EQUALITY_P (ttype) + || !targetm.comp_type_attributes (ntype, ttype)) SET_TYPE_STRUCTURAL_EQUALITY (ntype); + else + TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); ttype = build_qualified_type (ntype, quals); } + else if (TYPE_QUALS (ttype) != quals) + ttype = build_qualified_type (ttype, quals); return ttype; } @@ -3664,7 +3746,7 @@ build_type_attribute_variant (tree ttype, tree attribute) their canonicalized form. */ static int -is_attribute_with_length_p (const char *attr, int attr_len, tree ident) +is_attribute_with_length_p (const char *attr, int attr_len, const_tree ident) { int ident_len; const char *p; @@ -3707,7 +3789,7 @@ is_attribute_with_length_p (const char *attr, int attr_len, tree ident) We try both `text' and `__text__', ATTR may be either one. */ int -is_attribute_p (const char *attr, tree ident) +is_attribute_p (const char *attr, const_tree ident) { return is_attribute_with_length_p (attr, strlen (attr), ident); } @@ -3730,7 +3812,6 @@ lookup_attribute (const char *attr_name, tree list) if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l))) return l; } - return NULL_TREE; } @@ -3869,7 +3950,7 @@ merge_dllimport_decl_attributes (tree old, tree new) } else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new)) { - /* Warn about overriding a symbol that has already been used. eg: + /* Warn about overriding a symbol that has already been used, e.g.: extern int __attribute__ ((dllimport)) foo; int* bar () {return &foo;} int foo; @@ -3880,8 +3961,7 @@ merge_dllimport_decl_attributes (tree old, tree new) "after being referenced with dll linkage", new); /* If we have used a variable's address with dllimport linkage, keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the - decl may already have had TREE_INVARIANT and TREE_CONSTANT - computed. + decl may already have had TREE_CONSTANT computed. We still remove the attribute so that assembler code refers to '&foo rather than '_imp__foo'. */ if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old)) @@ -3942,18 +4022,35 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, *no_add_attrs = true; return tree_cons (name, args, NULL_TREE); } - if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) + if (TREE_CODE (node) == RECORD_TYPE + || TREE_CODE (node) == UNION_TYPE) + { + node = TYPE_NAME (node); + if (!node) + return NULL_TREE; + } + else { warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; + return NULL_TREE; } + } + if (TREE_CODE (node) != FUNCTION_DECL + && TREE_CODE (node) != VAR_DECL + && TREE_CODE (node) != TYPE_DECL) + { + *no_add_attrs = true; + warning (OPT_Wattributes, "%qs attribute ignored", + IDENTIFIER_POINTER (name)); return NULL_TREE; } - if (TREE_CODE (node) != FUNCTION_DECL - && TREE_CODE (node) != VAR_DECL) + if (TREE_CODE (node) == TYPE_DECL + && TREE_CODE (TREE_TYPE (node)) != RECORD_TYPE + && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE) { *no_add_attrs = true; warning (OPT_Wattributes, "%qs attribute ignored", @@ -4016,6 +4113,22 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, *no_add_attrs = true; } + /* A dllexport'd entity must have default visibility so that other + program units (shared libraries or the main executable) can see + it. A dllimport'd entity must have default visibility so that + the linker knows that undefined references within this program + unit can be resolved by the dynamic linker. */ + if (!*no_add_attrs) + { + 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); + DECL_VISIBILITY (node) = VISIBILITY_DEFAULT; + DECL_VISIBILITY_SPECIFIED (node) = 1; + } + return NULL_TREE; } @@ -4032,10 +4145,10 @@ set_type_quals (tree type, int type_quals) TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0; } -/* Returns true iff cand is equivalent to base with type_quals. */ +/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */ bool -check_qualified_type (tree cand, tree base, int type_quals) +check_qualified_type (const_tree cand, const_tree base, int type_quals) { return (TYPE_QUALS (cand) == type_quals && TYPE_NAME (cand) == TYPE_NAME (base) @@ -4124,7 +4237,11 @@ build_distinct_type_copy (tree type) /* Make it its own variant. */ TYPE_MAIN_VARIANT (t) = t; TYPE_NEXT_VARIANT (t) = 0; - + + /* Note that it is now possible for TYPE_MIN_VALUE to be a value + whose TREE_TYPE is not t. This can also happen in the Ada + frontend when using subtypes. */ + return t; } @@ -4156,18 +4273,18 @@ build_variant_type_copy (tree type) /* Return true if the from tree in both tree maps are equal. */ int -tree_map_eq (const void *va, const void *vb) +tree_map_base_eq (const void *va, const void *vb) { - const struct tree_map *a = va, *b = vb; + const struct tree_map_base *const a = va, *const b = vb; return (a->from == b->from); } /* Hash a from tree in a tree_map. */ unsigned int -tree_map_hash (const void *item) +tree_map_base_hash (const void *item) { - return (((const struct tree_map *) item)->hash); + return htab_hash_pointer (((const struct tree_map_base *)item)->from); } /* Return true if this tree map structure is marked for garbage collection @@ -4175,70 +4292,93 @@ tree_map_hash (const void *item) structure goes away when the from tree goes away. */ int -tree_map_marked_p (const void *p) +tree_map_base_marked_p (const void *p) { - tree from = ((struct tree_map *) p)->from; - - return ggc_marked_p (from); + return ggc_marked_p (((const struct tree_map_base *) p)->from); } -/* Return true if the trees in the tree_int_map *'s VA and VB are equal. */ - -static int -tree_int_map_eq (const void *va, const void *vb) -{ - const struct tree_int_map *a = va, *b = vb; - return (a->from == b->from); +unsigned int +tree_map_hash (const void *item) +{ + return (((const struct tree_map *) item)->hash); } -/* Hash a from tree in the tree_int_map * ITEM. */ +/* Return the initialization priority for DECL. */ -static unsigned int -tree_int_map_hash (const void *item) +priority_type +decl_init_priority_lookup (tree decl) { - return htab_hash_pointer (((const struct tree_int_map *)item)->from); + struct tree_priority_map *h; + struct tree_map_base in; + + gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); + in.from = decl; + h = htab_find (init_priority_for_decl, &in); + return h ? h->init : DEFAULT_INIT_PRIORITY; } -/* Return true if this tree int map structure is marked for garbage collection - purposes. We simply return true if the from tree_int_map *P's from tree is marked, so that this - structure goes away when the from tree goes away. */ +/* Return the finalization priority for DECL. */ -static int -tree_int_map_marked_p (const void *p) +priority_type +decl_fini_priority_lookup (tree decl) { - tree from = ((struct tree_int_map *) p)->from; + struct tree_priority_map *h; + struct tree_map_base in; - return ggc_marked_p (from); + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); + in.from = decl; + h = htab_find (init_priority_for_decl, &in); + return h ? h->fini : DEFAULT_INIT_PRIORITY; } -/* Lookup an init priority for FROM, and return it if we find one. */ -unsigned short -decl_init_priority_lookup (tree from) +/* Return the initialization and finalization priority information for + DECL. If there is no previous priority information, a freshly + allocated structure is returned. */ + +static struct tree_priority_map * +decl_priority_info (tree decl) { - struct tree_int_map *h, in; - in.from = from; + struct tree_priority_map in; + struct tree_priority_map *h; + void **loc; - h = htab_find_with_hash (init_priority_for_decl, - &in, htab_hash_pointer (from)); - if (h) - return h->to; - return 0; + in.base.from = decl; + loc = htab_find_slot (init_priority_for_decl, &in, INSERT); + h = *loc; + if (!h) + { + h = GGC_CNEW (struct tree_priority_map); + *loc = h; + h->base.from = decl; + h->init = DEFAULT_INIT_PRIORITY; + h->fini = DEFAULT_INIT_PRIORITY; + } + + return h; } -/* Insert a mapping FROM->TO in the init priority hashtable. */ +/* Set the initialization priority for DECL to PRIORITY. */ void -decl_init_priority_insert (tree from, unsigned short to) +decl_init_priority_insert (tree decl, priority_type priority) { - struct tree_int_map *h; - void **loc; + struct tree_priority_map *h; - h = ggc_alloc (sizeof (struct tree_int_map)); - h->from = from; - h->to = to; - loc = htab_find_slot_with_hash (init_priority_for_decl, h, - htab_hash_pointer (from), INSERT); - *(struct tree_int_map **) loc = h; + gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); + h = decl_priority_info (decl); + h->init = priority; +} + +/* Set the finalization priority for DECL to PRIORITY. */ + +void +decl_fini_priority_insert (tree decl, priority_type priority) +{ + struct tree_priority_map *h; + + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); + h = decl_priority_info (decl); + h->fini = priority; } /* Look up a restrict qualified base decl for FROM. */ @@ -4249,7 +4389,7 @@ decl_restrict_base_lookup (tree from) struct tree_map *h; struct tree_map in; - in.from = from; + in.base.from = from; h = htab_find_with_hash (restrict_base_for_decl, &in, htab_hash_pointer (from)); return h ? h->to : NULL_TREE; @@ -4265,7 +4405,7 @@ decl_restrict_base_insert (tree from, tree to) h = ggc_alloc (sizeof (struct tree_map)); h->hash = htab_hash_pointer (from); - h->from = from; + h->base.from = from; h->to = to; loc = htab_find_slot_with_hash (restrict_base_for_decl, h, h->hash, INSERT); *(struct tree_map **) loc = h; @@ -4313,7 +4453,7 @@ tree decl_debug_expr_lookup (tree from) { struct tree_map *h, in; - in.from = from; + in.base.from = from; h = htab_find_with_hash (debug_expr_for_decl, &in, htab_hash_pointer (from)); if (h) @@ -4331,7 +4471,7 @@ decl_debug_expr_insert (tree from, tree to) h = ggc_alloc (sizeof (struct tree_map)); h->hash = htab_hash_pointer (from); - h->from = from; + h->base.from = from; h->to = to; loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT); *(struct tree_map **) loc = h; @@ -4343,7 +4483,7 @@ tree decl_value_expr_lookup (tree from) { struct tree_map *h, in; - in.from = from; + in.base.from = from; h = htab_find_with_hash (value_expr_for_decl, &in, htab_hash_pointer (from)); if (h) @@ -4361,7 +4501,7 @@ decl_value_expr_insert (tree from, tree to) h = ggc_alloc (sizeof (struct tree_map)); h->hash = htab_hash_pointer (from); - h->from = from; + h->base.from = from; h->to = to; loc = htab_find_slot_with_hash (value_expr_for_decl, h, h->hash, INSERT); *(struct tree_map **) loc = h; @@ -4374,10 +4514,10 @@ decl_value_expr_insert (tree from, tree to) with types in the TREE_VALUE slots), by adding the hash codes of the individual types. */ -unsigned int -type_hash_list (tree list, hashval_t hashcode) +static unsigned int +type_hash_list (const_tree list, hashval_t hashcode) { - tree tail; + const_tree tail; for (tail = list; tail; tail = TREE_CHAIN (tail)) if (TREE_VALUE (tail) != error_mark_node) @@ -4394,7 +4534,7 @@ type_hash_list (tree list, hashval_t hashcode) static int type_hash_eq (const void *va, const void *vb) { - const struct type_hash *a = va, *b = vb; + const struct type_hash *const a = va, *const b = vb; /* First test the things that are the same for all types. */ if (a->hash != b->hash @@ -4439,6 +4579,9 @@ type_hash_eq (const void *va, const void *vb) || tree_int_cst_equal (TYPE_MIN_VALUE (a->type), TYPE_MIN_VALUE (b->type)))); + case FIXED_POINT_TYPE: + return TYPE_SATURATING (a->type) == TYPE_SATURATING (b->type); + case OFFSET_TYPE: return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type); @@ -4467,17 +4610,24 @@ type_hash_eq (const void *va, const void *vb) TYPE_FIELDS (b->type)))); case FUNCTION_TYPE: - return (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type) - || (TYPE_ARG_TYPES (a->type) - && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST - && TYPE_ARG_TYPES (b->type) - && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST - && type_list_equal (TYPE_ARG_TYPES (a->type), - TYPE_ARG_TYPES (b->type)))); + if (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type) + || (TYPE_ARG_TYPES (a->type) + && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST + && TYPE_ARG_TYPES (b->type) + && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST + && type_list_equal (TYPE_ARG_TYPES (a->type), + TYPE_ARG_TYPES (b->type)))) + break; + return 0; default: return 0; } + + if (lang_hooks.types.type_hash_eq != NULL) + return lang_hooks.types.type_hash_eq (a->type, b->type); + + return 1; } /* Return the cached hash value. */ @@ -4522,7 +4672,7 @@ type_hash_add (hashval_t hashcode, tree type) h->hash = hashcode; h->type = type; loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT); - *(struct type_hash **) loc = h; + *loc = (void *)h; } /* Given TYPE, and HASHCODE its hash code, return the canonical @@ -4573,7 +4723,7 @@ type_hash_canon (unsigned int hashcode, tree type) static int type_hash_marked_p (const void *p) { - tree type = ((struct type_hash *) p)->type; + const_tree const type = ((const struct type_hash *) p)->type; return ggc_marked_p (type) || TYPE_SYMTAB_POINTER (type); } @@ -4591,10 +4741,10 @@ print_type_hash_statistics (void) with names in the TREE_PURPOSE slots and args in the TREE_VALUE slots), by adding the hash codes of the individual attributes. */ -unsigned int -attribute_hash_list (tree list, hashval_t hashcode) +static unsigned int +attribute_hash_list (const_tree list, hashval_t hashcode) { - tree tail; + const_tree tail; for (tail = list; tail; tail = TREE_CHAIN (tail)) /* ??? Do we want to add in TREE_VALUE too? */ @@ -4607,7 +4757,7 @@ attribute_hash_list (tree list, hashval_t hashcode) equivalent to l1. */ int -attribute_list_equal (tree l1, tree l2) +attribute_list_equal (const_tree l1, const_tree l2) { return attribute_list_contained (l1, l2) && attribute_list_contained (l2, l1); @@ -4622,9 +4772,9 @@ attribute_list_equal (tree l1, tree l2) correctly. */ int -attribute_list_contained (tree l1, tree l2) +attribute_list_contained (const_tree l1, const_tree l2) { - tree t1, t2; + const_tree t1, t2; /* First check the obvious, maybe the lists are identical. */ if (l1 == l2) @@ -4643,8 +4793,12 @@ attribute_list_contained (tree l1, tree l2) for (; t2 != 0; t2 = TREE_CHAIN (t2)) { - tree attr; - for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1); + const_tree attr; + /* This CONST_CAST is okay because lookup_attribute does not + modify its argument and the return value is assigned to a + const_tree. */ + for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), + CONST_CAST_TREE(l1)); attr != NULL_TREE; attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), TREE_CHAIN (attr))) @@ -4675,9 +4829,9 @@ attribute_list_contained (tree l1, tree l2) Also, the TREE_PURPOSEs must match. */ int -type_list_equal (tree l1, tree l2) +type_list_equal (const_tree l1, const_tree l2) { - tree t1, t2; + const_tree t1, t2; for (t1 = l1, t2 = l2; t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) if (TREE_VALUE (t1) != TREE_VALUE (t2) @@ -4695,7 +4849,7 @@ type_list_equal (tree l1, tree l2) then this function counts only the ordinary arguments. */ int -type_num_arguments (tree type) +type_num_arguments (const_tree type) { int i = 0; tree t; @@ -4715,7 +4869,7 @@ type_num_arguments (tree type) represent the same constant value. */ int -tree_int_cst_equal (tree t1, tree t2) +tree_int_cst_equal (const_tree t1, const_tree t2) { if (t1 == t2) return 1; @@ -4736,7 +4890,7 @@ tree_int_cst_equal (tree t1, tree t2) The precise way of comparison depends on their data type. */ int -tree_int_cst_lt (tree t1, tree t2) +tree_int_cst_lt (const_tree t1, const_tree t2) { if (t1 == t2) return 0; @@ -4763,7 +4917,7 @@ tree_int_cst_lt (tree t1, tree t2) /* Returns -1 if T1 < T2, 0 if T1 == T2, and 1 if T1 > T2. */ int -tree_int_cst_compare (tree t1, tree t2) +tree_int_cst_compare (const_tree t1, const_tree t2) { if (tree_int_cst_lt (t1, t2)) return -1; @@ -4779,14 +4933,16 @@ tree_int_cst_compare (tree t1, tree t2) be represented in a single unsigned HOST_WIDE_INT. */ int -host_integerp (tree t, int pos) +host_integerp (const_tree t, int pos) { return (TREE_CODE (t) == INTEGER_CST && ((TREE_INT_CST_HIGH (t) == 0 && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0) || (! pos && TREE_INT_CST_HIGH (t) == -1 && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0 - && !TYPE_UNSIGNED (TREE_TYPE (t))) + && (!TYPE_UNSIGNED (TREE_TYPE (t)) + || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (TREE_TYPE (t))))) || (pos && TREE_INT_CST_HIGH (t) == 0))); } @@ -4795,7 +4951,7 @@ host_integerp (tree t, int pos) be non-negative. We must be able to satisfy the above conditions. */ HOST_WIDE_INT -tree_low_cst (tree t, int pos) +tree_low_cst (const_tree t, int pos) { gcc_assert (host_integerp (t, pos)); return TREE_INT_CST_LOW (t); @@ -4804,7 +4960,7 @@ tree_low_cst (tree t, int pos) /* Return the most significant bit of the integer constant T. */ int -tree_int_cst_msb (tree t) +tree_int_cst_msb (const_tree t) { int prec; HOST_WIDE_INT h; @@ -4823,7 +4979,7 @@ tree_int_cst_msb (tree t) Note that -1 will never be returned if T's type is unsigned. */ int -tree_int_cst_sgn (tree t) +tree_int_cst_sgn (const_tree t) { if (TREE_INT_CST_LOW (t) == 0 && TREE_INT_CST_HIGH (t) == 0) return 0; @@ -4839,7 +4995,7 @@ tree_int_cst_sgn (tree t) are known to be equal; otherwise return 0. */ int -simple_cst_list_equal (tree l1, tree l2) +simple_cst_list_equal (const_tree l1, const_tree l2) { while (l1 != NULL_TREE && l2 != NULL_TREE) { @@ -4860,7 +5016,7 @@ simple_cst_list_equal (tree l1, tree l2) this function. */ int -simple_cst_equal (tree t1, tree t2) +simple_cst_equal (const_tree t1, const_tree t2) { enum tree_code code1, code2; int cmp; @@ -4899,6 +5055,9 @@ simple_cst_equal (tree t1, tree t2) case REAL_CST: return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2)); + case FIXED_CST: + return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2)); + case STRING_CST: return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2) && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2), @@ -4925,11 +5084,26 @@ simple_cst_equal (tree t1, tree t2) return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); case CALL_EXPR: - cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); + cmp = simple_cst_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)); if (cmp <= 0) return cmp; - return - simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)); + if (call_expr_nargs (t1) != call_expr_nargs (t2)) + return 0; + { + const_tree arg1, arg2; + const_call_expr_arg_iterator iter1, iter2; + for (arg1 = first_const_call_expr_arg (t1, &iter1), + arg2 = first_const_call_expr_arg (t2, &iter2); + arg1 && arg2; + arg1 = next_const_call_expr_arg (&iter1), + arg2 = next_const_call_expr_arg (&iter2)) + { + cmp = simple_cst_equal (arg1, arg2); + if (cmp <= 0) + return cmp; + } + return arg1 == arg2; + } case TARGET_EXPR: /* Special case: if either target is an unallocated VAR_DECL, @@ -5009,7 +5183,7 @@ simple_cst_equal (tree t1, tree t2) than U, respectively. */ int -compare_tree_int (tree t, unsigned HOST_WIDE_INT u) +compare_tree_int (const_tree t, unsigned HOST_WIDE_INT u) { if (tree_int_cst_sgn (t) < 0) return -1; @@ -5083,7 +5257,7 @@ commutative_tree_code (enum tree_code code) would compare equal using operand_equal_p. */ hashval_t -iterative_hash_expr (tree t, hashval_t val) +iterative_hash_expr (const_tree t, hashval_t val) { int i; enum tree_code code; @@ -5107,6 +5281,12 @@ iterative_hash_expr (tree t, hashval_t val) return iterative_hash_hashval_t (val2, val); } + case FIXED_CST: + { + unsigned int val2 = fixed_hash (TREE_FIXED_CST_PTR (t)); + + return iterative_hash_hashval_t (val2, val); + } case STRING_CST: return iterative_hash (TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t), val); @@ -5193,7 +5373,7 @@ iterative_hash_expr (tree t, hashval_t val) val = iterative_hash_hashval_t (two, val); } else - for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; --i) + for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i) val = iterative_hash_expr (TREE_OPERAND (t, i), val); } return val; @@ -5506,20 +5686,90 @@ build_array_type (tree elt_type, tree index_type) return t; } -/* Return the TYPE of the elements comprising - the innermost dimension of ARRAY. */ +/* Recursively examines the array elements of TYPE, until a non-array + element type is found. */ tree -get_inner_array_type (tree array) +strip_array_types (tree type) { - tree type = TREE_TYPE (array); - while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); return type; } +/* Computes the canonical argument types from the argument type list + 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 + structural. + + Upon return, *ANY_NONCANONICAL_P will be true iff either it was + true on entry to this function, or if any of the ARGTYPES are + non-canonical. + + Returns a canonical argument list, which may be ARGTYPES when the + 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, + 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) + /* Fail gracefully by stating that the type is structural. */ + *any_structural_p = true; + else if (TYPE_STRUCTURAL_EQUALITY_P (TREE_VALUE (arg))) + *any_structural_p = true; + else if (TYPE_CANONICAL (TREE_VALUE (arg)) != TREE_VALUE (arg) + || TREE_PURPOSE (arg)) + /* If the argument has a default argument, we consider it + non-canonical even though the type itself is canonical. + That way, different variants of function and method types + with default arguments will all point to the variant with + no defaults as their canonical type. */ + any_noncanonical_argtypes_p = true; + } + + if (*any_structural_p) + return argtypes; + + if (any_noncanonical_argtypes_p) + { + /* Build the canonical list of argument types. */ + tree canon_argtypes = NULL_TREE; + bool is_void = false; + + for (arg = argtypes; arg; arg = TREE_CHAIN (arg)) + { + if (arg == void_list_node) + is_void = true; + else + canon_argtypes = tree_cons (NULL_TREE, + TYPE_CANONICAL (TREE_VALUE (arg)), + canon_argtypes); + } + + canon_argtypes = nreverse (canon_argtypes); + if (is_void) + canon_argtypes = chainon (canon_argtypes, void_list_node); + + /* There is a non-canonical type. */ + *any_noncanonical_p = true; + return canon_argtypes; + } + + /* The canonical argument types are the same as ARGTYPES. */ + return argtypes; +} + /* Construct, lay out and return the type of functions returning type VALUE_TYPE given arguments of types ARG_TYPES. @@ -5532,6 +5782,8 @@ build_function_type (tree value_type, tree arg_types) { tree t; hashval_t hashcode = 0; + bool any_structural_p, any_noncanonical_p; + tree canon_argtypes; if (TREE_CODE (value_type) == FUNCTION_TYPE) { @@ -5544,14 +5796,23 @@ build_function_type (tree value_type, tree arg_types) TREE_TYPE (t) = value_type; TYPE_ARG_TYPES (t) = arg_types; - /* We don't have canonicalization of function types, yet. */ - SET_TYPE_STRUCTURAL_EQUALITY (t); - /* If we already have such a type, use the old one. */ hashcode = iterative_hash_object (TYPE_HASH (value_type), hashcode); hashcode = type_hash_list (arg_types, hashcode); t = type_hash_canon (hashcode, t); + /* 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, + &any_structural_p, + &any_noncanonical_p); + if (any_structural_p) + SET_TYPE_STRUCTURAL_EQUALITY (t); + 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; @@ -5601,6 +5862,8 @@ build_method_type_directly (tree basetype, tree t; tree ptype; int hashcode = 0; + bool any_structural_p, any_noncanonical_p; + tree canon_argtypes; /* Make a node of the sort we want. */ t = make_node (METHOD_TYPE); @@ -5614,15 +5877,29 @@ build_method_type_directly (tree basetype, argtypes = tree_cons (NULL_TREE, ptype, argtypes); TYPE_ARG_TYPES (t) = argtypes; - /* We don't have canonicalization of method types yet. */ - SET_TYPE_STRUCTURAL_EQUALITY (t); - /* If we already have such a type, use the old one. */ hashcode = iterative_hash_object (TYPE_HASH (basetype), hashcode); hashcode = iterative_hash_object (TYPE_HASH (rettype), hashcode); hashcode = type_hash_list (argtypes, hashcode); t = type_hash_canon (hashcode, t); + /* Set up the canonical type. */ + any_structural_p + = (TYPE_STRUCTURAL_EQUALITY_P (basetype) + || TYPE_STRUCTURAL_EQUALITY_P (rettype)); + any_noncanonical_p + = (TYPE_CANONICAL (basetype) != basetype + || TYPE_CANONICAL (rettype) != rettype); + canon_argtypes = maybe_canonicalize_argtypes (TREE_CHAIN (argtypes), + &any_structural_p, + &any_noncanonical_p); + if (any_structural_p) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (any_noncanonical_p) + TYPE_CANONICAL (t) + = build_method_type_directly (TYPE_CANONICAL (basetype), + TYPE_CANONICAL (rettype), + canon_argtypes); if (!COMPLETE_TYPE_P (t)) layout_type (t); @@ -5673,10 +5950,10 @@ build_offset_type (tree basetype, tree type) if (TYPE_STRUCTURAL_EQUALITY_P (basetype) || TYPE_STRUCTURAL_EQUALITY_P (type)) SET_TYPE_STRUCTURAL_EQUALITY (t); - else if (TYPE_CANONICAL (basetype) != basetype + else if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)) != basetype || TYPE_CANONICAL (type) != type) TYPE_CANONICAL (t) - = build_offset_type (TYPE_CANONICAL (basetype), + = build_offset_type (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)), TYPE_CANONICAL (type)); } @@ -5712,10 +5989,8 @@ build_complex_type (tree component_type) = build_complex_type (TYPE_CANONICAL (component_type)); } - /* If we are writing Dwarf2 output we need to create a name, - since complex is a fundamental type. */ - if ((write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) - && ! TYPE_NAME (t)) + /* We need to create a name, since complex is a fundamental type. */ + if (! TYPE_NAME (t)) { const char *name; if (component_type == char_type_node) @@ -5744,7 +6019,7 @@ build_complex_type (tree component_type) name = 0; if (name != 0) - TYPE_NAME (t) = get_identifier (name); + TYPE_NAME (t) = build_decl (TYPE_DECL, get_identifier (name), t); } return build_qualified_type (t, TYPE_QUALS (component_type)); @@ -5756,11 +6031,6 @@ build_complex_type (tree component_type) If FOR_TYPE is nonzero, we return a value which, if converted to type FOR_TYPE, would be equivalent to converting OP to type FOR_TYPE. - If FOR_TYPE is nonzero, unaligned bit-field references may be changed to the - narrowest type that can hold the value, even if they don't exactly fit. - Otherwise, bit-field references are changed to a narrower type - only if they can be fetched directly from memory in that type. - OP must have integer, real or enumeral type. Pointers are not allowed! There are some cases where the obvious value we could return @@ -5786,8 +6056,7 @@ get_unwidened (tree op, tree for_type) && TYPE_UNSIGNED (type)); tree win = op; - while (TREE_CODE (op) == NOP_EXPR - || TREE_CODE (op) == CONVERT_EXPR) + while (CONVERT_EXPR_P (op)) { int bitschange; @@ -5825,8 +6094,7 @@ get_unwidened (tree op, tree for_type) Let's avoid computing it if it does not affect WIN and if UNS will not be needed again. */ if ((uns - || TREE_CODE (op) == NOP_EXPR - || TREE_CODE (op) == CONVERT_EXPR) + || CONVERT_EXPR_P (op)) && TYPE_UNSIGNED (TREE_TYPE (op))) { uns = 1; @@ -5835,37 +6103,6 @@ get_unwidened (tree op, tree for_type) } } - if (TREE_CODE (op) == COMPONENT_REF - /* Since type_for_size always gives an integer type. */ - && TREE_CODE (type) != REAL_TYPE - /* Don't crash if field not laid out yet. */ - && DECL_SIZE (TREE_OPERAND (op, 1)) != 0 - && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1)) - { - unsigned int innerprec - = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1); - int unsignedp = (DECL_UNSIGNED (TREE_OPERAND (op, 1)) - || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1)))); - type = lang_hooks.types.type_for_size (innerprec, unsignedp); - - /* We can get this structure field in the narrowest type it fits in. - If FOR_TYPE is 0, do this only for a field that matches the - narrower type exactly and is aligned for it - The resulting extension to its nominal type (a fullword type) - must fit the same conditions as for other extensions. */ - - if (type != 0 - && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (op))) - && (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1))) - && (! uns || final_prec <= innerprec || unsignedp)) - { - win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0), - TREE_OPERAND (op, 1), NULL_TREE); - TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op); - TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op); - } - } - return win; } @@ -5929,6 +6166,7 @@ get_narrower (tree op, int *unsignedp_ptr) if (TREE_CODE (op) == COMPONENT_REF /* Since type_for_size always gives an integer type. */ && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE + && TREE_CODE (TREE_TYPE (op)) != FIXED_POINT_TYPE /* Ensure field is laid out already. */ && DECL_SIZE (TREE_OPERAND (op, 1)) != 0 && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1)) @@ -5966,7 +6204,7 @@ get_narrower (tree op, int *unsignedp_ptr) for type TYPE (an INTEGER_TYPE). */ int -int_fits_type_p (tree c, tree type) +int_fits_type_p (const_tree c, const_tree type) { tree type_low_bound = TYPE_MIN_VALUE (type); tree type_high_bound = TYPE_MAX_VALUE (type); @@ -6038,6 +6276,60 @@ int_fits_type_p (tree c, tree type) return !fit_double_type (low, high, &low, &high, type); } +/* Stores bounds of an integer TYPE in MIN and MAX. If TYPE has non-constant + bounds or is a POINTER_TYPE, the maximum and/or minimum values that can be + represented (assuming two's-complement arithmetic) within the bit + precision of the type are returned instead. */ + +void +get_type_static_bounds (const_tree type, mpz_t min, mpz_t max) +{ + if (!POINTER_TYPE_P (type) && TYPE_MIN_VALUE (type) + && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST) + mpz_set_double_int (min, tree_to_double_int (TYPE_MIN_VALUE (type)), + TYPE_UNSIGNED (type)); + else + { + if (TYPE_UNSIGNED (type)) + mpz_set_ui (min, 0); + else + { + double_int mn; + mn = double_int_mask (TYPE_PRECISION (type) - 1); + mn = double_int_sext (double_int_add (mn, double_int_one), + TYPE_PRECISION (type)); + mpz_set_double_int (min, mn, false); + } + } + + 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)); + else + { + if (TYPE_UNSIGNED (type)) + mpz_set_double_int (max, double_int_mask (TYPE_PRECISION (type)), + true); + else + mpz_set_double_int (max, double_int_mask (TYPE_PRECISION (type) - 1), + true); + } +} + +/* auto_var_in_fn_p is called to determine whether VAR is an automatic + variable defined in function FN. */ + +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_STATIC (var)) + || TREE_CODE (var) == LABEL_DECL + || TREE_CODE (var) == RESULT_DECL)); +} + /* Subprogram of following function. Called by walk_tree. Return *TP if it is an automatic variable or parameter of the @@ -6052,7 +6344,7 @@ find_var_from_fn (tree *tp, int *walk_subtrees, void *data) *walk_subtrees = 0; else if (DECL_P (*tp) - && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn)) + && auto_var_in_fn_p (*tp, fn)) return *tp; return NULL_TREE; @@ -6111,6 +6403,7 @@ variably_modified_type_p (tree type, tree fn) case INTEGER_TYPE: case REAL_TYPE: + case FIXED_POINT_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: /* Scalar types are variably modified if their end points @@ -6160,7 +6453,7 @@ variably_modified_type_p (tree type, tree fn) NULL_TREE if there is no containing scope. */ tree -get_containing_scope (tree t) +get_containing_scope (const_tree t) { return (TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t)); } @@ -6169,7 +6462,7 @@ get_containing_scope (tree t) a FUNCTION_DECL, or zero if none. */ tree -decl_function_context (tree decl) +decl_function_context (const_tree decl) { tree context; @@ -6205,7 +6498,7 @@ decl_function_context (tree decl) TYPE_DECLs and FUNCTION_DECLs are transparent to this function. */ tree -decl_type_context (tree decl) +decl_type_context (const_tree decl) { tree context = DECL_CONTEXT (decl); @@ -6242,12 +6535,12 @@ decl_type_context (tree decl) determined. */ tree -get_callee_fndecl (tree call) +get_callee_fndecl (const_tree call) { tree addr; if (call == error_mark_node) - return call; + return error_mark_node; /* It's invalid to call this function with anything but a CALL_EXPR. */ @@ -6255,7 +6548,7 @@ get_callee_fndecl (tree call) /* The first operand to the CALL is the address of the function called. */ - addr = TREE_OPERAND (call, 0); + addr = CALL_EXPR_FN (call); STRIP_NOPS (addr); @@ -6415,7 +6708,7 @@ get_file_function_name (const char *type) clean_symbol_name (q); sprintf (q + len, "_%08X_%08X", crc32_string (0, name), - crc32_string (0, flag_random_seed)); + crc32_string (0, get_random_seed (false))); p = q; } @@ -6439,11 +6732,11 @@ get_file_function_name (const char *type) are of the caller. */ void -tree_check_failed (const tree node, const char *file, +tree_check_failed (const_tree node, const char *file, int line, const char *function, ...) { va_list args; - char *buffer; + const char *buffer; unsigned length = 0; int code; @@ -6453,23 +6746,24 @@ tree_check_failed (const tree node, const char *file, va_end (args); if (length) { + char *tmp; va_start (args, function); length += strlen ("expected "); - buffer = alloca (length); + buffer = tmp = alloca (length); length = 0; while ((code = va_arg (args, int))) { const char *prefix = length ? " or " : "expected "; - strcpy (buffer + length, prefix); + strcpy (tmp + length, prefix); length += strlen (prefix); - strcpy (buffer + length, tree_code_name[code]); + strcpy (tmp + length, tree_code_name[code]); length += strlen (tree_code_name[code]); } va_end (args); } else - buffer = (char *)"unexpected node"; + buffer = "unexpected node"; internal_error ("tree check: %s, have %s in %s, at %s:%d", buffer, tree_code_name[TREE_CODE (node)], @@ -6481,7 +6775,7 @@ tree_check_failed (const tree node, const char *file, the caller. */ void -tree_not_check_failed (const tree node, const char *file, +tree_not_check_failed (const_tree node, const char *file, int line, const char *function, ...) { va_list args; @@ -6517,7 +6811,7 @@ tree_not_check_failed (const tree node, const char *file, code, given in CL. */ void -tree_class_check_failed (const tree node, const enum tree_code_class cl, +tree_class_check_failed (const_tree node, const enum tree_code_class cl, const char *file, int line, const char *function) { internal_error @@ -6531,7 +6825,7 @@ tree_class_check_failed (const tree node, const enum tree_code_class cl, dozen codes, use the knowledge that they're all sequential. */ void -tree_range_check_failed (const tree node, const char *file, int line, +tree_range_check_failed (const_tree node, const char *file, int line, const char *function, enum tree_code c1, enum tree_code c2) { @@ -6566,7 +6860,7 @@ tree_range_check_failed (const tree node, const char *file, int line, not have the specified code, given in CL. */ void -tree_not_class_check_failed (const tree node, const enum tree_code_class cl, +tree_not_class_check_failed (const_tree node, const enum tree_code_class cl, const char *file, int line, const char *function) { internal_error @@ -6580,7 +6874,7 @@ tree_not_class_check_failed (const tree node, const enum tree_code_class cl, /* Similar to tree_check_failed but applied to OMP_CLAUSE codes. */ void -omp_clause_check_failed (const tree node, const char *file, int line, +omp_clause_check_failed (const_tree node, const char *file, int line, const char *function, enum omp_clause_code code) { internal_error ("tree check: expected omp_clause %s, have %s in %s, at %s:%d", @@ -6592,7 +6886,7 @@ omp_clause_check_failed (const tree node, const char *file, int line, /* Similar to tree_range_check_failed but applied to OMP_CLAUSE codes. */ void -omp_clause_range_check_failed (const tree node, const char *file, int line, +omp_clause_range_check_failed (const_tree node, const char *file, int line, const char *function, enum omp_clause_code c1, enum omp_clause_code c2) { @@ -6637,13 +6931,13 @@ 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 *function) { internal_error - ("tree check: expected tree that contains %qs structure, have %qs in %s, at %s:%d", + ("tree check: expected tree that contains %qs structure, have %qs in %s, at %s:%d", TS_ENUM_NAME(en), tree_code_name[TREE_CODE (node)], function, trim_filename (file), line); } @@ -6674,15 +6968,16 @@ phi_node_elt_check_failed (int idx, int len, const char *file, int line, } /* Similar to above, except that the check is for the bounds of the operand - vector of an expression node. */ + vector of an expression node EXP. */ void -tree_operand_check_failed (int idx, enum tree_code code, const char *file, +tree_operand_check_failed (int idx, const_tree exp, const char *file, int line, const char *function) { + int code = TREE_CODE (exp); internal_error ("tree check: accessed operand %d of %s with %d operands in %s, at %s:%d", - idx + 1, tree_code_name[code], TREE_CODE_LENGTH (code), + idx + 1, tree_code_name[code], TREE_OPERAND_LENGTH (exp), function, trim_filename (file), line); } @@ -6690,7 +6985,7 @@ tree_operand_check_failed (int idx, enum tree_code code, const char *file, operands of an OMP_CLAUSE node. */ void -omp_clause_operand_check_failed (int idx, tree t, const char *file, +omp_clause_operand_check_failed (int idx, const_tree t, const char *file, int line, const char *function) { internal_error @@ -6779,6 +7074,80 @@ make_or_reuse_type (unsigned size, int unsignedp) return make_signed_type (size); } +/* Create or reuse a fract type by SIZE, UNSIGNEDP, and SATP. */ + +static tree +make_or_reuse_fract_type (unsigned size, int unsignedp, int satp) +{ + if (satp) + { + if (size == SHORT_FRACT_TYPE_SIZE) + return unsignedp ? sat_unsigned_short_fract_type_node + : sat_short_fract_type_node; + if (size == FRACT_TYPE_SIZE) + return unsignedp ? sat_unsigned_fract_type_node : sat_fract_type_node; + if (size == LONG_FRACT_TYPE_SIZE) + return unsignedp ? sat_unsigned_long_fract_type_node + : sat_long_fract_type_node; + if (size == LONG_LONG_FRACT_TYPE_SIZE) + return unsignedp ? sat_unsigned_long_long_fract_type_node + : sat_long_long_fract_type_node; + } + else + { + if (size == SHORT_FRACT_TYPE_SIZE) + return unsignedp ? unsigned_short_fract_type_node + : short_fract_type_node; + if (size == FRACT_TYPE_SIZE) + return unsignedp ? unsigned_fract_type_node : fract_type_node; + if (size == LONG_FRACT_TYPE_SIZE) + return unsignedp ? unsigned_long_fract_type_node + : long_fract_type_node; + if (size == LONG_LONG_FRACT_TYPE_SIZE) + return unsignedp ? unsigned_long_long_fract_type_node + : long_long_fract_type_node; + } + + return make_fract_type (size, unsignedp, satp); +} + +/* Create or reuse an accum type by SIZE, UNSIGNEDP, and SATP. */ + +static tree +make_or_reuse_accum_type (unsigned size, int unsignedp, int satp) +{ + if (satp) + { + if (size == SHORT_ACCUM_TYPE_SIZE) + return unsignedp ? sat_unsigned_short_accum_type_node + : sat_short_accum_type_node; + if (size == ACCUM_TYPE_SIZE) + return unsignedp ? sat_unsigned_accum_type_node : sat_accum_type_node; + if (size == LONG_ACCUM_TYPE_SIZE) + return unsignedp ? sat_unsigned_long_accum_type_node + : sat_long_accum_type_node; + if (size == LONG_LONG_ACCUM_TYPE_SIZE) + return unsignedp ? sat_unsigned_long_long_accum_type_node + : sat_long_long_accum_type_node; + } + else + { + if (size == SHORT_ACCUM_TYPE_SIZE) + return unsignedp ? unsigned_short_accum_type_node + : short_accum_type_node; + if (size == ACCUM_TYPE_SIZE) + return unsignedp ? unsigned_accum_type_node : accum_type_node; + if (size == LONG_ACCUM_TYPE_SIZE) + return unsignedp ? unsigned_long_accum_type_node + : long_accum_type_node; + if (size == LONG_LONG_ACCUM_TYPE_SIZE) + return unsignedp ? unsigned_long_long_accum_type_node + : long_long_accum_type_node; + } + + return make_accum_type (size, unsignedp, satp); +} + /* Create nodes for all integer types (and error_mark_node) using the sizes of C datatypes. The caller should call set_sizetype soon after calling this function to select one of the types as sizetype. */ @@ -6921,21 +7290,54 @@ build_common_tree_nodes_2 (int short_double) TYPE_MODE (dfloat128_type_node) = TDmode; dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node); - complex_integer_type_node = make_node (COMPLEX_TYPE); - TREE_TYPE (complex_integer_type_node) = integer_type_node; - layout_type (complex_integer_type_node); - - complex_float_type_node = make_node (COMPLEX_TYPE); - TREE_TYPE (complex_float_type_node) = float_type_node; - layout_type (complex_float_type_node); - - complex_double_type_node = make_node (COMPLEX_TYPE); - TREE_TYPE (complex_double_type_node) = double_type_node; - layout_type (complex_double_type_node); - - complex_long_double_type_node = make_node (COMPLEX_TYPE); - TREE_TYPE (complex_long_double_type_node) = long_double_type_node; - layout_type (complex_long_double_type_node); + complex_integer_type_node = build_complex_type (integer_type_node); + complex_float_type_node = build_complex_type (float_type_node); + complex_double_type_node = build_complex_type (double_type_node); + complex_long_double_type_node = build_complex_type (long_double_type_node); + +/* Make fixed-point nodes based on sat/non-sat and signed/unsigned. */ +#define MAKE_FIXED_TYPE_NODE(KIND,WIDTH,SIZE) \ + sat_ ## WIDTH ## KIND ## _type_node = \ + make_sat_signed_ ## KIND ## _type (SIZE); \ + sat_unsigned_ ## WIDTH ## KIND ## _type_node = \ + make_sat_unsigned_ ## KIND ## _type (SIZE); \ + WIDTH ## KIND ## _type_node = make_signed_ ## KIND ## _type (SIZE); \ + unsigned_ ## WIDTH ## KIND ## _type_node = \ + make_unsigned_ ## KIND ## _type (SIZE); + +/* Make fixed-point type nodes based on four different widths. */ +#define MAKE_FIXED_TYPE_NODE_FAMILY(N1,N2) \ + MAKE_FIXED_TYPE_NODE (N1, short_, SHORT_ ## N2 ## _TYPE_SIZE) \ + MAKE_FIXED_TYPE_NODE (N1, , N2 ## _TYPE_SIZE) \ + MAKE_FIXED_TYPE_NODE (N1, long_, LONG_ ## N2 ## _TYPE_SIZE) \ + MAKE_FIXED_TYPE_NODE (N1, long_long_, LONG_LONG_ ## N2 ## _TYPE_SIZE) + +/* Make fixed-point mode nodes based on sat/non-sat and signed/unsigned. */ +#define MAKE_FIXED_MODE_NODE(KIND,NAME,MODE) \ + NAME ## _type_node = \ + make_or_reuse_signed_ ## KIND ## _type (GET_MODE_BITSIZE (MODE ## mode)); \ + u ## NAME ## _type_node = \ + make_or_reuse_unsigned_ ## KIND ## _type \ + (GET_MODE_BITSIZE (U ## MODE ## mode)); \ + sat_ ## NAME ## _type_node = \ + make_or_reuse_sat_signed_ ## KIND ## _type \ + (GET_MODE_BITSIZE (MODE ## mode)); \ + sat_u ## NAME ## _type_node = \ + make_or_reuse_sat_unsigned_ ## KIND ## _type \ + (GET_MODE_BITSIZE (U ## MODE ## mode)); + + /* Fixed-point type and mode nodes. */ + MAKE_FIXED_TYPE_NODE_FAMILY (fract, FRACT) + MAKE_FIXED_TYPE_NODE_FAMILY (accum, ACCUM) + MAKE_FIXED_MODE_NODE (fract, qq, QQ) + MAKE_FIXED_MODE_NODE (fract, hq, HQ) + MAKE_FIXED_MODE_NODE (fract, sq, SQ) + MAKE_FIXED_MODE_NODE (fract, dq, DQ) + MAKE_FIXED_MODE_NODE (fract, tq, TQ) + MAKE_FIXED_MODE_NODE (accum, ha, HA) + MAKE_FIXED_MODE_NODE (accum, sa, SA) + MAKE_FIXED_MODE_NODE (accum, da, DA) + MAKE_FIXED_MODE_NODE (accum, ta, TA) { tree t = targetm.build_builtin_va_list (); @@ -6965,7 +7367,9 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, if (ecf_flags & ECF_CONST) TREE_READONLY (decl) = 1; if (ecf_flags & ECF_PURE) - DECL_IS_PURE (decl) = 1; + DECL_PURE_P (decl) = 1; + if (ecf_flags & ECF_LOOPING_CONST_OR_PURE) + DECL_LOOPING_CONST_OR_PURE_P (decl) = 1; if (ecf_flags & ECF_NORETURN) TREE_THIS_VOLATILE (decl) = 1; if (ecf_flags & ECF_NOTHROW) @@ -7146,11 +7550,18 @@ tree reconstruct_complex_type (tree type, tree bottom) { tree inner, outer; - - if (POINTER_TYPE_P (type)) + + if (TREE_CODE (type) == POINTER_TYPE) + { + inner = reconstruct_complex_type (TREE_TYPE (type), bottom); + outer = build_pointer_type_for_mode (inner, TYPE_MODE (type), + TYPE_REF_CAN_ALIAS_ALL (type)); + } + else if (TREE_CODE (type) == REFERENCE_TYPE) { inner = reconstruct_complex_type (TREE_TYPE (type), bottom); - outer = build_pointer_type (inner); + outer = build_reference_type_for_mode (inner, TYPE_MODE (type), + TYPE_REF_CAN_ALIAS_ALL (type)); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -7164,23 +7575,24 @@ reconstruct_complex_type (tree type, tree bottom) } else if (TREE_CODE (type) == METHOD_TYPE) { - tree argtypes; inner = reconstruct_complex_type (TREE_TYPE (type), bottom); /* The build_method_type_directly() routine prepends 'this' to argument list, so we must compensate by getting rid of it. */ - argtypes = TYPE_ARG_TYPES (type); - outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type), - inner, - TYPE_ARG_TYPES (type)); - TYPE_ARG_TYPES (outer) = argtypes; + outer + = build_method_type_directly + (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))), + inner, + TREE_CHAIN (TYPE_ARG_TYPES (type))); + } + else if (TREE_CODE (type) == OFFSET_TYPE) + { + inner = reconstruct_complex_type (TREE_TYPE (type), bottom); + outer = build_offset_type (TYPE_OFFSET_BASETYPE (type), inner); } else return bottom; - TYPE_READONLY (outer) = TYPE_READONLY (type); - TYPE_VOLATILE (outer) = TYPE_VOLATILE (type); - - return outer; + return build_qualified_type (outer, TYPE_QUALS (type)); } /* Returns a vector tree node given a mode (integer, vector, or BLKmode) and @@ -7194,6 +7606,10 @@ build_vector_type_for_mode (tree innertype, enum machine_mode mode) { case MODE_VECTOR_INT: case MODE_VECTOR_FLOAT: + case MODE_VECTOR_FRACT: + case MODE_VECTOR_UFRACT: + case MODE_VECTOR_ACCUM: + case MODE_VECTOR_UACCUM: nunits = GET_MODE_NUNITS (mode); break; @@ -7236,7 +7652,7 @@ build_resx (int region_number) /* Given an initializer INIT, return TRUE if INIT is zero or some aggregate of zeros. Otherwise return FALSE. */ bool -initializer_zerop (tree init) +initializer_zerop (const_tree init) { tree elt; @@ -7254,6 +7670,9 @@ initializer_zerop (tree init) return real_zerop (init) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init)); + case FIXED_CST: + return fixed_zerop (init); + case COMPLEX_CST: return integer_zerop (init) || (real_zerop (init) @@ -7314,6 +7733,149 @@ build_omp_clause (enum omp_clause_code code) 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; +} + +/* Build a tcc_vl_exp object with code CODE and room for LEN operands. LEN + includes the implicit operand count in TREE_OPERAND 0, and so must be >= 1. + Except for the CODE and operand count field, other storage for the + object is initialized to zeros. */ + +tree +build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL) +{ + tree t; + int length = (len - 1) * sizeof (tree) + sizeof (struct tree_exp); + + gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp); + gcc_assert (len >= 1); + +#ifdef GATHER_STATISTICS + tree_node_counts[(int) e_kind]++; + tree_node_sizes[(int) e_kind] += length; +#endif + + t = ggc_alloc_zone_pass_stat (length, &tree_zone); + + memset (t, 0, length); + + TREE_SET_CODE (t, code); + + /* Can't use TREE_OPERAND to store the length because if checking is + enabled, it will try to check the length before we store it. :-P */ + t->exp.operands[0] = build_int_cst (sizetype, len); + + return t; +} + + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE + and FN and a null static chain slot. ARGLIST is a TREE_LIST of the + arguments. */ + +tree +build_call_list (tree return_type, tree fn, tree arglist) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++) + CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist); + process_call_operands (t); + return t; +} + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and + FN and a null static chain slot. NARGS is the number of call arguments + which are specified as "..." arguments. */ + +tree +build_call_nary (tree return_type, tree fn, int nargs, ...) +{ + tree ret; + va_list args; + va_start (args, nargs); + ret = build_call_valist (return_type, fn, nargs, args); + va_end (args); + return ret; +} + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and + FN and a null static chain slot. NARGS is the number of call arguments + which are specified as a va_list ARGS. */ + +tree +build_call_valist (tree return_type, tree fn, int nargs, va_list args) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, nargs + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; i < nargs; i++) + CALL_EXPR_ARG (t, i) = va_arg (args, tree); + process_call_operands (t); + return t; +} + +/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and + FN and a null static chain slot. NARGS is the number of call arguments + which are specified as a tree array ARGS. */ + +tree +build_call_array (tree return_type, tree fn, int nargs, tree *args) +{ + tree t; + int i; + + t = build_vl_exp (CALL_EXPR, nargs + 3); + TREE_TYPE (t) = return_type; + CALL_EXPR_FN (t) = fn; + CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE; + for (i = 0; i < nargs; i++) + CALL_EXPR_ARG (t, i) = args[i]; + process_call_operands (t); + return t; +} + /* Returns true if it is possible to prove that the index of an array access REF (an ARRAY_REF expression) falls into the @@ -7376,22 +7938,11 @@ range_in_array_bounds_p (tree ref) return true; } -/* Return true if T (assumed to be a DECL) is a global variable. */ - -bool -is_global_var (tree t) -{ - if (MTAG_P (t)) - return (TREE_STATIC (t) || MTAG_GLOBAL (t)); - else - return (TREE_STATIC (t) || DECL_EXTERNAL (t)); -} - /* Return true if T (assumed to be a DECL) must be assigned a memory location. */ bool -needs_to_live_in_memory (tree t) +needs_to_live_in_memory (const_tree t) { if (TREE_CODE (t) == SSA_NAME) t = SSA_NAME_VAR (t); @@ -7407,7 +7958,7 @@ needs_to_live_in_memory (tree t) are compatible. It is assumed that the parent records are compatible. */ bool -fields_compatible_p (tree f1, tree f2) +fields_compatible_p (const_tree f1, const_tree f2) { if (!operand_equal_p (DECL_FIELD_BIT_OFFSET (f1), DECL_FIELD_BIT_OFFSET (f2), OEP_ONLY_CONST)) @@ -7417,7 +7968,7 @@ fields_compatible_p (tree f1, tree f2) DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST)) return false; - if (!lang_hooks.types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2))) + if (!types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2))) return false; return true; @@ -7446,34 +7997,53 @@ find_compatible_field (tree record, tree orig_field) return orig_field; } -/* Return value of a constant X. */ +/* Return value of a constant X and sign-extend it. */ HOST_WIDE_INT -int_cst_value (tree x) +int_cst_value (const_tree x) { unsigned bits = TYPE_PRECISION (TREE_TYPE (x)); unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x); - bool negative = ((val >> (bits - 1)) & 1) != 0; - gcc_assert (bits <= HOST_BITS_PER_WIDE_INT); + /* 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); - if (negative) - val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1; - else - val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1); + if (bits < HOST_BITS_PER_WIDE_INT) + { + bool negative = ((val >> (bits - 1)) & 1) != 0; + if (negative) + val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1; + else + val &= ~((~(unsigned HOST_WIDE_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. */ + +tree +signed_or_unsigned_type_for (int unsignedp, tree type) +{ + tree t = type; + if (POINTER_TYPE_P (type)) + t = size_type_node; + + if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp) + return t; + + return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp); +} /* Returns unsigned variant of TYPE. */ tree unsigned_type_for (tree type) { - if (POINTER_TYPE_P (type)) - return lang_hooks.types.unsigned_type (size_type_node); - return lang_hooks.types.unsigned_type (type); + return signed_or_unsigned_type_for (1, type); } /* Returns signed variant of TYPE. */ @@ -7481,9 +8051,7 @@ unsigned_type_for (tree type) tree signed_type_for (tree type) { - if (POINTER_TYPE_P (type)) - return lang_hooks.types.signed_type (size_type_node); - return lang_hooks.types.signed_type (type); + return signed_or_unsigned_type_for (0, type); } /* Returns the largest value obtainable by casting something in INNER type to @@ -7602,7 +8170,7 @@ lower_bound_in_type (tree outer, tree inner) and get the same result, only slower. */ int -operand_equal_for_phi_arg_p (tree arg0, tree arg1) +operand_equal_for_phi_arg_p (const_tree arg0, const_tree arg1) { if (arg0 == arg1) return 1; @@ -7616,7 +8184,7 @@ operand_equal_for_phi_arg_p (tree arg0, tree arg1) ??? Use ffs if available? */ tree -num_ending_zeros (tree x) +num_ending_zeros (const_tree x) { unsigned HOST_WIDE_INT fr, nfr; unsigned num, abits; @@ -7653,7 +8221,7 @@ num_ending_zeros (tree x) #define WALK_SUBTREE(NODE) \ do \ { \ - result = walk_tree (&(NODE), func, data, pset); \ + result = walk_tree_1 (&(NODE), func, data, pset, lh); \ if (result) \ return result; \ } \ @@ -7665,7 +8233,7 @@ num_ending_zeros (tree x) static tree walk_type_fields (tree type, walk_tree_fn func, void *data, - struct pointer_set_t *pset) + struct pointer_set_t *pset, walk_tree_lh lh) { tree result = NULL_TREE; @@ -7716,10 +8284,12 @@ walk_type_fields (tree type, walk_tree_fn func, void *data, break; case ARRAY_TYPE: - /* Don't follow this nodes's type if a pointer for fear that we'll - have infinite recursion. Those types are uninteresting anyway. */ - if (!POINTER_TYPE_P (TREE_TYPE (type)) - && TREE_CODE (TREE_TYPE (type)) != OFFSET_TYPE) + /* Don't follow this nodes's type if a pointer for fear that + we'll have infinite recursion. If we have a PSET, then we + need not fear. */ + if (pset + || (!POINTER_TYPE_P (TREE_TYPE (type)) + && TREE_CODE (TREE_TYPE (type)) != OFFSET_TYPE)) WALK_SUBTREE (TREE_TYPE (type)); WALK_SUBTREE (TYPE_DOMAIN (type)); break; @@ -7743,7 +8313,8 @@ walk_type_fields (tree type, walk_tree_fn func, void *data, and to avoid visiting a node more than once. */ tree -walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) +walk_tree_1 (tree *tp, walk_tree_fn func, void *data, + struct pointer_set_t *pset, walk_tree_lh lh) { enum tree_code code; int walk_subtrees; @@ -7790,10 +8361,12 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) return NULL_TREE; } - result = lang_hooks.tree_inlining.walk_subtrees (tp, &walk_subtrees, func, - data, pset); - if (result || !walk_subtrees) - return result; + if (lh) + { + result = (*lh) (tp, &walk_subtrees, func, data, pset); + if (result || !walk_subtrees) + return result; + } switch (code) { @@ -7801,6 +8374,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) case IDENTIFIER_NODE: case INTEGER_CST: case REAL_CST: + case FIXED_CST: case VECTOR_CST: case STRING_CST: case BLOCK: @@ -7882,7 +8456,6 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) case OMP_CLAUSE_PRIVATE: case OMP_CLAUSE_SHARED: case OMP_CLAUSE_FIRSTPRIVATE: - case OMP_CLAUSE_LASTPRIVATE: case OMP_CLAUSE_COPYIN: case OMP_CLAUSE_COPYPRIVATE: case OMP_CLAUSE_IF: @@ -7894,8 +8467,22 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_DEFAULT: + case OMP_CLAUSE_UNTIED: + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + + case OMP_CLAUSE_LASTPRIVATE: + WALK_SUBTREE (OMP_CLAUSE_DECL (*tp)); + WALK_SUBTREE (OMP_CLAUSE_LASTPRIVATE_STMT (*tp)); WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + case OMP_CLAUSE_COLLAPSE: + { + int i; + for (i = 0; i < 3; i++) + WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + } + case OMP_CLAUSE_REDUCTION: { int i; @@ -7946,7 +8533,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) if (result || !walk_subtrees) return result; - result = walk_type_fields (*type_p, func, data, pset); + result = walk_type_fields (*type_p, func, data, pset, lh); if (result) return result; @@ -7979,6 +8566,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) else if (TREE_CODE (*type_p) == BOOLEAN_TYPE || TREE_CODE (*type_p) == ENUMERAL_TYPE || TREE_CODE (*type_p) == INTEGER_TYPE + || TREE_CODE (*type_p) == FIXED_POINT_TYPE || TREE_CODE (*type_p) == REAL_TYPE) { WALK_SUBTREE (TYPE_MIN_VALUE (*type_p)); @@ -7997,7 +8585,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) int i, len; /* Walk over all the sub-trees of this operand. */ - len = TREE_CODE_LENGTH (code); + len = TREE_OPERAND_LENGTH (*tp); /* Go through the subtrees. We need to do this in forward order so that the scope of a FOR_EXPR is handled properly. */ @@ -8010,7 +8598,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) } /* If this is a type, walk the needed fields in the type. */ else if (TYPE_P (*tp)) - return walk_type_fields (*tp, func, data, pset); + return walk_type_fields (*tp, func, data, pset, lh); break; } @@ -8024,13 +8612,14 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) /* Like walk_tree, but does not walk duplicate nodes more than once. */ tree -walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data) +walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data, + walk_tree_lh lh) { tree result; struct pointer_set_t *pset; pset = pointer_set_create (); - result = walk_tree (tp, func, data, pset); + result = walk_tree_1 (tp, func, data, pset, lh); pointer_set_destroy (pset); return result; } @@ -8090,4 +8679,107 @@ generic_tree_type (tree node) return &TREE_TYPE (node); } +/* Build and return a TREE_LIST of arguments in the CALL_EXPR exp. + FIXME: don't use this function. It exists for compatibility with + the old representation of CALL_EXPRs where a list was used to hold the + arguments. Places that currently extract the arglist from a CALL_EXPR + ought to be rewritten to use the CALL_EXPR itself. */ +tree +call_expr_arglist (tree exp) +{ + tree arglist = NULL_TREE; + int i; + for (i = call_expr_nargs (exp) - 1; i >= 0; i--) + arglist = tree_cons (NULL_TREE, CALL_EXPR_ARG (exp, i), arglist); + return arglist; +} + +/* Return true if TYPE has a variable argument list. */ + +bool +stdarg_p (tree fntype) +{ + function_args_iterator args_iter; + tree n = NULL_TREE, t; + + if (!fntype) + return false; + + FOREACH_FUNCTION_ARGS(fntype, t, args_iter) + { + n = t; + } + + return n != NULL_TREE && n != void_type_node; +} + +/* Return true if TYPE has a prototype. */ + +bool +prototype_p (tree fntype) +{ + tree t; + + gcc_assert (fntype != NULL_TREE); + + t = TYPE_ARG_TYPES (fntype); + return (t != NULL_TREE); +} + +/* Return the number of arguments that a function has. */ + +int +function_args_count (tree fntype) +{ + function_args_iterator args_iter; + tree t; + int num = 0; + + if (fntype) + { + FOREACH_FUNCTION_ARGS(fntype, t, args_iter) + { + num++; + } + } + + return num; +} + +/* If BLOCK is inlined from an __attribute__((__artificial__)) + routine, return pointer to location from where it has been + called. */ +location_t * +block_nonartificial_location (tree block) +{ + location_t *ret = NULL; + + while (block && TREE_CODE (block) == BLOCK + && BLOCK_ABSTRACT_ORIGIN (block)) + { + tree ao = BLOCK_ABSTRACT_ORIGIN (block); + + while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao)) + ao = BLOCK_ABSTRACT_ORIGIN (ao); + + if (TREE_CODE (ao) == FUNCTION_DECL) + { + /* If AO is an artificial inline, point RET to the + call site locus at which it has been inlined and continue + the loop, in case AO's caller is also an artificial + inline. */ + if (DECL_DECLARED_INLINE_P (ao) + && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao))) + ret = &BLOCK_SOURCE_LOCATION (block); + else + break; + } + else if (TREE_CODE (ao) != BLOCK) + break; + + block = BLOCK_SUPERCONTEXT (block); + } + return ret; +} + #include "gt-tree.h"