public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/2] driver: support state cleanup
  2015-01-01  0:00 [PATCH 0/2] Embed driver within libgccjit David Malcolm
  2015-01-01  0:00 ` [PATCH 2/2] jit: use an embedded copy of the driver David Malcolm
@ 2015-01-01  0:00 ` David Malcolm
  2015-01-01  0:00   ` Joseph Myers
  2015-01-01  0:00 ` [PING] Re: [PATCH 0/2] Embed driver within libgccjit David Malcolm
  2 siblings, 1 reply; 7+ messages in thread
From: David Malcolm @ 2015-01-01  0:00 UTC (permalink / raw)
  To: gcc-patches, jit, Joseph Myers; +Cc: David Malcolm

This patch implements enough state cleanup with the driver to allow
it to be linked within libgccjit.so and repeatedly run in-process.

The state cleanup is optional and is only performed by libgccjit.
When run within the driver executables, the code does the same as
before.

This corresponds to the first part of:
  https://gcc.gnu.org/ml/gcc-patches/2015-06/msg00123.html
with various cleanups.

In particular, I've fixed the "genenv" / "getenv" typo noted by
Bert Wesarg here:
  https://gcc.gnu.org/ml/gcc-patches/2015-06/msg00268.html
which required using "get" rather than "getenv" for the name of
the env_manager method (given that poisoning happens in the
preprocessor).

