libcc1: share GDB plugin code

The two GDB plugins in libcc1 share a fair amount of code.  This was
done by copy-and-paste, though in reality the underlying code is
nearly identical.

libcc1

	* libcp1.cc (struct libcp1): Derive from base_gdb_plugin.  Remove
	shared code.
	(class libcp1_connection): Remove.
	(rpc): Remove.
	(libcp1_set_verbose, libcp1_compile): Update.
	(cp_call_binding_oracle, cp_call_symbol_address)
	(cp_call_enter_scope, cp_call_leave_scope): Update.
	* libcc1.cc (struct libcc1): Derive from base_gdb_plugin.  Remove
	shared code.
	(class libcc1_connection): Remove.
	(c_call_binding_oracle, c_call_symbol_address): Update.
	(rpc): Remove.
	(libcc1_set_verbose, libcc1_compile): Update.
	* gdbctx.hh: New file.
This commit is contained in:
Tom Tromey 2021-05-04 15:26:58 -06:00
parent 0624823260
commit 1a51cb2990
3 changed files with 145 additions and 178 deletions

105
libcc1/gdbctx.hh Normal file
View File

@ -0,0 +1,105 @@
/* Generic GDB-side plugin
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of GCC.
GCC 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, or (at your option) any later
version.
GCC 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 GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef CC1_PLUGIN_GDBCTX_HH
#define CC1_PLUGIN_GDBCTX_HH
namespace cc1_plugin
{
// The compiler context that we hand back to our caller.
template<typename T>
struct base_gdb_plugin : public T
{
explicit base_gdb_plugin (const gcc_base_vtable *v)
: verbose (false),
compilerp (new compiler (verbose))
{
this->base.ops = v;
}
// A convenience function to print something.
void print (const char *str)
{
this->print_function (this->print_datum, str);
}
// Set the verbose flag.
void set_verbose (bool v)
{
verbose = v;
if (compilerp != nullptr)
compilerp->set_verbose (v);
}
// Make a new connection.
void set_connection (int fd, int aux_fd)
{
connection.reset (new local_connection (fd, aux_fd, this));
}
// A local subclass of connection that holds a back-pointer to the
// context object that we provide to our caller.
class local_connection : public cc1_plugin::connection
{
public:
local_connection (int fd, int aux_fd, base_gdb_plugin<T> *b)
: connection (fd, aux_fd),
back_ptr (b)
{
}
void print (const char *buf) override
{
back_ptr->print (buf);
}
base_gdb_plugin<T> *back_ptr;
};
std::unique_ptr<local_connection> connection;
void (*print_function) (void *datum, const char *message) = nullptr;
void *print_datum = nullptr;
std::vector<std::string> args;
std::string source_file;
/* Non-zero as an equivalent to gcc driver option "-v". */
bool verbose;
std::unique_ptr<cc1_plugin::compiler> compilerp;
};
// Instances of this rpc<> template function are installed into the
// "vtable"s. These functions are parameterized by type and method
// name and forward the call via the connection.
template<typename CTX, typename R, const char *&NAME, typename... Arg>
R rpc (CTX *s, Arg... rest)
{
base_gdb_plugin<CTX> *self = (base_gdb_plugin<CTX> *) s;
R result;
if (!cc1_plugin::call (self->connection.get (), NAME, &result, rest...))
return 0;
return result;
}
}
#endif // CC1_PLUGIN_GDBCTX_HH

View File

