summaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c138
1 files changed, 98 insertions, 40 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index f28db37b7cb..3b8ab9d9e7d 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2533,6 +2533,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 +2604,26 @@ 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 (!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 +2641,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 +2653,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 +2850,10 @@ 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) != ALIGN_INDIRECT_REF
+ && 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 +2870,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 +2957,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 +2971,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));
}
@@ -3642,9 +3696,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:
@@ -3653,6 +3710,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)))
{