Successfully bootstrapped and regression-tested on
x86_64-pc-linux-gnu (in combination with the followup patch, which
contains the jit-specific parts, which would be committed with it;
I've split them up for ease of review).

OK for trunk?

gcc/ChangeLog:
	* gcc-main.c (main): Add params to driver ctor.
	* gcc.c (class env_manager): New.
	(env): New global.
	(env_manager::init): New.
	(env_manager::get): New.
	(env_manager::xput): New.
	(env_manager::restore): New.
	Poison getenv and putenv.
	(DEFAULT_TARGET_SYSTEM_ROOT): New.
	(target_system_root): Update initialization to use
	DEFAULT_TARGET_SYSTEM_ROOT.
	(struct spec_list): Add field "default_ptr".
	(INIT_STATIC_SPEC): Initialize new field "default_ptr".
	(init_spec): Likewise.
	(set_spec): Clear field "default_ptr".
	(read_specs): Free "spec" and "buffer".
	(xputenv): Reimplement in terms of env_manager.
	(process_command): Replace ::getenv calls with calls to the
	env_manager singleton.
	(process_brace_body): Free string in three places.
	(driver::driver): New.
	(driver::~driver): New.
	(used_arg): Convert from a function to...
	(class used_arg_t): ...this class, and...
	(used_arg): ...this new global instance.
	(used_arg_t::finalize): New function.
	(getenv_spec_function): Add "const" to local "value".  Replace
	::getenv call with call to the env_manager singleton.
	(path_prefix_reset): New function.
	(driver::finalize): New function.
	* gcc.h (driver::driver): New.
	(driver::~driver): New.
	(driver::finalize): New.
---
 gcc/gcc-main.c |   3 +-
 gcc/gcc.c      | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 gcc/gcc.h      |   3 +
 3 files changed, 384 insertions(+), 22 deletions(-)

diff --git a/gcc/gcc-main.c b/gcc/gcc-main.c
index 230ba48..a0aaa3c 100644
--- a/gcc/gcc-main.c
+++ b/gcc/gcc-main.c
@@ -40,7 +40,8 @@ extern int main (int, char **);
 int
 main (int argc, char **argv)
 {
-  driver d;
+  driver d (false, /* can_finalize */
+	    false); /* debug */
 
   return d.main (argc, argv);
 }
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 290ec78..36f7ca1 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -43,6 +43,131 @@ compilation is specified by a string called a "spec".  */
 #include "params.h"
 #include "filenames.h"
 
+\f
+
+/* Manage the manipulation of env vars.
+
+   We poison "getenv" and "putenv", so that all enviroment-handling is
+   done through this class.  Note that poisoning happens in the
+   preprocessor at the identifier level, and doesn't distinguish between
+     env.getenv ();
+   and
+     getenv ();
+   Hence we need to use "get" for the accessor method, not "getenv".  */
+
+class env_manager
+{
+ public:
+  void init (bool can_restore, bool debug);
+  const char *get (const char *name);
+  void xput (const char *string);
+  void restore ();
+
+ private:
+  bool m_can_restore;
+  bool m_debug;
+  struct kv
+  {
+    char *m_key;
+    char *m_value;
+  };
+  vec<kv> m_keys;
+
+};
+
+/* The singleton instance of class env_manager.  */
+
+static env_manager env;
+
+/* Initializer for class env_manager.
+
+   We can't do this as a constructor since we have a statically
+   allocated instance ("env" above).  */
+
+void
+env_manager::init (bool can_restore, bool debug)
+{
+  m_can_restore = can_restore;
+  m_debug = debug;
+}
+
+/* Get the value of NAME within the environment.  Essentially
+   a wrapper for ::getenv, but adding logging, and the possibility
+   of caching results.  */
+
+const char *
+env_manager::get (const char *name)
+{
+  const char *result = ::getenv (name);
+  if (m_debug)
+    fprintf (stderr, "env_manager::getenv (%s) -> %s\n", name, result);
+  return result;
+}
+
+/* Put the given KEY=VALUE entry STRING into the environment.
+   If the env_manager was initialized with CAN_RESTORE set, then
+   also record the old value of KEY within the environment, so that it
+   can be later restored.  */
+
+void
+env_manager::xput (const char *string)
+{
+  if (m_debug)
+    fprintf (stderr, "env_manager::xput (%s)\n", string);
+  if (verbose_flag)
+    fnotice (stderr, "%s\n", string);
+
+  if (m_can_restore)
+    {
+      char *equals = strchr (const_cast <char *> (string), '=');
+      gcc_assert (equals);
+
+      struct kv kv;
+      kv.m_key = strndup (string, equals - string);
+      const char *cur_value = ::getenv (kv.m_key);
+      if (m_debug)
+	fprintf (stderr, "saving old value: %s\n",cur_value);
+      kv.m_value = cur_value ? xstrdup (cur_value) : NULL;
+      m_keys.safe_push (kv);
+    }
+
+  ::putenv (CONST_CAST (char *, string));
+}
+
+/* Undo any xputenv changes made since last restore.
+   Can only be called if the env_manager was initialized with
+   CAN_RESTORE enabled.  */
+
+void
+env_manager::restore ()
+{
+  unsigned int i;
+  struct kv *item;
+
+  gcc_assert (m_can_restore);
+
+  FOR_EACH_VEC_ELT_REVERSE (m_keys, i, item)
+    {
+      if (m_debug)
+	printf ("restoring saved key: %s value: %s\n", item->m_key, item->m_value);
+      if (item->m_value)
+	::setenv (item->m_key, item->m_value, 1);
+      else
+	::unsetenv (item->m_key);
+      free (item->m_key);
+      free (item->m_value);
+    }
+
+  m_keys.truncate (0);
+}
+
+/* Forbid other uses of getenv and putenv.  */
+#if (GCC_VERSION >= 3000)
+#pragma GCC poison getenv putenv
+#endif
+
+\f
+
 /* By default there is no special suffix for target executables.  */
 /* FIXME: when autoconf is fixed, remove the host check - dj */
 #if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
@@ -115,10 +240,11 @@ FILE *report_times_to_file = NULL;
    and library files can be found in an alternate location.  */
 
 #ifdef TARGET_SYSTEM_ROOT
-static const char *target_system_root = TARGET_SYSTEM_ROOT;
+#define DEFAULT_TARGET_SYSTEM_ROOT (TARGET_SYSTEM_ROOT)
 #else
-static const char *target_system_root = 0;
+#define DEFAULT_TARGET_SYSTEM_ROOT (0)
 #endif
+static const char *target_system_root = DEFAULT_TARGET_SYSTEM_ROOT;
 
 /* Nonzero means pass the updated target_system_root to the compiler.  */
 
@@ -235,7 +361,6 @@ static const char *validate_switches (const char *, bool);
 static void validate_all_switches (void);
 static inline void validate_switches_from_spec (const char *, bool);
 static void give_switch (int, int);
-static int used_arg (const char *, int);
 static int default_arg (const char *, int);
 static void set_multilib_dir (void);
 static void print_multilib_info (void);
@@ -1395,10 +1520,12 @@ struct spec_list
   int name_len;			/* length of the name */
   bool user_p;			/* whether string come from file spec.  */
   bool alloc_p;			/* whether string was allocated */
+  const char *default_ptr;	/* The default value of *ptr_spec.  */
 };
 
 #define INIT_STATIC_SPEC(NAME,PTR) \
