From 588043b1374954388642f0c4574ee6306d34e22e Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 16 Dec 2013 13:22:21 -0500
Subject: [PATCH 26/88] Introduce gimple_eh_else

gcc/
	* coretypes.h (gimple_eh_else): New typedef.
	(const_gimple_eh_else): New typedef.

	* gimple.h (gimple_build_eh_else): Return a gimple_eh_else rather
	than a plain gimple.
	(gimple_eh_else_n_body_ptr): Require a gimple_eh_else rather than
	a plain gimple.
	(gimple_eh_else_n_body): Likewise.
	(gimple_eh_else_e_body_ptr): Likewise.
	(gimple_eh_else_e_body): Likewise.
	(gimple_eh_else_set_n_body): Likewise.
	(gimple_eh_else_set_e_body): Likewise.

	* gimple-low.c (lower_stmt): Add checked cast to gimple_eh_else
	within GIMPLE_EH_ELSE case of switch statement, introducing a new
	local.
	(gimple_stmt_may_fallthru): Likewise.

	* gimple-pretty-print.c (dump_gimple_eh_else): Require a
	gimple_eh_else rather than a plain gimple.
	(pp_gimple_stmt_1): Add checked cast to gimple_eh_else within
	GIMPLE_EH_ELSE case of switch statement

	* gimple-walk.c (walk_gimple_stmt): Add checked cast to
	gimple_eh_else within GIMPLE_EH_ELSE case of switch statement,
	introducing a new local.

	* gimple.c (gimple_build_eh_else): Return a gimple_eh_else
	rather than a plain gimple.
	(gimple_copy): Add checked casts to gimple_eh_else within
	GIMPLE_EH_ELSE case of switch statement, introducing new locals.

	* tree-cfg.c (verify_gimple_in_seq_2): Add checked cast to
	gimple_eh_else within GIMPLE_EH_ELSE case of switch statement,
	introducing a new local.

	* tree-eh.c (collect_finally_tree): Likewise.
	(replace_goto_queue_1): Likewise.
	(get_eh_else): Return a gimple_eh_else rather than a plain gimple.
	(honor_protect_cleanup_actions): Convert local "eh_else" from
	gimple to gimple_eh_else.
	(lower_try_finally_nofallthru): Likewise.
	(lower_try_finally_onedest): Introduce locals "eh_else" and
	"label_stmt", using them in favor of "x" for the gimple_eh_else
	and the gimple_label.
	(lower_try_finally_copy): Convert local "eh_else" from gimple to
	gimple_eh_else.
	(lower_try_finally_switch): Likewise.
	(decide_copy_try_finally): Likewise.
	(refactor_eh_r): Add checked cast to gimple_eh_else within
	GIMPLE_EH_ELSE case of switch statement, introducing a new local.
---
 gcc/coretypes.h           |  4 ++++
 gcc/gimple-low.c          | 15 +++++++++----
 gcc/gimple-pretty-print.c |  5 +++--
 gcc/gimple-walk.c         | 19 +++++++++-------
 gcc/gimple.c              | 16 ++++++++------
 gcc/gimple.h              | 26 ++++++++--------------
 gcc/tree-cfg.c            |  7 ++++--
 gcc/tree-eh.c             | 55 +++++++++++++++++++++++++++++++----------------
 8 files changed, 89 insertions(+), 58 deletions(-)

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 51b73f6..ba076ec 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -146,6 +146,10 @@ struct gimple_statement_eh_mnt;
 typedef struct gimple_statement_eh_mnt *gimple_eh_must_not_throw;
 typedef const struct gimple_statement_eh_mnt *const_gimple_eh_must_not_throw;
 
+struct gimple_statement_eh_else;
+typedef struct gimple_statement_eh_else *gimple_eh_else;
+typedef const struct gimple_statement_eh_else *const_gimple_eh_else;
+
 struct gimple_statement_phi;
 typedef struct gimple_statement_phi *gimple_phi;
 typedef const struct gimple_statement_phi *const_gimple_phi;
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 9ac984e..b5dc823 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -288,8 +288,11 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
       return;
 
     case GIMPLE_EH_ELSE:
-      lower_sequence (gimple_eh_else_n_body_ptr (stmt), data);
-      lower_sequence (gimple_eh_else_e_body_ptr (stmt), data);
+      {
+	gimple_eh_else eh_else_stmt = as_a <gimple_eh_else> (stmt);
+	lower_sequence (gimple_eh_else_n_body_ptr (eh_else_stmt), data);
+	lower_sequence (gimple_eh_else_e_body_ptr (eh_else_stmt), data);
+      }
       break;
 
     case GIMPLE_NOP:
@@ -597,8 +600,12 @@ gimple_stmt_may_fallthru (gimple stmt)
 	      && gimple_seq_may_fallthru (gimple_try_cleanup (stmt)));
 
     case GIMPLE_EH_ELSE:
