From 18cdc6d8f8e8b55e84783e0a2b5a80b41a0e917b Mon Sep 17 00:00:00 2001 From: Keith Seitz Date: Fri, 10 Aug 2018 10:45:36 -0700 Subject: [PATCH] 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) : New member. * gcc-c-plugin.h: New file. Update all callers with API change. --- gdb/ChangeLog | 12 +++ gdb/Makefile.in | 1 + gdb/compile/compile-c-symbols.c | 30 +++---- gdb/compile/compile-c-types.c | 153 ++++++++++++++++++-------------- gdb/compile/compile-c.h | 9 +- gdb/compile/gcc-c-plugin.h | 64 +++++++++++++ 6 files changed, 180 insertions(+), 89 deletions(-) create mode 100644 gdb/compile/gcc-c-plugin.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c2a3a26a844..6873ee5073e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2018-08-10 Keith Seitz + + * 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) : New member. + * gcc-c-plugin.h: New file. + Update all callers with API change. + 2018-08-10 Keith Seitz * Makefile.in (SUBDIR_GCC_COMPILE_SRCS): Move header files ... diff --git a/gdb/Makefile.in b/gdb/Makefile.in index f9d1b007022..118c3c80626 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -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 \ diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c index c82e0086598..abd829838b1 100644 --- a/gdb/compile/compile-c-symbols.c +++ b/gdb/compile/compile-c-symbols.c @@ -161,9 +161,8 @@ 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), - sym_type, filename, line); + 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), - kind, sym_type, NULL, addr, - NULL, 0); - C_CTX (context)->c_ops->bind (C_CTX (context), decl, 1 /* is_global */); + decl = context->c_plugin->build_decl (MSYMBOL_NATURAL_NAME (msym), + kind, sym_type, NULL, addr, + NULL, 0); + 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 diff --git a/gdb/compile/compile-c-types.c b/gdb/compile/compile-c-types.c index 46b9f2b3b42..228966f7387 100644 --- a/gdb/compile/compile-c-types.c +++ b/gdb/compile/compile-c-types.c @@ -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,13 +113,11 @@ 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" - " lower bound is not supported")); + 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 " - "non-zero lower bound to C")); + return context->c_plugin->error (_("cannot convert array type with " + "non-zero lower bound to C")); if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR || TYPE_HIGH_BOUND_KIND (range) == PROP_LOCLIST) @@ -128,15 +125,13 @@ 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" - " is not supported")); + 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, - upper_bound.c_str ()); + result = context->c_plugin->build_vla_array_type (element_type, + upper_bound.c_str ()); return result; } else @@ -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, - TYPE_FIELD_NAME (type, i), - field_type, - bitsize, - TYPE_FIELD_BITPOS (type, i)); + 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), - TYPE_LENGTH (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, - TYPE_FIELD_NAME (type, i), - TYPE_FIELD_ENUMVAL (type, i)); + 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,9 +250,8 @@ 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, - &array, is_varargs); + result = context->c_plugin->build_function_type (return_type, + &array, is_varargs); xfree (array.elements); return result; @@ -274,22 +262,20 @@ 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), - TYPE_LENGTH (type), - TYPE_NAME (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), - TYPE_LENGTH (type)); + return context->c_plugin->int_type_v0 (TYPE_UNSIGNED (type), + TYPE_LENGTH (type)); } /* Convert a floating-point type to its gcc representation. */ @@ -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), - TYPE_NAME (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 diff --git a/gdb/compile/compile-c.h b/gdb/compile/compile-c.h index cff2aef906e..ffa58021e28 100644 --- a/gdb/compile/compile-c.h +++ b/gdb/compile/compile-c.h @@ -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,12 +47,10 @@ struct compile_c_instance /* Map from gdb symbols to gcc error messages to emit. */ htab_t symbol_err_map; -}; - -/* 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)) + /* GCC C plugin. */ + gcc_c_plugin *c_plugin; +}; /* 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 diff --git a/gdb/compile/gcc-c-plugin.h b/gdb/compile/gcc-c-plugin.h new file mode 100644 index 00000000000..12d422f6aae --- /dev/null +++ b/gdb/compile/gcc-c-plugin.h @@ -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 . */ + +/* 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; +}; -- 2.30.2