/* Language-independent node constructors for parse phase of GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+ 2011 Free Software Foundation, Inc.
This file is part of GCC.
#include "toplev.h"
#include "ggc.h"
#include "hashtab.h"
+#include "filenames.h"
#include "output.h"
#include "target.h"
#include "langhooks.h"
"exprs",
"constants",
"identifiers",
- "perm_tree_lists",
- "temp_tree_lists",
"vecs",
"binfos",
"ssa names",
return TS_TYPE_DECL;
case FUNCTION_DECL:
return TS_FUNCTION_DECL;
+ case TRANSLATION_UNIT_DECL:
+ return TS_TRANSLATION_UNIT_DECL;
default:
return TS_DECL_NON_COMMON;
}
{
unsigned i;
-#define MARK_TS_BASE(C) \
- do { \
- tree_contains_struct[C][TS_BASE] = 1; \
- } while (0)
-
-#define MARK_TS_COMMON(C) \
- do { \
- MARK_TS_BASE (C); \
- tree_contains_struct[C][TS_COMMON] = 1; \
- } while (0)
-
-#define MARK_TS_DECL_MINIMAL(C) \
- do { \
- MARK_TS_COMMON (C); \
- tree_contains_struct[C][TS_DECL_MINIMAL] = 1; \
- } while (0)
-
-#define MARK_TS_DECL_COMMON(C) \
- do { \
- MARK_TS_DECL_MINIMAL (C); \
- tree_contains_struct[C][TS_DECL_COMMON] = 1; \
- } while (0)
-
-#define MARK_TS_DECL_WRTL(C) \
- do { \
- MARK_TS_DECL_COMMON (C); \
- tree_contains_struct[C][TS_DECL_WRTL] = 1; \
- } while (0)
-
-#define MARK_TS_DECL_WITH_VIS(C) \
- do { \
- MARK_TS_DECL_WRTL (C); \
- tree_contains_struct[C][TS_DECL_WITH_VIS] = 1; \
- } while (0)
-
-#define MARK_TS_DECL_NON_COMMON(C) \
- do { \
- MARK_TS_DECL_WITH_VIS (C); \
- tree_contains_struct[C][TS_DECL_NON_COMMON] = 1; \
- } while (0)
-
for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++)
{
enum tree_code code;
/* Mark all the structures that TS is derived from. */
switch (ts_code)
{
- case TS_COMMON:
+ case TS_TYPED:
MARK_TS_BASE (code);
break;
+ case TS_COMMON:
case TS_INT_CST:
case TS_REAL_CST:
case TS_FIXED_CST:
case TS_VECTOR:
case TS_STRING:
case TS_COMPLEX:
+ case TS_SSA_NAME:
+ case TS_CONSTRUCTOR:
+ MARK_TS_TYPED (code);
+ break;
+
case TS_IDENTIFIER:
case TS_DECL_MINIMAL:
case TS_TYPE:
case TS_LIST:
case TS_VEC:
case TS_EXP:
- case TS_SSA_NAME:
case TS_BLOCK:
case TS_BINFO:
case TS_STATEMENT_LIST:
- case TS_CONSTRUCTOR:
case TS_OMP_CLAUSE:
case TS_OPTIMIZATION:
case TS_TARGET_OPTION:
break;
case TS_DECL_WRTL:
+ case TS_CONST_DECL:
MARK_TS_DECL_COMMON (code);
break;
case TS_PARM_DECL:
case TS_LABEL_DECL:
case TS_RESULT_DECL:
- case TS_CONST_DECL:
MARK_TS_DECL_WRTL (code);
break;
MARK_TS_DECL_NON_COMMON (code);
break;
+ case TS_TRANSLATION_UNIT_DECL:
+ MARK_TS_DECL_COMMON (code);
+ break;
+
default:
gcc_unreachable ();
}
/* Basic consistency checks for attributes used in fold. */
gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON]);
- gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON]);
gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON]);
gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_COMMON]);
gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_COMMON]);
- gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_WRTL]);
gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WRTL]);
gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_WRTL]);
gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_WRTL]);
gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS]);
gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS]);
gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS]);
- gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_WITH_VIS]);
gcc_assert (tree_contains_struct[VAR_DECL][TS_VAR_DECL]);
gcc_assert (tree_contains_struct[FIELD_DECL][TS_FIELD_DECL]);
gcc_assert (tree_contains_struct[PARM_DECL][TS_PARM_DECL]);
gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]);
gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]);
gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]);
-
-#undef MARK_TS_BASE
-#undef MARK_TS_COMMON
-#undef MARK_TS_DECL_MINIMAL
-#undef MARK_TS_DECL_COMMON
-#undef MARK_TS_DECL_WRTL
-#undef MARK_TS_DECL_WITH_VIS
-#undef MARK_TS_DECL_NON_COMMON
}
}
}
-/* Return a newly allocated node of code CODE. For decl and type
- nodes, some other fields are initialized. The rest of the node is
- initialized to zero. This function cannot be used for TREE_VEC or
- OMP_CLAUSE nodes, which is enforced by asserts in tree_code_size.
-
- Achoo! I got a code in the node. */
+/* Record interesting allocation statistics for a tree node with CODE
+ and LENGTH. */
-tree
-make_node_stat (enum tree_code code MEM_STAT_DECL)
+static void
+record_node_allocation_statistics (enum tree_code code ATTRIBUTE_UNUSED,
+ size_t length ATTRIBUTE_UNUSED)
{
- tree t;
- enum tree_code_class type = TREE_CODE_CLASS (code);
- size_t length = tree_code_size (code);
#ifdef GATHER_STATISTICS
+ enum tree_code_class type = TREE_CODE_CLASS (code);
tree_node_kind kind;
switch (type)
kind = constr_kind;
break;
+ case OMP_CLAUSE:
+ kind = omp_clause_kind;
+ break;
+
default:
kind = x_kind;
break;
}
break;
+ case tcc_vl_exp:
+ kind = e_kind;
+ break;
+
default:
gcc_unreachable ();
}
tree_node_counts[(int) kind]++;
tree_node_sizes[(int) kind] += length;
#endif
+}
+
+/* Allocate and return a new UID from the DECL_UID namespace. */
+
+int
+allocate_decl_uid (void)
+{
+ return next_decl_uid++;
+}
+
+/* Return a newly allocated node of code CODE. For decl and type
+ nodes, some other fields are initialized. The rest of the node is
+ initialized to zero. This function cannot be used for TREE_VEC or
+ OMP_CLAUSE nodes, which is enforced by asserts in tree_code_size.
+
+ Achoo! I got a code in the node. */
+
+tree
+make_node_stat (enum tree_code code MEM_STAT_DECL)
+{
+ tree t;
+ enum tree_code_class type = TREE_CODE_CLASS (code);
+ size_t length = tree_code_size (code);
+
+ record_node_allocation_statistics (code, length);
t = ggc_alloc_zone_cleared_tree_node_stat (
(code == IDENTIFIER_NODE) ? &tree_id_zone : &tree_zone,
DECL_UID (t) = --next_debug_decl_uid;
else
{
- DECL_UID (t) = next_decl_uid++;
+ DECL_UID (t) = allocate_decl_uid ();
SET_DECL_PT_UID (t, -1);
}
if (TREE_CODE (t) == LABEL_DECL)
}
\f
/* Return a new node with the same contents as NODE except that its
- TREE_CHAIN is zero and it has a fresh uid. */
+ TREE_CHAIN, if it has one, is zero and it has a fresh uid. */
tree
copy_node_stat (tree node MEM_STAT_DECL)
gcc_assert (code != STATEMENT_LIST);
length = tree_size (node);
+ record_node_allocation_statistics (code, length);
t = ggc_alloc_zone_tree_node_stat (&tree_zone, length PASS_MEM_STAT);
memcpy (t, node, length);
- TREE_CHAIN (t) = 0;
+ if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
+ TREE_CHAIN (t) = 0;
TREE_ASM_WRITTEN (t) = 0;
TREE_VISITED (t) = 0;
if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
DECL_UID (t) = --next_debug_decl_uid;
else
{
- DECL_UID (t) = next_decl_uid++;
+ DECL_UID (t) = allocate_decl_uid ();
if (DECL_PT_UID_SET_P (node))
SET_DECL_PT_UID (t, DECL_PT_UID (node));
}
}
\f
-/* Create an INT_CST node with a LOW value sign extended. */
+/* Create an INT_CST node with a LOW value sign extended to TYPE. */
tree
build_int_cst (tree type, HOST_WIDE_INT low)
if (!type)
type = integer_type_node;
- return build_int_cst_wide (type, low, low < 0 ? -1 : 0);
+ return double_int_to_tree (type, shwi_to_double_int (low));
}
-/* Create an INT_CST node with a LOW value in TYPE. The value is sign extended
- if it is negative. This function is similar to build_int_cst, but
- the extra bits outside of the type precision are cleared. Constants
- with these extra bits may confuse the fold so that it detects overflows
- even in cases when they do not occur, and in general should be avoided.
- We cannot however make this a default behavior of build_int_cst without
- more intrusive changes, since there are parts of gcc that rely on the extra
- precision of the integer constants. */
+/* Create an INT_CST node with a LOW value sign extended to TYPE. */
tree
build_int_cst_type (tree type, HOST_WIDE_INT low)
{
- unsigned HOST_WIDE_INT low1;
- HOST_WIDE_INT hi;
-
gcc_assert (type);
- fit_double_type (low, low < 0 ? -1 : 0, &low1, &hi, type);
-
- return build_int_cst_wide (type, low1, hi);
+ return double_int_to_tree (type, shwi_to_double_int (low));
}
/* Constructs tree in type TYPE from with value given by CST. Signedness
return double_int_equal_p (cst, ext);
}
+/* We force the double_int CST to the range of the type TYPE by sign or
+ zero extending it. OVERFLOWABLE indicates if we are interested in
+ overflow of the value, when >0 we are only interested in signed
+ overflow, for <0 we are interested in any overflow. OVERFLOWED
+ indicates whether overflow has already occurred. CONST_OVERFLOWED
+ indicates whether constant overflow has already occurred. We force
+ T's value to be within range of T's type (by setting to 0 or 1 all
+ the bits outside the type's range). We set TREE_OVERFLOWED if,
+ OVERFLOWED is nonzero,
+ or OVERFLOWABLE is >0 and signed overflow occurs
+ or OVERFLOWABLE is <0 and any overflow occurs
+ We return a new tree node for the extended double_int. The node
+ is shared if no overflow flags are set. */
+
+
+tree
+force_fit_type_double (tree type, double_int cst, int overflowable,
+ bool overflowed)
+{
+ bool sign_extended_type;
+
+ /* Size types *are* sign extended. */
+ sign_extended_type = (!TYPE_UNSIGNED (type)
+ || (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (type)));
+
+ /* If we need to set overflow flags, return a new unshared node. */
+ if (overflowed || !double_int_fits_to_tree_p(type, cst))
+ {
+ if (overflowed
+ || overflowable < 0
+ || (overflowable > 0 && sign_extended_type))
+ {
+ tree t = make_node (INTEGER_CST);
+ TREE_INT_CST (t) = double_int_ext (cst, TYPE_PRECISION (type),
+ !sign_extended_type);
+ TREE_TYPE (t) = type;
+ TREE_OVERFLOW (t) = 1;
+ return t;
+ }
+ }
+
+ /* Else build a shared node. */
+ return double_int_to_tree (type, cst);
+}
+
/* These are the hash table functions for the hash table of INTEGER_CST
nodes of a sizetype. */
switch (TREE_CODE (type))
{
+ case NULLPTR_TYPE:
+ gcc_assert (hi == 0 && low == 0);
+ /* Fallthru. */
+
case POINTER_TYPE:
case REFERENCE_TYPE:
/* Cache NULL pointer. */
tree v = make_node (VECTOR_CST);
int over = 0;
tree link;
+ unsigned cnt = 0;
TREE_VECTOR_CST_ELTS (v) = vals;
TREE_TYPE (v) = type;
for (link = vals; link; link = TREE_CHAIN (link))
{
tree value = TREE_VALUE (link);
+ cnt++;
/* Don't crash if we get an address constant. */
if (!CONSTANT_CLASS_P (value))
over |= TREE_OVERFLOW (value);
}
+ gcc_assert (cnt == TYPE_VECTOR_SUBPARTS (type));
+
TREE_OVERFLOW (v) = over;
return v;
}
FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
list = tree_cons (NULL_TREE, value, list);
+ for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx)
+ list = tree_cons (NULL_TREE,
+ build_zero_cst (TREE_TYPE (type)), list);
return build_vector (type, nreverse (list));
}
+/* Build a vector of type VECTYPE where all the elements are SCs. */
+tree
+build_vector_from_val (tree vectype, tree sc)
+{
+ int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+ VEC(constructor_elt, gc) *v = NULL;
+
+ if (sc == error_mark_node)
+ return sc;
+
+ /* Verify that the vector type is suitable for SC. Note that there
+ is some inconsistency in the type-system with respect to restrict
+ qualifications of pointers. Vector types always have a main-variant
+ element type and the qualification is applied to the vector-type.
+ So TREE_TYPE (vector-type) does not return a properly qualified
+ vector element-type. */
+ gcc_checking_assert (types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (sc)),
+ TREE_TYPE (vectype)));
+
+ v = VEC_alloc (constructor_elt, gc, nunits);
+ for (i = 0; i < nunits; ++i)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc);
+
+ if (CONSTANT_CLASS_P (sc))
+ return build_vector_from_ctor (vectype, v);
+ else
+ return build_constructor (vectype, v);
+}
+
/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
are in the VEC pointed to by VALS. */
tree
TREE_TYPE (c) = type;
CONSTRUCTOR_ELTS (c) = vals;
- for (i = 0; VEC_iterate (constructor_elt, vals, i, elt); i++)
+ FOR_EACH_VEC_ELT (constructor_elt, vals, i, elt)
if (!TREE_CONSTANT (elt->value))
{
constant_p = false;
/* Do not waste bytes provided by padding of struct tree_string. */
length = len + offsetof (struct tree_string, str) + 1;
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int) c_kind]++;
- tree_node_sizes[(int) c_kind] += length;
-#endif
+ record_node_allocation_statistics (STRING_CST, length);
s = ggc_alloc_tree_node (length);
- memset (s, 0, sizeof (struct tree_common));
+ memset (s, 0, sizeof (struct tree_typed));
TREE_SET_CODE (s, STRING_CST);
TREE_CONSTANT (s) = 1;
TREE_STRING_LENGTH (s) = len;
case VECTOR_TYPE:
{
- tree scalar, cst;
- int i;
+ tree scalar = build_one_cst (TREE_TYPE (type));
- scalar = build_one_cst (TREE_TYPE (type));
-
- /* Create 'vect_cst_ = {cst,cst,...,cst}' */
- cst = NULL_TREE;
- for (i = TYPE_VECTOR_SUBPARTS (type); --i >= 0; )
- cst = tree_cons (NULL_TREE, scalar, cst);
-
- return build_vector (type, cst);
+ return build_vector_from_val (type, scalar);
}
case COMPLEX_TYPE:
return build_complex (type,
build_one_cst (TREE_TYPE (type)),
- fold_convert (TREE_TYPE (type), integer_zero_node));
+ build_zero_cst (TREE_TYPE (type)));
default:
gcc_unreachable ();
}
}
+/* Build 0 constant of type TYPE. This is used by constructor folding
+ and thus the constant should be represented in memory by
+ zero(es). */
+
+tree
+build_zero_cst (tree type)
+{
+ switch (TREE_CODE (type))
+ {
+ case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+ case POINTER_TYPE: case REFERENCE_TYPE:
+ case OFFSET_TYPE:
+ return build_int_cst (type, 0);
+
+ case REAL_TYPE:
+ return build_real (type, dconst0);
+
+ case FIXED_POINT_TYPE:
+ return build_fixed (type, FCONST0 (TYPE_MODE (type)));
+
+ case VECTOR_TYPE:
+ {
+ tree scalar = build_zero_cst (TREE_TYPE (type));
+
+ return build_vector_from_val (type, scalar);
+ }
+
+ case COMPLEX_TYPE:
+ {
+ tree zero = build_zero_cst (TREE_TYPE (type));
+
+ return build_complex (type, zero, zero);
+ }
+
+ default:
+ if (!AGGREGATE_TYPE_P (type))
+ return fold_convert (type, integer_zero_node);
+ return build_constructor (type, NULL);
+ }
+}
+
+
/* Build a BINFO with LEN language slots. */
tree
size_t length = (offsetof (struct tree_binfo, base_binfos)
+ VEC_embedded_size (tree, base_binfos));
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int) binfo_kind]++;
- tree_node_sizes[(int) binfo_kind] += length;
-#endif
+ record_node_allocation_statistics (TREE_BINFO, length);
t = ggc_alloc_zone_tree_node_stat (&tree_zone, length PASS_MEM_STAT);
tree t;
int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int) vec_kind]++;
- tree_node_sizes[(int) vec_kind] += length;
-#endif
+ record_node_allocation_statistics (TREE_VEC, length);
t = ggc_alloc_zone_cleared_tree_node_stat (&tree_zone, length PASS_MEM_STAT);
{
unsigned ix;
tree t;
- for (ix = 0; VEC_iterate (tree, v, ix, t); ix++)
+ FOR_EACH_VEC_ELT (tree, v, ix, t)
if (elem == t)
return true;
return false;
{
if (elem == chain)
return 1;
- chain = TREE_CHAIN (chain);
+ chain = DECL_CHAIN (chain);
}
return 0;
tree t = TYPE_FIELDS (type);
int count = 0;
- for (; t; t = TREE_CHAIN (t))
+ for (; t; t = DECL_CHAIN (t))
if (TREE_CODE (t) == FIELD_DECL)
++count;
tree prev = 0, decl, next;
for (decl = t; decl; decl = next)
{
+ /* We shouldn't be using this function to reverse BLOCK chains; we
+ have blocks_nreverse for that. */
+ gcc_checking_assert (TREE_CODE (decl) != BLOCK);
next = TREE_CHAIN (decl);
TREE_CHAIN (decl) = prev;
prev = decl;
tree *pp = &ret;
unsigned int i;
tree t;
- for (i = 0; VEC_iterate (tree, vec, i, t); ++i)
+ FOR_EACH_VEC_ELT (tree, vec, i, t)
{
*pp = build_tree_list_stat (NULL, t PASS_MEM_STAT);
pp = &TREE_CHAIN (*pp);
PASS_MEM_STAT);
memset (node, 0, sizeof (struct tree_common));
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int) x_kind]++;
- tree_node_sizes[(int) x_kind] += sizeof (struct tree_list);
-#endif
+ record_node_allocation_statistics (TREE_LIST, sizeof (struct tree_list));
TREE_SET_CODE (node, TREE_LIST);
TREE_CHAIN (node) = chain;
min = TYPE_MIN_VALUE (index_type);
max = TYPE_MAX_VALUE (index_type);
+ /* TYPE_MAX_VALUE may not be set if the array has unknown length. */
+ if (!max)
+ return error_mark_node;
+
return (integer_zerop (min)
? max
: fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, min));
case BIT_FIELD_REF:
return NULL;
- case MISALIGNED_INDIRECT_REF:
- case ALIGN_INDIRECT_REF:
case INDIRECT_REF:
return TREE_CONSTANT (TREE_OPERAND (arg, 0)) ? arg : NULL;
return true;
case VAR_DECL:
- if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
- && !DECL_DLLIMPORT_P (op))
+ if ((TREE_STATIC (op) || DECL_EXTERNAL (op))
|| DECL_THREAD_LOCAL_P (op)
|| DECL_CONTEXT (op) == current_function_decl
|| decl_function_context (op) == current_function_decl)
TREE_READONLY (t) = read_only;
}
\f
-/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
- or offset that depends on a field within a record. */
+/* Return true if EXP contains a PLACEHOLDER_EXPR, i.e. if it represents a
+ size or offset that depends on a field within a record. */
bool
contains_placeholder_p (const_tree exp)
return 0;
}
-/* Return true if any part of the computation of TYPE involves a
- PLACEHOLDER_EXPR. This includes size, bounds, qualifiers
- (for QUAL_UNION_TYPE) and field positions. */
+/* Return true if any part of the structure of TYPE involves a PLACEHOLDER_EXPR
+ directly. This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and
+ field positions. */
static bool
type_contains_placeholder_1 (const_tree type)
the case of arrays) type involves a placeholder, this type does. */
if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type))
|| CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type))
- || (TREE_TYPE (type) != 0
+ || (!POINTER_TYPE_P (type)
+ && TREE_TYPE (type)
&& type_contains_placeholder_p (TREE_TYPE (type))))
return true;
|| CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
case ARRAY_TYPE:
- /* We're already checked the component type (TREE_TYPE), so just check
- the index type. */
+ /* We have already checked the component type above, so just check the
+ domain type. */
return type_contains_placeholder_p (TYPE_DOMAIN (type));
case RECORD_TYPE:
{
tree field;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL
&& (CONTAINS_PLACEHOLDER_P (DECL_FIELD_OFFSET (field))
|| (TREE_CODE (type) == QUAL_UNION_TYPE
}
}
+/* Wrapper around above function used to cache its result. */
+
bool
type_contains_placeholder_p (tree type)
{
unsigned int i;
tree iter;
- for (i = 0; VEC_iterate (tree, *queue, i, iter); i++)
+ FOR_EACH_VEC_ELT (tree, *queue, i, iter)
if (simple_cst_equal (iter, exp) == 1)
break;
}
TREE_READONLY (new_tree) |= TREE_READONLY (exp);
+
+ if (code == INDIRECT_REF || code == ARRAY_REF || code == ARRAY_RANGE_REF)
+ TREE_THIS_NOTRAP (new_tree) |= TREE_THIS_NOTRAP (exp);
+
return new_tree;
}
}
TREE_READONLY (new_tree) |= TREE_READONLY (exp);
+
+ if (code == INDIRECT_REF || code == ARRAY_REF || code == ARRAY_RANGE_REF)
+ TREE_THIS_NOTRAP (new_tree) |= TREE_THIS_NOTRAP (exp);
+
return new_tree;
}
\f
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)
+ if (TREE_CODE (node) == INDIRECT_REF
+ || TREE_CODE (node) == MEM_REF)
UPDATE_FLAGS (TREE_OPERAND (node, 0));
else if (CONSTANT_CLASS_P (node))
;
build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
{
int length = sizeof (struct tree_exp);
-#ifdef GATHER_STATISTICS
- tree_node_kind kind;
-#endif
tree t;
-#ifdef GATHER_STATISTICS
- switch (TREE_CODE_CLASS (code))
- {
- case tcc_statement: /* an expression with side effects */
- kind = s_kind;
- break;
- case tcc_reference: /* a reference */
- kind = r_kind;
- break;
- default:
- kind = e_kind;
- break;
- }
-
- tree_node_counts[(int) kind]++;
- tree_node_sizes[(int) kind] += length;
-#endif
+ record_node_allocation_statistics (code, length);
gcc_assert (TREE_CODE_LENGTH (code) == 1);
TREE_READONLY (t) = 0;
break;
- case MISALIGNED_INDIRECT_REF:
- case ALIGN_INDIRECT_REF:
case INDIRECT_REF:
/* Whether a dereference is readonly has nothing to do with whether
its operand is readonly. */
return t;
}
+/* Build a simple MEM_REF tree with the sematics of a plain INDIRECT_REF
+ on the pointer PTR. */
+
+tree
+build_simple_mem_ref_loc (location_t loc, tree ptr)
+{
+ HOST_WIDE_INT offset = 0;
+ tree ptype = TREE_TYPE (ptr);
+ tree tem;
+ /* For convenience allow addresses that collapse to a simple base
+ and offset. */
+ if (TREE_CODE (ptr) == ADDR_EXPR
+ && (handled_component_p (TREE_OPERAND (ptr, 0))
+ || TREE_CODE (TREE_OPERAND (ptr, 0)) == MEM_REF))
+ {
+ ptr = get_addr_base_and_unit_offset (TREE_OPERAND (ptr, 0), &offset);
+ gcc_assert (ptr);
+ ptr = build_fold_addr_expr (ptr);
+ gcc_assert (is_gimple_reg (ptr) || is_gimple_min_invariant (ptr));
+ }
+ tem = build2 (MEM_REF, TREE_TYPE (ptype),
+ ptr, build_int_cst (ptype, offset));
+ SET_EXPR_LOCATION (tem, loc);
+ return tem;
+}
+
+/* Return the constant offset of a MEM_REF or TARGET_MEM_REF tree T. */
+
+double_int
+mem_ref_offset (const_tree t)
+{
+ tree toff = TREE_OPERAND (t, 1);
+ return double_int_sext (tree_to_double_int (toff),
+ TYPE_PRECISION (TREE_TYPE (toff)));
+}
+
+/* Return the pointer-type relevant for TBAA purposes from the
+ gimple memory reference tree T. This is the type to be used for
+ the offset operand of MEM_REF or TARGET_MEM_REF replacements of T. */
+
+tree
+reference_alias_ptr_type (const_tree t)
+{
+ const_tree base = t;
+ while (handled_component_p (base))
+ base = TREE_OPERAND (base, 0);
+ if (TREE_CODE (base) == MEM_REF)
+ return TREE_TYPE (TREE_OPERAND (base, 1));
+ else if (TREE_CODE (base) == TARGET_MEM_REF)
+ return TREE_TYPE (TMR_OFFSET (base));
+ else
+ return build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (base)));
+}
+
+/* Return an invariant ADDR_EXPR of type TYPE taking the address of BASE
+ offsetted by OFFSET units. */
+
+tree
+build_invariant_address (tree type, tree base, HOST_WIDE_INT offset)
+{
+ tree ref = fold_build2 (MEM_REF, TREE_TYPE (type),
+ build_fold_addr_expr (base),
+ build_int_cst (ptr_type_node, offset));
+ tree addr = build1 (ADDR_EXPR, type, ref);
+ recompute_tree_invariant_for_addr_expr (addr);
+ return addr;
+}
+
/* Similar except don't specify the TREE_TYPE
and leave the TREE_SIDE_EFFECTS as 0.
It is permissible for arguments to be null,
ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3);
CALL_EXPR_FN (ret) = fn;
CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
- for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix)
+ FOR_EACH_VEC_ELT (tree, args, ix, t)
CALL_EXPR_ARG (ret, ix) = t;
return ret;
}
return decl;
}
+VEC(tree,gc) *all_translation_units;
+
+/* Builds a new translation-unit decl with name NAME, queues it in the
+ global list of translation-unit decls and returns it. */
+
+tree
+build_translation_unit_decl (tree name)
+{
+ tree tu = build_decl (UNKNOWN_LOCATION, TRANSLATION_UNIT_DECL,
+ name, NULL_TREE);
+ TRANSLATION_UNIT_LANGUAGE (tu) = lang_hooks.name;
+ VEC_safe_push (tree, gc, all_translation_units, tu);
+ return tu;
+}
+
\f
/* BLOCK nodes are used to represent the structure of binding contours
and declarations, once those contours have been exited and their contents
its canonical type, we will need to use structural equality
checks for this type. */
if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
- || !targetm.comp_type_attributes (ntype, ttype))
+ || !comp_type_attributes (ntype, ttype))
SET_TYPE_STRUCTURAL_EQUALITY (ntype);
else if (TYPE_CANONICAL (ntype) == ntype)
TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
return ttype;
}
+/* Compare two attributes for their value identity. Return true if the
+ attribute values are known to be equal; otherwise return false.
+*/
+
+static bool
+attribute_value_equal (const_tree attr1, const_tree attr2)
+{
+ if (TREE_VALUE (attr1) == TREE_VALUE (attr2))
+ return true;
+
+ if (TREE_VALUE (attr1) != NULL_TREE
+ && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
+ && TREE_VALUE (attr2) != NULL
+ && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
+ return (simple_cst_list_equal (TREE_VALUE (attr1),
+ TREE_VALUE (attr2)) == 1);
+
+ return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
+}
+
+/* Return 0 if the attributes for two types are incompatible, 1 if they
+ are compatible, and 2 if they are nearly compatible (which causes a
+ warning to be generated). */
+int
+comp_type_attributes (const_tree type1, const_tree type2)
+{
+ const_tree a1 = TYPE_ATTRIBUTES (type1);
+ const_tree a2 = TYPE_ATTRIBUTES (type2);
+ const_tree a;
+
+ if (a1 == a2)
+ return 1;
+ for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a))
+ {
+ const struct attribute_spec *as;
+ const_tree attr;
+
+ as = lookup_attribute_spec (TREE_PURPOSE (a));
+ if (!as || as->affects_type_identity == false)
+ continue;
+
+ attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
+ if (!attr || !attribute_value_equal (a, attr))
+ break;
+ }
+ if (!a)
+ {
+ for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
+ {
+ const struct attribute_spec *as;
+
+ as = lookup_attribute_spec (TREE_PURPOSE (a));
+ if (!as || as->affects_type_identity == false)
+ continue;
+
+ if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
+ break;
+ /* We don't need to compare trees again, as we did this
+ already in first loop. */
+ }
+ /* All types - affecting identity - are equal, so
+ there is no need to call target hook for comparison. */
+ if (!a)
+ return 1;
+ }
+ /* As some type combinations - like default calling-convention - might
+ be compatible, we have to call the target hook to get the final result. */
+ return targetm.comp_type_attributes (type1, type2);
+}
/* Return a type like TTYPE except that its TYPE_ATTRIBUTE
is ATTRIBUTE.
BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
- for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (binfo), i, t); i++)
+ FOR_EACH_VEC_ELT (tree, BINFO_BASE_BINFOS (binfo), i, t)
free_lang_data_in_binfo (t);
}
}
-/* Remove all the non-variable decls from BLOCK. LOCALS is the set of
- variables in DECL_STRUCT_FUNCTION (FN)->local_decls. Every decl
- in BLOCK that is not in LOCALS is removed. */
-
-static void
-free_lang_data_in_block (tree fn, tree block, struct pointer_set_t *locals)
-{
- tree *tp, t;
-
- tp = &BLOCK_VARS (block);
- while (*tp)
- {
- if (!pointer_set_contains (locals, *tp))
- *tp = TREE_CHAIN (*tp);
- else
- tp = &TREE_CHAIN (*tp);
- }
-
- for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
- free_lang_data_in_block (fn, t, locals);
-}
-
-
/* Reset all language specific information still present in symbol
DECL. */
TREE_LANG_FLAG_5 (decl) = 0;
TREE_LANG_FLAG_6 (decl) = 0;
- /* Identifiers need not have a type. */
- if (DECL_NAME (decl))
- TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
-
- /* Ignore any intervening types, because we are going to clear their
- TYPE_CONTEXT fields. */
- if (TREE_CODE (decl) != FIELD_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- DECL_CONTEXT (decl) = decl_function_context (decl);
-
- if (DECL_CONTEXT (decl)
- && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
- DECL_CONTEXT (decl) = NULL_TREE;
-
- if (TREE_CODE (decl) == VAR_DECL)
- {
- tree context = DECL_CONTEXT (decl);
-
- if (context)
- {
- enum tree_code code = TREE_CODE (context);
- if (code == FUNCTION_DECL && DECL_ABSTRACT (context))
- {
- /* Do not clear the decl context here, that will promote
- all vars to global ones. */
- DECL_INITIAL (decl) = NULL_TREE;
- }
-
- if (TREE_STATIC (decl))
- DECL_CONTEXT (decl) = NULL_TREE;
- }
- }
-
free_lang_data_in_one_sizepos (&DECL_SIZE (decl));
free_lang_data_in_one_sizepos (&DECL_SIZE_UNIT (decl));
if (TREE_CODE (decl) == FIELD_DECL)
if (gimple_has_body_p (decl))
{
tree t;
- struct pointer_set_t *locals;
/* If DECL has a gimple body, then the context for its
arguments must be DECL. Otherwise, it doesn't really
the PARM_DECL will be used in the function's body). */
for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t))
DECL_CONTEXT (t) = decl;
-
- /* Collect all the symbols declared in DECL. */
- locals = pointer_set_create ();
- t = DECL_STRUCT_FUNCTION (decl)->local_decls;
- for (; t; t = TREE_CHAIN (t))
- {
- pointer_set_insert (locals, TREE_VALUE (t));
-
- /* All the local symbols should have DECL as their
- context. */
- DECL_CONTEXT (TREE_VALUE (t)) = decl;
- }
-
- /* Get rid of any decl not in local_decls. */
- free_lang_data_in_block (decl, DECL_INITIAL (decl), locals);
-
- pointer_set_destroy (locals);
}
/* DECL_SAVED_TREE holds the GENERIC representation for DECL.
At this point, it is not needed anymore. */
DECL_SAVED_TREE (decl) = NULL_TREE;
+
+ /* Clear the abstract origin if it refers to a method. Otherwise
+ dwarf2out.c will ICE as we clear TYPE_METHODS and thus the
+ origin will not be output correctly. */
+ if (DECL_ABSTRACT_ORIGIN (decl)
+ && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))
+ && RECORD_OR_UNION_TYPE_P
+ (DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))))
+ DECL_ABSTRACT_ORIGIN (decl) = NULL_TREE;
+
+ /* Sometimes the C++ frontend doesn't manage to transform a temporary
+ DECL_VINDEX referring to itself into a vtable slot number as it
+ should. Happens with functions that are copied and then forgotten
+ about. Just clear it, it won't matter anymore. */
+ if (DECL_VINDEX (decl) && !host_integerp (DECL_VINDEX (decl), 0))
+ DECL_VINDEX (decl) = NULL_TREE;
}
else if (TREE_CODE (decl) == VAR_DECL)
{
- tree expr = DECL_DEBUG_EXPR (decl);
- if (expr
- && TREE_CODE (expr) == VAR_DECL
- && !TREE_STATIC (expr) && !DECL_EXTERNAL (expr))
- SET_DECL_DEBUG_EXPR (decl, NULL_TREE);
-
- if (DECL_EXTERNAL (decl)
- && (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
+ if ((DECL_EXTERNAL (decl)
+ && (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
+ || (decl_function_context (decl) && !TREE_STATIC (decl)))
DECL_INITIAL (decl) = NULL_TREE;
}
else if (TREE_CODE (decl) == TYPE_DECL)
- {
- DECL_INITIAL (decl) = NULL_TREE;
-
- /* DECL_CONTEXT is overloaded as DECL_FIELD_CONTEXT for
- FIELD_DECLs, which should be preserved. Otherwise,
- we shouldn't be concerned with source-level lexical
- nesting beyond this point. */
- DECL_CONTEXT (decl) = NULL_TREE;
+ DECL_INITIAL (decl) = NULL_TREE;
+ else if (TREE_CODE (decl) == TRANSLATION_UNIT_DECL
+ && DECL_INITIAL (decl)
+ && TREE_CODE (DECL_INITIAL (decl)) == BLOCK)
+ {
+ /* Strip builtins from the translation-unit BLOCK. We still have
+ targets without builtin_decl support and also builtins are
+ shared nodes and thus we can't use TREE_CHAIN in multiple
+ lists. */
+ tree *nextp = &BLOCK_VARS (DECL_INITIAL (decl));
+ while (*nextp)
+ {
+ tree var = *nextp;
+ if (TREE_CODE (var) == FUNCTION_DECL
+ && DECL_BUILT_IN (var))
+ *nextp = TREE_CHAIN (var);
+ else
+ nextp = &TREE_CHAIN (var);
+ }
}
}
&& DECL_HAS_VALUE_EXPR_P (t))
fld_worklist_push (DECL_VALUE_EXPR (t), fld);
- if (TREE_CODE (t) != FIELD_DECL)
+ if (TREE_CODE (t) != FIELD_DECL
+ && TREE_CODE (t) != TYPE_DECL)
fld_worklist_push (TREE_CHAIN (t), fld);
*ws = 0;
}
fld_worklist_push (TYPE_POINTER_TO (t), fld);
fld_worklist_push (TYPE_REFERENCE_TO (t), fld);
fld_worklist_push (TYPE_NAME (t), fld);
- fld_worklist_push (TYPE_MINVAL (t), fld);
+ /* Do not walk TYPE_NEXT_PTR_TO or TYPE_NEXT_REF_TO. We do not stream
+ them and thus do not and want not to reach unused pointer types
+ this way. */
+ if (!POINTER_TYPE_P (t))
+ fld_worklist_push (TYPE_MINVAL (t), fld);
if (!RECORD_OR_UNION_TYPE_P (t))
fld_worklist_push (TYPE_MAXVAL (t), fld);
fld_worklist_push (TYPE_MAIN_VARIANT (t), fld);
- fld_worklist_push (TYPE_NEXT_VARIANT (t), fld);
+ /* Do not walk TYPE_NEXT_VARIANT. We do not stream it and thus
+ do not and want not to reach unused variants this way. */
fld_worklist_push (TYPE_CONTEXT (t), fld);
- fld_worklist_push (TYPE_CANONICAL (t), fld);
+ /* Do not walk TYPE_CANONICAL. We do not stream it and thus do not
+ and want not to reach unused types this way. */
if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t))
{
fld_worklist_push (BLOCK_ABSTRACT_ORIGIN (t), fld);
}
- fld_worklist_push (TREE_TYPE (t), fld);
+ if (TREE_CODE (t) != IDENTIFIER_NODE)
+ fld_worklist_push (TREE_TYPE (t), fld);
return NULL_TREE;
}
{
basic_block bb;
struct function *fn;
+ unsigned ix;
tree t;
find_decls_types (n->decl, fld);
fn = DECL_STRUCT_FUNCTION (n->decl);
/* Traverse locals. */
- for (t = fn->local_decls; t; t = TREE_CHAIN (t))
- find_decls_types (TREE_VALUE (t), fld);
+ FOR_EACH_LOCAL_DECL (fn, ix, t)
+ find_decls_types (t, fld);
/* Traverse EH regions in FN. */
{
for (n = cgraph_nodes; n; n = n->next)
find_decls_types_in_node (n, &fld);
- for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
+ FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
find_decls_types (p->decl, &fld);
/* Find decls and types in every varpool symbol. */
- for (v = varpool_nodes_queue; v; v = v->next_needed)
+ for (v = varpool_nodes; v; v = v->next)
find_decls_types_in_var (v, &fld);
/* Set the assembler name on every decl found. We need to do this
now because free_lang_data_in_decl will invalidate data needed
for mangling. This breaks mangling on interdependent decls. */
- for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+ FOR_EACH_VEC_ELT (tree, fld.decls, i, t)
assign_assembler_name_if_neeeded (t);
/* Traverse every decl found freeing its language data. */
- for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+ FOR_EACH_VEC_ELT (tree, fld.decls, i, t)
free_lang_data_in_decl (t);
/* Traverse every type found freeing its language data. */
- for (i = 0; VEC_iterate (tree, fld.types, i, t); i++)
+ FOR_EACH_VEC_ELT (tree, fld.types, i, t)
free_lang_data_in_type (t);
pointer_set_destroy (fld.pset);
lang_hooks.callgraph.analyze_expr = NULL;
lang_hooks.dwarf_name = lhd_dwarf_name;
lang_hooks.decl_printable_name = gimple_decl_printable_name;
- lang_hooks.set_decl_assembler_name = lhd_set_decl_assembler_name;
+ /* We do not want the default decl_assembler_name implementation,
+ rather if we have fixed everything we want a wrapper around it
+ asserting that all non-local symbols already got their assembler
+ name and only produce assembler names for local symbols. Or rather
+ make sure we never call decl_assembler_name on local symbols and
+ devise a separate, middle-end private scheme for it. */
/* Reset diagnostic machinery. */
diagnostic_starter (global_dc) = default_tree_diagnostic_starter;
tree a;
for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
attributes);
- a != NULL_TREE;
+ a != NULL_TREE && !attribute_value_equal (a, a2);
a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
TREE_CHAIN (a)))
- {
- if (TREE_VALUE (a) != NULL
- && TREE_CODE (TREE_VALUE (a)) == TREE_LIST
- && TREE_VALUE (a2) != NULL
- && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST)
- {
- if (simple_cst_list_equal (TREE_VALUE (a),
- TREE_VALUE (a2)) == 1)
- break;
- }
- else if (simple_cst_equal (TREE_VALUE (a),
- TREE_VALUE (a2)) == 1)
- break;
- }
+ ;
if (a == NULL_TREE)
{
a1 = copy_node (a2);
DECL_DLLIMPORT_P (node) = 1;
}
else if (TREE_CODE (node) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (node))
+ && DECL_DECLARED_INLINE_P (node)
+ && flag_keep_inline_dllexport)
/* An exported function, even if inline, must be emitted. */
DECL_EXTERNAL (node) = 0;
&& TYPE_NAME (cand) == TYPE_NAME (base)
/* Apparently this is needed for Objective-C. */
&& TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
+ /* Check alignment. */
+ && TYPE_ALIGN (cand) == TYPE_ALIGN (base)
+ && attribute_list_equal (TYPE_ATTRIBUTES (cand),
+ TYPE_ATTRIBUTES (base)));
+}
+
+/* Returns true iff CAND is equivalent to BASE with ALIGN. */
+
+static bool
+check_aligned_type (const_tree cand, const_tree base, unsigned int align)
+{
+ return (TYPE_QUALS (cand) == TYPE_QUALS (base)
+ && TYPE_NAME (cand) == TYPE_NAME (base)
+ /* Apparently this is needed for Objective-C. */
+ && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
+ /* Check alignment. */
+ && TYPE_ALIGN (cand) == align
&& attribute_list_equal (TYPE_ATTRIBUTES (cand),
TYPE_ATTRIBUTES (base)));
}
/* T is its own canonical type. */
TYPE_CANONICAL (t) = t;
- }
+ }
+
+ return t;
+}
+
+/* Create a variant of type T with alignment ALIGN. */
+
+tree
+build_aligned_type (tree type, unsigned int align)
+{
+ tree t;
+
+ if (TYPE_PACKED (type)
+ || TYPE_ALIGN (type) == align)
+ return type;
+
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ if (check_aligned_type (t, type, align))
+ return t;
+
+ t = build_variant_type_copy (type);
+ TYPE_ALIGN (t) = align;
return t;
}
struct tree_priority_map *h;
gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
+ if (priority == DEFAULT_INIT_PRIORITY)
+ return;
h = decl_priority_info (decl);
h->init = priority;
}
struct tree_priority_map *h;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+ if (priority == DEFAULT_INIT_PRIORITY)
+ return;
h = decl_priority_info (decl);
h->fini = priority;
}
|| TREE_TYPE (a->type) != TREE_TYPE (b->type)
|| !attribute_list_equal (TYPE_ATTRIBUTES (a->type),
TYPE_ATTRIBUTES (b->type))
- || TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
- || TYPE_MODE (a->type) != TYPE_MODE (b->type)
|| (TREE_CODE (a->type) != COMPLEX_TYPE
&& TYPE_NAME (a->type) != TYPE_NAME (b->type)))
return 0;
+ /* Be careful about comparing arrays before and after the element type
+ has been completed; don't compare TYPE_ALIGN unless both types are
+ complete. */
+ if (COMPLETE_TYPE_P (a->type) && COMPLETE_TYPE_P (b->type)
+ && (TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
+ || TYPE_MODE (a->type) != TYPE_MODE (b->type)))
+ return 0;
+
switch (TREE_CODE (a->type))
{
case VOID_TYPE:
return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type);
case METHOD_TYPE:
- return (TYPE_METHOD_BASETYPE (a->type) == TYPE_METHOD_BASETYPE (b->type)
- && (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_METHOD_BASETYPE (a->type) == TYPE_METHOD_BASETYPE (b->type)
+ && (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;
case ARRAY_TYPE:
return TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type);
being passed. */
gcc_assert (TYPE_MAIN_VARIANT (type) == type);
- if (!lang_hooks.types.hash_types)
- return type;
-
/* See if the type is in the hash table already. If so, return it.
Otherwise, add the type. */
t1 = type_hash_lookup (hashcode, type);
/* See if the data pointed to by the type hash table is marked. We consider
it marked if the type is marked or if a debug type number or symbol
- table entry has been made for the type. This reduces the amount of
- debugging output and eliminates that dependency of the debug output on
- the number of garbage collections. */
+ table entry has been made for the type. */
static int
type_hash_marked_p (const void *p)
{
const_tree const type = ((const struct type_hash *) p)->type;
- return ggc_marked_p (type) || TYPE_SYMTAB_POINTER (type);
+ return ggc_marked_p (type);
}
static void
const_tree. */
for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
CONST_CAST_TREE(l1));
- attr != NULL_TREE;
+ attr != NULL_TREE && !attribute_value_equal (t2, attr);
attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
TREE_CHAIN (attr)))
- {
- if (TREE_VALUE (t2) != NULL
- && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST
- && TREE_VALUE (attr) != NULL
- && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST)
- {
- if (simple_cst_list_equal (TREE_VALUE (t2),
- TREE_VALUE (attr)) == 1)
- break;
- }
- else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
- break;
- }
+ ;
- if (attr == 0)
+ if (attr == NULL_TREE)
return 0;
}
}
return val;
}
+ case MEM_REF:
+ {
+ /* The type of the second operand is relevant, except for
+ its top-level qualifiers. */
+ tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (t, 1)));
+
+ val = iterative_hash_object (TYPE_HASH (type), val);
+
+ /* We could use the standard hash computation from this point
+ on. */
+ val = iterative_hash_object (code, val);
+ val = iterative_hash_expr (TREE_OPERAND (t, 1), val);
+ val = iterative_hash_expr (TREE_OPERAND (t, 0), val);
+ return val;
+ }
case FUNCTION_DECL:
/* When referring to a built-in FUNCTION_DECL, use the __builtin__ form.
Otherwise nodes that compare equal according to operand_equal_p might
}
}
-/* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE.
- MAXVAL should be the maximum value in the domain
- (one less than the length of the array).
-
- The maximum value that MAXVAL can have is INT_MAX for a HOST_WIDE_INT.
- We don't enforce this limit, that is up to caller (e.g. language front end).
- The limit exists because the result is a signed type and we don't handle
- sizes that use more than one HOST_WIDE_INT. */
-
-tree
-build_index_type (tree maxval)
-{
- tree itype = make_node (INTEGER_TYPE);
-
- TREE_TYPE (itype) = sizetype;
- TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
- TYPE_MIN_VALUE (itype) = size_zero_node;
- TYPE_MAX_VALUE (itype) = fold_convert (sizetype, maxval);
- SET_TYPE_MODE (itype, TYPE_MODE (sizetype));
- TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
- TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);
- TYPE_ALIGN (itype) = TYPE_ALIGN (sizetype);
- TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (sizetype);
-
- if (host_integerp (maxval, 1))
- return type_hash_canon (tree_low_cst (maxval, 1), itype);
- else
- {
- /* Since we cannot hash this type, we need to compare it using
- structural equality checks. */
- SET_TYPE_STRUCTURAL_EQUALITY (itype);
- return itype;
- }
-}
-
#define MAX_INT_CACHED_PREC \
(HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2];
ret = itype;
if (host_integerp (TYPE_MAX_VALUE (itype), 1))
ret = type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype);
- if (precision <= MAX_INT_CACHED_PREC && lang_hooks.types.hash_types)
+ if (precision <= MAX_INT_CACHED_PREC)
nonstandard_integer_type_cache[precision + unsignedp] = ret;
return ret;
}
-/* Create a range of some discrete type TYPE (an INTEGER_TYPE,
- ENUMERAL_TYPE or BOOLEAN_TYPE), with low bound LOWVAL and
- high bound HIGHVAL. If TYPE is NULL, sizetype is used. */
+/* Create a range of some discrete type TYPE (an INTEGER_TYPE, ENUMERAL_TYPE
+ or BOOLEAN_TYPE) with low bound LOWVAL and high bound HIGHVAL. If SHARED
+ is true, reuse such a type that has already been constructed. */
-tree
-build_range_type (tree type, tree lowval, tree highval)
+static tree
+build_range_type_1 (tree type, tree lowval, tree highval, bool shared)
{
tree itype = make_node (INTEGER_TYPE);
+ hashval_t hashcode = 0;
TREE_TYPE (itype) = type;
- if (type == NULL_TREE)
- type = sizetype;
TYPE_MIN_VALUE (itype) = fold_convert (type, lowval);
TYPE_MAX_VALUE (itype) = highval ? fold_convert (type, highval) : NULL;
TYPE_ALIGN (itype) = TYPE_ALIGN (type);
TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (type);
- if (host_integerp (lowval, 0) && highval != 0 && host_integerp (highval, 0))
- return type_hash_canon (tree_low_cst (highval, 0)
- - tree_low_cst (lowval, 0),
- itype);
- else
+ if (!shared)
return itype;
+
+ if ((TYPE_MIN_VALUE (itype)
+ && TREE_CODE (TYPE_MIN_VALUE (itype)) != INTEGER_CST)
+ || (TYPE_MAX_VALUE (itype)
+ && TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST))
+ {
+ /* Since we cannot reliably merge this type, we need to compare it using
+ structural equality checks. */
+ SET_TYPE_STRUCTURAL_EQUALITY (itype);
+ return itype;
+ }
+
+ hashcode = iterative_hash_expr (TYPE_MIN_VALUE (itype), hashcode);
+ hashcode = iterative_hash_expr (TYPE_MAX_VALUE (itype), hashcode);
+ hashcode = iterative_hash_hashval_t (TYPE_HASH (type), hashcode);
+ itype = type_hash_canon (hashcode, itype);
+
+ return itype;
+}
+
+/* Wrapper around build_range_type_1 with SHARED set to true. */
+
+tree
+build_range_type (tree type, tree lowval, tree highval)
+{
+ return build_range_type_1 (type, lowval, highval, true);
+}
+
+/* Wrapper around build_range_type_1 with SHARED set to false. */
+
+tree
+build_nonshared_range_type (tree type, tree lowval, tree highval)
+{
+ return build_range_type_1 (type, lowval, highval, false);
+}
+
+/* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE.
+ MAXVAL should be the maximum value in the domain
+ (one less than the length of the array).
+
+ The maximum value that MAXVAL can have is INT_MAX for a HOST_WIDE_INT.
+ We don't enforce this limit, that is up to caller (e.g. language front end).
+ The limit exists because the result is a signed type and we don't handle
+ sizes that use more than one HOST_WIDE_INT. */
+
+tree
+build_index_type (tree maxval)
+{
+ return build_range_type (sizetype, size_zero_node, maxval);
}
/* Return true if the debug information for TYPE, a subtype, should be emitted
return true;
}
-/* Just like build_index_type, but takes lowval and highval instead
- of just highval (maxval). */
-
-tree
-build_index_2_type (tree lowval, tree highval)
-{
- return build_range_type (sizetype, lowval, highval);
-}
-
/* Construct, lay out and return the type of arrays of elements with ELT_TYPE
and number of elements specified by the range of values of INDEX_TYPE.
- If such a type has already been constructed, reuse it. */
+ If SHARED is true, reuse such a type that has already been constructed. */
-tree
-build_array_type (tree elt_type, tree index_type)
+static tree
+build_array_type_1 (tree elt_type, tree index_type, bool shared)
{
tree t;
- hashval_t hashcode = 0;
if (TREE_CODE (elt_type) == FUNCTION_TYPE)
{
if (TYPE_STRUCTURAL_EQUALITY_P (t))
return t;
- hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
- if (index_type)
- hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
- t = type_hash_canon (hashcode, t);
+ if (shared)
+ {
+ hashval_t hashcode = iterative_hash_object (TYPE_HASH (elt_type), 0);
+ if (index_type)
+ hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
+ t = type_hash_canon (hashcode, t);
+ }
if (TYPE_CANONICAL (t) == t)
{
else if (TYPE_CANONICAL (elt_type) != elt_type
|| (index_type && TYPE_CANONICAL (index_type) != index_type))
TYPE_CANONICAL (t)
- = build_array_type (TYPE_CANONICAL (elt_type),
- index_type ? TYPE_CANONICAL (index_type) : NULL);
+ = build_array_type_1 (TYPE_CANONICAL (elt_type),
+ index_type
+ ? TYPE_CANONICAL (index_type) : NULL_TREE,
+ shared);
}
return t;
}
+/* Wrapper around build_array_type_1 with SHARED set to true. */
+
+tree
+build_array_type (tree elt_type, tree index_type)
+{
+ return build_array_type_1 (elt_type, index_type, true);
+}
+
+/* Wrapper around build_array_type_1 with SHARED set to false. */
+
+tree
+build_nonshared_array_type (tree elt_type, tree index_type)
+{
+ return build_array_type_1 (elt_type, index_type, false);
+}
+
/* Recursively examines the array elements of TYPE, until a non-array
element type is found. */
if (TREE_CODE (orig_type) != METHOD_TYPE
|| !bitmap_bit_p (args_to_skip, 0))
{
- new_type = copy_node (orig_type);
+ new_type = build_distinct_type_copy (orig_type);
TYPE_ARG_TYPES (new_type) = new_reversed;
}
else
we expect first argument to be THIS pointer. */
if (bitmap_bit_p (args_to_skip, 0))
DECL_VINDEX (new_decl) = NULL_TREE;
+
+ /* When signature changes, we need to clear builtin info. */
+ if (DECL_BUILT_IN (new_decl) && !bitmap_empty_p (args_to_skip))
+ {
+ DECL_BUILT_IN_CLASS (new_decl) = NOT_BUILT_IN;
+ DECL_FUNCTION_CODE (new_decl) = (enum built_in_function) 0;
+ }
return new_decl;
}
return win;
}
\f
-/* Nonzero if integer constant C has a value that is permissible
+/* Returns true if integer constant C has a value that is permissible
for type TYPE (an INTEGER_TYPE). */
-int
+bool
int_fits_type_p (const_tree c, const_tree type)
{
tree type_low_bound, type_high_bound;
/* If at least one bound of the type is a constant integer, we can check
ourselves and maybe make a decision. If no such decision is possible, but
this type is a subtype, try checking against that. Otherwise, use
- fit_double_type, which checks against the precision.
+ double_int_fits_to_tree_p, which checks against the precision.
Compute the status for each possibly constant bound, and return if we see
one does not match. Use ok_for_xxx_bound for this purpose, assigning -1
int t_neg = (unsc && double_int_negative_p (dd));
if (c_neg && !t_neg)
- return 0;
+ return false;
if ((c_neg || !t_neg) && double_int_ucmp (dc, dd) < 0)
- return 0;
+ return false;
}
else if (double_int_cmp (dc, dd, unsc) < 0)
- return 0;
+ return false;
ok_for_low_bound = true;
}
else
int t_neg = (unsc && double_int_negative_p (dd));
if (t_neg && !c_neg)
- return 0;
+ return false;
if ((t_neg || !c_neg) && double_int_ucmp (dc, dd) > 0)
- return 0;
+ return false;
}
else if (double_int_cmp (dc, dd, unsc) > 0)
- return 0;
+ return false;
ok_for_high_bound = true;
}
else
/* If the constant fits both bounds, the result is known. */
if (ok_for_low_bound && ok_for_high_bound)
- return 1;
+ return true;
/* Perform some generic filtering which may allow making a decision
even if the bounds are not constant. First, negative integers
never fit in unsigned types, */
if (TYPE_UNSIGNED (type) && !unsc && double_int_negative_p (dc))
- return 0;
+ return false;
/* Second, narrower types always fit in wider ones. */
if (TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (c)))
- return 1;
+ return true;
/* Third, unsigned integers with top bit set never fit signed types. */
if (! TYPE_UNSIGNED (type) && unsc)
if (prec < HOST_BITS_PER_WIDE_INT)
{
if (((((unsigned HOST_WIDE_INT) 1) << prec) & dc.low) != 0)
- return 0;
+ return false;
}
else if (((((unsigned HOST_WIDE_INT) 1)
<< (prec - HOST_BITS_PER_WIDE_INT)) & dc.high) != 0)
- return 0;
+ return false;
}
/* If we haven't been able to decide at this point, there nothing more we
goto retry;
}
- /* Or to fit_double_type, if nothing else. */
- return !fit_double_type (dc.low, dc.high, &dc.low, &dc.high, type);
+ /* Or to double_int_fits_to_tree_p, if nothing else. */
+ return double_int_fits_to_tree_p (type, dc);
}
/* Stores bounds of an integer TYPE in MIN and MAX. If TYPE has non-constant
definition we normally use, since that would produce infinite
recursion via pointers. */
/* This is variably modified if some field's type is. */
- for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+ for (t = TYPE_FIELDS (type); t; t = DECL_CHAIN (t))
if (TREE_CODE (t) == FIELD_DECL)
{
RETURN_TRUE_IF_VAR (DECL_FIELD_OFFSET (t));
\f
#define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
-/* Generate a crc32 of a string. */
+/* Generate a crc32 of a byte. */
unsigned
-crc32_string (unsigned chksum, const char *string)
+crc32_byte (unsigned chksum, char byte)
{
- do
- {
- unsigned value = *string << 24;
+ unsigned value = (unsigned) byte << 24;
unsigned ix;
for (ix = 8; ix--; value <<= 1)
chksum <<= 1;
chksum ^= feedback;
}
+ return chksum;
+}
+
+
+/* Generate a crc32 of a string. */
+
+unsigned
+crc32_string (unsigned chksum, const char *string)
+{
+ do
+ {
+ chksum = crc32_byte (chksum, *string);
}
while (*string++);
return chksum;
*p = '_';
}
-/* Generate a name for a special-purpose function function.
+/* Generate a name for a special-purpose function.
The generated name may need to be unique across the whole link.
+ Changes to this function may also require corresponding changes to
+ xstrdup_mask_random.
TYPE is some string to identify the purpose of this function to the
linker or collect2; it must start with an uppercase letter,
one of:
p = q = ASTRDUP (first_global_object_name);
/* If the target is handling the constructors/destructors, they
will be local to this file and the name is only necessary for
- debugging purposes. */
- else if ((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors)
+ debugging purposes.
+ We also assign sub_I and sub_D sufixes to constructors called from
+ the global static constructors. These are always local. */
+ else if (((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors)
+ || (strncmp (type, "sub_", 4) == 0
+ && (type[4] == 'I' || type[4] == 'D')))
{
const char *file = main_input_filename;
if (! file)
file = input_filename;
/* Just use the file's basename, because the full pathname
might be quite long. */
- p = strrchr (file, '/');
- if (p)
- p++;
- else
- p = file;
- p = q = ASTRDUP (p);
+ p = q = ASTRDUP (lbasename (file));
}
else
{
layout_type (t);
- {
- tree index = build_int_cst (NULL_TREE, nunits - 1);
- tree array = build_array_type (TYPE_MAIN_VARIANT (innertype),
- build_index_type (index));
- tree rt = make_node (RECORD_TYPE);
-
- TYPE_FIELDS (rt) = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
- get_identifier ("f"), array);
- DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
- layout_type (rt);
- TYPE_DEBUG_REPRESENTATION_TYPE (t) = rt;
- /* In dwarfout.c, type lookup uses TYPE_UID numbers. We want to output
- the representation type, and we want to find that die when looking up
- the vector type. This is most easily achieved by making the TYPE_UID
- numbers equal. */
- TYPE_UID (rt) = TYPE_UID (t);
- }
-
hashcode = iterative_hash_host_wide_int (VECTOR_TYPE, hashcode);
hashcode = iterative_hash_host_wide_int (nunits, hashcode);
hashcode = iterative_hash_host_wide_int (mode, hashcode);
build_common_tree_nodes_2 (int short_double)
{
/* Define these next since types below may used them. */
- integer_zero_node = build_int_cst (NULL_TREE, 0);
- integer_one_node = build_int_cst (NULL_TREE, 1);
- integer_minus_one_node = build_int_cst (NULL_TREE, -1);
+ integer_zero_node = build_int_cst (integer_type_node, 0);
+ integer_one_node = build_int_cst (integer_type_node, 1);
+ integer_three_node = build_int_cst (integer_type_node, 3);
+ integer_minus_one_node = build_int_cst (integer_type_node, -1);
size_zero_node = size_int (0);
size_one_node = size_int (1);
TREE_NOTHROW (decl) = 1;
if (ecf_flags & ECF_MALLOC)
DECL_IS_MALLOC (decl) = 1;
+ if (ecf_flags & ECF_LEAF)
+ DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
+ NULL, DECL_ATTRIBUTES (decl));
built_in_decls[code] = decl;
implicit_built_in_decls[code] = decl;
void
build_common_builtin_nodes (void)
{
- tree tmp, tmp2, ftype;
+ tree tmp, ftype;
if (built_in_decls[BUILT_IN_MEMCPY] == NULL
|| built_in_decls[BUILT_IN_MEMMOVE] == NULL)
{
- tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
- tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp);
- tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
- ftype = build_function_type (ptr_type_node, tmp);
+ ftype = build_function_type_list (ptr_type_node,
+ ptr_type_node, const_ptr_type_node,
+ size_type_node, NULL_TREE);
if (built_in_decls[BUILT_IN_MEMCPY] == NULL)
local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
- "memcpy", ECF_NOTHROW);
+ "memcpy", ECF_NOTHROW | ECF_LEAF);
if (built_in_decls[BUILT_IN_MEMMOVE] == NULL)
local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
- "memmove", ECF_NOTHROW);
+ "memmove", ECF_NOTHROW | ECF_LEAF);
}
if (built_in_decls[BUILT_IN_MEMCMP] == NULL)
{
- tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
- tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp);
- tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp);
- ftype = build_function_type (integer_type_node, tmp);
+ ftype = build_function_type_list (integer_type_node, const_ptr_type_node,
+ const_ptr_type_node, size_type_node,
+ NULL_TREE);
local_define_builtin ("__builtin_memcmp", ftype, BUILT_IN_MEMCMP,
- "memcmp", ECF_PURE | ECF_NOTHROW);
+ "memcmp", ECF_PURE | ECF_NOTHROW | ECF_LEAF);
}
if (built_in_decls[BUILT_IN_MEMSET] == NULL)
{
- tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
- tmp = tree_cons (NULL_TREE, integer_type_node, tmp);
- tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
- ftype = build_function_type (ptr_type_node, tmp);
+ ftype = build_function_type_list (ptr_type_node,
+ ptr_type_node, integer_type_node,
+ size_type_node, NULL_TREE);
local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET,
- "memset", ECF_NOTHROW);
+ "memset", ECF_NOTHROW | ECF_LEAF);
}
if (built_in_decls[BUILT_IN_ALLOCA] == NULL)
{
- tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
- ftype = build_function_type (ptr_type_node, tmp);
+ ftype = build_function_type_list (ptr_type_node,
+ size_type_node, NULL_TREE);
local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
- "alloca", ECF_MALLOC | ECF_NOTHROW);
+ "alloca", ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
}
/* If we're checking the stack, `alloca' can throw. */
if (flag_stack_check)
TREE_NOTHROW (built_in_decls[BUILT_IN_ALLOCA]) = 0;
- tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
- tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
- ftype = build_function_type (void_type_node, tmp);
+ ftype = build_function_type_list (void_type_node,
+ ptr_type_node, ptr_type_node,
+ ptr_type_node, NULL_TREE);
local_define_builtin ("__builtin_init_trampoline", ftype,
BUILT_IN_INIT_TRAMPOLINE,
- "__builtin_init_trampoline", ECF_NOTHROW);
+ "__builtin_init_trampoline", ECF_NOTHROW | ECF_LEAF);
- tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- ftype = build_function_type (ptr_type_node, tmp);
+ ftype = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
local_define_builtin ("__builtin_adjust_trampoline", ftype,
BUILT_IN_ADJUST_TRAMPOLINE,
"__builtin_adjust_trampoline",
ECF_CONST | ECF_NOTHROW);
- tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
- ftype = build_function_type (void_type_node, tmp);
+ ftype = build_function_type_list (void_type_node,
+ ptr_type_node, ptr_type_node, NULL_TREE);
local_define_builtin ("__builtin_nonlocal_goto", ftype,
BUILT_IN_NONLOCAL_GOTO,
"__builtin_nonlocal_goto",
ECF_NORETURN | ECF_NOTHROW);
- tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
- ftype = build_function_type (void_type_node, tmp);
+ ftype = build_function_type_list (void_type_node,
+ ptr_type_node, ptr_type_node, NULL_TREE);
local_define_builtin ("__builtin_setjmp_setup", ftype,
BUILT_IN_SETJMP_SETUP,
"__builtin_setjmp_setup", ECF_NOTHROW);
- tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- ftype = build_function_type (ptr_type_node, tmp);
+ ftype = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
local_define_builtin ("__builtin_setjmp_dispatcher", ftype,
BUILT_IN_SETJMP_DISPATCHER,
"__builtin_setjmp_dispatcher",
ECF_PURE | ECF_NOTHROW);
- tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- ftype = build_function_type (void_type_node, tmp);
+ ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
local_define_builtin ("__builtin_setjmp_receiver", ftype,
BUILT_IN_SETJMP_RECEIVER,
"__builtin_setjmp_receiver", ECF_NOTHROW);
- ftype = build_function_type (ptr_type_node, void_list_node);
+ ftype = build_function_type_list (ptr_type_node, NULL_TREE);
local_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE,
- "__builtin_stack_save", ECF_NOTHROW);
+ "__builtin_stack_save", ECF_NOTHROW | ECF_LEAF);
- tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- ftype = build_function_type (void_type_node, tmp);
+ ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
local_define_builtin ("__builtin_stack_restore", ftype,
BUILT_IN_STACK_RESTORE,
- "__builtin_stack_restore", ECF_NOTHROW);
-
- ftype = build_function_type (void_type_node, void_list_node);
- local_define_builtin ("__builtin_profile_func_enter", ftype,
- BUILT_IN_PROFILE_FUNC_ENTER, "profile_func_enter", 0);
- local_define_builtin ("__builtin_profile_func_exit", ftype,
- BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit", 0);
+ "__builtin_stack_restore", ECF_NOTHROW | ECF_LEAF);
/* If there's a possibility that we might use the ARM EABI, build the
alternate __cxa_end_cleanup node used to resume from C++ and Java. */
if (targetm.arm_eabi_unwinder)
{
- ftype = build_function_type (void_type_node, void_list_node);
+ ftype = build_function_type_list (void_type_node, NULL_TREE);
local_define_builtin ("__builtin_cxa_end_cleanup", ftype,
BUILT_IN_CXA_END_CLEANUP,
- "__cxa_end_cleanup", ECF_NORETURN);
+ "__cxa_end_cleanup", ECF_NORETURN | ECF_LEAF);
}
- tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- ftype = build_function_type (void_type_node, tmp);
+ ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
local_define_builtin ("__builtin_unwind_resume", ftype,
BUILT_IN_UNWIND_RESUME,
- (USING_SJLJ_EXCEPTIONS
+ ((targetm.except_unwind_info (&global_options)
+ == UI_SJLJ)
? "_Unwind_SjLj_Resume" : "_Unwind_Resume"),
ECF_NORETURN);
landing pad. These functions are PURE instead of CONST to prevent
them from being hoisted past the exception edge that will initialize
its value in the landing pad. */
- tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node);
- ftype = build_function_type (ptr_type_node, tmp);
+ ftype = build_function_type_list (ptr_type_node,
+ integer_type_node, NULL_TREE);
local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER,
- "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW);
+ "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW | ECF_LEAF);
- tmp2 = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0);
- ftype = build_function_type (tmp2, tmp);
+ tmp = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0);
+ ftype = build_function_type_list (tmp, integer_type_node, NULL_TREE);
local_define_builtin ("__builtin_eh_filter", ftype, BUILT_IN_EH_FILTER,
- "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW);
+ "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW | ECF_LEAF);
- tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node);
- tmp = tree_cons (NULL_TREE, integer_type_node, tmp);
- ftype = build_function_type (void_type_node, tmp);
+ ftype = build_function_type_list (void_type_node,
+ integer_type_node, integer_type_node,
+ NULL_TREE);
local_define_builtin ("__builtin_eh_copy_values", ftype,
BUILT_IN_EH_COPY_VALUES,
"__builtin_eh_copy_values", ECF_NOTHROW);
continue;
inner_type = TREE_TYPE (type);
- tmp = tree_cons (NULL_TREE, inner_type, void_list_node);
- tmp = tree_cons (NULL_TREE, inner_type, tmp);
- tmp = tree_cons (NULL_TREE, inner_type, tmp);
- tmp = tree_cons (NULL_TREE, inner_type, tmp);
- ftype = build_function_type (type, tmp);
+ ftype = build_function_type_list (type, inner_type, inner_type,
+ inner_type, inner_type, NULL_TREE);
mcode = ((enum built_in_function)
(BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
built_in_names[mcode] = concat ("__mul", mode_name_buf, "3", NULL);
local_define_builtin (built_in_names[mcode], ftype, mcode,
- built_in_names[mcode], ECF_CONST | ECF_NOTHROW);
+ built_in_names[mcode], ECF_CONST | ECF_NOTHROW | ECF_LEAF);
built_in_names[dcode] = concat ("__div", mode_name_buf, "3", NULL);
local_define_builtin (built_in_names[dcode], ftype, dcode,
- built_in_names[dcode], ECF_CONST | ECF_NOTHROW);
+ built_in_names[dcode], ECF_CONST | ECF_NOTHROW | ECF_LEAF);
}
}
}
length = omp_clause_num_ops[code];
size = (sizeof (struct tree_omp_clause) + (length - 1) * sizeof (tree));
+ record_node_allocation_statistics (OMP_CLAUSE, size);
+
t = ggc_alloc_tree_node (size);
memset (t, 0, size);
TREE_SET_CODE (t, OMP_CLAUSE);
OMP_CLAUSE_SET_CODE (t, code);
OMP_CLAUSE_LOCATION (t) = loc;
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int) omp_clause_kind]++;
- tree_node_sizes[(int) omp_clause_kind] += size;
-#endif
-
return t;
}
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
+ record_node_allocation_statistics (code, length);
t = ggc_alloc_zone_cleared_tree_node_stat (&tree_zone, length PASS_MEM_STAT);
return t;
}
+/* Helper function for build_call_* functions; build a CALL_EXPR with
+ indicated RETURN_TYPE, FN, and NARGS, but do not initialize any of
+ the argument slots. */
-/* 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)
+static tree
+build_call_1 (tree return_type, tree fn, int nargs)
{
tree t;
- int i;
- t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3);
+ 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; arglist; arglist = TREE_CHAIN (arglist), i++)
- CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist);
- process_call_operands (t);
+ CALL_EXPR_STATIC_CHAIN (t) = NULL;
+
return t;
}
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;
+ t = build_call_1 (return_type, fn, nargs);
for (i = 0; i < nargs; i++)
CALL_EXPR_ARG (t, i) = va_arg (args, tree);
process_call_operands (t);
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;
+ t = build_call_1 (return_type, fn, nargs);
for (i = 0; i < nargs; i++)
CALL_EXPR_ARG (t, i) = args[i];
process_call_operands (t);
tree ret, t;
unsigned int ix;
- ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3);
- TREE_TYPE (ret) = return_type;
- CALL_EXPR_FN (ret) = fn;
- CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
- for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix)
+ ret = build_call_1 (return_type, fn, VEC_length (tree, args));
+ FOR_EACH_VEC_ELT (tree, args, ix, t)
CALL_EXPR_ARG (ret, ix) = t;
process_call_operands (ret);
return ret;
return (TREE_ADDRESSABLE (t)
|| is_global_var (t)
|| (TREE_CODE (t) == RESULT_DECL
+ && !DECL_BY_REFERENCE (t)
&& aggregate_value_p (t, current_function_decl)));
}
-/* There are situations in which a language considers record types
- compatible which have different field lists. Decide if two fields
- are compatible. It is assumed that the parent records are compatible. */
-
-bool
-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))
- return false;
-
- if (!operand_equal_p (DECL_FIELD_OFFSET (f1),
- DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST))
- return false;
-
- if (!types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
- return false;
-
- return true;
-}
-
-/* Locate within RECORD a field that is compatible with ORIG_FIELD. */
-
-tree
-find_compatible_field (tree record, tree orig_field)
-{
- tree f;
-
- for (f = TYPE_FIELDS (record); f ; f = TREE_CHAIN (f))
- if (TREE_CODE (f) == FIELD_DECL
- && fields_compatible_p (f, orig_field))
- return f;
-
- /* ??? Why isn't this on the main fields list? */
- f = TYPE_VFIELD (record);
- if (f && TREE_CODE (f) == FIELD_DECL
- && fields_compatible_p (f, orig_field))
- return f;
-
- /* ??? We should abort here, but Java appears to do Bad Things
- with inherited fields. */
- return orig_field;
-}
-
/* Return value of a constant X and sign-extend it. */
HOST_WIDE_INT
tree
upper_bound_in_type (tree outer, tree inner)
{
- unsigned HOST_WIDE_INT lo, hi;
+ double_int high;
unsigned int det = 0;
unsigned oprec = TYPE_PRECISION (outer);
unsigned iprec = TYPE_PRECISION (inner);
/* Compute 2^^prec - 1. */
if (prec <= HOST_BITS_PER_WIDE_INT)
{
- hi = 0;
- lo = ((~(unsigned HOST_WIDE_INT) 0)
+ high.high = 0;
+ high.low = ((~(unsigned HOST_WIDE_INT) 0)
>> (HOST_BITS_PER_WIDE_INT - prec));
}
else
{
- hi = ((~(unsigned HOST_WIDE_INT) 0)
+ high.high = ((~(unsigned HOST_WIDE_INT) 0)
>> (2 * HOST_BITS_PER_WIDE_INT - prec));
- lo = ~(unsigned HOST_WIDE_INT) 0;
+ high.low = ~(unsigned HOST_WIDE_INT) 0;
}
- return build_int_cst_wide (outer, lo, hi);
+ return double_int_to_tree (outer, high);
}
/* Returns the smallest value obtainable by casting something in INNER type to
tree
lower_bound_in_type (tree outer, tree inner)
{
- unsigned HOST_WIDE_INT lo, hi;
+ double_int low;
unsigned oprec = TYPE_PRECISION (outer);
unsigned iprec = TYPE_PRECISION (inner);
contains all values of INNER type. In particular, both INNER
and OUTER types have zero in common. */
|| (oprec > iprec && TYPE_UNSIGNED (inner)))
- lo = hi = 0;
+ low.low = low.high = 0;
else
{
/* If we are widening a signed type to another signed type, we
if (prec <= HOST_BITS_PER_WIDE_INT)
{
- hi = ~(unsigned HOST_WIDE_INT) 0;
- lo = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
+ low.high = ~(unsigned HOST_WIDE_INT) 0;
+ low.low = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
}
else
{
- hi = ((~(unsigned HOST_WIDE_INT) 0)
+ low.high = ((~(unsigned HOST_WIDE_INT) 0)
<< (prec - HOST_BITS_PER_WIDE_INT - 1));
- lo = 0;
+ low.low = 0;
}
}
- return build_int_cst_wide (outer, lo, hi);
+ return double_int_to_tree (outer, low);
}
/* Return nonzero if two operands that are suitable for PHI nodes are
case BIND_EXPR:
{
tree decl;
- for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl))
+ for (decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
{
/* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk
into declarations that are just mentioned, rather than
tree field;
for (field = TYPE_FIELDS (*type_p); field;
- field = TREE_CHAIN (field))
+ field = DECL_CHAIN (field))
{
/* We'd like to look at the type of the field, but we can
easily get infinite recursion. So assume it's pointed
/* Return true if TYPE has a variable argument list. */
bool
-stdarg_p (tree fntype)
+stdarg_p (const_tree fntype)
{
function_args_iterator args_iter;
tree n = NULL_TREE, t;
/* Use the cache of optimization nodes. */
- cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node));
+ cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node),
+ &global_options);
slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT);
t = (tree) *slot;
/* Use the cache of optimization nodes. */
- cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node));
+ cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node),
+ &global_options);
slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT);
t = (tree) *slot;
lhd_gcc_personality (void)
{
if (!gcc_eh_personality_decl)
- gcc_eh_personality_decl
- = build_personality_function (USING_SJLJ_EXCEPTIONS
- ? "__gcc_personality_sj0"
- : "__gcc_personality_v0");
-
+ gcc_eh_personality_decl = build_personality_function ("gcc");
return gcc_eh_personality_decl;
}
tree
get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
{
- tree type;
-
- if (offset == 0)
- return binfo;
+ tree type = BINFO_TYPE (binfo);
- type = TREE_TYPE (binfo);
- while (offset > 0)
+ while (true)
{
- tree base_binfo, found_binfo;
HOST_WIDE_INT pos, size;
tree fld;
int i;
- if (TREE_CODE (type) != RECORD_TYPE)
+ if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (expected_type))
+ return binfo;
+ if (offset < 0)
return NULL_TREE;
- for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+ for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
{
if (TREE_CODE (fld) != FIELD_DECL)
continue;
if (pos <= offset && (pos + size) > offset)
break;
}
- if (!fld)
+ if (!fld || TREE_CODE (TREE_TYPE (fld)) != RECORD_TYPE)
return NULL_TREE;
- found_binfo = NULL_TREE;
- for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
- if (TREE_TYPE (base_binfo) == TREE_TYPE (fld))
- {
- found_binfo = base_binfo;
- break;
- }
-
- if (!found_binfo)
- return NULL_TREE;
+ if (!DECL_ARTIFICIAL (fld))
+ {
+ binfo = TYPE_BINFO (TREE_TYPE (fld));
+ if (!binfo)
+ return NULL_TREE;
+ }
+ /* Offset 0 indicates the primary base, whose vtable contents are
+ represented in the binfo for the derived class. */
+ else if (offset != 0)
+ {
+ tree base_binfo, found_binfo = NULL_TREE;
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (TREE_TYPE (base_binfo) == TREE_TYPE (fld))
+ {
+ found_binfo = base_binfo;
+ break;
+ }
+ if (!found_binfo)
+ return NULL_TREE;
+ binfo = found_binfo;
+ }
type = TREE_TYPE (fld);
- binfo = found_binfo;
offset -= pos;
}
- if (type != expected_type)
- return NULL_TREE;
- return binfo;
}
/* Returns true if X is a typedef decl. */
return is_typedef_decl (TYPE_NAME (type));
}
+/* Warn about a use of an identifier which was marked deprecated. */
+void
+warn_deprecated_use (tree node, tree attr)
+{
+ const char *msg;
+
+ if (node == 0 || !warn_deprecated_decl)
+ return;
+
+ if (!attr)
+ {
+ if (DECL_P (node))
+ attr = DECL_ATTRIBUTES (node);
+ else if (TYPE_P (node))
+ {
+ tree decl = TYPE_STUB_DECL (node);
+ if (decl)
+ attr = lookup_attribute ("deprecated",
+ TYPE_ATTRIBUTES (TREE_TYPE (decl)));
+ }
+ }
+
+ if (attr)
+ attr = lookup_attribute ("deprecated", attr);
+
+ if (attr)
+ msg = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)));
+ else
+ msg = NULL;
+
+ if (DECL_P (node))
+ {
+ expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (node));
+ if (msg)
+ warning (OPT_Wdeprecated_declarations,
+ "%qD is deprecated (declared at %s:%d): %s",
+ node, xloc.file, xloc.line, msg);
+ else
+ warning (OPT_Wdeprecated_declarations,
+ "%qD is deprecated (declared at %s:%d)",
+ node, xloc.file, xloc.line);
+ }
+ else if (TYPE_P (node))
+ {
+ tree what = NULL_TREE;
+ tree decl = TYPE_STUB_DECL (node);
+
+ if (TYPE_NAME (node))
+ {
+ if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
+ what = TYPE_NAME (node);
+ else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
+ && DECL_NAME (TYPE_NAME (node)))
+ what = DECL_NAME (TYPE_NAME (node));
+ }
+
+ if (decl)
+ {
+ expanded_location xloc
+ = expand_location (DECL_SOURCE_LOCATION (decl));
+ if (what)
+ {
+ if (msg)
+ warning (OPT_Wdeprecated_declarations,
+ "%qE is deprecated (declared at %s:%d): %s",
+ what, xloc.file, xloc.line, msg);
+ else
+ warning (OPT_Wdeprecated_declarations,
+ "%qE is deprecated (declared at %s:%d)", what,
+ xloc.file, xloc.line);
+ }
+ else
+ {
+ if (msg)
+ warning (OPT_Wdeprecated_declarations,
+ "type is deprecated (declared at %s:%d): %s",
+ xloc.file, xloc.line, msg);
+ else
+ warning (OPT_Wdeprecated_declarations,
+ "type is deprecated (declared at %s:%d)",
+ xloc.file, xloc.line);
+ }
+ }
+ else
+ {
+ if (what)
+ {
+ if (msg)
+ warning (OPT_Wdeprecated_declarations, "%qE is deprecated: %s",
+ what, msg);
+ else
+ warning (OPT_Wdeprecated_declarations, "%qE is deprecated", what);
+ }
+ else
+ {
+ if (msg)
+ warning (OPT_Wdeprecated_declarations, "type is deprecated: %s",
+ msg);
+ else
+ warning (OPT_Wdeprecated_declarations, "type is deprecated");
+ }
+ }
+ }
+}
+
#include "gt-tree.h"