Support embedding the driver in-process within libgccjit

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

From-SVN: r227188
This commit is contained in:
David Malcolm 2015-08-25 20:25:05 +00:00 committed by David Malcolm
parent 25c65938c8
commit 9376dd63e6
20 changed files with 635 additions and 34 deletions

View File

@ -1,3 +1,39 @@
2015-08-25 David Malcolm <dmalcolm@redhat.com>
* 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.
2015-08-25 Nathan Sidwell <nathan@acm.org>
* optabs.c (emit_indirect_jump): Don't try an emit a jump if the

View File

@ -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);
}

400
gcc/gcc.c
View File

@ -43,6 +43,131 @@ compilation is specified by a string called a "spec". */
#include "params.h"
#include "filenames.h"
/* 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
/* 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);
}
/* 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.
@ -3970,7 +4103,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;
@ -4075,7 +4208,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;
@ -4109,7 +4242,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;
@ -4142,7 +4275,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;
@ -4285,7 +4418,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] == '-')
{
@ -6217,7 +6350,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
{
@ -6233,12 +6369,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;
@ -6947,6 +7087,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
@ -8160,9 +8313,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;
@ -8171,8 +8328,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)
@ -8301,6 +8466,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)
{
@ -8855,7 +9028,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;
@ -8863,7 +9036,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]);
@ -9526,6 +9699,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

View File

@ -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;

View File

@ -1,3 +1,36 @@
2015-08-25 David Malcolm <dmalcolm@redhat.com>
* 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
2015-08-13 David Malcolm <dmalcolm@redhat.com>
* jit-playback.c (invoke_driver): On OS X, add

View File

@ -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
***************

View File

@ -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()

View File

@ -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`

View File

@ -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
***************

View File

@ -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
};

View File

@ -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);
@ -2425,8 +2427,10 @@ invoke_driver (const char *ctxt_progname,
ADD_ARG ("-Wl,-undefined,dynamic_lookup");
#endif
/* 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);
@ -2435,9 +2439,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 */
@ -2464,7 +2501,6 @@ invoke_driver (const char *ctxt_progname,
getenv ("PATH"));
return;
}
#undef ADD_ARG
}
/* Extract the target-specific MULTILIB_DEFAULTS to

View File

@ -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;

View File

@ -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). */

View File

@ -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);
@ -665,6 +666,13 @@ context::set_bool_allow_unreachable_blocks (int bool_value)
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)
{

View File

@ -2608,6 +2608,23 @@ gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt,
bool_value);
}
/* 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

View File

@ -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

View File

@ -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;

View File

@ -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")
. . │ . .

View File

@ -1,3 +1,8 @@
2015-08-25 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-error-pr63969-missing-driver.c: Add call to
gcc_jit_context_set_bool_use_external_driver.
2015-08-25 Nathan Sidwell <nathan@acm.org>
* gcc.c-torture/execute/builtins/20010124-1.x: New.

View File

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