This patch adds a new entrypoint to libgccjit:
gcc_jit_context_add_command_line_option
allowing client code to add arbitrary command-line options without
needing to recompile libgccjit.so
This is the first new entrypoint since the initial release of
libgccjit, so the patch also adds symbol-versioning to libgccjit.so,
putting all existing symbols within LIBGCCJIT_ABI_0, adding the new
symbol within LIBGCCJIT_ABI_1. It adds a discussion of API/ABI
stability to the documentation.
Tested with manually running old client binaries against a new
libgccjit.so, and via "make check-jit"; jit.sum goes from 8014 to
8039 passes.
Committed to trunk as r225205.
gcc/jit/ChangeLog:
PR jit/66628
* docs/cp/topics/contexts.rst (Additional command-line options):
New section.
* docs/topics/compatibility.rst: New file.
* docs/topics/contexts.rst (Additional command-line options): New
section.
* docs/topics/index.rst: Add compatibility.rst.
* docs/_build/texinfo/libgccjit.texi: Regenerate.
* jit-playback.c (make_fake_args): Add call to
append_command_line_options.
* jit-recording.c: Within namespace gcc::jit...
(recording::context::~context): Free the optnames within
m_command_line_options.
(recording::context::set_bool_option): Likewise.
(recording::context::add_command_line_option): New method.
(recording::context::append_command_line_options): New method.
(recording::context::dump_reproducer_to_file): Add command-line
options.
* jit-recording.h: Within namespace gcc::jit...
(recording::context::add_command_line_option): New method.
(recording::context::append_command_line_options): New method.
(recording::context::m_command_line_options): New field.
* libgccjit++.h (gccjit::context::add_command_line_option): New
method.
* libgccjit.c (gcc_jit_context_add_command_line_option): New API
entrypoint.
* libgccjit.h (gcc_jit_context_add_command_line_option): New API
entrypoint.
(LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option): New
macro.
* libgccjit.map: Put existing symbols within LIBGCCJIT_ABI_0; add
LIBGCCJIT_ABI_1 and gcc_jit_context_add_command_line_option.
gcc/testsuite/ChangeLog:
PR jit/66628
* jit.dg/all-non-failing-tests.h: Add note about
test-extra-options.c.
* jit.dg/test-extra-options.c: New testcase.
---
gcc/jit/docs/cp/topics/contexts.rst | 19 ++++
gcc/jit/docs/topics/compatibility.rst | 90 ++++++++++++++++++
gcc/jit/docs/topics/contexts.rst | 36 +++++++
gcc/jit/docs/topics/index.rst | 1 +
gcc/jit/jit-playback.c | 4 +
gcc/jit/jit-recording.c | 42 +++++++++
gcc/jit/jit-recording.h | 7 ++
gcc/jit/libgccjit++.h | 8 ++
gcc/jit/libgccjit.c | 19 ++++
gcc/jit/libgccjit.h | 23 +++++
gcc/jit/libgccjit.map | 11 ++-
gcc/testsuite/jit.dg/all-non-failing-tests.h | 3 +
gcc/testsuite/jit.dg/test-extra-options.c | 136 +++++++++++++++++++++++++++
13 files changed, 398 insertions(+), 1 deletion(-)
create mode 100644 gcc/jit/docs/topics/compatibility.rst
create mode 100644 gcc/testsuite/jit.dg/test-extra-options.c
diff --git a/gcc/jit/docs/cp/topics/contexts.rst
b/gcc/jit/docs/cp/topics/contexts.rst
index 12a4e50..b26a29d 100644
--- a/gcc/jit/docs/cp/topics/contexts.rst
+++ b/gcc/jit/docs/cp/topics/contexts.rst
@@ -196,3 +196,22 @@ Integer options
This is a thin wrapper around the C API
:c:func:`gcc_jit_context_set_int_option`; the options have the same
meaning.
+
+Additional command-line options
+*******************************
+
+.. function:: void \
+ gccjit::context::add_command_line_option (const char *optname)
+
+ Add an arbitrary gcc command-line option to the context for use
+ when compiling.
+
+ This is a thin wrapper around the C API
+ :c:func:`gcc_jit_context_add_command_line_option`.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_1`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
diff --git a/gcc/jit/docs/topics/compatibility.rst
b/gcc/jit/docs/topics/compatibility.rst
new file mode 100644
index 0000000..dff1d0b
--- /dev/null
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -0,0 +1,90 @@
+.. Copyright (C) 2015 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+ABI and API compatibility
+=========================
+
+The libgccjit developers strive for ABI and API backward-compatibility:
+programs built against libgccjit.so stand a good chance of running
+without recompilation against newer versions of libgccjit.so, and
+ought to recompile without modification against newer versions of
+libgccjit.h.
+
+.. note:: The libgccjit++.h C++ API is more experimental, and less
+ locked-down at this time.
+
+API compatibility is achieved by extending the API rather than changing
+it. For ABI compatiblity, we avoid bumping the SONAME, and instead use
+symbol versioning to tag each symbol, so that a binary linked against
+libgccjit.so is tagged according to the symbols that it uses.
+
+For example, :func:`gcc_jit_context_add_command_line_option` was added in
+``LIBGCCJIT_ABI_1``. If a client program uses it, this can be detected
+from metadata by using ``objdump``:
+
+.. code-block:: bash
+
+ $ objdump -p testsuite/jit/test-extra-options.c.exe | tail -n 8
+
+ Version References:
+ required from libgccjit.so.0:
+ 0x00824161 0x00 04 LIBGCCJIT_ABI_1
+ 0x00824160 0x00 03 LIBGCCJIT_ABI_0
+ required from libc.so.6:
+ 0x09691a75 0x00 02 GLIBC_2.2.5
+
+You can see the symbol tags provided by libgccjit.so using ``objdump``:
+
+.. code-block:: bash
+
+ $ objdump -p libgccjit.so | less
+ [...snip...]
+ Version definitions:
+ 1 0x01 0x0ff81f20 libgccjit.so.0
+ 2 0x00 0x00824160 LIBGCCJIT_ABI_0
+ 3 0x00 0x00824161 LIBGCCJIT_ABI_1
+ LIBGCCJIT_ABI_0
+ [...snip...]
+
+ABI symbol tags
+***************
+
+The initial release of libgccjit (in gcc 5.1) did not use symbol versioning.
+
+Newer releases use the following tags.
+
+.. _LIBGCCJIT_ABI_0:
+
+``LIBGCCJIT_ABI_0``
+-------------------
+
+All entrypoints in the initial release of libgccjit are tagged with
+``LIBGCCJIT_ABI_0``, to signify the transition to symbol versioning.
+
+Binaries built against older copies of ``libgccjit.so`` should
+continue to work, with this being handled transparently by the linker
+(see `this post
+<https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02126.html>`_)
+
+.. _LIBGCCJIT_ABI_1:
+
+``LIBGCCJIT_ABI_1``
+-------------------
+``LIBGCCJIT_ABI_1`` covers the addition of
+:func:`gcc_jit_context_add_command_line_option`
diff --git a/gcc/jit/docs/topics/contexts.rst b/gcc/jit/docs/topics/contexts.rst
index b3d42d9..401cbf1 100644
--- a/gcc/jit/docs/topics/contexts.rst
+++ b/gcc/jit/docs/topics/contexts.rst
@@ -465,3 +465,39 @@ Integer options
-O0 through -O3.
The default value is 0 (unoptimized).
+
+Additional command-line options
+*******************************
+
+.. function:: void gcc_jit_context_add_command_line_option (gcc_jit_context
*ctxt,\
+ const char
*optname)
+
+ Add an arbitrary gcc command-line option to the context, for use
+ by :func:`gcc_jit_context_compile` and
+ :func:`gcc_jit_context_compile_to_file`.
+
+ The parameter ``optname`` must be non-NULL. The underlying buffer is
+ copied, so that it does not need to outlive the call.
+
+ Extra options added by `gcc_jit_context_add_command_line_option` are
+ applied *after* the regular options above, potentially overriding them.
+ Options from parent contexts are inherited by child contexts; options
+ from the parent are applied *before* those from the child.
+
+ For example:
+
+ .. code-block:: c
+
+ gcc_jit_context_add_command_line_option (ctxt, "-ffast-math");
+ gcc_jit_context_add_command_line_option (ctxt, "-fverbose-asm");
+
+ Note that only some options are likely to be meaningful; there is no
+ "frontend" within libgccjit, so typically only those affecting
+ optimization and code-generation are likely to be useful.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_1`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
diff --git a/gcc/jit/docs/topics/index.rst b/gcc/jit/docs/topics/index.rst
index 4ebb623..76b3d0b 100644
--- a/gcc/jit/docs/topics/index.rst
+++ b/gcc/jit/docs/topics/index.rst
@@ -28,3 +28,4 @@ Topic Reference
functions.rst
locations.rst
compilation.rst
+ compatibility.rst
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 0f5013c..95ebfe0 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -2141,6 +2141,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
}
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 11b9739..3d7d571 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -517,6 +517,10 @@ recording::context::~context ()
for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
free (m_str_options[i]);
+ char *optname;
+ FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
+ free (optname);
+
if (m_builtins_manager)
delete m_builtins_manager;
@@ -1137,6 +1141,33 @@ recording::context::set_bool_option (enum
gcc_jit_bool_option opt,
log_bool_option (opt);
}
+/* Add the given optname to this context's list of extra options.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_add_command_line_option. */
+
+void
+recording::context::add_command_line_option (const char *optname)
+{
+ m_command_line_options.safe_push (xstrdup (optname));
+}
+
+/* Add any user-provided extra options, starting with any from
+ parent contexts.
+ Called by playback::context::make_fake_args. */
+
+void
+recording::context::append_command_line_options (vec <char *> *argvec)
+{
+ if (m_parent_ctxt)
+ m_parent_ctxt->append_command_line_options (argvec);
+
+ int i;
+ char *optname;
+ FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
+ argvec->safe_push (xstrdup (optname));
+}
+
/* Add the given dumpname/out_ptr pair to this context's list of requested
dumps.
@@ -1593,6 +1624,17 @@ recording::context::dump_reproducer_to_file (const char
*path)
bool_option_reproducer_strings[opt_idx],
m_bool_options[opt_idx]);
+ if (!m_command_line_options.is_empty ())
+ {
+ int i;
+ char *optname;
+ r.write (" /* User-provided command-line options. */\n");
+ FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
+ r.write (" gcc_jit_context_add_command_line_option (%s,
\"%s\");\n",
+ r.get_identifier (contexts[ctxt_idx]),
+ optname);
+ }
+
if (m_requested_dumps.length ())
{
r.write (" /* Requested dumps. */\n");
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index d3170fe..8cd2289 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -196,6 +196,12 @@ public:
int value);
void
+ add_command_line_option (const char *optname);
+
+ void
+ append_command_line_options (vec <char *> *argvec);
+
+ void
enable_dump (const char *dumpname,
char **out_ptr);
@@ -281,6 +287,7 @@ private:
char *m_str_options[GCC_JIT_NUM_STR_OPTIONS];
int m_int_options[GCC_JIT_NUM_INT_OPTIONS];
bool m_bool_options[GCC_JIT_NUM_BOOL_OPTIONS];
+ auto_vec <char *> m_command_line_options;
/* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
auto_vec<requested_dump> m_requested_dumps;
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index 62ef6a4..a5353ca 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -120,6 +120,8 @@ namespace gccjit
void set_bool_option (enum gcc_jit_bool_option opt,
int value);
+ void add_command_line_option (const char *optname);
+
location
new_location (const std::string &filename,
int line,
@@ -603,6 +605,12 @@ context::set_bool_option (enum gcc_jit_bool_option opt,
}
+inline void
+context::add_command_line_option (const char *optname)
+{
+ gcc_jit_context_add_command_line_option (m_inner_ctxt, optname);
+}
+
inline location
context::new_location (const std::string &filename,
int line,
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index dedf942..44791ab 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -2185,6 +2185,25 @@ gcc_jit_context_set_bool_option (gcc_jit_context *ctxt,
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
+ gcc::jit::recording::context::add_command_line_option method in
+ jit-recording.c. */
+
+void
+gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt,
+ const char *optname)
+{
+ RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ RETURN_IF_FAIL (optname, ctxt, NULL, "NULL optname");
+ if (ctxt->get_logger ())
+ ctxt->get_logger ()->log ("optname: %s", optname);
+
+ ctxt->add_command_line_option (optname);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
gcc::jit::recording::context::enable_dump method in
jit-recording.c. */
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 767e9e3..2c1a99a 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -243,6 +243,29 @@ gcc_jit_context_set_bool_option (gcc_jit_context *ctxt,
enum gcc_jit_bool_option opt,
int value);
+/* Add an arbitrary gcc command-line option to the context.
+ The context takes a copy of the string, so the
+ (const char *) optname is not needed anymore after the call
+ returns.
+
+ Note that only some options are likely to be meaningful; there is no
+ "frontend" within libgccjit, so typically only those affecting
+ optimization and code-generation are likely to be useful.
+
+ This entrypoint was added in LIBGCCJIT_ABI_1; you can test for
+ its presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
+*/
+
+extern void
+gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt,
+ const char *optname);
+
+/* Pre-canned feature-test macro for detecting the presence of
+ gcc_jit_context_add_command_line_option within libgccjit.h. */
+
+#define LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
+
/* Compile the context to in-memory machine code.
This can be called more that once on a given context,
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 89bd57be4..a42bc74 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -17,6 +17,9 @@
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>. */
+
+# The initial release of the library.
+LIBGCCJIT_ABI_0
{
global:
# Keep this list sorted alphabetically:
@@ -104,4 +107,10 @@
gcc_jit_type_get_volatile;
local: *;
-};
\ No newline at end of file
+};
+
+# Add support for adding arbitrary command-line options (PR jit/66628).
+LIBGCCJIT_ABI_1 {
+ global:
+ gcc_jit_context_add_command_line_option;
+} LIBGCCJIT_ABI_0;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h
b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index c9bbb34..8584555 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -95,6 +95,9 @@
#undef create_code
#undef verify_code
+/* test-extra-options.c: We don't use this one, since the extra options
+ affect the whole context. */
+
/* test-factorial.c */
#define create_code create_code_factorial
#define verify_code verify_code_factorial
diff --git a/gcc/testsuite/jit.dg/test-extra-options.c
b/gcc/testsuite/jit.dg/test-extra-options.c
new file mode 100644
index 0000000..3739834
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-extra-options.c
@@ -0,0 +1,136 @@
+/* Testcase for gcc_jit_context_add_command_line_option (PR jit/66628). */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+#ifndef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
+#error LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option was not defined
+#endif
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ gcc_jit_context_add_command_line_option (ctxt, "-ffast-math");
+ gcc_jit_context_add_command_line_option (ctxt, "-fverbose-asm");
+
+ /* Let's try to inject the equivalent of:
+
+ double
+ my_dot_product (int n, double *a, double *b)
+ {
+ double result = 0.;
+ for (int i = 0; i < n; i++)
+ result += a[i] * b[i];
+ return result
+ }
+
+ and see what the optimizer can do. */
+ gcc_jit_type *val_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+ gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (val_type);
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+ gcc_jit_type *return_type = val_type;
+ gcc_jit_param *param_n =
+ gcc_jit_context_new_param (ctxt, NULL, int_type, "n");
+ gcc_jit_param *param_a =
+ gcc_jit_context_new_param (ctxt, NULL, ptr_type, "a");
+ gcc_jit_param *param_b =
+ gcc_jit_context_new_param (ctxt, NULL, ptr_type, "b");
+ gcc_jit_param *params[3] = {param_n, param_a, param_b};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "my_dot_product",
+ 3, params, 0);
+
+ gcc_jit_block *initial = gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block *loop_test = gcc_jit_function_new_block (func, "loop_test");
+ gcc_jit_block *loop_body = gcc_jit_function_new_block (func, "loop_body");
+ gcc_jit_block *final = gcc_jit_function_new_block (func, "final");
+
+ /* Build: "double result = 0.;" */
+ gcc_jit_lvalue *result =
+ gcc_jit_function_new_local (func, NULL, val_type, "result");
+
+ gcc_jit_block_add_assignment (initial, NULL,
+ result, gcc_jit_context_zero (ctxt, val_type));
+
+ /* Build: "for (int i = 0; i < n; i++)" */
+ gcc_jit_lvalue *i =
+ gcc_jit_function_new_local (func, NULL, int_type, "i");
+ gcc_jit_block_add_assignment (initial, NULL,
+ i, gcc_jit_context_zero (ctxt, int_type));
+
+ gcc_jit_block_end_with_jump (initial, NULL, loop_test);
+
+ gcc_jit_block_end_with_conditional (
+ loop_test, NULL,
+
+ /* (i < n) */
+ gcc_jit_context_new_comparison (
+ ctxt, NULL,
+ GCC_JIT_COMPARISON_LT,
+ gcc_jit_lvalue_as_rvalue (i),
+ gcc_jit_param_as_rvalue (param_n)),
+
+ loop_body,
+ final);
+
+ /* Build: "result += a[i] * b[i];" */
+ gcc_jit_block_add_assignment_op (
+ loop_body, NULL,
+ result,
+ GCC_JIT_BINARY_OP_PLUS,
+ gcc_jit_context_new_binary_op (
+ ctxt, NULL,
+ GCC_JIT_BINARY_OP_MULT,
+ val_type,
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_context_new_array_access (
+ ctxt, NULL,
+ gcc_jit_param_as_rvalue (param_a),
+ gcc_jit_lvalue_as_rvalue (i))),
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_context_new_array_access (
+ ctxt, NULL,
+ gcc_jit_param_as_rvalue (param_b),
+ gcc_jit_lvalue_as_rvalue (i)))));
+
+ /* Build: "i++" */
+ gcc_jit_block_add_assignment_op (
+ loop_body, NULL,
+ i,
+ GCC_JIT_BINARY_OP_PLUS,
+ gcc_jit_context_one (ctxt, int_type));
+
+ gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
+
+ /* Build: "return result;" */
+ gcc_jit_block_end_with_return (
+ final,
+ NULL,
+ gcc_jit_lvalue_as_rvalue (result));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef double (*my_dot_product_fn_type) (int n, double *a, double *b);
+ CHECK_NON_NULL (result);
+
+ my_dot_product_fn_type my_dot_product =
+ (my_dot_product_fn_type)gcc_jit_result_get_code (result,
+ "my_dot_product");
+ CHECK_NON_NULL (my_dot_product);
+ double test_array[] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
+ double val = my_dot_product (10, test_array, test_array);
+ note ("my_dot_product returned: %f", val);
+ CHECK_VALUE (val, 385.0);
+}
--
1.8.5.3