diff options
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 182 |
1 files changed, 123 insertions, 59 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index f05aaaa505f..2a9e9d2d70e 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" #include "tree-dump.h" #include "tree-pass.h" +#include "diagnostic-core.h" #include "toplev.h" #include "except.h" #include "cfgloop.h" @@ -2533,6 +2534,49 @@ gimple_split_edge (edge edge_in) return new_bb; } + +/* Verify properties of the address expression T with base object BASE. */ + +static tree +verify_address (tree t, tree base) +{ + bool old_constant; + bool old_side_effects; + bool new_constant; + bool new_side_effects; + + old_constant = TREE_CONSTANT (t); + old_side_effects = TREE_SIDE_EFFECTS (t); + + recompute_tree_invariant_for_addr_expr (t); + new_side_effects = TREE_SIDE_EFFECTS (t); + new_constant = TREE_CONSTANT (t); + + if (old_constant != new_constant) + { + error ("constant not recomputed when ADDR_EXPR changed"); + return t; + } + if (old_side_effects != new_side_effects) + { + error ("side effects not recomputed when ADDR_EXPR changed"); + return t; + } + + if (!(TREE_CODE (base) == VAR_DECL + || TREE_CODE (base) == PARM_DECL + || TREE_CODE (base) == RESULT_DECL)) + return NULL_TREE; + + if (DECL_GIMPLE_REG_P (base)) + { + error ("DECL_GIMPLE_REG_P set on a variable with address taken"); + return base; + } + + return NULL_TREE; +} + /* Callback for walk_tree, check that all elements with address taken are properly noticed as such. The DATA is an int* that is 1 if TP was seen inside a PHI node. */ @@ -2561,12 +2605,27 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) break; case INDIRECT_REF: + error ("INDIRECT_REF in gimple IL"); + return t; + + case MEM_REF: x = TREE_OPERAND (t, 0); - if (!is_gimple_reg (x) && !is_gimple_min_invariant (x)) + if (!POINTER_TYPE_P (TREE_TYPE (x)) + || !is_gimple_mem_ref_addr (x)) { - error ("Indirect reference's operand is not a register or a constant."); + error ("Invalid first operand of MEM_REF."); return x; } + if (TREE_CODE (TREE_OPERAND (t, 1)) != INTEGER_CST + || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 1)))) + { + error ("Invalid offset operand of MEM_REF."); + return TREE_OPERAND (t, 1); + } + if (TREE_CODE (x) == ADDR_EXPR + && (x = verify_address (x, TREE_OPERAND (x, 0)))) + return x; + *walk_subtrees = 0; break; case ASSERT_EXPR: @@ -2584,31 +2643,10 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) case ADDR_EXPR: { - bool old_constant; - bool old_side_effects; - bool new_constant; - bool new_side_effects; + tree tem; gcc_assert (is_gimple_address (t)); - old_constant = TREE_CONSTANT (t); - old_side_effects = TREE_SIDE_EFFECTS (t); - - recompute_tree_invariant_for_addr_expr (t); - new_side_effects = TREE_SIDE_EFFECTS (t); - new_constant = TREE_CONSTANT (t); - - if (old_constant != new_constant) - { - error ("constant not recomputed when ADDR_EXPR changed"); - return t; - } - if (old_side_effects != new_side_effects) - { - error ("side effects not recomputed when ADDR_EXPR changed"); - return t; - } - /* Skip any references (they will be checked when we recurse down the tree) and ensure that any variable used as a prefix is marked addressable. */ @@ -2617,20 +2655,19 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) x = TREE_OPERAND (x, 0)) ; + if ((tem = verify_address (t, x))) + return tem; + if (!(TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == PARM_DECL || TREE_CODE (x) == RESULT_DECL)) return NULL; + if (!TREE_ADDRESSABLE (x)) { error ("address taken, but ADDRESSABLE bit not set"); return x; } - if (DECL_GIMPLE_REG_P (x)) - { - error ("DECL_GIMPLE_REG_P set on a variable with address taken"); - return x; - } break; } @@ -2815,8 +2852,9 @@ verify_types_in_gimple_min_lval (tree expr) if (is_gimple_id (expr)) return false; - if (!INDIRECT_REF_P (expr) - && TREE_CODE (expr) != TARGET_MEM_REF) + if (TREE_CODE (expr) != MISALIGNED_INDIRECT_REF + && TREE_CODE (expr) != TARGET_MEM_REF + && TREE_CODE (expr) != MEM_REF) { error ("invalid expression for min lvalue"); return true; @@ -2833,14 +2871,7 @@ verify_types_in_gimple_min_lval (tree expr) debug_generic_stmt (op); return true; } - if (!useless_type_conversion_p (TREE_TYPE (expr), - TREE_TYPE (TREE_TYPE (op)))) - { - error ("type mismatch in indirect reference"); - debug_generic_stmt (TREE_TYPE (expr)); - debug_generic_stmt (TREE_TYPE (TREE_TYPE (op))); - return true; - } + /* Memory references now generally can involve a value conversion. */ return false; } @@ -2927,6 +2958,13 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue) debug_generic_stmt (expr); return true; } + else if (TREE_CODE (op) == SSA_NAME + && TYPE_SIZE (TREE_TYPE (expr)) != TYPE_SIZE (TREE_TYPE (op))) + { + error ("Conversion of register to a different size."); + debug_generic_stmt (expr); + return true; + } else if (!handled_component_p (op)) return false; } @@ -2934,6 +2972,23 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue) expr = op; } + if (TREE_CODE (expr) == MEM_REF) + { + if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0))) + { + error ("Invalid address operand in MEM_REF."); + debug_generic_stmt (expr); + return true; + } + if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST + || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1)))) + { + error ("Invalid offset operand in MEM_REF."); + debug_generic_stmt (expr); + return true; + } + } + return ((require_lvalue || !is_gimple_min_invariant (expr)) && verify_types_in_gimple_min_lval (expr)); } @@ -3061,7 +3116,10 @@ verify_gimple_call (gimple stmt) for (i = 0; i < gimple_call_num_args (stmt); ++i) { tree arg = gimple_call_arg (stmt, i); - if (!is_gimple_operand (arg)) + if ((is_gimple_reg_type (TREE_TYPE (arg)) + && !is_gimple_val (arg)) + || (!is_gimple_reg_type (TREE_TYPE (arg)) + && !is_gimple_lvalue (arg))) { error ("invalid argument to gimple call"); debug_generic_expr (arg); @@ -3642,10 +3700,12 @@ verify_gimple_assign_single (gimple stmt) } /* tcc_reference */ + case INDIRECT_REF: + error ("INDIRECT_REF in gimple IL"); + return true; + case COMPONENT_REF: case BIT_FIELD_REF: - case INDIRECT_REF: - case ALIGN_INDIRECT_REF: case MISALIGNED_INDIRECT_REF: case ARRAY_REF: case ARRAY_RANGE_REF: @@ -3653,6 +3713,7 @@ verify_gimple_assign_single (gimple stmt) case REALPART_EXPR: case IMAGPART_EXPR: case TARGET_MEM_REF: + case MEM_REF: if (!is_gimple_reg (lhs) && is_gimple_reg_type (TREE_TYPE (lhs))) { @@ -3768,12 +3829,14 @@ verify_gimple_return (gimple stmt) return true; } - if (!useless_type_conversion_p (restype, TREE_TYPE (op)) - /* ??? With C++ we can have the situation that the result - decl is a reference type while the return type is an aggregate. */ - && !(TREE_CODE (op) == RESULT_DECL - && TREE_CODE (TREE_TYPE (op)) == REFERENCE_TYPE - && useless_type_conversion_p (restype, TREE_TYPE (TREE_TYPE (op))))) + if ((TREE_CODE (op) == RESULT_DECL + && DECL_BY_REFERENCE (op)) + || (TREE_CODE (op) == SSA_NAME + && TREE_CODE (SSA_NAME_VAR (op)) == RESULT_DECL + && DECL_BY_REFERENCE (SSA_NAME_VAR (op)))) + op = TREE_TYPE (op); + + if (!useless_type_conversion_p (restype, TREE_TYPE (op))) { error ("invalid conversion in return statement"); debug_generic_stmt (restype); @@ -5538,7 +5601,7 @@ replace_by_duplicate_decl (tree *tp, struct pointer_map_t *vars_map, if (SSA_VAR_P (t)) { new_t = copy_var_decl (t, DECL_NAME (t), TREE_TYPE (t)); - f->local_decls = tree_cons (NULL_TREE, new_t, f->local_decls); + add_local_decl (f, new_t); } else { @@ -6009,7 +6072,7 @@ replace_block_vars_by_duplicates (tree block, struct pointer_map_t *vars_map, { tree *tp, t; - for (tp = &BLOCK_VARS (block); *tp; tp = &TREE_CHAIN (*tp)) + for (tp = &BLOCK_VARS (block); *tp; tp = &DECL_CHAIN (*tp)) { t = *tp; if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != CONST_DECL) @@ -6022,7 +6085,7 @@ replace_block_vars_by_duplicates (tree block, struct pointer_map_t *vars_map, SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (*tp)); DECL_HAS_VALUE_EXPR_P (t) = 1; } - TREE_CHAIN (t) = TREE_CHAIN (*tp); + DECL_CHAIN (t) = DECL_CHAIN (*tp); *tp = t; } } @@ -6258,7 +6321,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, void dump_function_to_file (tree fn, FILE *file, int flags) { - tree arg, vars, var; + tree arg, var; struct function *dsf; bool ignore_topmost_bind = false, any_var = false; basic_block bb; @@ -6274,9 +6337,9 @@ dump_function_to_file (tree fn, FILE *file, int flags) print_generic_expr (file, arg, dump_flags); if (flags & TDF_VERBOSE) print_node (file, "", arg, 4); - if (TREE_CHAIN (arg)) + if (DECL_CHAIN (arg)) fprintf (file, ", "); - arg = TREE_CHAIN (arg); + arg = DECL_CHAIN (arg); } fprintf (file, ")\n"); @@ -6298,15 +6361,14 @@ dump_function_to_file (tree fn, FILE *file, int flags) /* When GIMPLE is lowered, the variables are no longer available in BIND_EXPRs, so display them separately. */ - if (cfun && cfun->decl == fn && cfun->local_decls) + if (cfun && cfun->decl == fn && !VEC_empty (tree, cfun->local_decls)) { + unsigned ix; ignore_topmost_bind = true; fprintf (file, "{\n"); - for (vars = cfun->local_decls; vars; vars = TREE_CHAIN (vars)) + FOR_EACH_LOCAL_DECL (cfun, ix, var) { - var = TREE_VALUE (vars); - print_generic_decl (file, var, flags); if (flags & TDF_VERBOSE) print_node (file, "", var, 4); @@ -6387,6 +6449,8 @@ dump_function_to_file (tree fn, FILE *file, int flags) fprintf (file, "}\n"); } + if (flags & TDF_ENUMERATE_LOCALS) + dump_enumerated_decls (file, flags); fprintf (file, "\n\n"); /* Restore CFUN. */ @@ -6568,7 +6632,7 @@ static bool gimple_block_ends_with_call_p (basic_block bb) { gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb); - return is_gimple_call (gsi_stmt (gsi)); + return !gsi_end_p (gsi) && is_gimple_call (gsi_stmt (gsi)); } |