gimplify.c (sort_case_labels): New.
authorSteven Bosscher <stevenb@suse.de>
Sun, 30 May 2004 18:19:18 +0000 (18:19 +0000)
committerSteven Bosscher <steven@gcc.gnu.org>
Sun, 30 May 2004 18:19:18 +0000 (18:19 +0000)
* gimplify.c (sort_case_labels): New.  Split out from...
(gimplify_switch_expr): ...here.  Use it.
* tree-eh.c (lower_try_finally_switch): Sort the labels of
the SWITCH_EXPR created here before leaving the function.
* tree.c (sort_case_labels): Add prototype.

From-SVN: r82462

gcc/ChangeLog
gcc/gimplify.c
gcc/tree-eh.c
gcc/tree.h

index f72a6e274fd4badfc9c133739c6e94052c197531..d80740694003703160d601f2fef73eeb20069098 100644 (file)
@@ -1,3 +1,11 @@
+2004-05-30  Steven Bosscher  <stevenb@suse.de>
+
+       * gimplify.c (sort_case_labels): New.  Split out from...
+       (gimplify_switch_expr): ...here.  Use it.
+       * tree-eh.c (lower_try_finally_switch): Sort the labels of
+       the SWITCH_EXPR created here before leaving the function.
+       * tree.c (sort_case_labels): Add prototype.
+
 2004-05-30  Andrew Pinski  <pinskia@physics.uc.edu>
 
        * fold-const.c (fold) [case TRUTH_NOT_EXPR]: Make sure the type is
index 173ae28b29b4956d05fc7c0390a8350822f270a1..4693c61f85dedeec999c1d4abc7cebc6022c91a8 100644 (file)
@@ -994,6 +994,37 @@ compare_case_labels (const void *p1, const void *p2)
   return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
 }
 
+/* Sort the case labels in LABEL_VEC in ascending order.  */
+
+void
+sort_case_labels (tree label_vec)
+{
+  size_t len = TREE_VEC_LENGTH (label_vec);
+  tree default_case = TREE_VEC_ELT (label_vec, len - 1);
+
+  if (CASE_LOW (default_case))
+    {
+      size_t i;
+
+      /* The last label in the vector should be the default case
+         but it is not.  */
+      for (i = 0; i < len; ++i)
+       {
+         tree t = TREE_VEC_ELT (label_vec, i);
+         if (!CASE_LOW (t))
+           {
+             default_case = t;
+             TREE_VEC_ELT (label_vec, i) = TREE_VEC_ELT (label_vec, len - 1);
+             TREE_VEC_ELT (label_vec, len - 1) = default_case;
+             break;
+           }
+       }
+    }
+
+  qsort (&TREE_VEC_ELT (label_vec, 0), len - 1, sizeof (tree),
+        compare_case_labels);
+}
+
 /* Gimplify a SWITCH_EXPR, and collect a TREE_VEC of the labels it can
    branch to.  */
 
@@ -1057,12 +1088,12 @@ gimplify_switch_expr (tree *expr_p, tree *pre_p)
       else
        *expr_p = SWITCH_BODY (switch_expr);
 
-      qsort (&VARRAY_TREE (labels, 0), len, sizeof (tree),
-            compare_case_labels);
       for (i = 0; i < len; ++i)
        TREE_VEC_ELT (label_vec, i) = VARRAY_TREE (labels, i);
       TREE_VEC_ELT (label_vec, len) = default_case;
 
+      sort_case_labels (label_vec);
+
       SWITCH_BODY (switch_expr) = NULL;
     }
   else if (!SWITCH_LABELS (switch_expr))
index 1f37ac6789c4c5c3f859e2676ad76ef11ef13143..9dd52a3b0bfa8375397715bcb4a30a24a1218c1d 100644 (file)
@@ -1200,8 +1200,10 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
   replace_goto_queue (tf);
   last_case_index += nlabels;
 
-  /* Make sure that we have a default label, as one is required.  */
+  /* Make sure that the last case is the default label, as one is required.
+     Then sort the labels, which is also required in GIMPLE.  */
   CASE_LOW (last_case) = NULL;
+  sort_case_labels (case_label_vec);
 
   /* Need to link switch_stmt after running replace_goto_queue due
      to not wanting to process the same goto stmts twice.  */
index 88223ca82c5a568b17a9c05d074f553fd8749129..48df21271132c41abfa0a70b6065f15d88af9b49 100644 (file)
@@ -3675,6 +3675,7 @@ extern tree create_artificial_label (void);
 extern void gimplify_function_tree (tree);
 extern const char *get_name (tree);
 extern tree unshare_expr (tree);
+extern void sort_case_labels (tree);
 
 /* If KIND=='I', return a suitable global initializer (constructor) name.
    If KIND=='D', return a suitable global clean-up (destructor) name.  */