Change compile_instance/compile_c_instance into classes

This patch changes structs compile_instance and compile_c_instance into
classes.

Because of the nature of the change, there are a number of unavoidably
mechanical changes buried in here, such as turning variable access of the
POD struct into method calls, removing the struct keyword, and changing
access of the plugin from "c_plugin->operation()" to
"plugin ().operation ()".

There is one "non-trivial" change associated with this patch, though.
The type cache and symbol error maps have been moved into the base class,
believing these facilities would be used other language implementations.
[They are indeed re-used by C++.]

gdb/ChangeLog:

        * compile/compile-c-support.c (c_get_compile_context): Use `new'
        instead of `new_compile_instance'.
        * compile/compile-c-symbols.c (compile_instance::insert_symbol_error):
        Update description.
        If the symbol error map is not initialized, create it.
        (generate_c_for_for_one_symbol): Do not check/initialize
        the symbol error map.
        * compile/compile-c-types.c (compile_c_instance): Make a class.
        Update all callers.
        (compile_instance::compile_instance): Initialize the type cache.
        (get_cached_type): New function.
        (insert_type): Update description.
        (compile_c_instance::m_default_cflags): Define.
        (convert_type): Update description.  Use get_cached_type.
        (delete_instance): Moved to destructor.
        (new_compile_instance): Moved to constructor.
        * compile/compile-c.h (compile_c_instance): Make class inheriting
        from compile_instance.
        <base>: Remove field.
        <type_map, symbol_err_map>: Move to base class.
        <c_plugin>: Rename to `m_plugin' and remove pointer type.
        * compile/compile-internal.h (compile_instance): Make class.
        <type_map_t, symbol_err_map_t>: Define.
        <fe>: Rename to `m_gcc_fe'.
        <scope, block, gcc_target_options>: Add `m_' prefix.
        <m_type_map, m_symbol_err_map>: New fields, moved from
        compile_c_instance.
        <destroy>: Remove.
        (convert_type, new_compile_instance): Remove.
        * compile/compile.c (cleanup_compile_instance): Remove.
        (compile_to_object): Use unique_ptr to eliminate cleanups.
        (compile_instance::set_print_callback, compile_instance::version)
        (compile_instance::set_verbose)
        (compile_instance::set_driver_filename)
        (compile_instance::set_triplet_regexp)
        (compile_instance::set_arguments)
        (compile_instance::set_source_file)
        (compile_instance::compile): Define.
This commit is contained in:
Keith Seitz 2018-08-10 10:48:03 -07:00
parent 18cdc6d8f8
commit 9cdfd9a26e
9 changed files with 428 additions and 260 deletions

View File

@ -1,3 +1,44 @@
2018-08-10 Keith Seitz <keiths@redhat.com>
* compile/compile-c-support.c (c_get_compile_context): Use `new'
instead of `new_compile_instance'.
* compile/compile-c-symbols.c (compile_instance::insert_symbol_error):
Update description.
If the symbol error map is not initialized, create it.
(generate_c_for_for_one_symbol): Do not check/initialize
the symbol error map.
* compile/compile-c-types.c (compile_c_instance): Make a class.
Update all callers.
(compile_instance::compile_instance): Initialize the type cache.
(get_cached_type): New function.
(insert_type): Update description.
(compile_c_instance::m_default_cflags): Define.
(convert_type): Update description. Use get_cached_type.
(delete_instance): Moved to destructor.
(new_compile_instance): Moved to constructor.
* compile/compile-c.h (compile_c_instance): Make class inheriting
from compile_instance.
<base>: Remove field.
<type_map, symbol_err_map>: Move to base class.
<c_plugin>: Rename to `m_plugin' and remove pointer type.
* compile/compile-internal.h (compile_instance): Make class.
<type_map_t, symbol_err_map_t>: Define.
<fe>: Rename to `m_gcc_fe'.
<scope, block, gcc_target_options>: Add `m_' prefix.
<m_type_map, m_symbol_err_map>: New fields, moved from
compile_c_instance.
<destroy>: Remove.
(convert_type, new_compile_instance): Remove.
* compile/compile.c (cleanup_compile_instance): Remove.
(compile_to_object): Use unique_ptr to eliminate cleanups.
(compile_instance::set_print_callback, compile_instance::version)
(compile_instance::set_verbose)
(compile_instance::set_driver_filename)
(compile_instance::set_triplet_regexp)
(compile_instance::set_arguments)
(compile_instance::set_source_file)
(compile_instance::compile): Define.
2018-08-10 Keith Seitz <keiths@redhat.com>
* Makefile.in (HFILES_NO_SRCDIR): Add compile/gcc-c-plugin.h.

View File

