diff mbox

[2/2] jit: use an embedded copy of the driver

Message ID 1438872724-18658-3-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm Aug. 6, 2015, 2:52 p.m. UTC
This patch requires the previous one, and would be committed with it;
I've split them up for ease of review.

This is an updated version of the second part of:
  https://gcc.gnu.org/ml/gcc-patches/2015-06/msg00123.html
with various cleanups; in particular, providing a boolean
option to support reverting back to using an external driver
in case this is useful for debugging.

gcc/jit/ChangeLog:
	* docs/cp/topics/contexts.rst
	(gccjit::context::set_bool_use_external_driver): New.
	* docs/internals/test-hello-world.exe.log.txt: Update.
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_5): New.
	* docs/topics/contexts.rst
	(gcc_jit_context_set_bool_use_external_driver): New.
	* jit-common.h (enum inner_bool_option): Add
	INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER.
	* jit-playback.c (gcc_driver_name): New global.
	(gcc:jit::playback::context::invoke_driver): Split out second
	half into...
	(gcc::jit::playback::context::invoke_embedded_driver): ...this new
	function, and...
	(gcc::jit::playback::context::invoke_external_driver): ...this new
	function.
	* jit-playback.h
	(gcc::jit::playback::context::get_inner_bool_option): New.
	(gcc::jit::playback::context::invoke_embedded_driver): New.
	(gcc::jit::playback::context::invoke_external_driver): New.
	* jit-recording.c (inner_bool_option_reproducer_strings):
	Add entry for INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER.
	* libgccjit++.h
	(gccjit::context::set_bool_use_external_driver): New.
	* libgccjit.c (gcc_jit_context_set_bool_use_external_driver): New.
	* libgccjit.h (gcc_jit_context_set_bool_use_external_driver): New.
	(LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver):
	New.
	* libgccjit.map (LIBGCCJIT_ABI_5): New.
	* notes.txt: Show invocation of embedded copy of driver.
	* docs/internals/test-hello-world.exe.log.txt: Update

gcc/testsuite/ChangeLog:
	* jit.dg/test-error-pr63969-missing-driver.c: Add call to
	gcc_jit_context_set_bool_use_external_driver.
---
 gcc/jit/docs/cp/topics/contexts.rst                | 20 +++++++++
 .../docs/internals/test-hello-world.exe.log.txt    |  6 ++-
 gcc/jit/docs/topics/compatibility.rst              |  7 +++
 gcc/jit/docs/topics/contexts.rst                   | 20 +++++++++
 gcc/jit/jit-common.h                               |  1 +
 gcc/jit/jit-playback.c                             | 52 ++++++++++++++++++----
 gcc/jit/jit-playback.h                             | 14 ++++++
 gcc/jit/jit-recording.c                            |  3 +-
 gcc/jit/libgccjit++.h                              |  8 ++++
 gcc/jit/libgccjit.c                                | 17 +++++++
 gcc/jit/libgccjit.h                                | 24 ++++++++++
 gcc/jit/libgccjit.map                              |  5 +++
 gcc/jit/notes.txt                                  |  8 +++-
 .../jit.dg/test-error-pr63969-missing-driver.c     |  4 ++
 14 files changed, 177 insertions(+), 12 deletions(-)
diff mbox

Patch

diff --git a/gcc/jit/docs/cp/topics/contexts.rst b/gcc/jit/docs/cp/topics/contexts.rst
index 162e4ae..05ce230 100644
--- a/gcc/jit/docs/cp/topics/contexts.rst
+++ b/gcc/jit/docs/cp/topics/contexts.rst
@@ -201,6 +201,26 @@  Boolean options
 
       #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
 
