Committed to branch dmalcolm/jit: gcc/jit/ * libgccjit.h (gcc_jit_function_add_void_return): New. * libgccjit.map (gcc_jit_function_add_void_return): New. * libgccjit.c (gcc_jit_function_add_void_return): New. * libgccjit++.h (add_return): Add overloaded variant with no rvalue, calling gcc_jit_function_add_void_return.
* internal-api.c (gcc::jit::recording::function::add_return): Add comment that rvalue could be NULL. (gcc::jit::playback::function::add_return): Support rvalue being NULL. gcc/testsuite/ * jit.dg/test-functions.c (create_use_of_void_return): New, to add test coverage for gcc_jit_function_add_void_return. (verify_void_return): Likewise. (create_code): Add call to create_use_of_void_return. (verify_code): Add call to verify_void_return. --- gcc/jit/ChangeLog.jit | 13 ++++++++ gcc/jit/internal-api.c | 31 +++++++++++------- gcc/jit/libgccjit++.h | 8 +++++ gcc/jit/libgccjit.c | 17 ++++++++++ gcc/jit/libgccjit.h | 11 +++++++ gcc/jit/libgccjit.map | 1 + gcc/testsuite/ChangeLog.jit | 8 +++++ gcc/testsuite/jit.dg/test-functions.c | 62 +++++++++++++++++++++++++++++++++++ 8 files changed, 139 insertions(+), 12 deletions(-) diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit index 40d445e..de352fa 100644 --- a/gcc/jit/ChangeLog.jit +++ b/gcc/jit/ChangeLog.jit @@ -1,5 +1,18 @@ 2014-02-25 David Malcolm <dmalc...@redhat.com> + * libgccjit.h (gcc_jit_function_add_void_return): New. + * libgccjit.map (gcc_jit_function_add_void_return): New. + * libgccjit.c (gcc_jit_function_add_void_return): New. + * libgccjit++.h (add_return): Add overloaded variant with no + rvalue, calling gcc_jit_function_add_void_return. + + * internal-api.c (gcc::jit::recording::function::add_return): Add + comment that rvalue could be NULL. + (gcc::jit::playback::function::add_return): Support rvalue being + NULL. + +2014-02-25 David Malcolm <dmalc...@redhat.com> + * internal-api.h (gcc::jit::playback::function): Add field m_inner_block. diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c index 43de7cd..1cb4717 100644 --- a/gcc/jit/internal-api.c +++ b/gcc/jit/internal-api.c @@ -1309,6 +1309,9 @@ void recording::function::add_return (recording::location *loc, recording::rvalue *rvalue) { + /* This is used by both gcc_jit_function_add_return and + gcc_jit_function_add_void_return; rvalue will be non-NULL for + the former and NULL for the latter. */ statement *result = new return_ (this, loc, rvalue); m_ctxt->record (result); m_activity.safe_push (result); @@ -3114,22 +3117,26 @@ add_return (location *loc, { gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED); + tree modify_retval = NULL; tree return_type = TREE_TYPE (TREE_TYPE (m_inner_fndecl)); - tree t_lvalue = DECL_RESULT (m_inner_fndecl); - tree t_rvalue = rvalue->as_tree (); - if (TREE_TYPE (t_rvalue) != TREE_TYPE (t_lvalue)) - t_rvalue = build1 (CONVERT_EXPR, - TREE_TYPE (t_lvalue), - t_rvalue); - tree modify_retval = build2 (MODIFY_EXPR, return_type, - t_lvalue, t_rvalue); + if (rvalue) + { + tree t_lvalue = DECL_RESULT (m_inner_fndecl); + tree t_rvalue = rvalue->as_tree (); + if (TREE_TYPE (t_rvalue) != TREE_TYPE (t_lvalue)) + t_rvalue = build1 (CONVERT_EXPR, + TREE_TYPE (t_lvalue), + t_rvalue); + modify_retval = build2 (MODIFY_EXPR, return_type, + t_lvalue, t_rvalue); + if (loc) + set_tree_location (modify_retval, loc); + } tree return_stmt = build1 (RETURN_EXPR, return_type, modify_retval); if (loc) - { - set_tree_location (modify_retval, loc); - set_tree_location (return_stmt, loc); - } + set_tree_location (return_stmt, loc); + add_stmt (return_stmt); } diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h index db01053..95a8c71 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -329,6 +329,7 @@ namespace gccjit void add_return (rvalue rvalue, location loc = location ()); + void add_return (location loc = location ()); /* A way to add a function call to the body of a function being defined, with various numbers of args. */ @@ -1213,6 +1214,13 @@ function::add_return (rvalue rvalue, rvalue.get_inner_rvalue ()); } +inline void +function::add_return (location loc) +{ + gcc_jit_function_add_void_return (get_inner_function (), + loc.get_inner_location ()); +} + inline rvalue function::add_call (function other, location loc) diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 7226d81..3493518 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -1108,6 +1108,23 @@ gcc_jit_function_add_return (gcc_jit_function *func, return func->add_return (loc, rvalue); } +void +gcc_jit_function_add_void_return (gcc_jit_function *func, + gcc_jit_location *loc) +{ + RETURN_IF_NOT_FUNC_DEFINITION (func); + gcc::jit::recording::context *ctxt = func->m_ctxt; + RETURN_IF_FAIL_PRINTF2 ( + func->get_return_type () == ctxt->get_type (GCC_JIT_TYPE_VOID), + ctxt, + "mismatching types:" + " void return in function %s (return type: %s)", + func->get_debug_string (), + func->get_return_type ()->get_debug_string ()); + + return func->add_return (loc, NULL); +} + gcc_jit_loop * gcc_jit_function_new_loop (gcc_jit_function *func, gcc_jit_location *loc, diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index f6fbcdf..9fe9b61 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -862,6 +862,17 @@ gcc_jit_function_add_return (gcc_jit_function *func, gcc_jit_location *loc, gcc_jit_rvalue *rvalue); +/* Add a valueless return, for use within a function with + "void" return type. + + This is equivalent to this C code: + + return; +*/ +extern void +gcc_jit_function_add_void_return (gcc_jit_function *func, + gcc_jit_location *loc); + /* Helper function for creating a loop: while (boolval) { diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 3a5bb10..13d9619 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -43,6 +43,7 @@ gcc_jit_function_add_jump; gcc_jit_function_add_label; gcc_jit_function_add_return; + gcc_jit_function_add_void_return; gcc_jit_function_as_object; gcc_jit_function_get_param; gcc_jit_function_new_forward_label; diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit index 0299115..b8619e6 100644 --- a/gcc/testsuite/ChangeLog.jit +++ b/gcc/testsuite/ChangeLog.jit @@ -1,3 +1,11 @@ +2014-02-25 David Malcolm <dmalc...@redhat.com> + + * jit.dg/test-functions.c (create_use_of_void_return): New, to add + test coverage for gcc_jit_function_add_void_return. + (verify_void_return): Likewise. + (create_code): Add call to create_use_of_void_return. + (verify_code): Add call to verify_void_return. + 2014-02-18 David Malcolm <dmalc...@redhat.com> * jit.dg/test-accessing-struct.c (create_code): Update for change to diff --git a/gcc/testsuite/jit.dg/test-functions.c b/gcc/testsuite/jit.dg/test-functions.c index 03f7590..d82995c 100644 --- a/gcc/testsuite/jit.dg/test-functions.c +++ b/gcc/testsuite/jit.dg/test-functions.c @@ -119,10 +119,56 @@ create_use_of_builtins (gcc_jit_context *ctxt) create_test_of_builtin_trig (ctxt); } +static void +create_use_of_void_return (gcc_jit_context *ctxt) +{ + /* Let's try to inject the equivalent of: + void + test_of_void_return (int *out) + { + *out = 1; + return; + *out = 2; + } + where the second assignment is unreachable. + */ + gcc_jit_type *void_t = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + gcc_jit_type *int_t = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_type *int_ptr_t = + gcc_jit_type_get_pointer (int_t); + + /* Build the test_fn. */ + gcc_jit_param *param_out = + gcc_jit_context_new_param (ctxt, NULL, int_ptr_t, "out"); + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_t, + "test_of_void_return", + 1, ¶m_out, + 0); + gcc_jit_function_add_assignment ( + test_fn, NULL, + /* "*out = ..." */ + gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (param_out), + NULL), + gcc_jit_context_one (ctxt, int_t)); + gcc_jit_function_add_void_return (test_fn, NULL); + gcc_jit_function_add_assignment ( + test_fn, NULL, + /* "*out = ..." */ + gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (param_out), + NULL), + gcc_jit_context_new_rvalue_from_int (ctxt, int_t, 2)); +} + void create_code (gcc_jit_context *ctxt, void *user_data) { create_use_of_builtins (ctxt); + create_use_of_void_return (ctxt); } static void @@ -168,8 +214,24 @@ verify_use_of_builtins (gcc_jit_context *ctxt, gcc_jit_result *result) verify_test_of_builtin_trig (ctxt, result); } +static void +verify_void_return (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + typedef void (*fn_type) (int *); + CHECK_NON_NULL (result); + + fn_type test_of_void_return = + (fn_type)gcc_jit_result_get_code (result, "test_of_void_return"); + CHECK_NON_NULL (test_of_void_return); + + int i; + test_of_void_return (&i); + CHECK_VALUE (i, 1); /* ensure correct value was written back */ +} + void verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) { verify_use_of_builtins (ctxt, result); + verify_void_return (ctxt, result); } -- 1.7.11.7