@ -158,7 +158,7 @@ extern int c_textual_element_type (struct type *, char);
exception on failure. This is suitable for use as the
la_get_compile_instance language method. */
extern struct compile_instance *c_get_compile_context (void);
extern compile_instance *c_get_compile_context (void);
/* This takes the user-supplied text and returns a new bit of code to
compile.
@ -166,7 +166,7 @@ extern struct compile_instance *c_get_compile_context (void);
This is used as the la_compute_program language method; see that
for a description of the arguments. */
extern std::string c_compute_program (struct compile_instance *inst,
extern std::string c_compute_program (compile_instance *inst,
const char *input,
struct gdbarch *gdbarch,
const struct block *expr_block,

View File

@ -96,7 +96,7 @@ load_libcc (void)
This function calls the symbol returned from the load_libcc
function. This will provide the gcc_c_context. */
struct compile_instance *
compile_instance *
c_get_compile_context (void)
{
static gcc_c_fe_context_function *func;
@ -114,7 +114,7 @@ c_get_compile_context (void)
error (_("The loaded version of GCC does not support the required version "
"of the API."));
return new_compile_instance (context);
return new compile_c_instance (context);
}
@ -334,13 +334,14 @@ generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch,
indicates the value of $PC. */
std::string
c_compute_program (struct compile_instance *inst,
c_compute_program (compile_instance *inst,
const char *input,
struct gdbarch *gdbarch,
const struct block *expr_block,
CORE_ADDR expr_pc)
{
struct compile_c_instance *context = (struct compile_c_instance *) inst;
compile_c_instance *context
= static_cast<compile_c_instance *> (inst);
string_file buf;
string_file var_stream;
@ -350,7 +351,7 @@ c_compute_program (struct compile_instance *inst,
/* Do not generate local variable information for "raw"
compilations. In this case we aren't emitting our own function
and the user's code may only refer to globals. */
if (inst->scope != COMPILE_I_RAW_SCOPE)
if (inst->scope () != COMPILE_I_RAW_SCOPE)
{
int i;
@ -384,11 +385,11 @@ c_compute_program (struct compile_instance *inst,
generate_register_struct (&buf, gdbarch, registers_used.get ());
}
add_code_header (inst->scope, &buf);
add_code_header (inst->scope (), &buf);
if (inst->scope == COMPILE_I_SIMPLE_SCOPE
|| inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
|| inst->scope == COMPILE_I_PRINT_VALUE_SCOPE)
if (inst->scope () == COMPILE_I_SIMPLE_SCOPE
|| inst->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE
|| inst->scope () == COMPILE_I_PRINT_VALUE_SCOPE)
{
buf.write (var_stream.c_str (), var_stream.size ());
buf.puts ("#pragma GCC user_expression\n");
@ -398,12 +399,12 @@ c_compute_program (struct compile_instance *inst,
works properly. Otherwise gcc thinks that the "extern"
declaration is in the same scope as the declaration provided by
gdb. */
if (inst->scope != COMPILE_I_RAW_SCOPE)
if (inst->scope () != COMPILE_I_RAW_SCOPE)
buf.puts ("{\n");
buf.puts ("#line 1 \"gdb command line\"\n");
switch (inst->scope)
switch (inst->scope ())
{
case COMPILE_I_PRINT_ADDRESS_SCOPE:
case COMPILE_I_PRINT_VALUE_SCOPE:
@ -413,7 +414,7 @@ c_compute_program (struct compile_instance *inst,
"memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s" COMPILE_I_EXPR_VAL ",\n"
"sizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n"
, input, input,
(inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
(inst->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE
? "&" : ""));
break;
default:
@ -428,9 +429,9 @@ c_compute_program (struct compile_instance *inst,
if (strchr (input, '\n') == NULL)
buf.puts (";\n");
if (inst->scope != COMPILE_I_RAW_SCOPE)
if (inst->scope () != COMPILE_I_RAW_SCOPE)
buf.puts ("}\n");
add_code_footer (inst->scope, &buf);
add_code_footer (inst->scope (), &buf);
return std::move (buf.string ());
}

View File

@ -79,16 +79,27 @@ del_symbol_error (void *a)
xfree (se);
}
/* Associate SYMBOL with some error text. */
/* See compile-internal.h. */
static void
insert_symbol_error (htab_t hash, const struct symbol *sym, const char *text)
void
compile_instance::insert_symbol_error (const struct symbol *sym,
const char *text)
{
struct symbol_error e;
void **slot;
if (m_symbol_err_map == NULL)
{
m_symbol_err_map = htab_create_alloc (10,
hash_symbol_error,
eq_symbol_error,
del_symbol_error,
xcalloc,
xfree);
}
e.sym = sym;
slot = htab_find_slot (hash, &e, INSERT);
slot = htab_find_slot (m_symbol_err_map, &e, INSERT);
if (*slot == NULL)
{
struct symbol_error *e = XNEW (struct symbol_error);
@ -99,21 +110,19 @@ insert_symbol_error (htab_t hash, const struct symbol *sym, const char *text)
}
}
/* Emit the error message corresponding to SYM, if one exists, and
arrange for it not to be emitted again. */
/* See compile-internal.h. */
static void
error_symbol_once (struct compile_c_instance *context,
const struct symbol *sym)
void
compile_instance::error_symbol_once (const struct symbol *sym)
{
struct symbol_error search;
struct symbol_error *err;
if (context->symbol_err_map == NULL)
if (m_symbol_err_map == NULL)
return;
search.sym = sym;
err = (struct symbol_error *) htab_find (context->symbol_err_map, &search);
err = (struct symbol_error *) htab_find (m_symbol_err_map, &search);
if (err == NULL || err->message == NULL)
return;
@ -142,7 +151,7 @@ c_symbol_substitution_name (struct symbol *sym)
scope.) */
static void
convert_one_symbol (struct compile_c_instance *context,
convert_one_symbol (compile_c_instance *context,
struct block_symbol sym,
int is_global,
int is_local)
@ -151,17 +160,17 @@ convert_one_symbol (struct compile_c_instance *context,
const char *filename = symbol_symtab (sym.symbol)->filename;
unsigned short line = SYMBOL_LINE (sym.symbol);
error_symbol_once (context, sym.symbol);
context->error_symbol_once (sym.symbol);
if (SYMBOL_CLASS (sym.symbol) == LOC_LABEL)
sym_type = 0;
else
sym_type = convert_type (context, SYMBOL_TYPE (sym.symbol));
sym_type = context->convert_type (SYMBOL_TYPE (sym.symbol));
if (SYMBOL_DOMAIN (sym.symbol) == STRUCT_DOMAIN)
{
/* Binding a tag, so we don't need to build a decl. */
context->c_plugin->tagbind (SYMBOL_NATURAL_NAME (sym.symbol),
context->plugin ().tagbind (SYMBOL_NATURAL_NAME (sym.symbol),
sym_type, filename, line);
}
else
@ -195,7 +204,7 @@ convert_one_symbol (struct compile_c_instance *context,
/* Already handled by convert_enum. */
return;
}
context->c_plugin->build_constant
context->plugin ().build_constant
(sym_type, SYMBOL_NATURAL_NAME (sym.symbol),
SYMBOL_VALUE (sym.symbol),
filename, line);
@ -280,17 +289,17 @@ convert_one_symbol (struct compile_c_instance *context,
}
/* Don't emit local variable decls for a raw expression. */
if (context->base.scope != COMPILE_I_RAW_SCOPE
if (context->scope () != COMPILE_I_RAW_SCOPE
|| symbol_name == NULL)
{
decl = context->c_plugin->build_decl
decl = context->plugin ().build_decl
(SYMBOL_NATURAL_NAME (sym.symbol),
kind,
sym_type,
symbol_name.get (), addr,
filename, line);
context->c_plugin->bind (decl, is_global);
context->plugin ().bind (decl, is_global);
}
}
}
@ -300,7 +309,7 @@ convert_one_symbol (struct compile_c_instance *context,
itself, and DOMAIN is the domain which was searched. */
static void
convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
convert_symbol_sym (compile_c_instance *context, const char *identifier,
struct block_symbol sym, domain_enum domain)
{
const struct block *static_block;
@ -350,7 +359,7 @@ convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
to use and BMSYM is the minimal symbol to convert. */
static void
convert_symbol_bmsym (struct compile_c_instance *context,
convert_symbol_bmsym (compile_c_instance *context,
struct bound_minimal_symbol bmsym)
{
struct minimal_symbol *msym = bmsym.minsym;
@ -398,11 +407,11 @@ convert_symbol_bmsym (struct compile_c_instance *context,
break;
}
sym_type = convert_type (context, type);
decl = context->c_plugin->build_decl (MSYMBOL_NATURAL_NAME (msym),
sym_type = context->convert_type (type);
decl = context->plugin ().build_decl (MSYMBOL_NATURAL_NAME (msym),
kind, sym_type, NULL, addr,
NULL, 0);
context->c_plugin->bind (decl, 1 /* is_global */);
context->plugin ().bind (decl, 1 /* is_global */);
}
/* See compile-internal.h. */
@ -413,7 +422,8 @@ gcc_convert_symbol (void *datum,
enum gcc_c_oracle_request request,
const char *identifier)
{
struct compile_c_instance *context = (struct compile_c_instance *) datum;
compile_c_instance *context
= static_cast<compile_c_instance *> (datum);
domain_enum domain;
int found = 0;
@ -438,7 +448,7 @@ gcc_convert_symbol (void *datum,
{
struct block_symbol sym;
sym = lookup_symbol (identifier, context->base.block, domain, NULL);
sym = lookup_symbol (identifier, context->block (), domain, NULL);
if (sym.symbol != NULL)
{
convert_symbol_sym (context, identifier, sym, domain);
@ -459,7 +469,7 @@ gcc_convert_symbol (void *datum,
CATCH (e, RETURN_MASK_ALL)
{
context->c_plugin->error (e.message);
context->plugin ().error (e.message);
}
END_CATCH
@ -476,7 +486,8 @@ gcc_address
gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
const char *identifier)
{
struct compile_c_instance *context = (struct compile_c_instance *) datum;
compile_c_instance *context
= static_cast<compile_c_instance *> (datum);
gcc_address result = 0;
int found = 0;
@ -521,7 +532,7 @@ gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
CATCH (e, RETURN_MASK_ERROR)
{
context->c_plugin->error (e.message);
context->plugin ().error (e.message);
}
END_CATCH
@ -575,7 +586,7 @@ symbol_seen (htab_t hashtab, struct symbol *sym)
/* Generate C code to compute the length of a VLA. */
static void
generate_vla_size (struct compile_c_instance *compiler,
generate_vla_size (compile_instance *compiler,
string_file &stream,
struct gdbarch *gdbarch,
unsigned char *registers_used,
@ -629,7 +640,7 @@ generate_vla_size (struct compile_c_instance *compiler,
/* Generate C code to compute the address of SYM. */
static void
generate_c_for_for_one_variable (struct compile_c_instance *compiler,
generate_c_for_for_one_variable (compile_instance *compiler,
string_file &stream,
struct gdbarch *gdbarch,
unsigned char *registers_used,
@ -691,14 +702,7 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler,
CATCH (e, RETURN_MASK_ERROR)
{
if (compiler->symbol_err_map == NULL)
compiler->symbol_err_map = htab_create_alloc (10,
hash_symbol_error,
eq_symbol_error,
del_symbol_error,
xcalloc,
xfree);
insert_symbol_error (compiler->symbol_err_map, sym, e.message);
compiler->insert_symbol_error (sym, e.message);
}
END_CATCH
}
@ -706,7 +710,7 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler,
/* See compile-c.h. */
gdb::unique_xmalloc_ptr<unsigned char>
generate_c_for_variable_locations (struct compile_c_instance *compiler,
generate_c_for_variable_locations (compile_instance *compiler,
string_file &stream,
struct gdbarch *gdbarch,
const struct block *block,

View File

@ -58,25 +58,49 @@ eq_type_map_instance (const void *a, const void *b)
return insta->type == instb->type;
}
/* Constructor for compile_instance. */
compile_instance::compile_instance (struct gcc_base_context *gcc_fe,
const char *options)
: m_gcc_fe (gcc_fe), m_gcc_target_options (options),
m_symbol_err_map (NULL)
{
m_type_map = htab_create_alloc (10, hash_type_map_instance,
eq_type_map_instance,
xfree, xcalloc, xfree);
}
/* Insert an entry into the type map associated with CONTEXT that maps
from the gdb type TYPE to the gcc type GCC_TYPE. It is ok for a
given type to be inserted more than once, provided that the exact
same association is made each time. This simplifies how type
caching works elsewhere in this file -- see how struct type caching
is handled. */
/* See compile-internal.h. */
static void
insert_type (struct compile_c_instance *context, struct type *type,
gcc_type gcc_type)
bool
compile_instance::get_cached_type (struct type *type, gcc_type &ret) const
{
struct type_map_instance inst, *found;
inst.type = type;
found = (struct type_map_instance *) htab_find (m_type_map, &inst);
if (found != NULL)
{
ret = found->gcc_type_handle;
return true;
}
return false;
}
/* See compile-internal.h. */
void
compile_instance::insert_type (struct type *type, gcc_type gcc_type)
{
struct type_map_instance inst, *add;
void **slot;
inst.type = type;
inst.gcc_type_handle = gcc_type;
slot = htab_find_slot (context->type_map, &inst, INSERT);
slot = htab_find_slot (m_type_map, &inst, INSERT);
add = (struct type_map_instance *) *slot;
/* The type might have already been inserted in order to handle
@ -95,28 +119,28 @@ insert_type (struct compile_c_instance *context, struct type *type,
/* Convert a pointer type to its gcc representation. */
static gcc_type
convert_pointer (struct compile_c_instance *context, struct type *type)
convert_pointer (compile_c_instance *context, struct type *type)
{
gcc_type target = convert_type (context, TYPE_TARGET_TYPE (type));
gcc_type target = context->convert_type (TYPE_TARGET_TYPE (type));
return context->c_plugin->build_pointer_type (target);
return context->plugin ().build_pointer_type (target);
}
/* Convert an array type to its gcc representation. */
static gcc_type
convert_array (struct compile_c_instance *context, struct type *type)
convert_array (compile_c_instance *context, struct type *type)
{
gcc_type element_type;
struct type *range = TYPE_INDEX_TYPE (type);
element_type = convert_type (context, TYPE_TARGET_TYPE (type));
element_type = context->convert_type (TYPE_TARGET_TYPE (type));
if (TYPE_LOW_BOUND_KIND (range) != PROP_CONST)
return context->c_plugin->error (_("array type with non-constant"
return context->plugin ().error (_("array type with non-constant"
" lower bound is not supported"));
if (TYPE_LOW_BOUND (range) != 0)
return context->c_plugin->error (_("cannot convert array type with "
return context->plugin ().error (_("cannot convert array type with "
"non-zero lower bound to C"));
if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR
@ -125,12 +149,12 @@ convert_array (struct compile_c_instance *context, struct type *type)
gcc_type result;
if (TYPE_VECTOR (type))
return context->c_plugin->error (_("variably-sized vector type"
return context->plugin ().error (_("variably-sized vector type"
" is not supported"));
std::string upper_bound
= c_get_range_decl_name (&TYPE_RANGE_DATA (range)->high);
result = context->c_plugin->build_vla_array_type (element_type,
result = context->plugin ().build_vla_array_type (element_type,
upper_bound.c_str ());
return result;
}
@ -147,15 +171,15 @@ convert_array (struct compile_c_instance *context, struct type *type)
}
if (TYPE_VECTOR (type))
return context->c_plugin->build_vector_type (element_type, count);
return context->c_plugin->build_array_type (element_type, count);
return context->plugin ().build_vector_type (element_type, count);
return context->plugin ().build_array_type (element_type, count);
}
}
/* Convert a struct or union type to its gcc representation. */
static gcc_type
convert_struct_or_union (struct compile_c_instance *context, struct type *type)
convert_struct_or_union (compile_c_instance *context, struct type *type)
{
int i;
gcc_type result;
@ -163,54 +187,52 @@ convert_struct_or_union (struct compile_c_instance *context, struct type *type)
/* First we create the resulting type and enter it into our hash
table. This lets recursive types work. */
if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
result = context->c_plugin->build_record_type ();
result = context->plugin ().build_record_type ();
else
{
gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
result = context->c_plugin->build_union_type ();
result = context->plugin ().build_union_type ();
}
insert_type (context, type, result);
context->insert_type (type, result);
for (i = 0; i < TYPE_NFIELDS (type); ++i)
{
gcc_type field_type;
unsigned long bitsize = TYPE_FIELD_BITSIZE (type, i);
field_type = convert_type (context, TYPE_FIELD_TYPE (type, i));
field_type = context->convert_type (TYPE_FIELD_TYPE (type, i));
if (bitsize == 0)
bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
context->c_plugin->build_add_field (result,
context->plugin ().build_add_field (result,
TYPE_FIELD_NAME (type, i),
field_type,
bitsize,
TYPE_FIELD_BITPOS (type, i));
}
context->c_plugin->finish_record_or_union (result, TYPE_LENGTH (type));
context->plugin ().finish_record_or_union (result, TYPE_LENGTH (type));
return result;
}
/* Convert an enum type to its gcc representation. */
static gcc_type
convert_enum (struct compile_c_instance *context, struct type *type)
convert_enum (compile_c_instance *context, struct type *type)
{
gcc_type int_type, result;
int i;
const gcc_c_plugin *plugin = context->c_plugin;
int_type = plugin->int_type_v0 (TYPE_UNSIGNED (type),
TYPE_LENGTH (type));
int_type = context->plugin ().int_type_v0 (TYPE_UNSIGNED (type),
TYPE_LENGTH (type));
result = plugin->build_enum_type (int_type);
result = context->plugin ().build_enum_type (int_type);
for (i = 0; i < TYPE_NFIELDS (type); ++i)
{
plugin->build_add_enum_constant (result,
TYPE_FIELD_NAME (type, i),
TYPE_FIELD_ENUMVAL (type, i));
context->plugin ().build_add_enum_constant
(result, TYPE_FIELD_NAME (type, i), TYPE_FIELD_ENUMVAL (type, i));
}
plugin->finish_enum_type (result);
context->plugin ().finish_enum_type (result);
return result;
}
@ -218,7 +240,7 @@ convert_enum (struct compile_c_instance *context, struct type *type)
/* Convert a function type to its gcc representation. */
static gcc_type
convert_func (struct compile_c_instance *context, struct type *type)
convert_func (compile_c_instance *context, struct type *type)
{
int i;
gcc_type result, return_type;
@ -243,14 +265,14 @@ convert_func (struct compile_c_instance *context, struct type *type)
/* This approach means we can't make self-referential function
types. Those are impossible in C, though. */
return_type = convert_type (context, target_type);
return_type = context->convert_type (target_type);
array.n_elements = TYPE_NFIELDS (type);
array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (type));
for (i = 0; i < TYPE_NFIELDS (type); ++i)
array.elements[i] = convert_type (context, TYPE_FIELD_TYPE (type, i));
array.elements[i] = context->convert_type (TYPE_FIELD_TYPE (type, i));
result = context->c_plugin->build_function_type (return_type,
result = context->plugin ().build_function_type (return_type,
&array, is_varargs);
xfree (array.elements);
@ -260,62 +282,62 @@ convert_func (struct compile_c_instance *context, struct type *type)
/* Convert an integer type to its gcc representation. */
static gcc_type
convert_int (struct compile_c_instance *context, struct type *type)
convert_int (compile_c_instance *context, struct type *type)
{
if (context->c_plugin->version () >= GCC_C_FE_VERSION_1)
if (context->plugin ().version () >= GCC_C_FE_VERSION_1)
{
if (TYPE_NOSIGN (type))
{
gdb_assert (TYPE_LENGTH (type) == 1);
return context->c_plugin->char_type ();
return context->plugin ().char_type ();
}
return context->c_plugin->int_type (TYPE_UNSIGNED (type),
return context->plugin ().int_type (TYPE_UNSIGNED (type),
TYPE_LENGTH (type),
TYPE_NAME (type));
}
else
return context->c_plugin->int_type_v0 (TYPE_UNSIGNED (type),
return context->plugin ().int_type_v0 (TYPE_UNSIGNED (type),
TYPE_LENGTH (type));
}
/* Convert a floating-point type to its gcc representation. */
static gcc_type
convert_float (struct compile_c_instance *context, struct type *type)
convert_float (compile_c_instance *context, struct type *type)
{
if (context->c_plugin->version () >= GCC_C_FE_VERSION_1)
return context->c_plugin->float_type (TYPE_LENGTH (type),
if (context->plugin ().version () >= GCC_C_FE_VERSION_1)
return context->plugin ().float_type (TYPE_LENGTH (type),
TYPE_NAME (type));
else
return context->c_plugin->float_type_v0 (TYPE_LENGTH (type));
return context->plugin ().float_type_v0 (TYPE_LENGTH (type));
}
/* Convert the 'void' type to its gcc representation. */
static gcc_type
convert_void (struct compile_c_instance *context, struct type *type)
convert_void (compile_c_instance *context, struct type *type)
{
return context->c_plugin->void_type ();
return context->plugin ().void_type ();
}
/* Convert a boolean type to its gcc representation. */
static gcc_type
convert_bool (struct compile_c_instance *context, struct type *type)
convert_bool (compile_c_instance *context, struct type *type)
{
return context->c_plugin->bool_type ();
return context->plugin ().bool_type ();
}
/* Convert a qualified type to its gcc representation. */
static gcc_type
convert_qualified (struct compile_c_instance *context, struct type *type)
convert_qualified (compile_c_instance *context, struct type *type)
{
struct type *unqual = make_unqualified_type (type);
gcc_type unqual_converted;
gcc_qualifiers_flags quals = 0;
unqual_converted = convert_type (context, unqual);
unqual_converted = context->convert_type (unqual);
if (TYPE_CONST (type))
quals |= GCC_QUALIFIER_CONST;
@ -324,17 +346,17 @@ convert_qualified (struct compile_c_instance *context, struct type *type)
if (TYPE_RESTRICT (type))
quals |= GCC_QUALIFIER_RESTRICT;
return context->c_plugin->build_qualified_type (unqual_converted, quals);
return context->plugin ().build_qualified_type (unqual_converted, quals);
}
/* Convert a complex type to its gcc representation. */
static gcc_type
convert_complex (struct compile_c_instance *context, struct type *type)
convert_complex (compile_c_instance *context, struct type *type)
{
gcc_type base = convert_type (context, TYPE_TARGET_TYPE (type));
gcc_type base = context->convert_type (TYPE_TARGET_TYPE (type));
return context->c_plugin->build_complex_type (base);
return context->plugin ().build_complex_type (base);
}
/* A helper function which knows how to convert most types from their
@ -343,7 +365,7 @@ convert_complex (struct compile_c_instance *context, struct type *type)
returns the gcc type. */
static gcc_type
convert_type_basic (struct compile_c_instance *context, struct type *type)
convert_type_basic (compile_c_instance *context, struct type *type)
{
/* If we are converting a qualified type, first convert the
unqualified type and then apply the qualifiers. */
@ -401,75 +423,38 @@ convert_type_basic (struct compile_c_instance *context, struct type *type)
}
}
return context->c_plugin->error (_("cannot convert gdb type to gcc type"));
return context->plugin ().error (_("cannot convert gdb type to gcc type"));
}
/* See compile-internal.h. */
/* Default compile flags for C. */
const char *compile_c_instance::m_default_cflags = "-std=gnu11"
/* Otherwise the .o file may need
"_Unwind_Resume" and
"__gcc_personality_v0". */
" -fno-exceptions"
" -Wno-implicit-function-declaration";
/* See compile-c.h. */
gcc_type
convert_type (struct compile_c_instance *context, struct type *type)
compile_c_instance::convert_type (struct type *type)
{
struct type_map_instance inst, *found;
gcc_type result;
/* We don't ever have to deal with typedefs in this code, because
those are only needed as symbols by the C compiler. */
type = check_typedef (type);
inst.type = type;
found = (struct type_map_instance *) htab_find (context->type_map, &inst);
if (found != NULL)
return found->gcc_type_handle;
gcc_type result;
if (get_cached_type (type, result))
return result;
result = convert_type_basic (context, type);
insert_type (context, type, result);
result = convert_type_basic (this, type);
insert_type (type, result);
return result;
}
/* Delete the compiler instance C. */
static void
delete_instance (struct compile_instance *c)
{
struct compile_c_instance *context = (struct compile_c_instance *) c;
context->base.fe->ops->destroy (context->base.fe);
delete context->c_plugin;
htab_delete (context->type_map);
if (context->symbol_err_map != NULL)
htab_delete (context->symbol_err_map);
xfree (context);
}
/* See compile-internal.h. */
struct compile_instance *
new_compile_instance (struct gcc_c_context *fe)
{
struct compile_c_instance *result = XCNEW (struct compile_c_instance);
result->base.fe = &fe->base;
result->base.destroy = delete_instance;
result->base.gcc_target_options = ("-std=gnu11"
/* Otherwise the .o file may need
"_Unwind_Resume" and
"__gcc_personality_v0". */
" -fno-exceptions");
result->type_map = htab_create_alloc (10, hash_type_map_instance,
eq_type_map_instance,
xfree, xcalloc, xfree);
result->c_plugin = new gcc_c_plugin (fe);
result->c_plugin->set_callbacks (gcc_convert_symbol, gcc_symbol_address,
result);
return &result->base;
}
/* C plug-in wrapper. */
#define FORWARD(OP,...) m_context->c_ops->OP(m_context, ##__VA_ARGS__)

View File

@ -19,7 +19,6 @@
#include "common/enum-flags.h"
#include "gcc-c-plugin.h"
#include "hashtab.h"
/* enum-flags wrapper. */
@ -36,20 +35,30 @@ extern gcc_c_symbol_address_function gcc_symbol_address;
/* A subclass of compile_instance that is specific to the C front
end. */
struct compile_c_instance
class compile_c_instance : public compile_instance
{
/* Base class. Note that the base class vtable actually points to a
gcc_c_fe_vtable. */
struct compile_instance base;
public:
explicit compile_c_instance (struct gcc_c_context *gcc_c)
: compile_instance (&gcc_c->base, m_default_cflags),
m_plugin (gcc_c)
{
m_plugin.set_callbacks (gcc_convert_symbol, gcc_symbol_address, this);
}
/* Map from gdb types to gcc types. */
htab_t type_map;
/* Convert a gdb type, TYPE, to a GCC type.
/* Map from gdb symbols to gcc error messages to emit. */
htab_t symbol_err_map;
The new GCC type is returned. */
gcc_type convert_type (struct type *type);
/* GCC C plugin. */
gcc_c_plugin *c_plugin;
/* Return a handle for the GCC plug-in. */
gcc_c_plugin &plugin () { return m_plugin; }
private:
/* Default compiler flags for C. */
static const char *m_default_cflags;
/* The GCC plug-in. */
gcc_c_plugin m_plugin;
};
/* Emit code to compute the address for all the local variables in
@ -59,7 +68,7 @@ struct compile_c_instance
extern gdb::unique_xmalloc_ptr<unsigned char>
generate_c_for_variable_locations
(struct compile_c_instance *compiler,
(compile_instance *compiler,
string_file &stream,
struct gdbarch *gdbarch,
const struct block *block,

View File

@ -28,28 +28,117 @@ struct block;
/* An object of this type holds state associated with a given
compilation job. */
struct compile_instance
class compile_instance
{
/* The GCC front end. */
public:
compile_instance (struct gcc_base_context *gcc_fe, const char *options);
struct gcc_base_context *fe;
virtual ~compile_instance ()
{
m_gcc_fe->ops->destroy (m_gcc_fe);
htab_delete (m_type_map);
if (m_symbol_err_map != NULL)
htab_delete (m_symbol_err_map);
}
/* Returns the GCC options to be passed during compilation. */
const std::string &gcc_target_options () const
{
return m_gcc_target_options;
}
/* Query the type cache for TYPE, returning the compiler's
type for it in RET. */
bool get_cached_type (struct type *type, gcc_type &ret) const;
/* Insert GCC_TYPE into the type cache for TYPE.
It is ok for a given type to be inserted more than once, provided that
the exact same association is made each time. */
void insert_type (struct type *type, gcc_type gcc_type);
/* Associate SYMBOL with some error text. */
void insert_symbol_error (const struct symbol *sym, const char *text);
/* Emit the error message corresponding to SYM, if one exists, and
arrange for it not to be emitted again. */
void error_symbol_once (const struct symbol *sym);
/* These currently just forward to the underlying ops
vtable. */
/* Set the plug-in print callback. */
void set_print_callback (void (*print_function) (void *, const char *),
void *datum);
/* Return the plug-in's front-end version. */
unsigned int version () const;
/* Set the plug-in's verbosity level. Nop for GCC_FE_VERSION_0. */
void set_verbose (int level);
/* Set the plug-in driver program. Nop for GCC_FE_VERSION_0. */
void set_driver_filename (const char *filename);
/* Set the regular expression used to match the configury triplet
prefix to the compiler. Nop for GCC_FE_VERSION_0. */
void set_triplet_regexp (const char *regexp);
/* Set compilation arguments. REGEXP is only used for protocol
version GCC_FE_VERSION_0. */
char *set_arguments (int argc, char **argv, const char *regexp = NULL);
/* Set the filename of the program to compile. Nop for GCC_FE_VERSION_0. */
void set_source_file (const char *filename);
/* Compile the previously specified source file to FILENAME.
VERBOSE_LEVEL is only used for protocol version GCC_FE_VERSION_0. */
bool compile (const char *filename, int verbose_level = -1);
/* Set the scope type for this compile. */
void set_scope (enum compile_i_scope_types scope)
{
m_scope = scope;
}
/* Return the scope type. */
enum compile_i_scope_types scope () const
{
return m_scope;
}
/* Set the block to be used for symbol searches. */
void set_block (const struct block *block)
{
m_block = block;
}
/* Return the search block. */
const struct block *block () const
{
return m_block;
}
protected:
/* The GCC front end. */
struct gcc_base_context *m_gcc_fe;
/* The "scope" of this compilation. */
enum compile_i_scope_types scope;
enum compile_i_scope_types m_scope;
/* The block in which an expression is being parsed. */
const struct block *block;
const struct block *m_block;
/* Specify "-std=gnu11", "-std=gnu++11" or similar. These options are put
after CU's DW_AT_producer compilation options to override them. */
std::string m_gcc_target_options;
const char *gcc_target_options;
/* Map from gdb types to gcc types. */
htab_t m_type_map;
/* How to destroy this object. */
void (*destroy) (struct compile_instance *);
/* Map from gdb symbols to gcc error messages to emit. */
htab_t m_symbol_err_map;
};
/* Define header and footers for different scopes. */
@ -79,18 +168,6 @@ extern std::string compile_register_name_mangled (struct gdbarch *gdbarch,
extern int compile_register_name_demangle (struct gdbarch *gdbarch,
const char *reg_name);
/* Convert a gdb type, TYPE, to a GCC type. CONTEXT is used to do the
actual conversion. The new GCC type is returned. */
struct type;
extern gcc_type convert_type (struct compile_c_instance *context,
struct type *type);
/* Instantiate a GDB object holding state for the GCC context FE. The
new object is returned. */
extern struct compile_instance *new_compile_instance (struct gcc_c_context *fe);
/* Type used to hold and pass around the source and object file names
to use for compilation. */
class compile_file_names

View File

@ -415,7 +415,7 @@ filter_args (int *argcp, char **argv)
generated above. */
static void
get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
get_args (const compile_instance *compiler, struct gdbarch *gdbarch,
int *argcp, char ***argvp)
{
const char *cs_producer_options;
@ -437,7 +437,7 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
freeargv (argv_producer);
}
build_argc_argv (compiler->gcc_target_options,
build_argc_argv (compiler->gcc_target_options ().c_str (),
&argc_compiler, &argv_compiler);
append_args (argcp, argvp, argc_compiler, argv_compiler);
freeargv (argv_compiler);
@ -445,16 +445,6 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
append_args (argcp, argvp, compile_args_argc, compile_args_argv);
}
/* A cleanup function to destroy a gdb_gcc_instance. */
static void
cleanup_compile_instance (void *arg)
{
struct compile_instance *inst = (struct compile_instance *) arg;
inst->destroy (inst);
}
/* A helper function suitable for use as the "print_callback" in the
compiler object. */
@ -472,8 +462,6 @@ static compile_file_names
compile_to_object (struct command_line *cmd, const char *cmd_string,
enum compile_i_scope_types scope)
{
struct compile_instance *compiler;
struct cleanup *cleanup;
const struct block *expr_block;
CORE_ADDR trash_pc, expr_pc;
int argc;
@ -481,7 +469,6 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
int ok;
struct gdbarch *gdbarch = get_current_arch ();
std::string triplet_rx;
char *error_message;
if (!target_has_execution)
error (_("The program must be running for the compile command to "\
@ -494,13 +481,13 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
if (current_language->la_get_compile_instance == NULL)
error (_("No compiler support for language %s."),
current_language->la_name);
compiler = current_language->la_get_compile_instance ();
cleanup = make_cleanup (cleanup_compile_instance, compiler);
compiler->fe->ops->set_print_callback (compiler->fe, print_callback, NULL);
compiler->scope = scope;
compiler->block = expr_block;
compile_instance *compiler_instance
= current_language->la_get_compile_instance ();
std::unique_ptr<compile_instance> compiler (compiler_instance);
compiler->set_print_callback (print_callback, NULL);
compiler->set_scope (scope);
compiler->set_block (expr_block);
/* From the provided expression, build a scope to pass to the
compiler. */
@ -526,21 +513,20 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
error (_("Neither a simple expression, or a multi-line specified."));
std::string code
= current_language->la_compute_program (compiler, input, gdbarch,
= current_language->la_compute_program (compiler.get (), input, gdbarch,
expr_block, expr_pc);
if (compile_debug)
fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code.c_str ());
if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
compiler->fe->ops->set_verbose (compiler->fe, compile_debug);
compiler->set_verbose (compile_debug);
if (compile_gcc[0] != 0)
{
if (compiler->fe->ops->version < GCC_FE_VERSION_1)
if (compiler->version () < GCC_FE_VERSION_1)
error (_("Command 'set compile-gcc' requires GCC version 6 or higher "
"(libcc1 interface version 1 or higher)"));
compiler->fe->ops->set_driver_filename (compiler->fe, compile_gcc);
compiler->set_driver_filename (compile_gcc);
}
else
{
@ -549,27 +535,19 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
/* Allow triplets with or without vendor set. */
triplet_rx = std::string (arch_rx) + "(-[^-]*)?-" + os_rx;
if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
compiler->fe->ops->set_triplet_regexp (compiler->fe,
triplet_rx.c_str ());
compiler->set_triplet_regexp (triplet_rx.c_str ());
}
/* Set compiler command-line arguments. */
get_args (compiler, gdbarch, &argc, &argv);
get_args (compiler.get (), gdbarch, &argc, &argv);
gdb_argv argv_holder (argv);
if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
error_message = compiler->fe->ops->set_arguments (compiler->fe, argc, argv);
else
error_message = compiler->fe->ops->set_arguments_v0 (compiler->fe,
triplet_rx.c_str (),
argc, argv);
gdb::unique_xmalloc_ptr<char> error_message;
error_message.reset (compiler->set_arguments (argc, argv,
triplet_rx.c_str ()));
if (error_message != NULL)
{
make_cleanup (xfree, error_message);
error ("%s", error_message);
}
error ("%s", error_message.get ());
if (compile_debug)
{
@ -601,13 +579,8 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
fnames.source_file ());
/* Call the compiler and start the compilation process. */
compiler->fe->ops->set_source_file (compiler->fe, fnames.source_file ());
if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
ok = compiler->fe->ops->compile (compiler->fe, fnames.object_file ());
else
ok = compiler->fe->ops->compile_v0 (compiler->fe, fnames.object_file (),
compile_debug);
compiler->set_source_file (fnames.source_file ());
ok = compiler->compile (fnames.object_file (), compile_debug);
if (!ok)
error (_("Compilation failed."));
@ -617,9 +590,6 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
/* Keep the source file. */
source_remover->keep ();
do_cleanups (cleanup);
return fnames;
}
@ -691,6 +661,87 @@ compile_register_name_demangle (struct gdbarch *gdbarch,
error (_("Cannot find gdbarch register \"%s\"."), regname);
}
/* Forwards to the plug-in. */
#define FORWARD(OP,...) (m_gcc_fe->ops->OP (m_gcc_fe, ##__VA_ARGS__))
/* See compile-internal.h. */
void
compile_instance::set_print_callback
(void (*print_function) (void *, const char *), void *datum)
{
FORWARD (set_print_callback, print_function, datum);
}
/* See compile-internal.h. */
unsigned int
compile_instance::version () const
{
return m_gcc_fe->ops->version;
}
/* See compile-internal.h. */
void
compile_instance::set_verbose (int level)
{
if (version () >= GCC_FE_VERSION_1)
FORWARD (set_verbose, level);
}
/* See compile-internal.h. */
void
compile_instance::set_driver_filename (const char *filename)
{
if (version () >= GCC_FE_VERSION_1)
FORWARD (set_driver_filename, filename);
}
/* See compile-internal.h. */
void
compile_instance::set_triplet_regexp (const char *regexp)
{
if (version () >= GCC_FE_VERSION_1)
FORWARD (set_triplet_regexp, regexp);
}
/* See compile-internal.h. */
char *
compile_instance::set_arguments (int argc, char **argv, const char *regexp)
{
if (version () >= GCC_FE_VERSION_1)
return FORWARD (set_arguments, argc, argv);
else
return FORWARD (set_arguments_v0, regexp, argc, argv);
}
/* See compile-internal.h. */
void
compile_instance::set_source_file (const char *filename)
{
FORWARD (set_source_file, filename);
}
/* See compile-internal.h. */
bool
compile_instance::compile (const char *filename, int verbose_level)
{
if (version () >= GCC_FE_VERSION_1)
return FORWARD (compile, filename);
else
return FORWARD (compile_v0, filename, verbose_level);
}
#undef FORWARD
void
_initialize_compile (void)
{

View File

@ -36,7 +36,7 @@ struct value_print_options;
struct type_print_options;
struct lang_varobj_ops;
struct parser_state;
struct compile_instance;
class compile_instance;
struct completion_match_for_lcd;
#define MAX_FORTRAN_DIMS 7 /* Maximum number of F77 array dims. */
@ -424,7 +424,7 @@ struct language_defn
instance is owned by its caller and must be deallocated by
calling its 'destroy' method. */
struct compile_instance *(*la_get_compile_instance) (void);
compile_instance *(*la_get_compile_instance) (void);
/* This method must be defined if 'la_get_gcc_context' is defined.
If 'la_get_gcc_context' is not defined, then this method is
@ -440,7 +440,7 @@ struct language_defn
parsed.
EXPR_PC is the PC at which the expression is being parsed. */
std::string (*la_compute_program) (struct compile_instance *inst,
std::string (*la_compute_program) (compile_instance *inst,
const char *input,
struct gdbarch *gdbarch,
const struct block *expr_block,