+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.
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.
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,
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;
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);
}
\f
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;
/* 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;
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");
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:
"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:
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 ());
}
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);
}
}
-/* 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;
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)
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
/* 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);
}
/* 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);
}
}
}
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;
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;
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. */
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;
{
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);
CATCH (e, RETURN_MASK_ALL)
{
- context->c_plugin->error (e.message);
+ context->plugin ().error (e.message);
}
END_CATCH
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;
CATCH (e, RETURN_MASK_ERROR)
{
- context->c_plugin->error (e.message);
+ context->plugin ().error (e.message);
}
END_CATCH
/* 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,
/* 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,
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
}
/* 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,
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);
+}
+
\f
-/* 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. */
+
+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. */
-static void
-insert_type (struct compile_c_instance *context, struct type *type,
- gcc_type gcc_type)
+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
/* 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
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;
}
}
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;
/* 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;
}
/* 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;
/* 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);
/* 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;
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
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. */
}
}
- 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;
}
\f
-/* 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__)
#include "common/enum-flags.h"
#include "gcc-c-plugin.h"
-#include "hashtab.h"
/* enum-flags wrapper. */
/* 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
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,
/* 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);
+ }
- /* The "scope" of this compilation. */
+ /* Returns the GCC options to be passed during compilation. */
+ const std::string &gcc_target_options () const
+ {
+ return m_gcc_target_options;
+ }
- enum compile_i_scope_types scope;
+ /* 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;
- /* The block in which an expression is being parsed. */
+ /* 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);
- const struct block *block;
+ /* 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 m_scope;
+
+ /* The block in which an expression is being parsed. */
+ 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. */
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
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;
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);
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. */
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;
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 "\
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. */
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
{
/* 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)
{
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."));
/* Keep the source file. */
source_remover->keep ();
-
- do_cleanups (cleanup);
-
return fnames;
}
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)
{
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. */
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
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,