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:
parent
25c65938c8
commit
9376dd63e6
|
@ -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
|
||||
|
|
|
@ -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
400
gcc/gcc.c
|
@ -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
|
||||
|
|
|
@ -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,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
|
||||
|
|
|
@ -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
|
||||
***************
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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
|
||||
***************
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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). */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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")
|
||||
. . │ . .
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in New Issue