#include "timevar.h"
#include "tree-dump.h"
#include "tree-pass.h"
+#include "diagnostic-core.h"
#include "toplev.h"
#include "except.h"
#include "cfgloop.h"
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. */
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:
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. */
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;
}
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;
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;
}
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;
}
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));
}
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);
}
/* 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:
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)))
{
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);
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
{
return NULL_TREE;
}
-/* Marks virtual operands of all statements in basic blocks BBS for
- renaming. */
-
-void
-mark_virtual_ops_in_bb (basic_block bb)
-{
- gimple_stmt_iterator gsi;
-
- for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- mark_virtual_ops_for_renaming (gsi_stmt (gsi));
-
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- mark_virtual_ops_for_renaming (gsi_stmt (gsi));
-}
-
/* Move basic block BB from function CFUN to function DEST_FN. The
block is moved out of the original linked list and placed after
block AFTER in the new list. Also, the block is removed from the
{
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)
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;
}
}
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;
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");
/* 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);
fprintf (file, "}\n");
}
+ if (flags & TDF_ENUMERATE_LOCALS)
+ dump_enumerated_decls (file, flags);
fprintf (file, "\n\n");
/* Restore CFUN. */
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));
}