From 078a020797210f4d8f9491bbfe16ec31e9efb652 Mon Sep 17 00:00:00 2001 From: Keith Seitz Date: Wed, 29 Aug 2018 15:12:24 -0700 Subject: 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. --- gdb/compile/compile-c-support.c | 205 +++++++++++++++++++++++++++++++++++----- 1 file changed, 180 insertions(+), 25 deletions(-) (limited to 'gdb/compile/compile-c-support.c') 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 +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 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 (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 + + (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 + + (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 \n" + "#include \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::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 c_compile_program; +typedef compile_program 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 (inst); + cplus_compile_program program (cplus_inst, gdbarch); + + return program.compute (input, expr_block, expr_pc); +} -- cgit v1.1