-  { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, false, false }
+  { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, false, false, \
+    *PTR }
 
 /* List of statically defined specs.  */
 static struct spec_list static_specs[] =
@@ -1566,6 +1693,8 @@ init_spec (void)
       sl->next = next;
       sl->name_len = strlen (sl->name);
       sl->ptr_spec = &sl->ptr;
+      gcc_assert (sl->ptr_spec != NULL);
+      sl->default_ptr = sl->ptr;
       next = sl;
     }
 #endif
@@ -1740,6 +1869,7 @@ set_spec (const char *name, const char *spec, bool user_p)
       sl->alloc_p = 0;
       *(sl->ptr_spec) = "";
       sl->next = specs;
+      sl->default_ptr = NULL;
       specs = sl;
     }
 
@@ -2132,7 +2262,10 @@ read_specs (const char *filename, bool main_p, bool user_p)
 	  if (! strcmp (suffix, "*link_command"))
 	    link_command_spec = spec;
 	  else
-	    set_spec (suffix + 1, spec, user_p);
+	    {
+	      set_spec (suffix + 1, spec, user_p);
+	      free (spec);
+	    }
 	}
       else
 	{
@@ -2152,6 +2285,8 @@ read_specs (const char *filename, bool main_p, bool user_p)
 
   if (link_command_spec == 0)
     fatal_error (input_location, "spec file has no spec for linking");
+
+  XDELETEVEC (buffer);
 }
 \f
 /* Record the names of temporary files we tell compilers to write,
@@ -2494,9 +2629,7 @@ add_to_obstack (char *path, void *data)
 static void
 xputenv (const char *string)
 {
-  if (verbose_flag)
-    fnotice (stderr, "%s\n", string);
-  putenv (CONST_CAST (char *, string));
+  env.xput (string);
 }
 
 /* Build a list of search directories from PATHS.
@@ -3965,7 +4098,7 @@ process_command (unsigned int decoded_options_count,
   struct cl_option_handlers handlers;
   unsigned int j;
 
-  gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
+  gcc_exec_prefix = env.get ("GCC_EXEC_PREFIX");
 
   n_switches = 0;
   n_infiles = 0;
@@ -4070,7 +4203,7 @@ process_command (unsigned int decoded_options_count,
   /* COMPILER_PATH and LIBRARY_PATH have values
      that are lists of directory names with colons.  */
 
-  temp = getenv ("COMPILER_PATH");
+  temp = env.get ("COMPILER_PATH");
   if (temp)
     {
       const char *startp, *endp;
@@ -4104,7 +4237,7 @@ process_command (unsigned int decoded_options_count,
 	}
     }
 
