* gimple.c (create_gimple_tmp): New.
(get_expr_type): New.
(build_assign): New.
(build_type_cast): New.
* gimple.h (enum ssa_mode): Define.
(gimple_seq_set_location): New.
* asan.c (build_check_stmt): Change some gimple_build_* calls
to use build_assign and build_type_cast.
From-SVN: r198056
+2013-04-18 Diego Novillo <dnovillo@google.com>
+
+ * gimple.c (create_gimple_tmp): New.
+ (get_expr_type): New.
+ (build_assign): New.
+ (build_type_cast): New.
+ * gimple.h (enum ssa_mode): Define.
+ (gimple_seq_set_location): New.
+ * asan.c (build_check_stmt): Change some gimple_build_* calls
+ to use build_assign and build_type_cast.
+
2013-04-18 Richard Biener <rguenther@suse.de>
* tree-vect-data-refs.c (vect_analyze_group_access): Properly
/* Slow path for 1, 2 and 4 byte accesses.
Test (shadow != 0)
& ((base_addr & 7) + (size_in_bytes - 1)) >= shadow). */
- g = gimple_build_assign_with_ops (NE_EXPR,
- make_ssa_name (boolean_type_node,
- NULL),
- shadow,
- build_int_cst (shadow_type, 0));
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
- t = gimple_assign_lhs (g);
-
- g = gimple_build_assign_with_ops (BIT_AND_EXPR,
- make_ssa_name (uintptr_type,
- NULL),
- base_addr,
- build_int_cst (uintptr_type, 7));
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
- g = gimple_build_assign_with_ops (NOP_EXPR,
- make_ssa_name (shadow_type,
- NULL),
- gimple_assign_lhs (g), NULL_TREE);
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
+ gimple_seq seq = NULL;
+ gimple shadow_test = build_assign (NE_EXPR, shadow, 0);
+ gimple_seq_add_stmt (&seq, shadow_test);
+ gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, base_addr, 7));
+ gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
+ gimple_seq_last (seq)));
if (size_in_bytes > 1)
- {
- g = gimple_build_assign_with_ops (PLUS_EXPR,
- make_ssa_name (shadow_type,
- NULL),
- gimple_assign_lhs (g),
- build_int_cst (shadow_type,
- size_in_bytes - 1));
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
- }
-
- g = gimple_build_assign_with_ops (GE_EXPR,
- make_ssa_name (boolean_type_node,
- NULL),
- gimple_assign_lhs (g),
- shadow);
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
- g = gimple_build_assign_with_ops (BIT_AND_EXPR,
- make_ssa_name (boolean_type_node,
- NULL),
- t, gimple_assign_lhs (g));
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
- t = gimple_assign_lhs (g);
+ gimple_seq_add_stmt (&seq,
+ build_assign (PLUS_EXPR, gimple_seq_last (seq),
+ size_in_bytes - 1));
+ gimple_seq_add_stmt (&seq, build_assign (GE_EXPR, gimple_seq_last (seq),
+ shadow));
+ gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
+ gimple_seq_last (seq)));
+ t = gimple_assign_lhs (gimple_seq_last (seq));
+ gimple_seq_set_location (seq, location);
+ gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
}
else
t = shadow;
return false;
}
+
+
+/* Create and return an unnamed temporary. MODE indicates whether
+ this should be an SSA or NORMAL temporary. TYPE is the type to use
+ for the new temporary. */
+
+tree
+create_gimple_tmp (tree type, enum ssa_mode mode)
+{
+ return (mode == M_SSA)
+ ? make_ssa_name (type, NULL)
+ : create_tmp_var (type, NULL);
+}
+
+
+/* Return the expression type to use based on the CODE and type of
+ the given operand OP. If the expression CODE is a comparison,
+ the returned type is boolean_type_node. Otherwise, it returns
+ the type of OP. */
+
+static tree
+get_expr_type (enum tree_code code, tree op)
+{
+ return (TREE_CODE_CLASS (code) == tcc_comparison)
+ ? boolean_type_node
+ : TREE_TYPE (op);
+}
+
+
+/* Build a new gimple assignment. The LHS of the assignment is a new
+ temporary whose type matches the given expression. MODE indicates
+ whether the LHS should be an SSA or a normal temporary. CODE is
+ the expression code for the RHS. OP1 is the first operand and VAL
+ is an integer value to be used as the second operand. */
+
+gimple
+build_assign (enum tree_code code, tree op1, int val, enum ssa_mode mode)
+{
+ tree op2 = build_int_cst (TREE_TYPE (op1), val);
+ tree lhs = create_gimple_tmp (get_expr_type (code, op1), mode);
+ return gimple_build_assign_with_ops (code, lhs, op1, op2);
+}
+
+gimple
+build_assign (enum tree_code code, gimple g, int val, enum ssa_mode mode)
+{
+ return build_assign (code, gimple_assign_lhs (g), val, mode);
+}
+
+
+/* Build and return a new GIMPLE assignment. The new assignment will
+ have the opcode CODE and operands OP1 and OP2. The type of the
+ expression on the RHS is inferred to be the type of OP1.
+
+ The LHS of the statement will be an SSA name or a GIMPLE temporary
+ in normal form depending on the type of builder invoking this
+ function. */
+
+gimple
+build_assign (enum tree_code code, tree op1, tree op2, enum ssa_mode mode)
+{
+ tree lhs = create_gimple_tmp (get_expr_type (code, op1), mode);
+ return gimple_build_assign_with_ops (code, lhs, op1, op2);
+}
+
+gimple
+build_assign (enum tree_code code, gimple op1, tree op2, enum ssa_mode mode)
+{
+ return build_assign (code, gimple_assign_lhs (op1), op2, mode);
+}
+
+gimple
+build_assign (enum tree_code code, tree op1, gimple op2, enum ssa_mode mode)
+{
+ return build_assign (code, op1, gimple_assign_lhs (op2), mode);
+}
+
+gimple
+build_assign (enum tree_code code, gimple op1, gimple op2, enum ssa_mode mode)
+{
+ return build_assign (code, gimple_assign_lhs (op1), gimple_assign_lhs (op2),
+ mode);
+}
+
+
+/* Create and return a type cast assignment. This creates a NOP_EXPR
+ that converts OP to TO_TYPE. */
+
+gimple
+build_type_cast (tree to_type, tree op, enum ssa_mode mode)
+{
+ tree lhs = create_gimple_tmp (to_type, mode);
+ return gimple_build_assign_with_ops (NOP_EXPR, lhs, op, NULL_TREE);
+}
+
+gimple
+build_type_cast (tree to_type, gimple op, enum ssa_mode mode)
+{
+ return build_type_cast (to_type, gimple_assign_lhs (op), mode);
+}
+
#include "gt-gimple.h"
typedef gimple gimple_seq_node;
+/* Types of supported temporaries. GIMPLE temporaries may be symbols
+ in normal form (i.e., regular decls) or SSA names. This enum is
+ used by create_gimple_tmp to tell it what kind of temporary the
+ caller wants. */
+enum ssa_mode {
+ M_SSA = 0,
+ M_NORMAL
+};
+
/* For each block, the PHI nodes that need to be rewritten are stored into
these vectors. */
typedef vec<gimple> gimple_vec;
/* In gimple.c. */
+/* Helper functions to build GIMPLE statements. */
+tree create_gimple_tmp (tree, enum ssa_mode = M_SSA);
+gimple build_assign (enum tree_code, tree, int, enum ssa_mode = M_SSA);
+gimple build_assign (enum tree_code, gimple, int, enum ssa_mode = M_SSA);
+gimple build_assign (enum tree_code, tree, tree, enum ssa_mode = M_SSA);
+gimple build_assign (enum tree_code, gimple, tree, enum ssa_mode = M_SSA);
+gimple build_assign (enum tree_code, tree, gimple, enum ssa_mode = M_SSA);
+gimple build_assign (enum tree_code, gimple, gimple, enum ssa_mode = M_SSA);
+gimple build_type_cast (tree, tree, enum ssa_mode = M_SSA);
+gimple build_type_cast (tree, gimple, enum ssa_mode = M_SSA);
+
/* Offset in bytes to the location of the operand vector.
Zero if there is no operand vector for this tuple structure. */
extern size_t const gimple_ops_offset_[];
return s == NULL;
}
-
void gimple_seq_add_stmt (gimple_seq *, gimple);
/* Link gimple statement GS to the end of the sequence *SEQ_P. If
enum tree_code, tree, tree);
bool gimple_val_nonnegative_real_p (tree);
+
+
+/* Set the location of all statements in SEQ to LOC. */
+
+static inline void
+gimple_seq_set_location (gimple_seq seq, location_t loc)
+{
+ for (gimple_stmt_iterator i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
+ gimple_set_location (gsi_stmt (i), loc);
+}
+
#endif /* GCC_GIMPLE_H */