#include "tree-dump.h"
#include "tree-pass.h"
#include "diagnostic-core.h"
-#include "toplev.h"
#include "except.h"
#include "cfgloop.h"
#include "cfglayout.h"
size_t i;
fold_stmt_inplace (stmt);
- if (cfgcleanup_altered_bbs)
+ if (cfgcleanup_altered_bbs && !is_gimple_debug (stmt))
bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index);
/* FIXME. This should go in update_stmt. */
if (!POINTER_TYPE_P (TREE_TYPE (x))
|| !is_gimple_mem_ref_addr (x))
{
- error ("Invalid first operand of MEM_REF.");
+ 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.");
+ error ("invalid offset operand of MEM_REF");
return TREE_OPERAND (t, 1);
}
if (TREE_CODE (x) == ADDR_EXPR
break;
case MODIFY_EXPR:
- error ("MODIFY_EXPR not expected while having tuples.");
+ error ("MODIFY_EXPR not expected while having tuples");
return *tp;
case ADDR_EXPR:
TREE_TYPE (TREE_OPERAND (t, 1))))
{
error ("invalid operand to pointer plus, second operand is not an "
- "integer with type of sizetype.");
+ "integer with type of sizetype");
return t;
}
/* FALLTHROUGH */
&& (TREE_CODE (op) == SSA_NAME
|| is_gimple_min_invariant (op)))
{
- error ("Conversion of an SSA_NAME on the left hand side.");
+ error ("conversion of an SSA_NAME on the left hand side");
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.");
+ error ("conversion of register to a different size");
debug_generic_stmt (expr);
return true;
}
{
if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0)))
{
- error ("Invalid address operand in MEM_REF.");
+ 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.");
+ error ("invalid offset operand in MEM_REF");
debug_generic_stmt (expr);
return true;
}
if (!TMR_BASE (expr)
|| !is_gimple_mem_ref_addr (TMR_BASE (expr)))
{
- error ("Invalid address operand in in TARGET_MEM_REF.");
+ error ("invalid address operand in in TARGET_MEM_REF");
return true;
}
if (!TMR_OFFSET (expr)
|| TREE_CODE (TMR_OFFSET (expr)) != INTEGER_CST
|| !POINTER_TYPE_P (TREE_TYPE (TMR_OFFSET (expr))))
{
- error ("Invalid offset operand in TARGET_MEM_REF.");
+ error ("invalid offset operand in TARGET_MEM_REF");
debug_generic_stmt (expr);
return true;
}
call, and the decl should have DECL_STATIC_CHAIN set. */
if (gimple_call_chain (stmt))
{
- if (TREE_CODE (fn) != ADDR_EXPR
- || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
+ if (!gimple_call_fndecl (stmt))
{
error ("static chain in indirect gimple call");
return true;
if (!DECL_STATIC_CHAIN (fn))
{
- error ("static chain with function that doesn't use one");
+ error ("static chain with function that doesn%'t use one");
return true;
}
}
{
if (TREE_CODE (rhs1_type) != VECTOR_TYPE
|| !(INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
+ || POINTER_TYPE_P (TREE_TYPE (rhs1_type))
|| FIXED_POINT_TYPE_P (TREE_TYPE (rhs1_type))
|| SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type)))
|| (!INTEGRAL_TYPE_P (rhs2_type)
debug_generic_expr (rhs2_type);
return true;
}
- /* For shifting a vector of floating point components we
+ /* For shifting a vector of non-integral components we
only allow shifting by a constant multiple of the element size. */
- if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type))
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
&& (TREE_CODE (rhs2) != INTEGER_CST
|| !div_if_zero_remainder (EXACT_DIV_EXPR, rhs2,
TYPE_SIZE (TREE_TYPE (rhs1_type)))))
}
break;
+ case FMA_EXPR:
+ if (!useless_type_conversion_p (lhs_type, rhs1_type)
+ || !useless_type_conversion_p (lhs_type, rhs2_type)
+ || !useless_type_conversion_p (lhs_type, rhs3_type))
+ {
+ error ("type mismatch in fused multiply-add expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+ break;
+
default:
gcc_unreachable ();
}
return true;
}
- if (!types_compatible_p (TREE_TYPE (op), TREE_TYPE (TREE_TYPE (rhs1)))
+ /* Technically there is no longer a need for matching types, but
+ gimple hygiene asks for this check. In LTO we can end up
+ combining incompatible units and thus end up with addresses
+ of globals that change their type to a common one. */
+ if (!in_lto_p
+ && !types_compatible_p (TREE_TYPE (op),
+ TREE_TYPE (TREE_TYPE (rhs1)))
&& !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
TREE_TYPE (op)))
{
if (TREE_CODE (gimple_phi_result (stmt)) != SSA_NAME)
{
- error ("Invalid PHI result");
+ error ("invalid PHI result");
return true;
}
|| (!is_gimple_reg (gimple_phi_result (stmt))
&& !is_gimple_addressable (arg)))
{
- error ("Invalid PHI argument");
+ error ("invalid PHI argument");
debug_generic_stmt (arg);
return true;
}
if (!useless_type_conversion_p (type, TREE_TYPE (arg)))
{
- error ("Incompatible types in PHI argument %u", i);
+ error ("incompatible types in PHI argument %u", i);
debug_generic_stmt (type);
debug_generic_stmt (TREE_TYPE (arg));
return true;
if (!pointer_set_contains (visited, node->stmt))
{
- error ("Dead STMT in EH table");
+ error ("dead STMT in EH table");
debug_gimple_stmt (node->stmt);
eh_error_found = true;
}
if (check_last_block)
{
basic_block bb = EXIT_BLOCK_PTR->prev_bb;
- gimple_stmt_iterator gsi = gsi_last_bb (bb);
+ gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
gimple t = NULL;
if (!gsi_end_p (gsi))
if (blocks && !TEST_BIT (blocks, i))
continue;
- gsi = gsi_last_bb (bb);
+ gsi = gsi_last_nondebug_bb (bb);
if (!gsi_end_p (gsi))
{
last_stmt = gsi_stmt (gsi);
return blocks_split;
}
-/* Purge dead abnormal call edges from basic block BB. */
-
-bool
-gimple_purge_dead_abnormal_call_edges (basic_block bb)
-{
- bool changed = gimple_purge_dead_eh_edges (bb);
-
- if (cfun->has_nonlocal_label)
- {
- gimple stmt = last_stmt (bb);
- edge_iterator ei;
- edge e;
-
- if (!(stmt && stmt_can_make_abnormal_goto (stmt)))
- for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
- {
- if (e->flags & EDGE_ABNORMAL)
- {
- remove_edge (e);
- changed = true;
- }
- else
- ei_next (&ei);
- }
-
- /* See gimple_purge_dead_eh_edges below. */
- if (changed)
- free_dominance_info (CDI_DOMINATORS);
- }
-
- return changed;
-}
-
/* Removes edge E and all the blocks dominated by it, and updates dominance
information. The IL in E->src needs to be updated separately.
If dominance info is not available, only the edge E is removed.*/
return changed;
}
+/* Purge dead EH edges from basic block listed in BLOCKS. */
+
bool
gimple_purge_all_dead_eh_edges (const_bitmap blocks)
{
return changed;
}
+/* Purge dead abnormal call edges from basic block BB. */
+
+bool
+gimple_purge_dead_abnormal_call_edges (basic_block bb)
+{
+ bool changed = false;
+ edge e;
+ edge_iterator ei;
+ gimple stmt = last_stmt (bb);
+
+ if (!cfun->has_nonlocal_label)
+ return false;
+
+ if (stmt && stmt_can_make_abnormal_goto (stmt))
+ return false;
+
+ for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+ {
+ if (e->flags & EDGE_ABNORMAL)
+ {
+ remove_edge_and_dominated_blocks (e);
+ changed = true;
+ }
+ else
+ ei_next (&ei);
+ }
+
+ return changed;
+}
+
+/* Purge dead abnormal call edges from basic block listed in BLOCKS. */
+
+bool
+gimple_purge_all_dead_abnormal_call_edges (const_bitmap blocks)
+{
+ bool changed = false;
+ unsigned i;
+ bitmap_iterator bi;
+
+ EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i, bi)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+
+ /* Earlier gimple_purge_dead_abnormal_call_edges could have removed
+ this basic block already. */
+ gcc_assert (bb || changed);
+ if (bb != NULL)
+ changed |= gimple_purge_dead_abnormal_call_edges (bb);
+ }
+
+ return changed;
+}
+
/* This function is called whenever a new edge is created or
redirected. */