-      return (gimple_seq_may_fallthru (gimple_eh_else_n_body (stmt))
-	      || gimple_seq_may_fallthru (gimple_eh_else_e_body (stmt)));
+      {
+	gimple_eh_else eh_else_stmt = as_a <gimple_eh_else> (stmt);
+	return (gimple_seq_may_fallthru (gimple_eh_else_n_body (eh_else_stmt))
+		|| gimple_seq_may_fallthru (gimple_eh_else_e_body (
+					      eh_else_stmt)));
+      }
 
     case GIMPLE_CALL:
       /* Functions that do not return do not fall through.  */
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index a15c2a3..4ee8af1 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1038,7 +1038,8 @@ dump_gimple_eh_must_not_throw (pretty_printer *buffer,
    dumpfile.h).  */
 
 static void
-dump_gimple_eh_else (pretty_printer *buffer, gimple gs, int spc, int flags)
+dump_gimple_eh_else (pretty_printer *buffer, gimple_eh_else gs, int spc,
+		     int flags)
 {
   if (flags & TDF_RAW)
     dump_gimple_fmt (buffer, spc, flags,
@@ -2235,7 +2236,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
       break;
 
     case GIMPLE_EH_ELSE:
-      dump_gimple_eh_else (buffer, gs, spc, flags);
+      dump_gimple_eh_else (buffer, as_a <gimple_eh_else> (gs), spc, flags);
       break;
 
     case GIMPLE_RESX:
diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
index fc74f49..d36263a 100644
--- a/gcc/gimple-walk.c
+++ b/gcc/gimple-walk.c
@@ -566,14 +566,17 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
       break;
 
     case GIMPLE_EH_ELSE:
-      ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (stmt),
-			     callback_stmt, callback_op, wi);
-      if (ret)
-	return wi->callback_result;
-      ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (stmt),
-			     callback_stmt, callback_op, wi);
-      if (ret)
-	return wi->callback_result;
+      {
+	gimple_eh_else eh_else_stmt = as_a <gimple_eh_else> (stmt);
+	ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (eh_else_stmt),
+				   callback_stmt, callback_op, wi);
+	if (ret)
+	  return wi->callback_result;
+	ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (eh_else_stmt),
+				   callback_stmt, callback_op, wi);
+	if (ret)
+	  return wi->callback_result;
+      }
       break;
 
     case GIMPLE_TRY:
diff --git a/gcc/gimple.c b/gcc/gimple.c
index a52d989..b3c663c 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -660,10 +660,10 @@ gimple_build_eh_must_not_throw (tree decl)
 
 /* Build a GIMPLE_EH_ELSE statement.  */
 
