Add a C++ wrapper for GCC C plug-in
This patch introduces a new class which wraps the GCC C compile plug-in. It is a little unfortunate that this all happened in between the time that GCC moved to C++ and GDB moved to C++, leaving us with an ABI promise to support a C-like interface. The hope is to isolate GDB from some of this should it change in the future. Broadly, what this does is replace calls like: C_CTX (context)->c_ops->operation (C_CTX (context), ...); with calls that now look like: context->c_plugin->operation (...); This API will be further refined in following patches when struct compile_instance/compile_c_instance are changed into classes. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add compile/gcc-c-plugin.h. * compile/compile-c-types.c: Define GCC_METHODN macros and include gcc-c-fe.def to define C plugin. (delete_instance): Delete `c_plugin'. (new_compile_instance): Initialize `c_plugin'. * compile/compile-c.h: Include gcc_c_plugin.h. (struct compile_c_instance) <c_plugin>: New member. * gcc-c-plugin.h: New file. Update all callers with API change.
This commit is contained in:
parent
b7dc48b4a8
commit
18cdc6d8f8
@ -1,3 +1,15 @@
|
||||
2018-08-10 Keith Seitz <keiths@redhat.com>
|
||||
|
||||
* Makefile.in (HFILES_NO_SRCDIR): Add compile/gcc-c-plugin.h.
|
||||
* compile/compile-c-types.c: Define GCC_METHODN macros and include
|
||||
gcc-c-fe.def to define C plugin.
|
||||
(delete_instance): Delete `c_plugin'.
|
||||
(new_compile_instance): Initialize `c_plugin'.
|
||||
* compile/compile-c.h: Include gcc_c_plugin.h.
|
||||
(struct compile_c_instance) <c_plugin>: New member.
|
||||
* gcc-c-plugin.h: New file.
|
||||
Update all callers with API change.
|
||||
|
||||
2018-08-10 Keith Seitz <keiths@redhat.com>
|
||||
|
||||
* Makefile.in (SUBDIR_GCC_COMPILE_SRCS): Move header files ...
|
||||
|
@ -1464,6 +1464,7 @@ HFILES_NO_SRCDIR = \
|
||||
compile/compile-internal.h \
|
||||
compile/compile-object-load.h \
|
||||
compile/compile-object-run.h \
|
||||
compile/gcc-c-plugin.h \
|
||||
config/nm-linux.h \
|
||||
config/nm-nto.h \
|
||||
config/djgpp/langinfo.h \
|
||||
|
@ -161,8 +161,7 @@ convert_one_symbol (struct compile_c_instance *context,
|
||||
if (SYMBOL_DOMAIN (sym.symbol) == STRUCT_DOMAIN)
|
||||
{
|
||||
/* Binding a tag, so we don't need to build a decl. */
|
||||
C_CTX (context)->c_ops->tagbind (C_CTX (context),
|
||||
SYMBOL_NATURAL_NAME (sym.symbol),
|
||||
context->c_plugin->tagbind (SYMBOL_NATURAL_NAME (sym.symbol),
|
||||
sym_type, filename, line);
|
||||
}
|
||||
else
|
||||
@ -196,9 +195,8 @@ convert_one_symbol (struct compile_c_instance *context,
|
||||
/* Already handled by convert_enum. */
|
||||
return;
|
||||
}
|
||||
C_CTX (context)->c_ops->build_constant
|
||||
(C_CTX (context),
|
||||
sym_type, SYMBOL_NATURAL_NAME (sym.symbol),
|
||||
context->c_plugin->build_constant
|
||||
(sym_type, SYMBOL_NATURAL_NAME (sym.symbol),
|
||||
SYMBOL_VALUE (sym.symbol),
|
||||
filename, line);
|
||||
return;
|
||||
@ -285,15 +283,14 @@ convert_one_symbol (struct compile_c_instance *context,
|
||||
if (context->base.scope != COMPILE_I_RAW_SCOPE
|
||||
|| symbol_name == NULL)
|
||||
{
|
||||
decl = C_CTX (context)->c_ops->build_decl
|
||||
(C_CTX (context),
|
||||
SYMBOL_NATURAL_NAME (sym.symbol),
|
||||
decl = context->c_plugin->build_decl
|
||||
(SYMBOL_NATURAL_NAME (sym.symbol),
|
||||
kind,
|
||||
sym_type,
|
||||
symbol_name.get (), addr,
|
||||
filename, line);
|
||||
|
||||
C_CTX (context)->c_ops->bind (C_CTX (context), decl, is_global);
|
||||
context->c_plugin->bind (decl, is_global);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -402,11 +399,10 @@ convert_symbol_bmsym (struct compile_c_instance *context,
|
||||
}
|
||||
|
||||
sym_type = convert_type (context, type);
|
||||
decl = C_CTX (context)->c_ops->build_decl (C_CTX (context),
|
||||
MSYMBOL_NATURAL_NAME (msym),
|
||||
decl = context->c_plugin->build_decl (MSYMBOL_NATURAL_NAME (msym),
|
||||
kind, sym_type, NULL, addr,
|
||||
NULL, 0);
|
||||
C_CTX (context)->c_ops->bind (C_CTX (context), decl, 1 /* is_global */);
|
||||
context->c_plugin->bind (decl, 1 /* is_global */);
|
||||
}
|
||||
|
||||
/* See compile-internal.h. */
|
||||
@ -463,7 +459,7 @@ gcc_convert_symbol (void *datum,
|
||||
|
||||
CATCH (e, RETURN_MASK_ALL)
|
||||
{
|
||||
C_CTX (context)->c_ops->error (C_CTX (context), e.message);
|
||||
context->c_plugin->error (e.message);
|
||||
}
|
||||
END_CATCH
|
||||
|
||||
@ -525,7 +521,7 @@ gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
|
||||
|
||||
CATCH (e, RETURN_MASK_ERROR)
|
||||
{
|
||||
C_CTX (context)->c_ops->error (C_CTX (context), e.message);
|
||||
context->c_plugin->error (e.message);
|
||||
}
|
||||
END_CATCH
|
||||
|
||||
|
@ -99,8 +99,7 @@ convert_pointer (struct compile_c_instance *context, struct type *type)
|
||||
{
|
||||
gcc_type target = convert_type (context, TYPE_TARGET_TYPE (type));
|
||||
|
||||
return C_CTX (context)->c_ops->build_pointer_type (C_CTX (context),
|
||||
target);
|
||||
return context->c_plugin->build_pointer_type (target);
|
||||
}
|
||||
|
||||
/* Convert an array type to its gcc representation. */
|
||||
@ -114,12 +113,10 @@ convert_array (struct compile_c_instance *context, struct type *type)
|
||||
element_type = convert_type (context, TYPE_TARGET_TYPE (type));
|
||||
|
||||
if (TYPE_LOW_BOUND_KIND (range) != PROP_CONST)
|
||||
return C_CTX (context)->c_ops->error (C_CTX (context),
|
||||
_("array type with non-constant"
|
||||
return context->c_plugin->error (_("array type with non-constant"
|
||||
" lower bound is not supported"));
|
||||
if (TYPE_LOW_BOUND (range) != 0)
|
||||
return C_CTX (context)->c_ops->error (C_CTX (context),
|
||||
_("cannot convert array type with "
|
||||
return context->c_plugin->error (_("cannot convert array type with "
|
||||
"non-zero lower bound to C"));
|
||||
|
||||
if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR
|
||||
@ -128,14 +125,12 @@ convert_array (struct compile_c_instance *context, struct type *type)
|
||||
gcc_type result;
|
||||
|
||||
if (TYPE_VECTOR (type))
|
||||
return C_CTX (context)->c_ops->error (C_CTX (context),
|
||||
_("variably-sized vector type"
|
||||
return context->c_plugin->error (_("variably-sized vector type"
|
||||
" is not supported"));
|
||||
|
||||
std::string upper_bound
|
||||
= c_get_range_decl_name (&TYPE_RANGE_DATA (range)->high);
|
||||
result = C_CTX (context)->c_ops->build_vla_array_type (C_CTX (context),
|
||||
element_type,
|
||||
result = context->c_plugin->build_vla_array_type (element_type,
|
||||
upper_bound.c_str ());
|
||||
return result;
|
||||
}
|
||||
@ -152,11 +147,8 @@ convert_array (struct compile_c_instance *context, struct type *type)
|
||||
}
|
||||
|
||||
if (TYPE_VECTOR (type))
|
||||
return C_CTX (context)->c_ops->build_vector_type (C_CTX (context),
|
||||
element_type,
|
||||
count);
|
||||
return C_CTX (context)->c_ops->build_array_type (C_CTX (context),
|
||||
element_type, count);
|
||||
return context->c_plugin->build_vector_type (element_type, count);
|
||||
return context->c_plugin->build_array_type (element_type, count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,11 +163,11 @@ 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 = C_CTX (context)->c_ops->build_record_type (C_CTX (context));
|
||||
result = context->c_plugin->build_record_type ();
|
||||
else
|
||||
{
|
||||
gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
|
||||
result = C_CTX (context)->c_ops->build_union_type (C_CTX (context));
|
||||
result = context->c_plugin->build_union_type ();
|
||||
}
|
||||
insert_type (context, type, result);
|
||||
|
||||
@ -187,15 +179,14 @@ convert_struct_or_union (struct compile_c_instance *context, struct type *type)
|
||||
field_type = convert_type (context, TYPE_FIELD_TYPE (type, i));
|
||||
if (bitsize == 0)
|
||||
bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
|
||||
C_CTX (context)->c_ops->build_add_field (C_CTX (context), result,
|
||||
context->c_plugin->build_add_field (result,
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
field_type,
|
||||
bitsize,
|
||||
TYPE_FIELD_BITPOS (type, i));
|
||||
}
|
||||
|
||||
C_CTX (context)->c_ops->finish_record_or_union (C_CTX (context), result,
|
||||
TYPE_LENGTH (type));
|
||||
context->c_plugin->finish_record_or_union (result, TYPE_LENGTH (type));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -206,22 +197,20 @@ convert_enum (struct compile_c_instance *context, struct type *type)
|
||||
{
|
||||
gcc_type int_type, result;
|
||||
int i;
|
||||
struct gcc_c_context *ctx = C_CTX (context);
|
||||
const gcc_c_plugin *plugin = context->c_plugin;
|
||||
|
||||
int_type = ctx->c_ops->int_type_v0 (ctx,
|
||||
TYPE_UNSIGNED (type),
|
||||
int_type = plugin->int_type_v0 (TYPE_UNSIGNED (type),
|
||||
TYPE_LENGTH (type));
|
||||
|
||||
result = ctx->c_ops->build_enum_type (ctx, int_type);
|
||||
result = plugin->build_enum_type (int_type);
|
||||
for (i = 0; i < TYPE_NFIELDS (type); ++i)
|
||||
{
|
||||
ctx->c_ops->build_add_enum_constant (ctx,
|
||||
result,
|
||||
plugin->build_add_enum_constant (result,
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
TYPE_FIELD_ENUMVAL (type, i));
|
||||
}
|
||||
|
||||
ctx->c_ops->finish_enum_type (ctx, result);
|
||||
plugin->finish_enum_type (result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -261,8 +250,7 @@ convert_func (struct compile_c_instance *context, struct type *type)
|
||||
for (i = 0; i < TYPE_NFIELDS (type); ++i)
|
||||
array.elements[i] = convert_type (context, TYPE_FIELD_TYPE (type, i));
|
||||
|
||||
result = C_CTX (context)->c_ops->build_function_type (C_CTX (context),
|
||||
return_type,
|
||||
result = context->c_plugin->build_function_type (return_type,
|
||||
&array, is_varargs);
|
||||
xfree (array.elements);
|
||||
|
||||
@ -274,21 +262,19 @@ convert_func (struct compile_c_instance *context, struct type *type)
|
||||
static gcc_type
|
||||
convert_int (struct compile_c_instance *context, struct type *type)
|
||||
{
|
||||
if (C_CTX (context)->c_ops->c_version >= GCC_C_FE_VERSION_1)
|
||||
if (context->c_plugin->version () >= GCC_C_FE_VERSION_1)
|
||||
{
|
||||
if (TYPE_NOSIGN (type))
|
||||
{
|
||||
gdb_assert (TYPE_LENGTH (type) == 1);
|
||||
return C_CTX (context)->c_ops->char_type (C_CTX (context));
|
||||
return context->c_plugin->char_type ();
|
||||
}
|
||||
return C_CTX (context)->c_ops->int_type (C_CTX (context),
|
||||
TYPE_UNSIGNED (type),
|
||||
return context->c_plugin->int_type (TYPE_UNSIGNED (type),
|
||||
TYPE_LENGTH (type),
|
||||
TYPE_NAME (type));
|
||||
}
|
||||
else
|
||||
return C_CTX (context)->c_ops->int_type_v0 (C_CTX (context),
|
||||
TYPE_UNSIGNED (type),
|
||||
return context->c_plugin->int_type_v0 (TYPE_UNSIGNED (type),
|
||||
TYPE_LENGTH (type));
|
||||
}
|
||||
|
||||
@ -297,13 +283,11 @@ convert_int (struct compile_c_instance *context, struct type *type)
|
||||
static gcc_type
|
||||
convert_float (struct compile_c_instance *context, struct type *type)
|
||||
{
|
||||
if (C_CTX (context)->c_ops->c_version >= GCC_C_FE_VERSION_1)
|
||||
return C_CTX (context)->c_ops->float_type (C_CTX (context),
|
||||
TYPE_LENGTH (type),
|
||||
if (context->c_plugin->version () >= GCC_C_FE_VERSION_1)
|
||||
return context->c_plugin->float_type (TYPE_LENGTH (type),
|
||||
TYPE_NAME (type));
|
||||
else
|
||||
return C_CTX (context)->c_ops->float_type_v0 (C_CTX (context),
|
||||
TYPE_LENGTH (type));
|
||||
return context->c_plugin->float_type_v0 (TYPE_LENGTH (type));
|
||||
}
|
||||
|
||||
/* Convert the 'void' type to its gcc representation. */
|
||||
@ -311,7 +295,7 @@ convert_float (struct compile_c_instance *context, struct type *type)
|
||||
static gcc_type
|
||||
convert_void (struct compile_c_instance *context, struct type *type)
|
||||
{
|
||||
return C_CTX (context)->c_ops->void_type (C_CTX (context));
|
||||
return context->c_plugin->void_type ();
|
||||
}
|
||||
|
||||
/* Convert a boolean type to its gcc representation. */
|
||||
@ -319,7 +303,7 @@ convert_void (struct compile_c_instance *context, struct type *type)
|
||||
static gcc_type
|
||||
convert_bool (struct compile_c_instance *context, struct type *type)
|
||||
{
|
||||
return C_CTX (context)->c_ops->bool_type (C_CTX (context));
|
||||
return context->c_plugin->bool_type ();
|
||||
}
|
||||
|
||||
/* Convert a qualified type to its gcc representation. */
|
||||
@ -340,9 +324,7 @@ convert_qualified (struct compile_c_instance *context, struct type *type)
|
||||
if (TYPE_RESTRICT (type))
|
||||
quals |= GCC_QUALIFIER_RESTRICT;
|
||||
|
||||
return C_CTX (context)->c_ops->build_qualified_type (C_CTX (context),
|
||||
unqual_converted,
|
||||
quals);
|
||||
return context->c_plugin->build_qualified_type (unqual_converted, quals);
|
||||
}
|
||||
|
||||
/* Convert a complex type to its gcc representation. */
|
||||
@ -352,7 +334,7 @@ convert_complex (struct compile_c_instance *context, struct type *type)
|
||||
{
|
||||
gcc_type base = convert_type (context, TYPE_TARGET_TYPE (type));
|
||||
|
||||
return C_CTX (context)->c_ops->build_complex_type (C_CTX (context), base);
|
||||
return context->c_plugin->build_complex_type (base);
|
||||
}
|
||||
|
||||
/* A helper function which knows how to convert most types from their
|
||||
@ -419,9 +401,7 @@ convert_type_basic (struct compile_c_instance *context, struct type *type)
|
||||
}
|
||||
}
|
||||
|
||||
return C_CTX (context)->c_ops->error (C_CTX (context),
|
||||
_("cannot convert gdb type "
|
||||
"to gcc type"));
|
||||
return context->c_plugin->error (_("cannot convert gdb type to gcc type"));
|
||||
}
|
||||
|
||||
/* See compile-internal.h. */
|
||||
@ -456,6 +436,7 @@ 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);
|
||||
@ -481,8 +462,46 @@ new_compile_instance (struct gcc_c_context *fe)
|
||||
eq_type_map_instance,
|
||||
xfree, xcalloc, xfree);
|
||||
|
||||
fe->c_ops->set_callbacks (fe, gcc_convert_symbol,
|
||||
gcc_symbol_address, result);
|
||||
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__)
|
||||
#define GCC_METHOD0(R, N) \
|
||||
R gcc_c_plugin::N () const \
|
||||
{ return FORWARD (N); }
|
||||
#define GCC_METHOD1(R, N, A) \
|
||||
R gcc_c_plugin::N (A a) const \
|
||||
{ return FORWARD (N, a); }
|
||||
#define GCC_METHOD2(R, N, A, B) \
|
||||
R gcc_c_plugin::N (A a, B b) const \
|
||||
{ return FORWARD (N, a, b); }
|
||||
#define GCC_METHOD3(R, N, A, B, C) \
|
||||
R gcc_c_plugin::N (A a, B b, C c) const \
|
||||
{ return FORWARD (N, a, b, c); }
|
||||
#define GCC_METHOD4(R, N, A, B, C, D) \
|
||||
R gcc_c_plugin::N (A a, B b, C c, D d) const \
|
||||
{ return FORWARD (N, a, b, c, d); }
|
||||
#define GCC_METHOD5(R, N, A, B, C, D, E) \
|
||||
R gcc_c_plugin::N (A a, B b, C c, D d, E e) const \
|
||||
{ return FORWARD (N, a, b, c, d, e); }
|
||||
#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
|
||||
R gcc_c_plugin::N (A a, B b, C c, D d, E e, F f, G g) const \
|
||||
{ return FORWARD (N, a, b, c, d, e, f, g); }
|
||||
|
||||
#include "gcc-c-fe.def"
|
||||
|
||||
#undef GCC_METHOD0
|
||||
#undef GCC_METHOD1
|
||||
#undef GCC_METHOD2
|
||||
#undef GCC_METHOD3
|
||||
#undef GCC_METHOD4
|
||||
#undef GCC_METHOD5
|
||||
#undef GCC_METHOD7
|
||||
#undef FORWARD
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define GDB_COMPILE_C_H
|
||||
|
||||
#include "common/enum-flags.h"
|
||||
#include "gcc-c-plugin.h"
|
||||
#include "hashtab.h"
|
||||
|
||||
/* enum-flags wrapper. */
|
||||
@ -46,13 +47,11 @@ struct compile_c_instance
|
||||
|
||||
/* Map from gdb symbols to gcc error messages to emit. */
|
||||
htab_t symbol_err_map;
|
||||
|
||||
/* GCC C plugin. */
|
||||
gcc_c_plugin *c_plugin;
|
||||
};
|
||||
|
||||
/* A helper macro that takes a compile_c_instance and returns its
|
||||
corresponding gcc_c_context. */
|
||||
|
||||
#define C_CTX(I) ((struct gcc_c_context *) ((I)->base.fe))
|
||||
|
||||
/* Emit code to compute the address for all the local variables in
|
||||
scope at PC in BLOCK. Returns a malloc'd vector, indexed by gdb
|
||||
register number, where each element indicates if the corresponding
|
||||
|
64
gdb/compile/gcc-c-plugin.h
Normal file
64
gdb/compile/gcc-c-plugin.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* GCC C plug-in wrapper for GDB.
|
||||
|
||||
Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* A class representing the C plug-in. */
|
||||
|
||||
class gcc_c_plugin
|
||||
{
|
||||
public:
|
||||
|
||||
explicit gcc_c_plugin (struct gcc_c_context *gcc_c)
|
||||
: m_context (gcc_c)
|
||||
{
|
||||
}
|
||||
|
||||
/* Set the oracle callbacks to be used by the compiler plug-in. */
|
||||
void set_callbacks (gcc_c_oracle_function *binding_oracle,
|
||||
gcc_c_symbol_address_function *address_oracle,
|
||||
void *datum)
|
||||
{
|
||||
m_context->c_ops->set_callbacks (m_context, binding_oracle,
|
||||
address_oracle, datum);
|
||||
}
|
||||
|
||||
/* Returns the interface version of the compiler plug-in. */
|
||||
int version () const { return m_context->c_ops->c_version; }
|
||||
|
||||
#define GCC_METHOD0(R, N) R N () const;
|
||||
#define GCC_METHOD1(R, N, A) R N (A) const;
|
||||
#define GCC_METHOD2(R, N, A, B) R N (A, B) const;
|
||||
#define GCC_METHOD3(R, N, A, B, C) R N (A, B, C) const;
|
||||
#define GCC_METHOD4(R, N, A, B, C, D) R N (A, B, C, D) const;
|
||||
#define GCC_METHOD5(R, N, A, B, C, D, E) R N (A, B, C, D, E) const;
|
||||
#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) R N (A, B, C, D, E, F, G) const;
|
||||
|
||||
#include "gcc-c-fe.def"
|
||||
|
||||
#undef GCC_METHOD0
|
||||
#undef GCC_METHOD1
|
||||
#undef GCC_METHOD2
|
||||
#undef GCC_METHOD3
|
||||
#undef GCC_METHOD4
|
||||
#undef GCC_METHOD5
|
||||
#undef GCC_METHOD7
|
||||
|
||||
private:
|
||||
/* The GCC C context. */
|
||||
struct gcc_c_context *m_context;
|
||||
};
|
Loading…
Reference in New Issue
Block a user