From 0f1f6967a21f8e4cc6ca7448dd9adc5d09c99edb Mon Sep 17 00:00:00 2001 From: Steven Bosscher Date: Sun, 30 May 2004 18:19:18 +0000 Subject: [PATCH] gimplify.c (sort_case_labels): New. * 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 | 8 ++++++++ gcc/gimplify.c | 35 +++++++++++++++++++++++++++++++++-- gcc/tree-eh.c | 4 +++- gcc/tree.h | 1 + 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 + + * 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 * 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. */ -- 2.30.2