diff options
author | Richard Biener <rguenther@suse.de> | 2015-07-01 08:37:19 +0000 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2015-07-01 08:37:19 +0000 |
commit | d9ab4649161bc60fc68c9bb36d54b28142a3797a (patch) | |
tree | e4a5056a7da5f93f5dbacd47b6f22b61fdf92aad /gcc/jit/jit-playback.c | |
parent | e79886b1b133e4fd15f1c5c16d3e5a28c1233c33 (diff) | |
parent | 00b24710e5527e8b51904824c6e2a7717455c233 (diff) |
2015-07-01 Richard Biener <rguenther@suse.de>match-and-simplify
Merge from trunk r225116 through r225225.
* match-bitwise.pd: Removed and merged remains into
match.pd.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/match-and-simplify@225229 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/jit/jit-playback.c')
-rw-r--r-- | gcc/jit/jit-playback.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 90a6cd1eeb1..c9d7c8c607a 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -1576,6 +1576,80 @@ add_return (location *loc, add_stmt (return_stmt); } +/* Helper function for playback::block::add_switch. + Construct a case label for the given range, followed by a goto stmt + to the given block, appending them to stmt list *ptr_t_switch_body. */ + +static void +add_case (tree *ptr_t_switch_body, + tree t_low_value, + tree t_high_value, + playback::block *dest_block) +{ + tree t_label = create_artificial_label (UNKNOWN_LOCATION); + DECL_CONTEXT (t_label) = dest_block->get_function ()->as_fndecl (); + + tree t_case_label = + build_case_label (t_low_value, t_high_value, t_label); + append_to_statement_list (t_case_label, ptr_t_switch_body); + + tree t_goto_stmt = + build1 (GOTO_EXPR, void_type_node, dest_block->as_label_decl ()); + append_to_statement_list (t_goto_stmt, ptr_t_switch_body); +} + +/* Add a switch statement to the function's statement list. + + My initial attempt at implementing this constructed a TREE_VEC + of the cases and set it as SWITCH_LABELS (switch_expr). However, + gimplify.c:gimplify_switch_expr is set up to deal with SWITCH_BODY, and + doesn't have any logic for gimplifying SWITCH_LABELS. + + Hence we create a switch body, and populate it with case labels, each + followed by a goto to the desired block. */ + +void +playback::block:: +add_switch (location *loc, + rvalue *expr, + block *default_block, + const auto_vec <case_> *cases) +{ + /* Compare with: + - c/c-typeck.c: c_start_case + - c-family/c-common.c:c_add_case_label + - java/expr.c:expand_java_switch and expand_java_add_case + We've already rejected overlaps and duplicates in + libgccjit.c:case_range_validator::validate. */ + + tree t_expr = expr->as_tree (); + tree t_type = TREE_TYPE (t_expr); + + tree t_switch_body = alloc_stmt_list (); + + int i; + case_ *c; + FOR_EACH_VEC_ELT (*cases, i, c) + { + tree t_low_value = c->m_min_value->as_tree (); + tree t_high_value = c->m_max_value->as_tree (); + add_case (&t_switch_body, + t_low_value, + t_high_value, + c->m_dest_block); + } + /* Default label. */ + add_case (&t_switch_body, + NULL_TREE, NULL_TREE, + default_block); + + tree switch_stmt = build3 (SWITCH_EXPR, t_type, t_expr, + t_switch_body, NULL_TREE); + if (loc) + set_tree_location (switch_stmt, loc); + add_stmt (switch_stmt); +} + /* Constructor for gcc::jit::playback::block. */ playback::block:: @@ -2139,6 +2213,10 @@ make_fake_args (vec <char *> *argvec, } } + /* Add any user-provided extra options, starting with any from + parent contexts. */ + m_recording_ctxt->append_command_line_options (argvec); + #undef ADD_ARG #undef ADD_ARG_TAKE_OWNERSHIP } |