+.. function:: void \
+              gccjit::context::set_bool_use_external_driver (int bool_value)
+
+   libgccjit internally generates assembler, and uses "driver" code
+   for converting it to other formats (e.g. shared libraries).
+
+   By default, libgccjit will use an embedded copy of the driver
+   code.
+
+   This option can be used to instead invoke an external driver executable
+   as a subprocess; it is a thin wrapper around the C API
+   :c:func:`gcc_jit_context_set_bool_use_external_driver`.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_5`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver
+
 Integer options
 ***************
 
diff --git a/gcc/jit/docs/internals/test-hello-world.exe.log.txt b/gcc/jit/docs/internals/test-hello-world.exe.log.txt
index d82038b..0bab86c 100644
--- a/gcc/jit/docs/internals/test-hello-world.exe.log.txt
+++ b/gcc/jit/docs/internals/test-hello-world.exe.log.txt
@@ -1,4 +1,4 @@ 
-JIT: libgccjit (GCC) version 6.0.0 20150723 (experimental) (x86_64-unknown-linux-gnu)
+JIT: libgccjit (GCC) version 6.0.0 20150803 (experimental) (x86_64-pc-linux-gnu)
 JIT:	compiled by GNU C version 4.8.3 20140911 (Red Hat 4.8.3-7), GMP version 5.1.2, MPFR version 3.1.2, MPC version 1.0.1
 JIT: entering: gcc_jit_context_set_str_option
 JIT:  GCC_JIT_STR_OPTION_PROGNAME: "./test-hello-world.c.exe"
@@ -65,6 +65,7 @@  JIT:   GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING: false
 JIT:   GCC_JIT_BOOL_OPTION_SELFCHECK_GC: true
 JIT:   GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES: false
 JIT:   gcc_jit_context_set_bool_allow_unreachable_blocks: false
+JIT:   gcc_jit_context_set_bool_use_external_driver: false
 JIT:   entering: void gcc::jit::recording::context::validate()
 JIT:   exiting: void gcc::jit::recording::context::validate()
 JIT:   entering: gcc::jit::playback::context::context(gcc::jit::recording::context*)
@@ -133,7 +134,8 @@  JIT:       argv[3]: /tmp/libgccjit-CKq1M9/fake.s
 JIT:       argv[4]: -o
 JIT:       argv[5]: /tmp/libgccjit-CKq1M9/fake.so
 JIT:       argv[6]: -fno-use-linker-plugin
-JIT:       argv[7]: (null)
+JIT:       entering: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*)
+JIT:       exiting: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*)
 JIT:      exiting: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool)
 JIT:     exiting: void gcc::jit::playback::context::convert_to_dso(const char*)
 JIT:     entering: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso()
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 0a4b453..e947cad 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -128,3 +128,10 @@  entrypoints:
   * :func:`gcc_jit_timer_pop`
 
   * :func:`gcc_jit_timer_print`
+
+.. _LIBGCCJIT_ABI_5:
+
+``LIBGCCJIT_ABI_5``
+-------------------
+``LIBGCCJIT_ABI_5`` covers the addition of
+:func:`gcc_jit_context_set_bool_use_external_driver`
diff --git a/gcc/jit/docs/topics/contexts.rst b/gcc/jit/docs/topics/contexts.rst
index 1aa319a..53ceffb 100644
--- a/gcc/jit/docs/topics/contexts.rst
+++ b/gcc/jit/docs/topics/contexts.rst
@@ -469,6 +469,26 @@  Boolean options
 
       #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
 
+.. function:: void \
+              gcc_jit_context_set_bool_use_external_driver (gcc_jit_context *ctxt, \
+                                                            int bool_value)
+
+   libgccjit internally generates assembler, and uses "driver" code
+   for converting it to other formats (e.g. shared libraries).
+
+   By default, libgccjit will use an embedded copy of the driver
+   code.
+
+   This option can be used to instead invoke an external driver executable
+   as a subprocess.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_5`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver
+
 Integer options
 ***************
 
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index e6fc132..6400f30 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -191,6 +191,7 @@  private:
 enum inner_bool_option
 {
   INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS,
+  INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER,
 
   NUM_INNER_BOOL_OPTIONS
 };
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 925fa86..8a67e4b 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -2373,6 +2373,8 @@  convert_to_dso (const char *ctxt_progname)
 		 true);/* bool run_linker */
 }
 
