This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[jit] Add GCC_JIT_FUNCTION_ALWAYS_INLINE and fix GCC_JIT_FUNCTION_INTERNAL.
- From: David Malcolm <dmalcolm at redhat dot com>
- To: jit at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Cc: David Malcolm <dmalcolm at redhat dot com>
- Date: Fri, 7 Mar 2014 14:54:07 -0500
- Subject: [jit] Add GCC_JIT_FUNCTION_ALWAYS_INLINE and fix GCC_JIT_FUNCTION_INTERNAL.
- Authentication-results: sourceware.org; auth=none
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 <dmalcolm@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 <dmalcolm@redhat.com>
+
* libgccjit++.h (gccjit::context::new_global): New.
2014-03-07 David Malcolm <dmalcolm@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 <dmalcolm@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 <dmalcolm@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