void
pass_waccess::check_stmt (gimple *stmt)
{
- if (m_check_dangling_p && gimple_clobber_p (stmt))
+ if (m_check_dangling_p
+ && gimple_clobber_p (stmt, CLOBBER_EOL))
{
/* Ignore clobber statemts in blocks with exceptional edges. */
basic_block bb = gimple_bb (stmt);
&& TREE_CLOBBER_P (gimple_assign_rhs1 (s));
}
+/* Return true if S is a clobber statement. */
+
+static inline bool
+gimple_clobber_p (const gimple *s, enum clobber_kind kind)
+{
+ return gimple_clobber_p (s)
+ && CLOBBER_KIND (gimple_assign_rhs1 (s)) == kind;
+}
+
/* Return true if GS is a GIMPLE_CALL. */
static inline bool
&& !is_gimple_reg (t)
&& flag_stack_reuse != SR_NONE)
{
- tree clobber = build_clobber (TREE_TYPE (t));
+ tree clobber = build_clobber (TREE_TYPE (t), CLOBBER_EOL);
gimple *clobber_stmt;
clobber_stmt = gimple_build_assign (t, clobber);
gimple_set_location (clobber_stmt, end_locus);
{
if (flag_stack_reuse == SR_ALL)
{
- tree clobber = build_clobber (TREE_TYPE (temp));
+ tree clobber = build_clobber (TREE_TYPE (temp), CLOBBER_EOL);
clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
gimple_push_cleanup (temp, clobber, false, pre_p, true);
}
return false;
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
- compare_values (CONSTRUCTOR_NELTS);
+ {
+ compare_values (CLOBBER_KIND);
+ compare_values (CONSTRUCTOR_NELTS);
+ }
if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER))
if (IDENTIFIER_LENGTH (t1) != IDENTIFIER_LENGTH (t2)
{ dg-final { scan-tree-dump-times "c = \"\";" 1 "gimple" } }
{ dg-final { scan-tree-dump-times "d = { *};" 1 "gimple" } }
{ dg-final { scan-tree-dump-times "e = " 1 "gimple" } }
- { dg-final { scan-tree-dump-times "e = {CLOBBER}" 1 "gimple" } } */
+ { dg-final { scan-tree-dump-times "e = {CLOBBER\\(eol\\)}" 1 "gimple" } } */
annot_expr_kind_last
};
+/* The kind of a TREE_CLOBBER_P CONSTRUCTOR node. */
+enum clobber_kind {
+ /* Unspecified, this clobber acts as a store of an undefined value. */
+ CLOBBER_UNDEF,
+ /* This clobber ends the lifetime of the storage. */
+ CLOBBER_EOL,
+ CLOBBER_LAST
+};
+
/*---------------------------------------------------------------------------
Type definitions
---------------------------------------------------------------------------*/
/* This field is only used with TREE_TYPE nodes; the only reason it is
present in tree_base instead of tree_type is to save space. The size
- of the field must be large enough to hold addr_space_t values. */
+ of the field must be large enough to hold addr_space_t values.
+ For CONSTRUCTOR nodes this holds the clobber_kind enum. */
unsigned address_space : 8;
} bits;
&& !is_gimple_reg (*varp)
&& !(id->debug_map && id->debug_map->get (p)))
{
- tree clobber = build_clobber (TREE_TYPE (*varp));
+ tree clobber = build_clobber (TREE_TYPE (*varp), CLOBBER_EOL);
gimple *clobber_stmt;
clobber_stmt = gimple_build_assign (*varp, clobber);
gimple_set_location (clobber_stmt, gimple_location (stmt));
&& !is_gimple_reg (id->retvar)
&& !stmt_ends_bb_p (stmt))
{
- tree clobber = build_clobber (TREE_TYPE (id->retvar));
+ tree clobber = build_clobber (TREE_TYPE (id->retvar), CLOBBER_EOL);
gimple *clobber_stmt;
clobber_stmt = gimple_build_assign (id->retvar, clobber);
gimple_set_location (clobber_stmt, gimple_location (old_stmt));
}
pp_left_brace (pp);
if (TREE_CLOBBER_P (node))
- pp_string (pp, "CLOBBER");
+ {
+ pp_string (pp, "CLOBBER");
+ if (CLOBBER_KIND (node) == CLOBBER_EOL)
+ pp_string (pp, "(eol)");
+ }
else if (TREE_CODE (TREE_TYPE (node)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (node)) == UNION_TYPE)
is_struct_init = true;
FOR_EACH_IMM_USE_STMT (stmt, iter, saved_val)
if (gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE))
{
- clobber = build_clobber (TREE_TYPE (var));
+ clobber = build_clobber (TREE_TYPE (var), CLOBBER_EOL);
clobber_stmt = gimple_build_assign (var, clobber);
i = gsi_for_stmt (stmt);
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
{
+ CLOBBER_KIND (expr)
+ = bp_unpack_enum (&bp, clobber_kind, CLOBBER_LAST);
unsigned HOST_WIDE_INT length = bp_unpack_var_len_unsigned (&bp);
if (length > 0)
vec_safe_grow (CONSTRUCTOR_ELTS (expr), length, true);
cl_optimization_stream_out (ob, &bp, TREE_OPTIMIZATION (expr));
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
- bp_pack_var_len_unsigned (&bp, CONSTRUCTOR_NELTS (expr));
+ {
+ bp_pack_enum (&bp, clobber_kind, CLOBBER_LAST, CLOBBER_KIND (expr));
+ bp_pack_var_len_unsigned (&bp, CONSTRUCTOR_NELTS (expr));
+ }
if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)
/* Don't stream these when passing things to a different target. */
/* Return a node of type TYPE for which TREE_CLOBBER_P is true. */
tree
-build_clobber (tree type)
+build_clobber (tree type, enum clobber_kind kind)
{
tree clobber = build_constructor (type, NULL);
TREE_THIS_VOLATILE (clobber) = true;
+ CLOBBER_KIND (clobber) = kind;
return clobber;
}
#define TREE_CLOBBER_P(NODE) \
(TREE_CODE (NODE) == CONSTRUCTOR && TREE_THIS_VOLATILE (NODE))
+/* Return the clobber_kind of a CLOBBER CONSTRUCTOR. */
+#define CLOBBER_KIND(NODE) \
+ (CONSTRUCTOR_CHECK (NODE)->base.u.bits.address_space)
+
/* Define fields and accessors for some nodes that represent expressions. */
/* Nonzero if NODE is an empty statement (NOP_EXPR <0>). */
extern tree build_constructor_from_list (tree, tree);
extern tree build_constructor_from_vec (tree, const vec<tree, va_gc> *);
extern tree build_constructor_va (tree, int, ...);
-extern tree build_clobber (tree);
+extern tree build_clobber (tree, enum clobber_kind = CLOBBER_UNDEF);
extern tree build_real_from_int_cst (tree, const_tree);
extern tree build_real_from_wide (tree, const wide_int_ref &, signop);
extern tree build_complex (tree, tree, tree);