static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
htab_t int_cst_hash_table;
+/* General tree->tree mapping structure for use in hash tables. */
+
+struct tree_map GTY(())
+{
+ hashval_t hash;
+ tree from;
+ tree to;
+};
+
+static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
+ htab_t debug_expr_for_decl;
+
+static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
+ htab_t value_expr_for_decl;
+
static void set_type_quals (tree, int);
static int type_hash_eq (const void *, const void *);
static hashval_t type_hash_hash (const void *);
+static int tree_map_eq (const void *, const void *);
+static hashval_t tree_map_hash (const void *);
static hashval_t int_cst_hash_hash (const void *);
static int int_cst_hash_eq (const void *, const void *);
static void print_type_hash_statistics (void);
+static void print_debug_expr_statistics (void);
+static void print_value_expr_statistics (void);
static tree make_vector_type (tree, int, enum machine_mode);
static int type_hash_marked_p (const void *);
+static int tree_map_marked_p (const void *);
static unsigned int type_hash_list (tree, hashval_t);
static unsigned int attribute_hash_list (tree, hashval_t);
tree global_trees[TI_MAX];
tree integer_types[itk_none];
+
\f
/* Init tree.c. */
/* Initialize the hash table of types. */
type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
type_hash_eq, 0);
+
+ debug_expr_for_decl = htab_create_ggc (512, tree_map_hash,
+ tree_map_eq, 0);
+
+ value_expr_for_decl = htab_create_ggc (512, tree_map_hash,
+ tree_map_eq, 0);
+
int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
int_cst_hash_eq, NULL);
+
int_cst_node = make_node (INTEGER_CST);
+
}
\f
#endif
if (code == IDENTIFIER_NODE)
- t = ggc_alloc_zone_stat (length, &tree_id_zone PASS_MEM_STAT);
+ t = ggc_alloc_zone_pass_stat (length, &tree_id_zone);
else
- t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+ t = ggc_alloc_zone_pass_stat (length, &tree_zone);
memset (t, 0, length);
gcc_assert (code != STATEMENT_LIST);
length = tree_size (node);
- t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+ t = ggc_alloc_zone_pass_stat (length, &tree_zone);
memcpy (t, node, length);
TREE_CHAIN (t) = 0;
t->common.ann = 0;
if (TREE_CODE_CLASS (code) == tcc_declaration)
- DECL_UID (t) = next_decl_uid++;
+ {
+ DECL_UID (t) = next_decl_uid++;
+ if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
+ && DECL_HAS_VALUE_EXPR_P (node))
+ {
+ SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node));
+ DECL_HAS_VALUE_EXPR_P (t) = 1;
+ }
+
+ }
else if (TREE_CODE_CLASS (code) == tcc_type)
{
TYPE_UID (t) = next_type_uid++;
build_int_cst_type (tree type, HOST_WIDE_INT low)
{
unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low;
- unsigned HOST_WIDE_INT hi;
+ unsigned HOST_WIDE_INT hi, mask;
unsigned bits;
bool signed_p;
bool negative;
negative = ((val >> (bits - 1)) & 1) != 0;
/* Mask out the bits outside of the precision of the constant. */
+ mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
+
if (signed_p && negative)
- val = val | ((~(unsigned HOST_WIDE_INT) 0) << bits);
+ val |= ~mask;
else
- val = val & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
+ val &= mask;
}
/* Determine the high bits. */
else
{
bits -= HOST_BITS_PER_WIDE_INT;
- hi = hi & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
+ mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
+ hi &= mask;
}
}
tree_node_sizes[(int) binfo_kind] += length;
#endif
- t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+ t = ggc_alloc_zone_pass_stat (length, &tree_zone);
memset (t, 0, offsetof (struct tree_binfo, base_binfos));
tree_node_sizes[(int) vec_kind] += length;
#endif
- t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+ t = ggc_alloc_zone_pass_stat (length, &tree_zone);
memset (t, 0, length);
{
tree node;
- node = ggc_alloc_zone_stat (sizeof (struct tree_list),
- &tree_zone PASS_MEM_STAT);
+ node = ggc_alloc_zone_pass_stat (sizeof (struct tree_list), &tree_zone);
memset (node, 0, sizeof (struct tree_common));
gcc_assert (TREE_CODE_LENGTH (code) == 1);
- t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+ t = ggc_alloc_zone_pass_stat (length, &tree_zone);
memset (t, 0, sizeof (struct tree_common));
TREE_SIDE_EFFECTS (t) = 1;
else switch (code)
{
- case INIT_EXPR:
- case MODIFY_EXPR:
case VA_ARG_EXPR:
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
/* All of these have side-effects, no matter what their
operands are. */
TREE_SIDE_EFFECTS (t) = 1;
return t;
}
+tree
+build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2, tree arg3, tree arg4, tree arg5,
+ tree arg6 MEM_STAT_DECL)
+{
+ bool constant, read_only, side_effects, invariant;
+ tree t;
+
+ gcc_assert (code == TARGET_MEM_REF);
+
+ t = make_node_stat (code PASS_MEM_STAT);
+ TREE_TYPE (t) = tt;
+
+ side_effects = TREE_SIDE_EFFECTS (t);
+
+ PROCESS_ARG(0);
+ PROCESS_ARG(1);
+ PROCESS_ARG(2);
+ PROCESS_ARG(3);
+ PROCESS_ARG(4);
+ PROCESS_ARG(5);
+ PROCESS_ARG(6);
+
+ TREE_SIDE_EFFECTS (t) = side_effects;
+ TREE_THIS_VOLATILE (t) = 0;
+
+ return t;
+}
+
/* Backup definition for non-gcc build compilers. */
tree
(build) (enum tree_code code, tree tt, ...)
{
- tree t, arg0, arg1, arg2, arg3;
+ tree t, arg0, arg1, arg2, arg3, arg4, arg5, arg6;
int length = TREE_CODE_LENGTH (code);
va_list p;
arg3 = va_arg (p, tree);
t = build4 (code, tt, arg0, arg1, arg2, arg3);
break;
+ case 7:
+ arg0 = va_arg (p, tree);
+ arg1 = va_arg (p, tree);
+ arg2 = va_arg (p, tree);
+ arg3 = va_arg (p, tree);
+ arg4 = va_arg (p, tree);
+ arg5 = va_arg (p, tree);
+ arg6 = va_arg (p, tree);
+ t = build7 (code, tt, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
default:
gcc_unreachable ();
}
compiled. This information is used for outputting debugging info. */
tree
-build_block (tree vars, tree tags ATTRIBUTE_UNUSED, tree subblocks,
- tree supercontext, tree chain)
+build_block (tree vars, tree subblocks, tree supercontext, tree chain)
{
tree block = make_node (BLOCK);
}
if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
{
- warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
return t;
}
\f
+/* Return true if the from tree in both tree maps are equal. */
+
+static int
+tree_map_eq (const void *va, const void *vb)
+{
+ const struct tree_map *a = va, *b = vb;
+ return (a->from == b->from);
+}
+
+/* Hash a from tree in a tree_map. */
+
+static hashval_t
+tree_map_hash (const void *item)
+{
+ return (((const struct tree_map *) item)->hash);
+}
+
+/* Return true if this tree map structure is marked for garbage collection
+ purposes. We simply return true if the from tree is marked, so that this
+ structure goes away when the from tree goes away. */
+
+static int
+tree_map_marked_p (const void *p)
+{
+ tree from = ((struct tree_map *) p)->from;
+
+ return ggc_marked_p (from);
+}
+
+/* Print out the statistics for the DECL_DEBUG_EXPR hash table. */
+
+static void
+print_debug_expr_statistics (void)
+{
+ fprintf (stderr, "DECL_DEBUG_EXPR hash: size %ld, %ld elements, %f collisions\n",
+ (long) htab_size (debug_expr_for_decl),
+ (long) htab_elements (debug_expr_for_decl),
+ htab_collisions (debug_expr_for_decl));
+}
+
+/* Print out the statistics for the DECL_VALUE_EXPR hash table. */
+
+static void
+print_value_expr_statistics (void)
+{
+ fprintf (stderr, "DECL_VALUE_EXPR hash: size %ld, %ld elements, %f collisions\n",
+ (long) htab_size (value_expr_for_decl),
+ (long) htab_elements (value_expr_for_decl),
+ htab_collisions (value_expr_for_decl));
+}
+/* Lookup a debug expression for FROM, and return it if we find one. */
+
+tree
+decl_debug_expr_lookup (tree from)
+{
+ struct tree_map *h, in;
+ in.from = from;
+
+ h = htab_find_with_hash (debug_expr_for_decl, &in, htab_hash_pointer (from));
+ if (h)
+ return h->to;
+ return NULL_TREE;
+}
+
+/* Insert a mapping FROM->TO in the debug expression hashtable. */
+
+void
+decl_debug_expr_insert (tree from, tree to)
+{
+ struct tree_map *h;
+ void **loc;
+
+ h = ggc_alloc (sizeof (struct tree_map));
+ h->hash = htab_hash_pointer (from);
+ h->from = from;
+ h->to = to;
+ loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT);
+ *(struct tree_map **) loc = h;
+}
+
+/* Lookup a value expression for FROM, and return it if we find one. */
+
+tree
+decl_value_expr_lookup (tree from)
+{
+ struct tree_map *h, in;
+ in.from = from;
+
+ h = htab_find_with_hash (value_expr_for_decl, &in, htab_hash_pointer (from));
+ if (h)
+ return h->to;
+ return NULL_TREE;
+}
+
+/* Insert a mapping FROM->TO in the value expression hashtable. */
+
+void
+decl_value_expr_insert (tree from, tree to)
+{
+ struct tree_map *h;
+ void **loc;
+
+ h = ggc_alloc (sizeof (struct tree_map));
+ h->hash = htab_hash_pointer (from);
+ h->from = from;
+ h->to = to;
+ loc = htab_find_slot_with_hash (value_expr_for_decl, h, h->hash, INSERT);
+ *(struct tree_map **) loc = h;
+}
+
/* Hashing of types so that we don't make duplicates.
The entry point is `type_hash_canon'. */
while (TREE_CODE (op) == NOP_EXPR
|| TREE_CODE (op) == CONVERT_EXPR)
{
- int bitschange
- = TYPE_PRECISION (TREE_TYPE (op))
- - TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0)));
+ int bitschange;
+
+ /* TYPE_PRECISION on vector types has different meaning
+ (TYPE_VECTOR_SUBPARTS) and casts from vectors are view conversions,
+ so avoid them here. */
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) == VECTOR_TYPE)
+ break;
+
+ bitschange = TYPE_PRECISION (TREE_TYPE (op))
+ - TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0)));
/* Truncations are many-one so cannot be removed.
Unless we are later going to truncate down even farther. */
fprintf (stderr, "(No per-node statistics)\n");
#endif
print_type_hash_statistics ();
+ print_debug_expr_statistics ();
+ print_value_expr_statistics ();
lang_hooks.print_statistics ();
}
\f
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 (ptr_type_node, tmp);
+ ftype = build_function_type (integer_type_node, tmp);
local_define_builtin ("__builtin_memcmp", ftype, BUILT_IN_MEMCMP,
"memcmp", ECF_PURE | ECF_NOTHROW);
}
return make_vector_type (innertype, nunits, VOIDmode);
}
+/* Build RESX_EXPR with given REGION_NUMBER. */
+tree
+build_resx (int region_number)
+{
+ tree t;
+ t = build1 (RESX_EXPR, void_type_node,
+ build_int_cst (NULL_TREE, region_number));
+ return t;
+}
+
/* Given an initializer INIT, return TRUE if INIT is zero or some
aggregate of zeros. Otherwise return FALSE. */
bool
case SSA_NAME:
case FIELD_DECL:
case RESULT_DECL:
- /* None of thse have subtrees other than those already walked
+ /* None of these have subtrees other than those already walked
above. */
break;