summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/gimplify.c35
-rw-r--r--gcc/tree-eh.c4
-rw-r--r--gcc/tree.h1
4 files changed, 45 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f72a6e274fd..d8074069400 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 173ae28b29b..4693c61f85d 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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))
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 1f37ac6789c..9dd52a3b0bf 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -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. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 88223ca82c5..48df2127113 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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. */