aboutsummaryrefslogtreecommitdiff
path: root/gdb/compile/compile-c-support.c
diff options
context:
space:
mode:
authorKeith Seitz <keiths@redhat.com>2018-08-29 15:12:24 -0700
committerKeith Seitz <keiths@redhat.com>2018-08-29 15:12:24 -0700
commit078a020797210f4d8f9491bbfe16ec31e9efb652 (patch)
tree278f541a2e88d33fcc3c4f782b5265a477abb540 /gdb/compile/compile-c-support.c
parentfcaad03cc027ec2cdf7f2cff70d792867d43c57f (diff)
downloadfsf-binutils-gdb-078a020797210f4d8f9491bbfe16ec31e9efb652.zip
fsf-binutils-gdb-078a020797210f4d8f9491bbfe16ec31e9efb652.tar.gz
fsf-binutils-gdb-078a020797210f4d8f9491bbfe16ec31e9efb652.tar.bz2
C++ compile support
This patch adds *basic* support for C++ to the compile feature. It does most simple type conversions, including everything that C compile does and your basic "with-classes" type of C++. I've written a new compile-support.exp support file which adds a new test facility for automating and simplifying "compile print" vs "compile code" testing. See testsuite/lib/compile-support.exp and CompileExpression for more on that. The tests use this facility extensively. This initial support has several glaring omissions: - No template support at all I have follow-on patches for this, but they add much complexity to this "basic" support. Consequently, they will be submitted separately. - Cannot print functions The code template needs tweaking, and I simply haven't gotten to it yet. - So-called "special function" support is not included Using constructors, destructors, operators, etc will not work. I have follow-on patches for that, but they require some work because of the recent churn in symbol searching. - There are several test suite references to "compile/1234" bugs. I will file bugs and update the test suite's bug references before pushing these patches. The test suite started as a copy of the original C-language support, but I have written tests to exercise the basic functionality of the plug-in. I've added a new option for outputting debug messages for C++ type-conversion ("debug compile-cplus-types"). gdb/ChangeLog: * Makefile.in (SUBDIR_GCC_COMPILE_SRCS): Add compile-cplus-symbols.c and compile-cplus-types.c. (HFILES_NO_SRCDIR): Add gcc-cp-plugin.h. * c-lang.c (cplus_language_defn): Set C++ compile functions. * c-lang.h (cplus_get_compile_context, cplus_compute_program): Declare. * compile/compile-c-support.c: Include compile-cplus.h. (load_libcompile): Templatize. (get_compile_context): "New" function. (c_get_compile_context): Use get_compile_context. (cplus_get_compile_context): New function. (cplus_push_user_expression, cplus_pop_user_expression) (cplus_add_code_header, cplus_add_input, cplus_compile_program) (cplus_compute_program): Define new structs/functions. * compile/compile-cplus-symmbols.c: New file. * compile/compile-cplus-types.c: New file. * compile/compile-cplus.h: New file. * compile/compile-internal.h (debug_compile_oracle, GCC_TYPE_NONE): Declare. * compile/compile-object-load.c (get_out_value_type): Use strncmp_iw when comparing symbol names. (compile_object_load): Add mst_bss and mst_data. * compile/compile.c (_initialize_compile): Remove -Wno-implicit-function-declaration from `compile_args'. * compile/gcc-cp-plugin.h: New file. * NEWS: Mention C++ compile support and new debug options. gdb/testsuite/ChangeLog: * gdb.compile/compile-cplus-anonymous.cc: New file. * gdb.compile/compile-cplus-anonymous.exp: New file. * gdb.compile/compile-cplus-array-decay.cc: New file. * gdb.compile/compile-cplus-array-decay.exp: New file. * gdb.compile/compile-cplus-inherit.cc: New file. * gdb.compile/compile-cplus-inherit.exp: New file. * gdb.compile/compile-cplus-member.cc: New file. * gdb.compile/compile-cplus-member.exp: New file. * gdb.compile/compile-cplus-method.cc: New file. * gdb.compile/compile-cplus-method.exp: New file. * gdb.compile/compile-cplus-mod.c: "New" file. * gdb.compile/compile-cplus-namespace.cc: New file. * gdb.compile/compile-cplus-namespace.exp: New file. * gdb.compile/compile-cplus-nested.cc: New file. * gdb.compile/compile-cplus-nested.exp: New file. * gdb.compile/compile-cplus-print.c: "New" file. * gdb.compile/compile-cplus-print.exp: "New" file. * gdb.compile/compile-cplus-virtual.cc: New file. * gdb.compile/compile-cplus-virtual.exp: New file. * gdb.compile/compile-cplus.c: "New" file. * gdb.compile/compile-cplus.exp: "New" file. * lib/compile-support.exp: New file. doc/ChangeLog: * gdb.texinfo (Compiling and injecting code in GDB): Document set/show "compile-oracle" and "compile-cplus-types" commands.
Diffstat (limited to 'gdb/compile/compile-c-support.c')
-rw-r--r--gdb/compile/compile-c-support.c205
1 files changed, 180 insertions, 25 deletions
diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index e8993aa..5c700bb 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -1,4 +1,4 @@
-/* C language support for compilation.
+/* C/C++ language support for compilation.
Copyright (C) 2014-2018 Free Software Foundation, Inc.
@@ -20,6 +20,7 @@
#include "defs.h"
#include "compile-internal.h"
#include "compile-c.h"
+#include "compile-cplus.h"
#include "compile.h"
#include "gdb-dlfcn.h"
#include "c-lang.h"
@@ -67,25 +68,22 @@ c_get_range_decl_name (const struct dynamic_prop *prop)
-/* Helper function for c_get_compile_context. Open the GCC front-end
- shared library and return the symbol specified by the current
- GCC_C_FE_CONTEXT. */
+/* Load the plug-in library FE_LIBCC and return the initialization function
+ FE_CONTEXT. */
-static gcc_c_fe_context_function *
-load_libcc (void)
+template <typename FUNCTYPE>
+FUNCTYPE *
+load_libcompile (const char *fe_libcc, const char *fe_context)
{
- gcc_c_fe_context_function *func;
+ FUNCTYPE *func;
- /* gdb_dlopen will call error () on an error, so no need to check
- value. */
- gdb_dlhandle_up handle = gdb_dlopen (STRINGIFY (GCC_C_FE_LIBCC));
- func = (gcc_c_fe_context_function *) gdb_dlsym (handle,
- STRINGIFY (GCC_C_FE_CONTEXT));
+ /* gdb_dlopen will call error () on an error, so no need to check
+ value. */
+ gdb_dlhandle_up handle = gdb_dlopen (fe_libcc);
+ func = (FUNCTYPE *) gdb_dlsym (handle, fe_context);
if (func == NULL)
- error (_("could not find symbol %s in library %s"),
- STRINGIFY (GCC_C_FE_CONTEXT),
- STRINGIFY (GCC_C_FE_LIBCC));
+ error (_("could not find symbol %s in library %s"), fe_context, fe_libcc);
/* Leave the library open. */
handle.release ();
@@ -93,28 +91,57 @@ load_libcc (void)
}
/* Return the compile instance associated with the current context.
- This function calls the symbol returned from the load_libcc
- function. This will provide the gcc_c_context. */
+ This function calls the symbol returned from the load_libcompile
+ function. FE_LIBCC is the library to load. BASE_VERSION is the
+ base compile plug-in version we support. API_VERSION is the
+ API version supported. */
+template <typename INSTTYPE, typename FUNCTYPE, typename CTXTYPE,
+ typename BASE_VERSION_TYPE, typename API_VERSION_TYPE>
compile_instance *
-c_get_compile_context (void)
+get_compile_context (const char *fe_libcc, const char *fe_context,
+ BASE_VERSION_TYPE base_version,
+ API_VERSION_TYPE api_version)
{
- static gcc_c_fe_context_function *func;
-
- struct gcc_c_context *context;
+ static FUNCTYPE *func;
+ static CTXTYPE *context;
if (func == NULL)
{
- func = load_libcc ();
+ func = load_libcompile<FUNCTYPE> (fe_libcc, fe_context);
gdb_assert (func != NULL);
}
- context = (*func) (GCC_FE_VERSION_0, GCC_C_FE_VERSION_0);
+ context = (*func) (base_version, api_version);
if (context == NULL)
error (_("The loaded version of GCC does not support the required version "
"of the API."));
- return new compile_c_instance (context);
+ return new INSTTYPE (context);
+}
+
+/* A C-language implementation of get_compile_context. */
+
+compile_instance *
+c_get_compile_context ()
+{
+ return get_compile_context
+ <compile_c_instance, gcc_c_fe_context_function, gcc_c_context,
+ gcc_base_api_version, gcc_c_api_version>
+ (STRINGIFY (GCC_C_FE_LIBCC), STRINGIFY (GCC_C_FE_CONTEXT),
+ GCC_FE_VERSION_0, GCC_C_FE_VERSION_0);
+}
+
+/* A C++-language implementation of get_compile_context. */
+
+compile_instance *
+cplus_get_compile_context ()
+{
+ return get_compile_context
+ <compile_cplus_instance, gcc_cp_fe_context_function, gcc_cp_context,
+ gcc_base_api_version, gcc_cp_api_version>
+ (STRINGIFY (GCC_CP_FE_LIBCC), STRINGIFY (GCC_CP_FE_CONTEXT),
+ GCC_FE_VERSION_0, GCC_CP_FE_VERSION_0);
}
@@ -384,6 +411,113 @@ struct c_add_input
}
};
+/* C++-language policy to emit a push user expression pragma into
+ BUF. */
+
+struct cplus_push_user_expression
+{
+ void push_user_expression (struct ui_file *buf)
+ {
+ fputs_unfiltered ("#pragma GCC push_user_expression\n", buf);
+ }
+};
+
+/* C++-language policy to emit a pop user expression pragma into BUF. */
+
+struct cplus_pop_user_expression
+{
+ void pop_user_expression (struct ui_file *buf)
+ {
+ fputs_unfiltered ("#pragma GCC pop_user_expression\n", buf);
+ }
+};
+
+/* C++-language policy to construct a code header for a block of code.
+ Takes a scope TYPE argument which selects the correct header to
+ insert into BUF. */
+
+struct cplus_add_code_header
+{
+ void add_code_header (enum compile_i_scope_types type, struct ui_file *buf)
+ {
+ switch (type)
+ {
+ case COMPILE_I_SIMPLE_SCOPE:
+ fputs_unfiltered ("void "
+ GCC_FE_WRAPPER_FUNCTION
+ " (struct "
+ COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
+ " *"
+ COMPILE_I_SIMPLE_REGISTER_ARG_NAME
+ ") {\n",
+ buf);
+ break;
+
+ case COMPILE_I_PRINT_ADDRESS_SCOPE:
+ case COMPILE_I_PRINT_VALUE_SCOPE:
+ fputs_unfiltered (
+ "#include <cstring>\n"
+ "#include <bits/move.h>\n"
+ "void "
+ GCC_FE_WRAPPER_FUNCTION
+ " (struct "
+ COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
+ " *"
+ COMPILE_I_SIMPLE_REGISTER_ARG_NAME
+ ", "
+ COMPILE_I_PRINT_OUT_ARG_TYPE
+ " "
+ COMPILE_I_PRINT_OUT_ARG
+ ") {\n",
+ buf);
+ break;
+
+ case COMPILE_I_RAW_SCOPE:
+ break;
+
+ default:
+ gdb_assert_not_reached (_("Unknown compiler scope reached."));
+ }
+ }
+};
+
+/* C++-language policy to emit the user code snippet INPUT into BUF based on
+ the scope TYPE. */
+
+struct cplus_add_input
+{
+ void add_input (enum compile_i_scope_types type, const char *input,
+ struct ui_file *buf)
+ {
+ switch (type)
+ {
+ case COMPILE_I_PRINT_VALUE_SCOPE:
+ case COMPILE_I_PRINT_ADDRESS_SCOPE:
+ fprintf_unfiltered
+ (buf,
+ /* "auto" strips ref- and cv- qualifiers, so we need to also strip
+ those from COMPILE_I_EXPR_PTR_TYPE. */
+ "auto " COMPILE_I_EXPR_VAL " = %s;\n"
+ "typedef "
+ "std::add_pointer<std::remove_cv<decltype (%s)>::type>::type "
+ " __gdb_expr_ptr;\n"
+ "__gdb_expr_ptr " COMPILE_I_EXPR_PTR_TYPE ";\n"
+ "std::memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s ("
+ COMPILE_I_EXPR_VAL "),\n"
+ "\tsizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n"
+ ,input, input,
+ (type == COMPILE_I_PRINT_ADDRESS_SCOPE
+ ? "__builtin_addressof" : ""));
+ break;
+
+ default:
+ fputs_unfiltered (input, buf);
+ break;
+ }
+ fputs_unfiltered ("\n", buf);
+ }
+};
+
/* A host class representing a compile program.
CompileInstanceType is the type of the compile_instance for the
@@ -513,13 +647,18 @@ private:
struct gdbarch *m_arch;
};
-/* Type used for C program computations. */
+/* The types used for C and C++ program computations. */
typedef compile_program<compile_c_instance,
c_push_user_expression, pop_user_expression_nop,
c_add_code_header, c_add_code_footer,
c_add_input> c_compile_program;
+typedef compile_program<compile_cplus_instance,
+ cplus_push_user_expression, cplus_pop_user_expression,
+ cplus_add_code_header, c_add_code_footer,
+ cplus_add_input> cplus_compile_program;
+
/* The la_compute_program method for C. */
std::string
@@ -534,3 +673,19 @@ c_compute_program (compile_instance *inst,
return program.compute (input, expr_block, expr_pc);
}
+
+/* The la_compute_program method for C++. */
+
+std::string
+cplus_compute_program (compile_instance *inst,
+ const char *input,
+ struct gdbarch *gdbarch,
+ const struct block *expr_block,
+ CORE_ADDR expr_pc)
+{
+ compile_cplus_instance *cplus_inst
+ = static_cast<compile_cplus_instance *> (inst);
+ cplus_compile_program program (cplus_inst, gdbarch);
+
+ return program.compute (input, expr_block, expr_pc);
+}