Committed to branch dmalcolm/jit: gcc/jit/ * libgccjit.h (enum gcc_jit_function_kind): Add GCC_JIT_FUNCTION_ALWAYS_INLINE. * internal-api.c (gcc::jit::recording::function::write_to_dump): Handle GCC_JIT_FUNCTION_ALWAYS_INLINE. (gcc::jit::playback::context::new_function): Likewise. (gcc::jit::playback::context::postprocess): Handle GCC_JIT_FUNCTION_INTERNAL and GCC_JIT_FUNCTION_ALWAYS_INLINE by clearing DECL_EXTERNAL and TREE_PUBLIC. Doing so fixes the "undefined symbol" bug seen with GCC_JIT_FUNCTION_INTERNAL. * TODO.rst: Update.
gcc/testsuite/ * jit.dg/test-functions.c (create_test_of_hidden_function): New, adding test coverage for GCC_JIT_FUNCTION_ALWAYS_INLINE and GCC_JIT_FUNCTION_INTERNAL. (create_tests_of_hidden_functions): Likewise. (verify_hidden_functions): Likewise. (create_code): Add call to create_tests_of_hidden_functions. (verify_code): Add call to verify_hidden_functions. * jit.dg/test-quadratic.c (make_calc_discriminant): Convert from GCC_JIT_FUNCTION_EXPORTED to GCC_JIT_FUNCTION_INTERNAL. --- gcc/jit/ChangeLog.jit | 13 +++++ gcc/jit/TODO.rst | 5 -- gcc/jit/internal-api.c | 21 +++++++ gcc/jit/libgccjit.h | 12 +++- gcc/testsuite/ChangeLog.jit | 12 ++++ gcc/testsuite/jit.dg/test-functions.c | 107 ++++++++++++++++++++++++++++++++++ gcc/testsuite/jit.dg/test-quadratic.c | 4 +- 7 files changed, 166 insertions(+), 8 deletions(-) diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit index ef820ea..223fd6a 100644 --- a/gcc/jit/ChangeLog.jit +++ b/gcc/jit/ChangeLog.jit @@ -1,5 +1,18 @@ 2014-03-07 David Malcolm <dmalc...@redhat.com> + * libgccjit.h (enum gcc_jit_function_kind): Add + GCC_JIT_FUNCTION_ALWAYS_INLINE. + * internal-api.c (gcc::jit::recording::function::write_to_dump): + Handle GCC_JIT_FUNCTION_ALWAYS_INLINE. + (gcc::jit::playback::context::new_function): Likewise. + (gcc::jit::playback::context::postprocess): Handle + GCC_JIT_FUNCTION_INTERNAL and GCC_JIT_FUNCTION_ALWAYS_INLINE by + clearing DECL_EXTERNAL and TREE_PUBLIC. Doing so fixes the + "undefined symbol" bug seen with GCC_JIT_FUNCTION_INTERNAL. + * TODO.rst: Update. + +2014-03-07 David Malcolm <dmalc...@redhat.com> + * libgccjit++.h (gccjit::context::new_global): New. 2014-03-07 David Malcolm <dmalc...@redhat.com> diff --git a/gcc/jit/TODO.rst b/gcc/jit/TODO.rst index ea09e45..b2d8c04 100644 --- a/gcc/jit/TODO.rst +++ b/gcc/jit/TODO.rst @@ -114,11 +114,6 @@ Initial Release Bugs ==== -* INTERNAL functions don't seem to work (see e.g. test-quadratic, on trying - to make calc_disc be internal leads to: - /tmp/libgccjit-4FZm6B/fake.so: undefined symbol: calc_discriminant - works at -O3 (because it inlines away the call); fails at -O0 - * fixing all the state issues: make it work repeatedly with optimization turned up to full. diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c index 1cb15ce..17c8e9e 100644 --- a/gcc/jit/internal-api.c +++ b/gcc/jit/internal-api.c @@ -1317,6 +1317,9 @@ recording::function::write_to_dump (dump &d) case GCC_JIT_FUNCTION_INTERNAL: d.write ("static "); break; + case GCC_JIT_FUNCTION_ALWAYS_INLINE: + d.write ("static inline "); + break; } d.write ("%s\n", m_return_type->get_debug_string ()); @@ -2534,6 +2537,17 @@ new_function (location *loc, DECL_ARGUMENTS(fndecl) = param_decl_list; } + if (kind == GCC_JIT_FUNCTION_ALWAYS_INLINE) + { + DECL_DECLARED_INLINE_P (fndecl) = 1; + + /* Add attribute "always_inline": */ + DECL_ATTRIBUTES (fndecl) = + tree_cons (get_identifier ("always_inline"), + NULL, + DECL_ATTRIBUTES (fndecl)); + } + function *func = new function (this, fndecl, kind); m_functions.safe_push (func); return func; @@ -3195,6 +3209,13 @@ postprocess () DECL_PRESERVE_P (m_inner_fndecl) = 1; } + if (m_kind == GCC_JIT_FUNCTION_INTERNAL + ||m_kind == GCC_JIT_FUNCTION_ALWAYS_INLINE) + { + DECL_EXTERNAL (m_inner_fndecl) = 0; + TREE_PUBLIC (m_inner_fndecl) = 0; + } + if (m_kind != GCC_JIT_FUNCTION_IMPORTED) { /* Seem to need this in gimple-low.c: */ diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index e8f35b9..3019449 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -468,8 +468,18 @@ enum gcc_jit_function_kind /* Function is not defined by the client code; we're merely referring to it. Analogous to using an "extern" function from a header file. */ - GCC_JIT_FUNCTION_IMPORTED + GCC_JIT_FUNCTION_IMPORTED, + /* Function is only ever inlined into other functions, and is + invisible outside of the JIT. + + Analogous to prefixing with "inline" and adding + __attribute__((always_inline)). + + Inlining will only occur when the optimization level is + above 0; when optimization is off, this is essentially the + same as GCC_JIT_FUNCTION_INTERNAL. */ + GCC_JIT_FUNCTION_ALWAYS_INLINE }; diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit index 08fe76c..ec8af3d 100644 --- a/gcc/testsuite/ChangeLog.jit +++ b/gcc/testsuite/ChangeLog.jit @@ -1,5 +1,17 @@ 2014-03-07 David Malcolm <dmalc...@redhat.com> + * jit.dg/test-functions.c (create_test_of_hidden_function): New, + adding test coverage for GCC_JIT_FUNCTION_ALWAYS_INLINE and + GCC_JIT_FUNCTION_INTERNAL. + (create_tests_of_hidden_functions): Likewise. + (verify_hidden_functions): Likewise. + (create_code): Add call to create_tests_of_hidden_functions. + (verify_code): Add call to verify_hidden_functions. + * jit.dg/test-quadratic.c (make_calc_discriminant): Convert + from GCC_JIT_FUNCTION_EXPORTED to GCC_JIT_FUNCTION_INTERNAL. + +2014-03-07 David Malcolm <dmalc...@redhat.com> + * jit.dg/test-functions.c: Reorder function definitions, grouping them by subject-matter rather than by create-vs-verify phase. diff --git a/gcc/testsuite/jit.dg/test-functions.c b/gcc/testsuite/jit.dg/test-functions.c index b3e3251..3d03ada 100644 --- a/gcc/testsuite/jit.dg/test-functions.c +++ b/gcc/testsuite/jit.dg/test-functions.c @@ -7,6 +7,111 @@ #include "harness.h" /********************************************************************** + GCC_JIT_FUNCTION_ALWAYS_INLINE and GCC_JIT_FUNCTION_INTERNAL + **********************************************************************/ +static void +create_test_of_hidden_function (gcc_jit_context *ctxt, + enum gcc_jit_function_kind hidden_kind, + const char *hidden_func_name, + const char *visible_func_name) +{ + /* Let's try to inject the equivalent of: + static double hidden_mult (double a, double b) + { + return x * x; + } + double my_square (double x) + { + return my_mult (x, x); + } + + where hidden_mult can potentially be + inline __attribute__((always_inline)). */ + gcc_jit_type *double_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE); + + /* Create "my_mult" */ + gcc_jit_param *param_a = + gcc_jit_context_new_param (ctxt, NULL, double_type, "a"); + gcc_jit_param *param_b = + gcc_jit_context_new_param (ctxt, NULL, double_type, "b"); + gcc_jit_param *params[2] = {param_a, param_b}; + gcc_jit_function *my_mult = + gcc_jit_context_new_function (ctxt, NULL, + hidden_kind, + double_type, + hidden_func_name, + 2, params, + 0); + gcc_jit_block *body_of_my_mult = + gcc_jit_function_new_block (my_mult, NULL); + gcc_jit_block_end_with_return ( + body_of_my_mult, NULL, + gcc_jit_context_new_binary_op ( + ctxt, NULL, + GCC_JIT_BINARY_OP_MULT, + double_type, + gcc_jit_param_as_rvalue (param_a), + gcc_jit_param_as_rvalue (param_b))); + + /* Create "my_square" */ + gcc_jit_param *param_x = + gcc_jit_context_new_param (ctxt, NULL, double_type, "x"); + gcc_jit_function *my_square = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + double_type, + visible_func_name, + 1, ¶m_x, + 0); + gcc_jit_block *body_of_my_square = + gcc_jit_function_new_block (my_square, NULL); + gcc_jit_rvalue *args[2] = {gcc_jit_param_as_rvalue (param_x), + gcc_jit_param_as_rvalue (param_x)}; + gcc_jit_block_end_with_return ( + body_of_my_square, NULL, + gcc_jit_context_new_call ( + ctxt, NULL, + my_mult, + 2, args)); +} + +static void +create_tests_of_hidden_functions (gcc_jit_context *ctxt) +{ + create_test_of_hidden_function (ctxt, + GCC_JIT_FUNCTION_INTERNAL, + "my_internal_mult", + "my_square_with_internal"); + create_test_of_hidden_function (ctxt, + GCC_JIT_FUNCTION_ALWAYS_INLINE, + "my_always_inline_mult", + "my_square_with_always_inline"); +} + +static void +verify_hidden_functions (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_NON_NULL (result); + + /* GCC_JIT_FUNCTION_INTERNAL and GCC_JIT_FUNCTION_ALWAYS_INLINE + functions should not be accessible in the result. */ + CHECK_VALUE (NULL, gcc_jit_result_get_code (result, "my_internal_mult")); + CHECK_VALUE (NULL, gcc_jit_result_get_code (result, "my_always_inline_mult")); + + typedef double (*fn_type) (double); + fn_type my_square_with_internal = + (fn_type)gcc_jit_result_get_code (result, "my_square_with_internal"); + CHECK_NON_NULL (my_square_with_internal); + CHECK_VALUE (my_square_with_internal (5.0), 25.0); + + fn_type my_square_with_always_inline = + (fn_type)gcc_jit_result_get_code (result, "my_square_with_always_inline"); + CHECK_NON_NULL (my_square_with_always_inline); + CHECK_VALUE (my_square_with_always_inline (5.0), 25.0); +} + +/********************************************************************** Builtin functions **********************************************************************/ @@ -236,6 +341,7 @@ verify_void_return (gcc_jit_context *ctxt, gcc_jit_result *result) void create_code (gcc_jit_context *ctxt, void *user_data) { + create_tests_of_hidden_functions (ctxt); create_use_of_builtins (ctxt); create_use_of_void_return (ctxt); } @@ -244,6 +350,7 @@ create_code (gcc_jit_context *ctxt, void *user_data) void verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) { + verify_hidden_functions (ctxt, result); verify_use_of_builtins (ctxt, result); verify_void_return (ctxt, result); } diff --git a/gcc/testsuite/jit.dg/test-quadratic.c b/gcc/testsuite/jit.dg/test-quadratic.c index b984445..715174c 100644 --- a/gcc/testsuite/jit.dg/test-quadratic.c +++ b/gcc/testsuite/jit.dg/test-quadratic.c @@ -17,7 +17,7 @@ struct quadratic extern double sqrt (double); - void + static void calc_discriminant (struct quadratic *q) { // (b^2 - 4ac) @@ -149,7 +149,7 @@ make_calc_discriminant (struct quadratic_test *testcase) testcase->quadratic_ptr, "q"); testcase->calc_discriminant = gcc_jit_context_new_function (testcase->ctxt, NULL, - GCC_JIT_FUNCTION_EXPORTED, + GCC_JIT_FUNCTION_INTERNAL, testcase->void_type, "calc_discriminant", 1, ¶m_q, -- 1.7.11.7