-  temp = getenv (LIBRARY_PATH_ENV);
+  temp = env.get (LIBRARY_PATH_ENV);
   if (temp && *cross_compile == '0')
     {
       const char *startp, *endp;
@@ -4137,7 +4270,7 @@ process_command (unsigned int decoded_options_count,
     }
 
   /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
-  temp = getenv ("LPATH");
+  temp = env.get ("LPATH");
   if (temp && *cross_compile == '0')
     {
       const char *startp, *endp;
@@ -4280,7 +4413,7 @@ process_command (unsigned int decoded_options_count,
 
   if (!compare_debug)
     {
-      const char *gcd = getenv ("GCC_COMPARE_DEBUG");
+      const char *gcd = env.get ("GCC_COMPARE_DEBUG");
 
       if (gcd && gcd[0] == '-')
 	{
@@ -6212,7 +6345,10 @@ process_brace_body (const char *p, const char *atom, const char *end_atom,
       if (!have_subst)
 	{
 	  if (do_spec_1 (string, 0, NULL) < 0)
-	    return 0;
+	    {
+	      free (string);
+	      return 0;
+	    }
 	}
       else
 	{
@@ -6228,12 +6364,16 @@ process_brace_body (const char *p, const char *atom, const char *end_atom,
 	      {
 		if (do_spec_1 (string, 0,
 			       &switches[i].part1[hard_match_len]) < 0)
-		  return 0;
+		  {
+		    free (string);
+		    return 0;
+		  }
 		/* Pass any arguments this switch has.  */
 		give_switch (i, 1);
 		suffix_subst = NULL;
 	      }
 	}
+      free (string);
     }
 
   return p;
@@ -6942,6 +7082,19 @@ compare_files (char *cmpfile[])
   return ret;
 }
 
+driver::driver (bool can_finalize, bool debug) :
+  explicit_link_files (NULL),
+  decoded_options (NULL)
+{
+  env.init (can_finalize, debug);
+}
+
+driver::~driver ()
+{
+  XDELETEVEC (explicit_link_files);
+  XDELETEVEC (decoded_options);
+}
+
 /* driver::main is implemented as a series of driver:: method calls.  */
 
 int
@@ -8155,9 +8308,13 @@ static int n_mdswitches;
 /* Check whether a particular argument was used.  The first time we
    canonicalize the switches to keep only the ones we care about.  */
 
-static int
-used_arg (const char *p, int len)
+class used_arg_t
 {
+ public:
+  int operator () (const char *p, int len);
+  void finalize ();
+
+ private:
   struct mswitchstr
   {
     const char *str;
@@ -8166,8 +8323,16 @@ used_arg (const char *p, int len)
     int rep_len;
   };
 
-  static struct mswitchstr *mswitches;
-  static int n_mswitches;
+  mswitchstr *mswitches;
+  int n_mswitches;
+
+};
+
+used_arg_t used_arg;
+
+int
+used_arg_t::operator () (const char *p, int len)
+{
   int i, j;
 
   if (!mswitches)
@@ -8296,6 +8461,14 @@ used_arg (const char *p, int len)
   return 0;
 }
 
+void used_arg_t::finalize ()
+{
+  XDELETEVEC (mswitches);
+  mswitches = NULL;
+  n_mswitches = 0;
+}
+
+
 static int
 default_arg (const char *p, int len)
 {
@@ -8850,7 +9023,7 @@ print_multilib_info (void)
 static const char *
 getenv_spec_function (int argc, const char **argv)
 {
-  char *value;
+  const char *value;
   char *result;
   char *ptr;
   size_t len;
@@ -8858,7 +9031,7 @@ getenv_spec_function (int argc, const char **argv)
   if (argc != 2)
     return NULL;
 
-  value = getenv (argv[0]);
+  value = env.get (argv[0]);
   if (!value)
     fatal_error (input_location,
 		 "environment variable %qs not defined", argv[0]);
@@ -9521,6 +9694,191 @@ convert_white_space (char *orig)
     return orig;
 }
 
+static void
+path_prefix_reset (path_prefix *prefix)
+{
+  struct prefix_list *iter, *next;
+  iter = prefix->plist;
+  while (iter)
+    {
+      next = iter->next;
+      free (const_cast <char *> (iter->prefix));
+      XDELETE (iter);
+      iter = next;
+    }
+  prefix->plist = 0;
+  prefix->max_len = 0;
+}
+
+/* Restore all state within gcc.c to the initial state, so that the driver
+   code can be safely re-run in-process.
+
+   Many const char * variables are referenced by static specs (see
+   INIT_STATIC_SPEC above).  These variables are restored to their default
+   values by a simple loop over the static specs.
+
+   For other variables, we directly restore them all to their initial
+   values (often implicitly 0).
+
+   Free the various obstacks in this file, along with "opts_obstack"
+   from opts.c.
+
+   This function also restores any environment variables that were changed.  */
+
+void
+driver::finalize ()
+{
+  env.restore ();
+  params_c_finalize ();
+  diagnostic_finish (global_dc);
+
+  is_cpp_driver = 0;
+  at_file_supplied = 0;
+  print_help_list = 0;
+  print_version = 0;
+  verbose_only_flag = 0;
+  print_subprocess_help = 0;
+  use_ld = NULL;
+  report_times_to_file = NULL;
+  target_system_root = DEFAULT_TARGET_SYSTEM_ROOT;
+  target_system_root_changed = 0;
+  target_sysroot_suffix = 0;
+  target_sysroot_hdrs_suffix = 0;
+  save_temps_flag = SAVE_TEMPS_NONE;
+  save_temps_prefix = 0;
+  save_temps_length = 0;
+  spec_machine = DEFAULT_TARGET_MACHINE;
+  greatest_status = 1;
+
+  finalize_options_struct (&global_options);
+  finalize_options_struct (&global_options_set);
+
+  obstack_free (&obstack, NULL);
+  obstack_free (&opts_obstack, NULL); /* in opts.c */
+  obstack_free (&collect_obstack, NULL);
+
+  link_command_spec = LINK_COMMAND_SPEC;
+
+  obstack_free (&multilib_obstack, NULL);
+
+  user_specs_head = NULL;
+  user_specs_tail = NULL;
+
+  /* Within the "compilers" vec, the fields "suffix" and "spec" were
+     statically allocated for the default compilers, but dynamically
+     allocated for additional compilers.  Delete them for the latter. */
+  for (int i = n_default_compilers; i < n_compilers; i++)
+    {
+      free (const_cast <char *> (compilers[i].suffix));
+      free (const_cast <char *> (compilers[i].spec));
+    }
+  XDELETEVEC (compilers);
+  compilers = NULL;
+  n_compilers = 0;
+
+  linker_options.truncate (0);
+  assembler_options.truncate (0);
+  preprocessor_options.truncate (0);
+
+  path_prefix_reset (&exec_prefixes);
+  path_prefix_reset (&startfile_prefixes);
+  path_prefix_reset (&include_prefixes);
+
+  machine_suffix = 0;
+  just_machine_suffix = 0;
+  gcc_exec_prefix = 0;
+  gcc_libexec_prefix = 0;
+  md_exec_prefix = MD_EXEC_PREFIX;
+  md_startfile_prefix = MD_STARTFILE_PREFIX;
+  md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
+  multilib_dir = 0;
+  multilib_os_dir = 0;
+  multiarch_dir = 0;
+
+  XDELETEVEC (specs);
+  specs = 0;
+  for (unsigned i = 0; i < ARRAY_SIZE (static_specs); i++)
+    {
+      spec_list *sl = &static_specs[i];
+      if (sl->alloc_p)
+	{
+	  if (0)
+	    free (const_cast <char *> (*(sl->ptr_spec)));
+	  sl->alloc_p = false;
+	}
+      *(sl->ptr_spec) = sl->default_ptr;
+    }
+  extra_specs = NULL;
+
+  processing_spec_function = 0;
+
+  argbuf.truncate (0);
+
+  have_c = 0;
+  have_o = 0;
+
+  temp_names = NULL;
+  execution_count = 0;
+  signal_count = 0;
+
+  temp_filename = NULL;
+  temp_filename_length = 0;
+  always_delete_queue = NULL;
+  failure_delete_queue = NULL;
+
+  XDELETEVEC (switches);
+  switches = NULL;
+  n_switches = 0;
+  n_switches_alloc = 0;
+
+  compare_debug = 0;
+  compare_debug_second = 0;
+  compare_debug_opt = NULL;
+  for (int i = 0; i < 2; i++)
+    {
+      switches_debug_check[i] = NULL;
+      n_switches_debug_check[i] = 0;
+      n_switches_alloc_debug_check[i] = 0;
+      debug_check_temp_file[i] = NULL;
+    }
+
+  XDELETEVEC (infiles);
+  infiles = NULL;
+  n_infiles = 0;
+  n_infiles_alloc = 0;
+
+  combine_inputs = false;
+  added_libraries = 0;
+  XDELETEVEC (outfiles);
+  outfiles = NULL;
+  spec_lang = 0;
+  last_language_n_infiles = 0;
+  gcc_input_filename = NULL;
+  input_file_number = 0;
+  input_filename_length = 0;
+  basename_length = 0;
+  suffixed_basename_length = 0;
+  input_basename = NULL;
+  input_suffix = NULL;
+  /* We don't need to purge "input_stat", just to unset "input_stat_set".  */
+  input_stat_set = 0;
+  input_file_compiler = NULL;
+  arg_going = 0;
+  delete_this_arg = 0;
+  this_is_output_file = 0;
+  this_is_library_file = 0;
+  this_is_linker_script = 0;
+  input_from_pipe = 0;
+  suffix_subst = NULL;
+
+  mdswitches = NULL;
+  n_mdswitches = 0;
+
+  debug_auxbase_opt = NULL;
+
+  used_arg.finalize ();
+}
+
 /* PR jit/64810.
    Targets can provide configure-time default options in
    OPTION_DEFAULT_SPECS.  The jit needs to access these, but
diff --git a/gcc/gcc.h b/gcc/gcc.h
index f10a103..e1abe43 100644
--- a/gcc/gcc.h
+++ b/gcc/gcc.h
@@ -30,7 +30,10 @@ along with GCC; see the file COPYING3.  If not see
 class driver
 {
  public:
+  driver (bool can_finalize, bool debug);
+  ~driver ();
   int main (int argc, char **argv);
+  void finalize ();
 
  private:
   void set_progname (const char *argv0) const;
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] driver: support state cleanup
  2015-01-01  0:00     ` David Malcolm
@ 2015-01-01  0:00       ` Joseph Myers
  0 siblings, 0 replies; 7+ messages in thread
From: Joseph Myers @ 2015-01-01  0:00 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, jit

I've committed as obvious this patch to fix a build failure this 
introduced for targets not defining EXTRA_SPECS, in which case extra_specs 
is not declared.  (nvptx-none was the target for which I came across such 
a failure.)

2015-08-25  Joseph Myers  <joseph@codesourcery.com>

	* gcc.c (driver::finalize): Only assign to extra_specs if
	[EXTRA_SPECS].

Index: gcc.c
===================================================================
--- gcc.c	(revision 227191)
+++ gcc.c	(working copy)
@@ -9813,7 +9813,9 @@ driver::finalize ()
 	}
       *(sl->ptr_spec) = sl->default_ptr;
     }
+#ifdef EXTRA_SPECS
   extra_specs = NULL;
+#endif
 
   processing_spec_function = 0;
 

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] driver: support state cleanup
  2015-01-01  0:00 ` [PATCH 1/2] driver: support state cleanup David Malcolm
@ 2015-01-01  0:00   ` Joseph Myers
  2015-01-01  0:00     ` David Malcolm
  0 siblings, 1 reply; 7+ messages in thread
From: Joseph Myers @ 2015-01-01  0:00 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, jit

On Thu, 6 Aug 2015, David Malcolm wrote:

> gcc/ChangeLog:
> 	* gcc-main.c (main): Add params to driver ctor.
> 	* gcc.c (class env_manager): New.
> 	(env): New global.
> 	(env_manager::init): New.
> 	(env_manager::get): New.
> 	(env_manager::xput): New.
> 	(env_manager::restore): New.
> 	Poison getenv and putenv.
> 	(DEFAULT_TARGET_SYSTEM_ROOT): New.
> 	(target_system_root): Update initialization to use
> 	DEFAULT_TARGET_SYSTEM_ROOT.
> 	(struct spec_list): Add field "default_ptr".
> 	(INIT_STATIC_SPEC): Initialize new field "default_ptr".
> 	(init_spec): Likewise.
> 	(set_spec): Clear field "default_ptr".
> 	(read_specs): Free "spec" and "buffer".
> 	(xputenv): Reimplement in terms of env_manager.
> 	(process_command): Replace ::getenv calls with calls to the
> 	env_manager singleton.
> 	(process_brace_body): Free string in three places.
> 	(driver::driver): New.
> 	(driver::~driver): New.
> 	(used_arg): Convert from a function to...
> 	(class used_arg_t): ...this class, and...
> 	(used_arg): ...this new global instance.
> 	(used_arg_t::finalize): New function.
> 	(getenv_spec_function): Add "const" to local "value".  Replace
> 	::getenv call with call to the env_manager singleton.
> 	(path_prefix_reset): New function.
> 	(driver::finalize): New function.
> 	* gcc.h (driver::driver): New.
> 	(driver::~driver): New.
> 	(driver::finalize): New.

OK.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] driver: support state cleanup
  2015-01-01  0:00   ` Joseph Myers
@ 2015-01-01  0:00     ` David Malcolm
  2015-01-01  0:00       ` Joseph Myers
  0 siblings, 1 reply; 7+ messages in thread
From: David Malcolm @ 2015-01-01  0:00 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches, jit

On Tue, 2015-08-25 at 13:48 +0000, Joseph Myers wrote:
> On Thu, 6 Aug 2015, David Malcolm wrote:
> 
> > gcc/ChangeLog:
> > 	* gcc-main.c (main): Add params to driver ctor.
> > 	* gcc.c (class env_manager): New.
> > 	(env): New global.
> > 	(env_manager::init): New.
> > 	(env_manager::get): New.
> > 	(env_manager::xput): New.
> > 	(env_manager::restore): New.
> > 	Poison getenv and putenv.
> > 	(DEFAULT_TARGET_SYSTEM_ROOT): New.
> > 	(target_system_root): Update initialization to use
> > 	DEFAULT_TARGET_SYSTEM_ROOT.
> > 	(struct spec_list): Add field "default_ptr".
> > 	(INIT_STATIC_SPEC): Initialize new field "default_ptr".
> > 	(init_spec): Likewise.
> > 	(set_spec): Clear field "default_ptr".
> > 	(read_specs): Free "spec" and "buffer".
> > 	(xputenv): Reimplement in terms of env_manager.
> > 	(process_command): Replace ::getenv calls with calls to the
> > 	env_manager singleton.
> > 	(process_brace_body): Free string in three places.
> > 	(driver::driver): New.
> > 	(driver::~driver): New.
> > 	(used_arg): Convert from a function to...
> > 	(class used_arg_t): ...this class, and...
> > 	(used_arg): ...this new global instance.
> > 	(used_arg_t::finalize): New function.
> > 	(getenv_spec_function): Add "const" to local "value".  Replace
> > 	::getenv call with call to the env_manager singleton.
> > 	(path_prefix_reset): New function.
> > 	(driver::finalize): New function.
> > 	* gcc.h (driver::driver): New.
> > 	(driver::~driver): New.
> > 	(driver::finalize): New.
> 
> OK.

Thanks.

I've committed the combination of patches 1 and 2 to trunk as r227188,
having double-checked that it still bootstraps & passes regression
testing (on x86_64-pc-linux-gnu).

[some people on the jit list were specifically interested in this patch
kit, hence this email].

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PING] Re: [PATCH 0/2] Embed driver within libgccjit
  2015-01-01  0:00 [PATCH 0/2] Embed driver within libgccjit David Malcolm
  2015-01-01  0:00 ` [PATCH 2/2] jit: use an embedded copy of the driver David Malcolm
  2015-01-01  0:00 ` [PATCH 1/2] driver: support state cleanup David Malcolm
@ 2015-01-01  0:00 ` David Malcolm
  2 siblings, 0 replies; 7+ messages in thread
From: David Malcolm @ 2015-01-01  0:00 UTC (permalink / raw)
  To: gcc-patches; +Cc: jit, Joseph Myers

On Thu, 2015-08-06 at 10:52 -0400, David Malcolm wrote:

Ping:
  https://gcc.gnu.org/ml/gcc-patches/2015-08/msg00355.html

In particular, I'm hoping for review of patch 1, which provides a way to
clean up state within the driver code (patch 2 uses this from libgccjit
to embed it in-process, rather that via pex, achieving a speedup and
enabling followup improvements).

> The attached two patches are an updated version of this patch
> sent in June:
>  https://gcc.gnu.org/ml/gcc-patches/2015-06/msg00123.html
>   "[PATCH 02/16] gcc: Embed the driver in-process within libgccjit"
> 
> (an updated version of [patch 01/16] from that kit is in trunk as of
> r226530;  https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02713.html)
> 
> They provide a modest speedup of jit.dg/test-benchmark.c and hence
> are useful in their own right:
> 
> Median time taken for 100 in-process compiles (lower is better) over
> multiple runs, showing mean within each run:
> 
>  Control build of r226530, with pex-execution of driver binary:
>   optlevel 0: 6.210s (0.062s per iteration)
>   optlevel 1: 6.990s (0.070s per iteration)
>   optlevel 2: 7.240s (0.072s per iteration)
>   optlevel 3: 9.010s (0.090s per iteration)
> 
>  With these patches, embedding the driver:
>   optlevel 0: 6.020s (0.060s per iteration)
>   optlevel 1: 6.720s (0.067s per iteration)
>   optlevel 2: 7.020s (0.070s per iteration)
>   optlevel 3: 8.660s (0.087s per iteration)
> 
> They are also a prerequisite for some of the much larger speedups
> proposed in the followup patches sent in June.
> 
> I've split them out into the driver part (patch 1) and the jit-specific
> part (patch 2) for ease of review.



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 0/2] Embed driver within libgccjit
@ 2015-01-01  0:00 David Malcolm
  2015-01-01  0:00 ` [PATCH 2/2] jit: use an embedded copy of the driver David Malcolm
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: David Malcolm @ 2015-01-01  0:00 UTC (permalink / raw)
  To: gcc-patches, jit, Joseph Myers; +Cc: David Malcolm

The attached two patches are an updated version of this patch
sent in June:
 https://gcc.gnu.org/ml/gcc-patches/2015-06/msg00123.html
  "[PATCH 02/16] gcc: Embed the driver in-process within libgccjit"

(an updated version of [patch 01/16] from that kit is in trunk as of
r226530;  https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02713.html)

They provide a modest speedup of jit.dg/test-benchmark.c and hence
are useful in their own right:

Median time taken for 100 in-process compiles (lower is better) over
multiple runs, showing mean within each run:

 Control build of r226530, with pex-execution of driver binary:
  optlevel 0: 6.210s (0.062s per iteration)
  optlevel 1: 6.990s (0.070s per iteration)
  optlevel 2: 7.240s (0.072s per iteration)
  optlevel 3: 9.010s (0.090s per iteration)

 With these patches, embedding the driver:
  optlevel 0: 6.020s (0.060s per iteration)
  optlevel 1: 6.720s (0.067s per iteration)
  optlevel 2: 7.020s (0.070s per iteration)
  optlevel 3: 8.660s (0.087s per iteration)

They are also a prerequisite for some of the much larger speedups
proposed in the followup patches sent in June.

I've split them out into the driver part (patch 1) and the jit-specific
part (patch 2) for ease of review.

Successfully bootstrapped and regression-tested the combination of the
two patches on x86_64-pc-linux-gnu.

OK for trunk?

David Malcolm (2):
  driver: support state cleanup
  jit: use an embedded copy of the driver

 gcc/gcc-main.c                                     |   3 +-
 gcc/gcc.c                                          | 400 +++++++++++++++++++--
 gcc/gcc.h                                          |   3 +
 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 +
 17 files changed, 561 insertions(+), 34 deletions(-)

-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/2] jit: use an embedded copy of the driver
  2015-01-01  0:00 [PATCH 0/2] Embed driver within libgccjit David Malcolm
@ 2015-01-01  0:00 ` David Malcolm
  2015-01-01  0:00 ` [PATCH 1/2] driver: support state cleanup David Malcolm
  2015-01-01  0:00 ` [PING] Re: [PATCH 0/2] Embed driver within libgccjit David Malcolm
  2 siblings, 0 replies; 7+ messages in thread
From: David Malcolm @ 2015-01-01  0:00 UTC (permalink / raw)
  To: gcc-patches, jit, Joseph Myers; +Cc: David Malcolm

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 --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.  */
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-08-25 21:23 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-01  0:00 [PATCH 0/2] Embed driver within libgccjit David Malcolm
2015-01-01  0:00 ` [PATCH 2/2] jit: use an embedded copy of the driver David Malcolm
2015-01-01  0:00 ` [PATCH 1/2] driver: support state cleanup David Malcolm
2015-01-01  0:00   ` Joseph Myers
2015-01-01  0:00     ` David Malcolm
2015-01-01  0:00       ` Joseph Myers
2015-01-01  0:00 ` [PING] Re: [PATCH 0/2] Embed driver within libgccjit David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).