@ -37,73 +37,21 @@ along with GCC; see the file COPYING3. If not see
#include "compiler-name.hh"
#include "gcc-c-interface.h"
#include "compiler.hh"
struct libcc1;
class libcc1_connection;
#include "gdbctx.hh"
// The C compiler context that we hand back to our caller.
struct libcc1 : public gcc_c_context
struct libcc1 : public cc1_plugin::base_gdb_plugin<gcc_c_context>
{
libcc1 (const gcc_base_vtable *, const gcc_c_fe_vtable *);
// A convenience function to print something.
void print (const char *str)
{
this->print_function (this->print_datum, str);
}
std::unique_ptr<libcc1_connection> connection;
gcc_c_oracle_function *binding_oracle;
gcc_c_symbol_address_function *address_oracle;
void *oracle_datum;
void (*print_function) (void *datum, const char *message);
void *print_datum;
std::vector<std::string> args;
std::string source_file;
/* Non-zero as an equivalent to gcc driver option "-v". */
bool verbose;
std::unique_ptr<cc1_plugin::compiler> compilerp;
gcc_c_oracle_function *binding_oracle = nullptr;
gcc_c_symbol_address_function *address_oracle = nullptr;
void *oracle_datum = nullptr;
};
// A local subclass of connection that holds a back-pointer to the
// gcc_c_context object that we provide to our caller.
class libcc1_connection : public cc1_plugin::connection
libcc1::libcc1 (const gcc_base_vtable *v, const gcc_c_fe_vtable *cv)
: cc1_plugin::base_gdb_plugin<gcc_c_context> (v)
{
public:
libcc1_connection (int fd, int aux_fd, libcc1 *b)
: connection (fd, aux_fd),
back_ptr (b)
{
}
void print (const char *buf) override
{
back_ptr->print (buf);
}
libcc1 *back_ptr;
};
libcc1::libcc1 (const gcc_base_vtable *v,
const gcc_c_fe_vtable *cv)
: binding_oracle (NULL),
address_oracle (NULL),
oracle_datum (NULL),
print_function (NULL),
print_datum (NULL),
args (),
source_file (),
verbose (false),
compilerp (new cc1_plugin::compiler (verbose))
{
base.ops = v;
c_ops = cv;
}
@ -122,7 +70,7 @@ namespace {
enum gcc_c_oracle_request request,
const char *identifier)
{
libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
libcc1 *self = (libcc1 *) (((libcc1::local_connection *) conn)->back_ptr);
self->binding_oracle (self->oracle_datum, self, request, identifier);
return 1;
@ -133,7 +81,7 @@ namespace {
gcc_address
c_call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
{
libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
libcc1 *self = (libcc1 *) (((libcc1::local_connection *) conn)->back_ptr);
return self->address_oracle (self->oracle_datum, self, identifier);
}
@ -154,40 +102,25 @@ set_callbacks (struct gcc_c_context *s,
self->oracle_datum = datum;
}
// Instances of this rpc<> template function are installed into the
// "c_vtable". These functions are parameterized by type and method
// name and forward the call via the connection.
template<typename R, const char *&NAME, typename... Arg>
R rpc (struct gcc_c_context *s, Arg... rest)
{
libcc1 *self = (libcc1 *) s;
R result;
if (!cc1_plugin::call (self->connection.get (), NAME, &result, rest...))
return 0;
return result;
}
static const struct gcc_c_fe_vtable c_vtable =
{
GCC_C_FE_VERSION_0,
set_callbacks,
#define GCC_METHOD0(R, N) \
rpc<R, cc1_plugin::c::N>,
cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N>,
#define GCC_METHOD1(R, N, A) \
rpc<R, cc1_plugin::c::N, A>,
cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A>,
#define GCC_METHOD2(R, N, A, B) \
rpc<R, cc1_plugin::c::N, A, B>,
cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B>,
#define GCC_METHOD3(R, N, A, B, C) \
rpc<R, cc1_plugin::c::N, A, B, C>,
cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B, C>,
#define GCC_METHOD4(R, N, A, B, C, D) \
rpc<R, cc1_plugin::c::N, A, B, C, D>,
cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B, C, D>,
#define GCC_METHOD5(R, N, A, B, C, D, E) \
rpc<R, cc1_plugin::c::N, A, B, C, D, E>,
cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B, C, D, E>,
#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
rpc<R, cc1_plugin::c::N, A, B, C, D, E, F, G>,
cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B, C, D, E, F, G>,
#include "gcc-c-fe.def"
@ -207,9 +140,7 @@ libcc1_set_verbose (struct gcc_base_context *s, int /* bool */ verbose)
{
libcc1 *self = (libcc1 *) s;
self->verbose = verbose != 0;
if (self->compilerp != nullptr)
self->compilerp->set_verbose (self->verbose);
self->set_verbose (verbose != 0);
}
static char *
@ -386,7 +317,7 @@ libcc1_compile (struct gcc_base_context *s,
if (self->verbose)
self->args.push_back ("-v");
self->connection.reset (new libcc1_connection (fds[0], stderr_fds[0], self));
self->set_connection (fds[0], stderr_fds[0]);
cc1_plugin::callback_ftype *fun
= cc1_plugin::callback<int,

View File

@ -36,75 +36,23 @@ along with GCC; see the file COPYING3. If not see
#include "libiberty.h"
#include "compiler-name.hh"
#include "compiler.hh"
struct libcp1;
class libcp1_connection;
#include "gdbctx.hh"
// The C compiler context that we hand back to our caller.
struct libcp1 : public gcc_cp_context
struct libcp1 : public cc1_plugin::base_gdb_plugin<gcc_cp_context>
{
libcp1 (const gcc_base_vtable *, const gcc_cp_fe_vtable *);
// A convenience function to print something.
void print (const char *str)
{
this->print_function (this->print_datum, str);
}
std::unique_ptr<libcp1_connection> connection;
gcc_cp_oracle_function *binding_oracle;
gcc_cp_symbol_address_function *address_oracle;
gcc_cp_enter_leave_user_expr_scope_function *enter_scope;
gcc_cp_enter_leave_user_expr_scope_function *leave_scope;
void *oracle_datum;
void (*print_function) (void *datum, const char *message);
void *print_datum;
std::vector<std::string> args;
std::string source_file;
/* Non-zero as an equivalent to gcc driver option "-v". */
bool verbose;
std::unique_ptr<cc1_plugin::compiler> compilerp;
gcc_cp_oracle_function *binding_oracle = nullptr;
gcc_cp_symbol_address_function *address_oracle = nullptr;
gcc_cp_enter_leave_user_expr_scope_function *enter_scope = nullptr;
gcc_cp_enter_leave_user_expr_scope_function *leave_scope = nullptr;
void *oracle_datum = nullptr;
};
// A local subclass of connection that holds a back-pointer to the
// gcc_c_context object that we provide to our caller.
class libcp1_connection : public cc1_plugin::connection
libcp1::libcp1 (const gcc_base_vtable *v, const gcc_cp_fe_vtable *cv)
: cc1_plugin::base_gdb_plugin<gcc_cp_context> (v)
{
public:
libcp1_connection (int fd, int aux_fd, libcp1 *b)
: connection (fd, aux_fd),
back_ptr (b)
{
}
void print (const char *buf) override
{
back_ptr->print (buf);
}
libcp1 *back_ptr;
};
libcp1::libcp1 (const gcc_base_vtable *v,
const gcc_cp_fe_vtable *cv)
: binding_oracle (NULL),
address_oracle (NULL),
oracle_datum (NULL),
print_function (NULL),
print_datum (NULL),
args (),
source_file (),
verbose (false),
compilerp (new cc1_plugin::compiler (verbose))
{
base.ops = v;
cp_ops = cv;
}
@ -123,7 +71,7 @@ namespace {
enum gcc_cp_oracle_request request,
const char *identifier)
{
libcp1 *self = ((libcp1_connection *) conn)->back_ptr;
libcp1 *self = (libcp1 *) (((libcp1::local_connection *) conn)->back_ptr);
self->binding_oracle (self->oracle_datum, self, request, identifier);
return 1;
@ -134,7 +82,7 @@ namespace {
gcc_address
cp_call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
{
libcp1 *self = ((libcp1_connection *) conn)->back_ptr;
libcp1 *self = (libcp1 *) (((libcp1::local_connection *) conn)->back_ptr);
return self->address_oracle (self->oracle_datum, self, identifier);
}
@ -142,7 +90,7 @@ namespace {
int
cp_call_enter_scope (cc1_plugin::connection *conn)
{
libcp1 *self = ((libcp1_connection *) conn)->back_ptr;
libcp1 *self = (libcp1 *) (((libcp1::local_connection *) conn)->back_ptr);
self->enter_scope (self->oracle_datum, self);
return 1;
@ -151,7 +99,7 @@ namespace {
int
cp_call_leave_scope (cc1_plugin::connection *conn)
{
libcp1 *self = ((libcp1_connection *) conn)->back_ptr;
libcp1 *self = (libcp1 *) (((libcp1::local_connection *) conn)->back_ptr);
self->leave_scope (self->oracle_datum, self);
return 1;
@ -177,40 +125,25 @@ set_callbacks (struct gcc_cp_context *s,
self->oracle_datum = datum;
}
// Instances of this rpc<> template function are installed into the
// "cp_vtable". These functions are parameterized by type and method
// name and forward the call via the connection.
template<typename R, const char *&NAME, typename... Arg>
R rpc (struct gcc_cp_context *s, Arg... rest)
{
libcp1 *self = (libcp1 *) s;
R result;
if (!cc1_plugin::call (self->connection.get (), NAME, &result, rest...))
return 0;
return result;
}
static const struct gcc_cp_fe_vtable cp_vtable =
{
GCC_CP_FE_VERSION_0,
set_callbacks,
#define GCC_METHOD0(R, N) \
rpc<R, cc1_plugin::cp::N>,
cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N>,
#define GCC_METHOD1(R, N, A) \
rpc<R, cc1_plugin::cp::N, A>,
cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A>,
#define GCC_METHOD2(R, N, A, B) \
rpc<R, cc1_plugin::cp::N, A, B>,
cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B>,
#define GCC_METHOD3(R, N, A, B, C) \
rpc<R, cc1_plugin::cp::N, A, B, C>,
cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B, C>,
#define GCC_METHOD4(R, N, A, B, C, D) \
rpc<R, cc1_plugin::cp::N, A, B, C, D>,
cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B, C, D>,
#define GCC_METHOD5(R, N, A, B, C, D, E) \
rpc<R, cc1_plugin::cp::N, A, B, C, D, E>,
cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B, C, D, E>,
#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
rpc<R, cc1_plugin::cp::N, A, B, C, D, E, F, G>,
cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B, C, D, E, F, G>,
#include "gcc-cp-fe.def"
@ -230,9 +163,7 @@ libcp1_set_verbose (struct gcc_base_context *s, int /* bool */ verbose)
{
libcp1 *self = (libcp1 *) s;
self->verbose = verbose != 0;
if (self->compilerp != nullptr)
self->compilerp->set_verbose (self->verbose);
self->set_verbose (verbose != 0);
}
static char *
@ -409,7 +340,7 @@ libcp1_compile (struct gcc_base_context *s,
if (self->verbose)
self->args.push_back ("-v");
self->connection.reset (new libcp1_connection (fds[0], stderr_fds[0], self));
self->set_connection (fds[0], stderr_fds[0]);
cc1_plugin::callback_ftype *fun
= cc1_plugin::callback<int,