-gimple
+gimple_eh_else
 gimple_build_eh_else (gimple_seq n_body, gimple_seq e_body)
 {
-  gimple p = gimple_alloc (GIMPLE_EH_ELSE, 0);
+  gimple_eh_else p = as_a <gimple_eh_else> (gimple_alloc (GIMPLE_EH_ELSE, 0));
   gimple_eh_else_set_n_body (p, n_body);
   gimple_eh_else_set_e_body (p, e_body);
   return p;
@@ -1685,10 +1685,14 @@ gimple_copy (gimple stmt)
 	  break;
 
 	case GIMPLE_EH_ELSE:
-	  new_seq = gimple_seq_copy (gimple_eh_else_n_body (stmt));
-	  gimple_eh_else_set_n_body (copy, new_seq);
-	  new_seq = gimple_seq_copy (gimple_eh_else_e_body (stmt));
-	  gimple_eh_else_set_e_body (copy, new_seq);
+	  {
+	    gimple_eh_else eh_else_stmt = as_a <gimple_eh_else> (stmt);
+	    gimple_eh_else eh_else_copy = as_a <gimple_eh_else> (copy);
+	    new_seq = gimple_seq_copy (gimple_eh_else_n_body (eh_else_stmt));
+	    gimple_eh_else_set_n_body (eh_else_copy, new_seq);
+	    new_seq = gimple_seq_copy (gimple_eh_else_e_body (eh_else_stmt));
+	    gimple_eh_else_set_e_body (eh_else_copy, new_seq);
+	  }
 	  break;
 
 	case GIMPLE_TRY:
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 445a1c0..9b73e00 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1328,7 +1328,7 @@ gimple_asm gimple_build_asm_vec (const char *, vec<tree, va_gc> *,
 gimple_catch gimple_build_catch (tree, gimple_seq);
 gimple_eh_filter gimple_build_eh_filter (tree, gimple_seq);
 gimple_eh_must_not_throw gimple_build_eh_must_not_throw (tree);
-gimple gimple_build_eh_else (gimple_seq, gimple_seq);
+gimple_eh_else gimple_build_eh_else (gimple_seq, gimple_seq);
 gimple_statement_try *gimple_build_try (gimple_seq, gimple_seq,
 					enum gimple_try_flags);
 gimple gimple_build_wce (gimple_seq);
@@ -3669,46 +3669,38 @@ gimple_eh_must_not_throw_set_fndecl (gimple_eh_must_not_throw eh_mnt_stmt,
 /* GIMPLE_EH_ELSE accessors.  */
 
 static inline gimple_seq *
-gimple_eh_else_n_body_ptr (gimple gs)
+gimple_eh_else_n_body_ptr (gimple_eh_else eh_else_stmt)
 {
-  gimple_statement_eh_else *eh_else_stmt =
-    as_a <gimple_statement_eh_else *> (gs);
   return &eh_else_stmt->n_body;
 }
 
 static inline gimple_seq
-gimple_eh_else_n_body (gimple gs)
+gimple_eh_else_n_body (gimple_eh_else eh_else_stmt)
 {
-  return *gimple_eh_else_n_body_ptr (gs);
+  return *gimple_eh_else_n_body_ptr (eh_else_stmt);
 }
 
 static inline gimple_seq *
-gimple_eh_else_e_body_ptr (gimple gs)
+gimple_eh_else_e_body_ptr (gimple_eh_else eh_else_stmt)
 {
-  gimple_statement_eh_else *eh_else_stmt =
-    as_a <gimple_statement_eh_else *> (gs);
   return &eh_else_stmt->e_body;
 }
 
 static inline gimple_seq
-gimple_eh_else_e_body (gimple gs)
+gimple_eh_else_e_body (gimple_eh_else eh_else_stmt)
 {
-  return *gimple_eh_else_e_body_ptr (gs);
+  return *gimple_eh_else_e_body_ptr (eh_else_stmt);
 }
 
 static inline void
-gimple_eh_else_set_n_body (gimple gs, gimple_seq seq)
+gimple_eh_else_set_n_body (gimple_eh_else eh_else_stmt, gimple_seq seq)
 {
-  gimple_statement_eh_else *eh_else_stmt =
-    as_a <gimple_statement_eh_else *> (gs);
   eh_else_stmt->n_body = seq;
 }
 
 static inline void
-gimple_eh_else_set_e_body (gimple gs, gimple_seq seq)
+gimple_eh_else_set_e_body (gimple_eh_else eh_else_stmt, gimple_seq seq)
 {
-  gimple_statement_eh_else *eh_else_stmt =
-    as_a <gimple_statement_eh_else *> (gs);
   eh_else_stmt->e_body = seq;
 }
 
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 7ec0517..d166477 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4639,8 +4639,11 @@ verify_gimple_in_seq_2 (gimple_seq stmts)
 	  break;
 
 	case GIMPLE_EH_ELSE:
-	  err |= verify_gimple_in_seq_2 (gimple_eh_else_n_body (stmt));
-	  err |= verify_gimple_in_seq_2 (gimple_eh_else_e_body (stmt));
+	  {
+	    gimple_eh_else eh_else = as_a <gimple_eh_else> (stmt);
+	    err |= verify_gimple_in_seq_2 (gimple_eh_else_n_body (eh_else));
+	    err |= verify_gimple_in_seq_2 (gimple_eh_else_e_body (eh_else));
+	  }
 	  break;
 
 	case GIMPLE_CATCH:
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index d22eb45..fbb40e5 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -273,8 +273,11 @@ collect_finally_tree (gimple stmt, gimple region)
       break;
 
     case GIMPLE_EH_ELSE:
-      collect_finally_tree_1 (gimple_eh_else_n_body (stmt), region);
-      collect_finally_tree_1 (gimple_eh_else_e_body (stmt), region);
+      {
+	gimple_eh_else eh_else_stmt = as_a <gimple_eh_else> (stmt);
+	collect_finally_tree_1 (gimple_eh_else_n_body (eh_else_stmt), region);
+	collect_finally_tree_1 (gimple_eh_else_e_body (eh_else_stmt), region);
+      }
       break;
 
     default:
@@ -529,8 +532,13 @@ replace_goto_queue_1 (gimple stmt, struct leh_tf_state *tf,
       replace_goto_queue_stmt_list (gimple_eh_filter_failure_ptr (stmt), tf);
       break;
     case GIMPLE_EH_ELSE:
-      replace_goto_queue_stmt_list (gimple_eh_else_n_body_ptr (stmt), tf);
-      replace_goto_queue_stmt_list (gimple_eh_else_e_body_ptr (stmt), tf);
+      {
+	gimple_eh_else eh_else_stmt = as_a <gimple_eh_else> (stmt);
+	replace_goto_queue_stmt_list (gimple_eh_else_n_body_ptr (eh_else_stmt),
+				      tf);
+	replace_goto_queue_stmt_list (gimple_eh_else_e_body_ptr (eh_else_stmt),
+				      tf);
+      }
       break;
 
     default:
@@ -940,14 +948,14 @@ lower_try_finally_fallthru_label (struct leh_tf_state *tf)
 /* A subroutine of lower_try_finally.  If FINALLY consits of a
    GIMPLE_EH_ELSE node, return it.  */
 
-static inline gimple
+static inline gimple_eh_else
 get_eh_else (gimple_seq finally)
 {
   gimple x = gimple_seq_first_stmt (finally);
   if (gimple_code (x) == GIMPLE_EH_ELSE)
     {
       gcc_assert (gimple_seq_singleton_p (finally));
-      return x;
+      return as_a <gimple_eh_else> (x);
     }
   return NULL;
 }
@@ -981,7 +989,8 @@ honor_protect_cleanup_actions (struct leh_state *outer_state,
   gimple_stmt_iterator gsi;
   bool finally_may_fallthru;
   gimple_seq finally;
-  gimple x, eh_else;
+  gimple x;
+  gimple_eh_else eh_else;
 
   /* First check for nothing to do.  */
   if (lang_hooks.eh_protect_cleanup_actions == NULL)
@@ -1049,7 +1058,8 @@ lower_try_finally_nofallthru (struct leh_state *state,
 			      struct leh_tf_state *tf)
 {
   tree lab;
-  gimple x, eh_else;
+  gimple x;
+  gimple_eh_else eh_else;
   gimple_seq finally;
   struct goto_queue_node *q, *qe;
 
@@ -1113,6 +1123,8 @@ static void
 lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
 {
   struct goto_queue_node *q, *qe;
+  gimple_eh_else eh_else;
+  gimple_label label_stmt;
   gimple x;
   gimple_seq finally;
   gimple_stmt_iterator gsi;
@@ -1125,13 +1137,13 @@ lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
   /* Since there's only one destination, and the destination edge can only
      either be EH or non-EH, that implies that all of our incoming edges
      are of the same type.  Therefore we can lower EH_ELSE immediately.  */
-  x = get_eh_else (finally);
-  if (x)
+  eh_else = get_eh_else (finally);
+  if (eh_else)
     {
       if (tf->may_throw)
-	finally = gimple_eh_else_e_body (x);
+	finally = gimple_eh_else_e_body (eh_else);
       else
-	finally = gimple_eh_else_n_body (x);
+	finally = gimple_eh_else_n_body (eh_else);
     }
 
   lower_eh_constructs_1 (state, &finally);
@@ -1166,8 +1178,8 @@ lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
     }
 
   finally_label = create_artificial_label (loc);
-  x = gimple_build_label (finally_label);
-  gimple_seq_add_stmt (&tf->top_p_seq, x);
+  label_stmt = gimple_build_label (finally_label);
+  gimple_seq_add_stmt (&tf->top_p_seq, label_stmt);
 
   gimple_seq_add_seq (&tf->top_p_seq, finally);
 
@@ -1215,7 +1227,8 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
   gimple_seq finally;
   gimple_seq new_stmt;
   gimple_seq seq;
-  gimple x, eh_else;
+  gimple x;
+  gimple_eh_else eh_else;
   tree tmp;
   location_t tf_loc = gimple_location (tf->try_finally_expr);
 
@@ -1348,7 +1361,8 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
   tree last_case;
   vec<tree> case_label_vec;
   gimple_seq switch_body = NULL;
-  gimple x, eh_else;
+  gimple x;
+  gimple_eh_else eh_else;
   tree tmp;
   gimple switch_stmt;
   gimple_seq finally;
@@ -1560,7 +1574,7 @@ static bool
 decide_copy_try_finally (int ndests, bool may_throw, gimple_seq finally)
 {
   int f_estimate, sw_estimate;
-  gimple eh_else;
+  gimple_eh_else eh_else;
 
   /* If there's an EH_ELSE involved, the exception path is separate
      and really doesn't come into play for this computation.  */
@@ -3072,8 +3086,11 @@ refactor_eh_r (gimple_seq seq)
 	    refactor_eh_r (gimple_eh_filter_failure (one));
 	    break;
 	  case GIMPLE_EH_ELSE:
-	    refactor_eh_r (gimple_eh_else_n_body (one));
-	    refactor_eh_r (gimple_eh_else_e_body (one));
+	    {
+	      gimple_eh_else eh_else_stmt = as_a <gimple_eh_else> (one);
+	      refactor_eh_r (gimple_eh_else_n_body (eh_else_stmt));
+	      refactor_eh_r (gimple_eh_else_e_body (eh_else_stmt));
+	    }
 	    break;
 	  default:
 	    break;
-- 
1.8.5.3

