aboutsummaryrefslogtreecommitdiff
path: root/gcc/jit/jit-playback.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2015-07-01 08:37:19 +0000
committerRichard Biener <rguenther@suse.de>2015-07-01 08:37:19 +0000
commitd9ab4649161bc60fc68c9bb36d54b28142a3797a (patch)
treee4a5056a7da5f93f5dbacd47b6f22b61fdf92aad /gcc/jit/jit-playback.c
parente79886b1b133e4fd15f1c5c16d3e5a28c1233c33 (diff)
parent00b24710e5527e8b51904824c6e2a7717455c233 (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.c78
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
}