+static const char * const gcc_driver_name = GCC_DRIVER_NAME;
+
 void
 playback::context::
 invoke_driver (const char *ctxt_progname,
@@ -2383,15 +2385,15 @@  invoke_driver (const char *ctxt_progname,
 	       bool run_linker)
 {
   JIT_LOG_SCOPE (get_logger ());
+
+  bool embedded_driver
+    = !get_inner_bool_option (INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER);
+
   /* Currently this lumps together both assembling and linking into
      TV_ASSEMBLE.  */
   auto_timevar assemble_timevar (get_timer (), tv_id);
-  const char *errmsg;
   auto_argvec argvec;
 #define ADD_ARG(arg) argvec.safe_push (xstrdup (arg))
-  int exit_status = 0;
-  int err = 0;
-  const char *gcc_driver_name = GCC_DRIVER_NAME;
 
   ADD_ARG (gcc_driver_name);
 
@@ -2416,8 +2418,10 @@  invoke_driver (const char *ctxt_progname,
      time.  */
   ADD_ARG ("-fno-use-linker-plugin");
 
-  /* pex argv arrays are NULL-terminated.  */
-  argvec.safe_push (NULL);
+  if (0)
+    ADD_ARG ("-v");
+
+#undef ADD_ARG
 
   /* pex_one's error-handling requires pname to be non-NULL.  */
   gcc_assert (ctxt_progname);
@@ -2426,9 +2430,42 @@  invoke_driver (const char *ctxt_progname,
     for (unsigned i = 0; i < argvec.length (); i++)
       get_logger ()->log ("argv[%i]: %s", i, argvec[i]);
 
+  if (embedded_driver)
+    invoke_embedded_driver (&argvec);
+  else
+    invoke_external_driver (ctxt_progname, &argvec);
+}
+
+void
+playback::context::
+invoke_embedded_driver (const vec <char *> *argvec)
+{
+  JIT_LOG_SCOPE (get_logger ());
+  driver d (true, /* can_finalize */
+	    false); /* debug */
+  int result = d.main (argvec->length (),
+		       const_cast <char **> (argvec->address ()));
+  d.finalize ();
+  if (result)
+    add_error (NULL, "error invoking gcc driver");
+}
+
+void
+playback::context::
+invoke_external_driver (const char *ctxt_progname,
+			vec <char *> *argvec)
+{
+  JIT_LOG_SCOPE (get_logger ());
+  const char *errmsg;
+  int exit_status = 0;
+  int err = 0;
+
+  /* pex argv arrays are NULL-terminated.  */
+  argvec->safe_push (NULL);
+
   errmsg = pex_one (PEX_SEARCH, /* int flags, */
 		    gcc_driver_name,
-		    const_cast <char *const *> (argvec.address ()),
+		    const_cast <char *const *> (argvec->address ()),
 		    ctxt_progname, /* const char *pname */
 		    NULL, /* const char *outname */
 		    NULL, /* const char *errname */
@@ -2455,7 +2492,6 @@  invoke_driver (const char *ctxt_progname,
 		 getenv ("PATH"));
       return;
     }
-#undef ADD_ARG
 }
 
 /* Extract the target-specific MULTILIB_DEFAULTS to
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 52e402f..d99db54 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -177,6 +177,12 @@  public:
     return m_recording_ctxt->get_bool_option (opt);
   }
 
+  int
+  get_inner_bool_option (enum inner_bool_option opt) const
+  {
+    return m_recording_ctxt->get_inner_bool_option (opt);
+  }
+
   builtins_manager *get_builtins_manager () const
   {
     return m_recording_ctxt->get_builtins_manager ();
@@ -280,6 +286,14 @@  protected:
   result *
   dlopen_built_dso ();
 
+ private:
+  void
+  invoke_embedded_driver (const vec <char *> *argvec);
+
+  void
+  invoke_external_driver (const char *ctxt_progname,
+			  vec <char *> *argvec);
+
 private:
   ::gcc::jit::recording::context *m_recording_ctxt;
 
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 811d7c0..70bd171 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -1452,7 +1452,8 @@  static const char * const
 
 static const char * const
  inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
-  "gcc_jit_context_set_bool_allow_unreachable_blocks"
+  "gcc_jit_context_set_bool_allow_unreachable_blocks",
+  "gcc_jit_context_set_bool_use_external_driver"
 };
 
 /* Write the current value of all options to the log file (if any).  */
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index d7e491b..ef9bef1 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -124,6 +124,7 @@  namespace gccjit
 			  int value);
 
     void set_bool_allow_unreachable_blocks (int bool_value);
+    void set_bool_use_external_driver (int bool_value);
 
     void add_command_line_option (const char *optname);
 
@@ -666,6 +667,13 @@  context::set_bool_allow_unreachable_blocks (int bool_value)
 }
 
 inline void
+context::set_bool_use_external_driver (int bool_value)
+{
+  gcc_jit_context_set_bool_use_external_driver (m_inner_ctxt,
+						bool_value);
+}
+
+inline void
 context::add_command_line_option (const char *optname)
 {
   gcc_jit_context_add_command_line_option (m_inner_ctxt, optname);
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index eb9200c..55cda6b 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -2611,6 +2611,23 @@  gcc_jit_context_set_bool_allow_unreachable_blocks (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::set_inner_bool_option method in
+   jit-recording.c.  */
+
+extern void
+gcc_jit_context_set_bool_use_external_driver (gcc_jit_context *ctxt,
+					      int bool_value)
+{
+  RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  ctxt->set_inner_bool_option (
+    gcc::jit::INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER,
+    bool_value);
+}
+
+/* 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.  */
 
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 88e4ff3..442ad0a 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -278,6 +278,30 @@  gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt,
    tested for with #ifdef.  */
 #define LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
 
+/* Implementation detail:
+   libgccjit internally generates assembler, and uses "driver" code
+   for converting it to other formats (e.g. shared libraries).
+
+   By default, libgccjit will use an embedded copy of the driver
+   code.
+
+   This option can be used to instead invoke an external driver executable
+   as a subprocess.
+
+   This entrypoint was added in LIBGCCJIT_ABI_5; you can test for
+   its presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver
+*/
+
+extern void
+gcc_jit_context_set_bool_use_external_driver (gcc_jit_context *ctxt,
+					      int bool_value);
+
+/* Pre-canned feature macro to indicate the presence of
+   gcc_jit_context_set_bool_use_external_driver.  This can be
+   tested for with #ifdef.  */
+#define LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver
+
 /* 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
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index e4302c6..a3ced26 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -140,3 +140,8 @@  LIBGCCJIT_ABI_4 {
     gcc_jit_timer_pop;
     gcc_jit_timer_print;
 };
+
+LIBGCCJIT_ABI_5 {
+  global:
+    gcc_jit_context_set_bool_use_external_driver;
+} LIBGCCJIT_ABI_4;
diff --git a/gcc/jit/notes.txt b/gcc/jit/notes.txt
index e92c665..36e05cb 100644
--- a/gcc/jit/notes.txt
+++ b/gcc/jit/notes.txt
@@ -78,7 +78,13 @@  Client Code   . Generated .            libgccjit.so
               .           .      │   .               .
               .           .      │   (assuming an in-memory compile):
               .           .      │   .               .
-              .           .      │   . Convert assembler to DSO ("fake.so")
+              .           .      --> Convert assembler to DSO, via embedded
+              .           .          copy of driver:
+              .           .           driver::main ()
+              .           .             invocation of "as"
+              .           .             invocation of "ld"
+              .           .           driver::finalize ()
+              .           .      <----
               .           .      │   .               .
               .           .      │   . Load DSO (dlopen "fake.so")
               .           .      │   .               .
diff --git a/gcc/testsuite/jit.dg/test-error-pr63969-missing-driver.c b/gcc/testsuite/jit.dg/test-error-pr63969-missing-driver.c
index 13f5e3b..7335223 100644
--- a/gcc/testsuite/jit.dg/test-error-pr63969-missing-driver.c
+++ b/gcc/testsuite/jit.dg/test-error-pr63969-missing-driver.c
@@ -21,6 +21,10 @@  create_code (gcc_jit_context *ctxt, void *user_data)
      Unset it.  */
   gcc_jit_context_set_str_option (ctxt, GCC_JIT_STR_OPTION_PROGNAME, NULL);
 
+  /* By default, we use an embedded copy of the driver.
+     Opt-in to using an external copy of the driver.  */
+  gcc_jit_context_set_bool_use_external_driver (ctxt, 1);
+
   /* Break PATH, so that the driver can't be found
      by gcc::jit::playback::context::compile ()
      within gcc_jit_context_compile.  */