]> gcc.gnu.org Git - gcc.git/commitdiff
tree-cfg: check placement of returns_twice calls
authorAlexander Monakov <amonakov@ispras.ru>
Fri, 14 Jan 2022 18:05:12 +0000 (21:05 +0300)
committerAlexander Monakov <amonakov@ispras.ru>
Tue, 19 Jul 2022 14:16:17 +0000 (17:16 +0300)
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.

gcc/tree-cfg.cc

index a365aad678f322339c6228f5d6c84acd6af61695..5bcf78198e78b018669e1c60889e8915d409421e 100644 (file)
@@ -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);
This page took 0.076641 seconds and 5 git commands to generate.