diff options
author | Keith Seitz <keiths@redhat.com> | 2018-08-29 15:12:24 -0700 |
---|---|---|
committer | Keith Seitz <keiths@redhat.com> | 2018-08-29 15:12:24 -0700 |
commit | 078a020797210f4d8f9491bbfe16ec31e9efb652 (patch) | |
tree | 278f541a2e88d33fcc3c4f782b5265a477abb540 /gdb/compile/compile-c-support.c | |
parent | fcaad03cc027ec2cdf7f2cff70d792867d43c57f (diff) | |
download | fsf-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.c | 205 |
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); +} |