X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree.c;h=73adaa10b037ca9643f44d3c5cf8d65f6e1c2596;hb=5d2fc50913d8f07dac579d636b6b46040df073f1;hp=2bd45b7e959a628d7f2cdd2ffcaff0659c074ba3;hpb=aae87fc346d89bc5cf107a45dd5bade361b16533;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree.c b/gcc/tree.c index 2bd45b7e959..73adaa10b03 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. */ @@ -400,6 +400,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 (); @@ -620,7 +621,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: @@ -1096,6 +1096,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. */ @@ -1175,10 +1191,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; } @@ -1216,6 +1231,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; @@ -1435,6 +1455,15 @@ integer_nonzerop (const_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. */ @@ -1770,7 +1799,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; @@ -1816,7 +1845,7 @@ int_size_in_bytes (const_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; @@ -2025,7 +2054,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. @@ -2060,11 +2193,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 @@ -2085,7 +2217,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; } @@ -2113,9 +2244,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; @@ -2185,6 +2316,7 @@ tree_node_structure (const_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 +2346,7 @@ tree_node_structure (const_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; @@ -2275,9 +2407,9 @@ contains_placeholder_p (tree exp) { case CALL_EXPR: { - tree arg; - call_expr_arg_iterator iter; - FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + 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; @@ -2325,6 +2457,7 @@ type_contains_placeholder_1 (const_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))); @@ -2497,8 +2630,8 @@ substitute_in_expr (tree exp, tree f, tree r) { tree copy = NULL_TREE; int i; - int n = TREE_OPERAND_LENGTH (exp); - for (i = 1; i < n; i++) + + for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++) { tree op = TREE_OPERAND (exp, i); tree newop = SUBSTITUTE_IN_EXPR (op, f, r); @@ -2513,6 +2646,7 @@ substitute_in_expr (tree exp, tree f, tree r) else return exp; } + break; default: gcc_unreachable (); @@ -2781,7 +2915,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)) @@ -2834,7 +2968,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; } @@ -2842,13 +2975,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 @@ -2858,9 +2991,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) @@ -2874,11 +3006,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 @@ -2887,46 +3019,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 @@ -2985,11 +3106,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_OPERAND (t, 0) = node; TREE_BLOCK (t) = NULL_TREE; if (node && !TYPE_P (node)) @@ -3027,9 +3144,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; @@ -3050,15 +3164,13 @@ 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); @@ -3078,7 +3190,7 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL) if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt) gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0)) - && TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (arg1)) && useless_type_conversion_p (sizetype, TREE_TYPE (arg1))); t = make_node_stat (code PASS_MEM_STAT); @@ -3095,14 +3207,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 @@ -3131,7 +3241,7 @@ 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); @@ -3167,7 +3277,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); @@ -3194,7 +3304,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); @@ -3223,7 +3333,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); @@ -3351,13 +3461,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) { @@ -3370,7 +3473,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); @@ -3378,50 +3481,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. */ @@ -3430,73 +3489,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)) @@ -3511,41 +3538,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. */ @@ -3639,21 +3651,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); @@ -3668,8 +3685,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 @@ -3678,6 +3696,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); @@ -3692,11 +3711,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; } @@ -3789,7 +3814,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; } @@ -3939,8 +3963,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)) @@ -4027,6 +4050,16 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, return NULL_TREE; } + 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", + IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + /* Report error on dllimport ambiguities seen now before they cause any damage. */ else if (is_attribute_p ("dllimport", name)) @@ -4114,7 +4147,7 @@ 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 (const_tree cand, const_tree base, int type_quals) @@ -4281,9 +4314,6 @@ decl_init_priority_lookup (tree decl) struct tree_map_base in; gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); - gcc_assert (TREE_CODE (decl) == VAR_DECL - ? DECL_HAS_INIT_PRIORITY_P (decl) - : DECL_STATIC_CONSTRUCTOR (decl)); in.from = decl; h = htab_find (init_priority_for_decl, &in); return h ? h->init : DEFAULT_INIT_PRIORITY; @@ -4298,7 +4328,6 @@ decl_fini_priority_lookup (tree decl) struct tree_map_base in; gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); - gcc_assert (DECL_STATIC_DESTRUCTOR (decl)); in.from = decl; h = htab_find (init_priority_for_decl, &in); return h ? h->fini : DEFAULT_INIT_PRIORITY; @@ -4552,6 +4581,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); @@ -4580,17 +4612,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. */ @@ -4635,7 +4674,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 @@ -4720,7 +4759,7 @@ attribute_hash_list (const_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); @@ -4735,9 +4774,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) @@ -4756,8 +4795,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))) @@ -4788,9 +4831,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) @@ -4899,7 +4942,9 @@ host_integerp (const_tree t, int pos) && (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))); } @@ -4973,7 +5018,7 @@ simple_cst_list_equal (const_tree l1, const_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; @@ -5012,6 +5057,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), @@ -5044,13 +5092,13 @@ simple_cst_equal (tree t1, tree t2) if (call_expr_nargs (t1) != call_expr_nargs (t2)) return 0; { - tree arg1, arg2; - call_expr_arg_iterator iter1, iter2; - for (arg1 = first_call_expr_arg (t1, &iter1), - arg2 = first_call_expr_arg (t2, &iter2); + 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_call_expr_arg (&iter1), - arg2 = next_call_expr_arg (&iter2)) + arg1 = next_const_call_expr_arg (&iter1), + arg2 = next_const_call_expr_arg (&iter2)) { cmp = simple_cst_equal (arg1, arg2); if (cmp <= 0) @@ -5235,6 +5283,12 @@ iterative_hash_expr (const_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); @@ -5638,7 +5692,7 @@ build_array_type (tree elt_type, tree index_type) the innermost dimension of ARRAY. */ tree -get_inner_array_type (tree array) +get_inner_array_type (const_tree array) { tree type = TREE_TYPE (array); @@ -5900,10 +5954,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)); } @@ -5939,10 +5993,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) @@ -5983,11 +6035,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 @@ -6062,37 +6109,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; } @@ -6156,6 +6172,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)) @@ -6271,7 +6288,7 @@ int_fits_type_p (const_tree c, const_tree type) precision of the type are returned instead. */ void -get_type_static_bounds (tree type, mpz_t min, mpz_t max) +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) @@ -6306,6 +6323,19 @@ get_type_static_bounds (tree type, mpz_t min, mpz_t max) } } +/* 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 @@ -6320,7 +6350,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; @@ -6379,6 +6409,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 @@ -6510,12 +6541,12 @@ decl_type_context (const_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. */ @@ -7049,6 +7080,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. */ @@ -7196,6 +7301,50 @@ build_common_tree_nodes_2 (int short_double) 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 (); @@ -7439,13 +7588,15 @@ reconstruct_complex_type (tree type, tree bottom) 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 @@ -7459,6 +7610,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; @@ -7519,6 +7674,9 @@ initializer_zerop (const_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) @@ -7788,7 +7946,7 @@ range_in_array_bounds_p (tree ref) 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); @@ -7804,7 +7962,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)) @@ -7843,21 +8001,26 @@ 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 (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; } @@ -8011,7 +8174,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; @@ -8062,7 +8225,7 @@ num_ending_zeros (const_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; \ } \ @@ -8074,7 +8237,7 @@ num_ending_zeros (const_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; @@ -8154,7 +8317,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; @@ -8201,10 +8365,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) { @@ -8212,6 +8378,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: @@ -8357,7 +8524,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; @@ -8390,6 +8557,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)); @@ -8421,7 +8589,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; } @@ -8435,13 +8603,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; } @@ -8516,4 +8685,92 @@ call_expr_arglist (tree exp) 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"