aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexander Monakov <amonakov@ispras.ru>2022-01-14 21:05:12 +0300
committerAlexander Monakov <amonakov@ispras.ru>2022-07-19 17:16:17 +0300
commit7a158a5776f5ca95a318fcae0ca2dfefb0789538 (patch)
tree33e56c811962726550398a53187fb45b8d54dd12 /gcc
parent26cea5f108e0facdb080e385000bb141b086845f (diff)
downloadgcc-7a158a5776f5ca95a318fcae0ca2dfefb0789538.zip
gcc-7a158a5776f5ca95a318fcae0ca2dfefb0789538.tar.gz
gcc-7a158a5776f5ca95a318fcae0ca2dfefb0789538.tar.bz2
tree-cfg: check placement of returns_twice calls
When a returns_twice call has an associated abnormal edge, the edge corresponds to the "second return" from the call. It wouldn't make sense if any executable statements appeared between the call and the destination of the edge (they wouldn't be re-executed upon the "second return"), so verify that. gcc/ChangeLog: * tree-cfg.cc (gimple_verify_flow_info): Check placement of returns_twice calls.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/tree-cfg.cc33
1 files changed, 33 insertions, 0 deletions
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index a365aad..5bcf781 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -5653,6 +5653,7 @@ gimple_verify_flow_info (void)
}
/* Verify that body of basic block BB is free of control flow. */
+ bool seen_nondebug_stmt = false;
for (; !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
@@ -5673,6 +5674,38 @@ gimple_verify_flow_info (void)
gimple_label_label (label_stmt), bb->index);
err = 1;
}
+
+ /* Check that no statements appear between a returns_twice call
+ and its associated abnormal edge. */
+ if (gimple_code (stmt) == GIMPLE_CALL
+ && gimple_call_flags (stmt) & ECF_RETURNS_TWICE)
+ {
+ const char *misplaced = NULL;
+ /* TM is an exception: it points abnormal edges just after the
+ call that starts a transaction, i.e. it must end the BB. */
+ if (gimple_call_builtin_p (stmt, BUILT_IN_TM_START))
+ {
+ if (single_succ_p (bb)
+ && bb_has_abnormal_pred (single_succ (bb))
+ && !gsi_one_nondebug_before_end_p (gsi))
+ misplaced = "not last";
+ }
+ else
+ {
+ if (seen_nondebug_stmt
+ && bb_has_abnormal_pred (bb))
+ misplaced = "not first";
+ }
+ if (misplaced)
+ {
+ error ("returns_twice call is %s in basic block %d",
+ misplaced, bb->index);
+ print_gimple_stmt (stderr, stmt, 0, TDF_SLIM);
+ err = 1;
+ }
+ }
+ if (!is_gimple_debug (stmt))
+ seen_nondebug_stmt = true;
}
gsi = gsi_last_nondebug_bb (bb);