From 9cdfd9a26ef63ef2fee58c0e7475b5373b61e5d1 Mon Sep 17 00:00:00 2001 From: Keith Seitz Date: Fri, 10 Aug 2018 10:48:03 -0700 Subject: [PATCH] Change compile_instance/compile_c_instance into classes This patch changes structs compile_instance and compile_c_instance into classes. Because of the nature of the change, there are a number of unavoidably mechanical changes buried in here, such as turning variable access of the POD struct into method calls, removing the struct keyword, and changing access of the plugin from "c_plugin->operation()" to "plugin ().operation ()". There is one "non-trivial" change associated with this patch, though. The type cache and symbol error maps have been moved into the base class, believing these facilities would be used other language implementations. [They are indeed re-used by C++.] gdb/ChangeLog: * compile/compile-c-support.c (c_get_compile_context): Use `new' instead of `new_compile_instance'. * compile/compile-c-symbols.c (compile_instance::insert_symbol_error): Update description. If the symbol error map is not initialized, create it. (generate_c_for_for_one_symbol): Do not check/initialize the symbol error map. * compile/compile-c-types.c (compile_c_instance): Make a class. Update all callers. (compile_instance::compile_instance): Initialize the type cache. (get_cached_type): New function. (insert_type): Update description. (compile_c_instance::m_default_cflags): Define. (convert_type): Update description. Use get_cached_type. (delete_instance): Moved to destructor. (new_compile_instance): Moved to constructor. * compile/compile-c.h (compile_c_instance): Make class inheriting from compile_instance. : Remove field. : Move to base class. : Rename to `m_plugin' and remove pointer type. * compile/compile-internal.h (compile_instance): Make class. : Define. : Rename to `m_gcc_fe'. : Add `m_' prefix. : New fields, moved from compile_c_instance. : Remove. (convert_type, new_compile_instance): Remove. * compile/compile.c (cleanup_compile_instance): Remove. (compile_to_object): Use unique_ptr to eliminate cleanups. (compile_instance::set_print_callback, compile_instance::version) (compile_instance::set_verbose) (compile_instance::set_driver_filename) (compile_instance::set_triplet_regexp) (compile_instance::set_arguments) (compile_instance::set_source_file) (compile_instance::compile): Define. --- gdb/ChangeLog | 41 ++++++ gdb/c-lang.h | 4 +- gdb/compile/compile-c-support.c | 29 ++--- gdb/compile/compile-c-symbols.c | 84 +++++++------ gdb/compile/compile-c-types.c | 215 +++++++++++++++----------------- gdb/compile/compile-c.h | 33 +++-- gdb/compile/compile-internal.h | 123 ++++++++++++++---- gdb/compile/compile.c | 153 +++++++++++++++-------- gdb/language.h | 6 +- 9 files changed, 428 insertions(+), 260 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6873ee5073e..e70a503d488 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,44 @@ +2018-08-10 Keith Seitz + + * compile/compile-c-support.c (c_get_compile_context): Use `new' + instead of `new_compile_instance'. + * compile/compile-c-symbols.c (compile_instance::insert_symbol_error): + Update description. + If the symbol error map is not initialized, create it. + (generate_c_for_for_one_symbol): Do not check/initialize + the symbol error map. + * compile/compile-c-types.c (compile_c_instance): Make a class. + Update all callers. + (compile_instance::compile_instance): Initialize the type cache. + (get_cached_type): New function. + (insert_type): Update description. + (compile_c_instance::m_default_cflags): Define. + (convert_type): Update description. Use get_cached_type. + (delete_instance): Moved to destructor. + (new_compile_instance): Moved to constructor. + * compile/compile-c.h (compile_c_instance): Make class inheriting + from compile_instance. + : Remove field. + : Move to base class. + : Rename to `m_plugin' and remove pointer type. + * compile/compile-internal.h (compile_instance): Make class. + : Define. + : Rename to `m_gcc_fe'. + : Add `m_' prefix. + : New fields, moved from + compile_c_instance. + : Remove. + (convert_type, new_compile_instance): Remove. + * compile/compile.c (cleanup_compile_instance): Remove. + (compile_to_object): Use unique_ptr to eliminate cleanups. + (compile_instance::set_print_callback, compile_instance::version) + (compile_instance::set_verbose) + (compile_instance::set_driver_filename) + (compile_instance::set_triplet_regexp) + (compile_instance::set_arguments) + (compile_instance::set_source_file) + (compile_instance::compile): Define. + 2018-08-10 Keith Seitz * Makefile.in (HFILES_NO_SRCDIR): Add compile/gcc-c-plugin.h. diff --git a/gdb/c-lang.h b/gdb/c-lang.h index e961826407e..b7bf08992b9 100644 --- a/gdb/c-lang.h +++ b/gdb/c-lang.h @@ -158,7 +158,7 @@ extern int c_textual_element_type (struct type *, char); exception on failure. This is suitable for use as the la_get_compile_instance language method. */ -extern struct compile_instance *c_get_compile_context (void); +extern compile_instance *c_get_compile_context (void); /* This takes the user-supplied text and returns a new bit of code to compile. @@ -166,7 +166,7 @@ extern struct compile_instance *c_get_compile_context (void); This is used as the la_compute_program language method; see that for a description of the arguments. */ -extern std::string c_compute_program (struct compile_instance *inst, +extern std::string c_compute_program (compile_instance *inst, const char *input, struct gdbarch *gdbarch, const struct block *expr_block, diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c index 41fead9ad19..d77c7d96257 100644 --- a/gdb/compile/compile-c-support.c +++ b/gdb/compile/compile-c-support.c @@ -96,7 +96,7 @@ load_libcc (void) This function calls the symbol returned from the load_libcc function. This will provide the gcc_c_context. */ -struct compile_instance * +compile_instance * c_get_compile_context (void) { static gcc_c_fe_context_function *func; @@ -114,7 +114,7 @@ c_get_compile_context (void) error (_("The loaded version of GCC does not support the required version " "of the API.")); - return new_compile_instance (context); + return new compile_c_instance (context); } @@ -334,13 +334,14 @@ generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch, indicates the value of $PC. */ std::string -c_compute_program (struct compile_instance *inst, +c_compute_program (compile_instance *inst, const char *input, struct gdbarch *gdbarch, const struct block *expr_block, CORE_ADDR expr_pc) { - struct compile_c_instance *context = (struct compile_c_instance *) inst; + compile_c_instance *context + = static_cast (inst); string_file buf; string_file var_stream; @@ -350,7 +351,7 @@ c_compute_program (struct compile_instance *inst, /* Do not generate local variable information for "raw" compilations. In this case we aren't emitting our own function and the user's code may only refer to globals. */ - if (inst->scope != COMPILE_I_RAW_SCOPE) + if (inst->scope () != COMPILE_I_RAW_SCOPE) { int i; @@ -384,11 +385,11 @@ c_compute_program (struct compile_instance *inst, generate_register_struct (&buf, gdbarch, registers_used.get ()); } - add_code_header (inst->scope, &buf); + add_code_header (inst->scope (), &buf); - if (inst->scope == COMPILE_I_SIMPLE_SCOPE - || inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE - || inst->scope == COMPILE_I_PRINT_VALUE_SCOPE) + if (inst->scope () == COMPILE_I_SIMPLE_SCOPE + || inst->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE + || inst->scope () == COMPILE_I_PRINT_VALUE_SCOPE) { buf.write (var_stream.c_str (), var_stream.size ()); buf.puts ("#pragma GCC user_expression\n"); @@ -398,12 +399,12 @@ c_compute_program (struct compile_instance *inst, works properly. Otherwise gcc thinks that the "extern" declaration is in the same scope as the declaration provided by gdb. */ - if (inst->scope != COMPILE_I_RAW_SCOPE) + if (inst->scope () != COMPILE_I_RAW_SCOPE) buf.puts ("{\n"); buf.puts ("#line 1 \"gdb command line\"\n"); - switch (inst->scope) + switch (inst->scope ()) { case COMPILE_I_PRINT_ADDRESS_SCOPE: case COMPILE_I_PRINT_VALUE_SCOPE: @@ -413,7 +414,7 @@ c_compute_program (struct compile_instance *inst, "memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s" COMPILE_I_EXPR_VAL ",\n" "sizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n" , input, input, - (inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE + (inst->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE ? "&" : "")); break; default: @@ -428,9 +429,9 @@ c_compute_program (struct compile_instance *inst, if (strchr (input, '\n') == NULL) buf.puts (";\n"); - if (inst->scope != COMPILE_I_RAW_SCOPE) + if (inst->scope () != COMPILE_I_RAW_SCOPE) buf.puts ("}\n"); - add_code_footer (inst->scope, &buf); + add_code_footer (inst->scope (), &buf); return std::move (buf.string ()); } diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c index abd829838b1..b60b8ddcc94 100644 --- a/gdb/compile/compile-c-symbols.c +++ b/gdb/compile/compile-c-symbols.c @@ -79,16 +79,27 @@ del_symbol_error (void *a) xfree (se); } -/* Associate SYMBOL with some error text. */ +/* See compile-internal.h. */ -static void -insert_symbol_error (htab_t hash, const struct symbol *sym, const char *text) +void +compile_instance::insert_symbol_error (const struct symbol *sym, + const char *text) { struct symbol_error e; void **slot; + if (m_symbol_err_map == NULL) + { + m_symbol_err_map = htab_create_alloc (10, + hash_symbol_error, + eq_symbol_error, + del_symbol_error, + xcalloc, + xfree); + } + e.sym = sym; - slot = htab_find_slot (hash, &e, INSERT); + slot = htab_find_slot (m_symbol_err_map, &e, INSERT); if (*slot == NULL) { struct symbol_error *e = XNEW (struct symbol_error); @@ -99,21 +110,19 @@ insert_symbol_error (htab_t hash, const struct symbol *sym, const char *text) } } -/* Emit the error message corresponding to SYM, if one exists, and - arrange for it not to be emitted again. */ +/* See compile-internal.h. */ -static void -error_symbol_once (struct compile_c_instance *context, - const struct symbol *sym) +void +compile_instance::error_symbol_once (const struct symbol *sym) { struct symbol_error search; struct symbol_error *err; - if (context->symbol_err_map == NULL) + if (m_symbol_err_map == NULL) return; search.sym = sym; - err = (struct symbol_error *) htab_find (context->symbol_err_map, &search); + err = (struct symbol_error *) htab_find (m_symbol_err_map, &search); if (err == NULL || err->message == NULL) return; @@ -142,7 +151,7 @@ c_symbol_substitution_name (struct symbol *sym) scope.) */ static void -convert_one_symbol (struct compile_c_instance *context, +convert_one_symbol (compile_c_instance *context, struct block_symbol sym, int is_global, int is_local) @@ -151,17 +160,17 @@ convert_one_symbol (struct compile_c_instance *context, const char *filename = symbol_symtab (sym.symbol)->filename; unsigned short line = SYMBOL_LINE (sym.symbol); - error_symbol_once (context, sym.symbol); + context->error_symbol_once (sym.symbol); if (SYMBOL_CLASS (sym.symbol) == LOC_LABEL) sym_type = 0; else - sym_type = convert_type (context, SYMBOL_TYPE (sym.symbol)); + sym_type = context->convert_type (SYMBOL_TYPE (sym.symbol)); if (SYMBOL_DOMAIN (sym.symbol) == STRUCT_DOMAIN) { /* Binding a tag, so we don't need to build a decl. */ - context->c_plugin->tagbind (SYMBOL_NATURAL_NAME (sym.symbol), + context->plugin ().tagbind (SYMBOL_NATURAL_NAME (sym.symbol), sym_type, filename, line); } else @@ -195,7 +204,7 @@ convert_one_symbol (struct compile_c_instance *context, /* Already handled by convert_enum. */ return; } - context->c_plugin->build_constant + context->plugin ().build_constant (sym_type, SYMBOL_NATURAL_NAME (sym.symbol), SYMBOL_VALUE (sym.symbol), filename, line); @@ -280,17 +289,17 @@ convert_one_symbol (struct compile_c_instance *context, } /* Don't emit local variable decls for a raw expression. */ - if (context->base.scope != COMPILE_I_RAW_SCOPE + if (context->scope () != COMPILE_I_RAW_SCOPE || symbol_name == NULL) { - decl = context->c_plugin->build_decl + decl = context->plugin ().build_decl (SYMBOL_NATURAL_NAME (sym.symbol), kind, sym_type, symbol_name.get (), addr, filename, line); - context->c_plugin->bind (decl, is_global); + context->plugin ().bind (decl, is_global); } } } @@ -300,7 +309,7 @@ convert_one_symbol (struct compile_c_instance *context, itself, and DOMAIN is the domain which was searched. */ static void -convert_symbol_sym (struct compile_c_instance *context, const char *identifier, +convert_symbol_sym (compile_c_instance *context, const char *identifier, struct block_symbol sym, domain_enum domain) { const struct block *static_block; @@ -350,7 +359,7 @@ convert_symbol_sym (struct compile_c_instance *context, const char *identifier, to use and BMSYM is the minimal symbol to convert. */ static void -convert_symbol_bmsym (struct compile_c_instance *context, +convert_symbol_bmsym (compile_c_instance *context, struct bound_minimal_symbol bmsym) { struct minimal_symbol *msym = bmsym.minsym; @@ -398,11 +407,11 @@ convert_symbol_bmsym (struct compile_c_instance *context, break; } - sym_type = convert_type (context, type); - decl = context->c_plugin->build_decl (MSYMBOL_NATURAL_NAME (msym), + sym_type = context->convert_type (type); + decl = context->plugin ().build_decl (MSYMBOL_NATURAL_NAME (msym), kind, sym_type, NULL, addr, NULL, 0); - context->c_plugin->bind (decl, 1 /* is_global */); + context->plugin ().bind (decl, 1 /* is_global */); } /* See compile-internal.h. */ @@ -413,7 +422,8 @@ gcc_convert_symbol (void *datum, enum gcc_c_oracle_request request, const char *identifier) { - struct compile_c_instance *context = (struct compile_c_instance *) datum; + compile_c_instance *context + = static_cast (datum); domain_enum domain; int found = 0; @@ -438,7 +448,7 @@ gcc_convert_symbol (void *datum, { struct block_symbol sym; - sym = lookup_symbol (identifier, context->base.block, domain, NULL); + sym = lookup_symbol (identifier, context->block (), domain, NULL); if (sym.symbol != NULL) { convert_symbol_sym (context, identifier, sym, domain); @@ -459,7 +469,7 @@ gcc_convert_symbol (void *datum, CATCH (e, RETURN_MASK_ALL) { - context->c_plugin->error (e.message); + context->plugin ().error (e.message); } END_CATCH @@ -476,7 +486,8 @@ gcc_address gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context, const char *identifier) { - struct compile_c_instance *context = (struct compile_c_instance *) datum; + compile_c_instance *context + = static_cast (datum); gcc_address result = 0; int found = 0; @@ -521,7 +532,7 @@ gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context, CATCH (e, RETURN_MASK_ERROR) { - context->c_plugin->error (e.message); + context->plugin ().error (e.message); } END_CATCH @@ -575,7 +586,7 @@ symbol_seen (htab_t hashtab, struct symbol *sym) /* Generate C code to compute the length of a VLA. */ static void -generate_vla_size (struct compile_c_instance *compiler, +generate_vla_size (compile_instance *compiler, string_file &stream, struct gdbarch *gdbarch, unsigned char *registers_used, @@ -629,7 +640,7 @@ generate_vla_size (struct compile_c_instance *compiler, /* Generate C code to compute the address of SYM. */ static void -generate_c_for_for_one_variable (struct compile_c_instance *compiler, +generate_c_for_for_one_variable (compile_instance *compiler, string_file &stream, struct gdbarch *gdbarch, unsigned char *registers_used, @@ -691,14 +702,7 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler, CATCH (e, RETURN_MASK_ERROR) { - if (compiler->symbol_err_map == NULL) - compiler->symbol_err_map = htab_create_alloc (10, - hash_symbol_error, - eq_symbol_error, - del_symbol_error, - xcalloc, - xfree); - insert_symbol_error (compiler->symbol_err_map, sym, e.message); + compiler->insert_symbol_error (sym, e.message); } END_CATCH } @@ -706,7 +710,7 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler, /* See compile-c.h. */ gdb::unique_xmalloc_ptr -generate_c_for_variable_locations (struct compile_c_instance *compiler, +generate_c_for_variable_locations (compile_instance *compiler, string_file &stream, struct gdbarch *gdbarch, const struct block *block, diff --git a/gdb/compile/compile-c-types.c b/gdb/compile/compile-c-types.c index 228966f7387..bfc6ccf1bb2 100644 --- a/gdb/compile/compile-c-types.c +++ b/gdb/compile/compile-c-types.c @@ -58,25 +58,49 @@ eq_type_map_instance (const void *a, const void *b) return insta->type == instb->type; } +/* Constructor for compile_instance. */ + +compile_instance::compile_instance (struct gcc_base_context *gcc_fe, + const char *options) + : m_gcc_fe (gcc_fe), m_gcc_target_options (options), + m_symbol_err_map (NULL) +{ + m_type_map = htab_create_alloc (10, hash_type_map_instance, + eq_type_map_instance, + xfree, xcalloc, xfree); +} + -/* Insert an entry into the type map associated with CONTEXT that maps - from the gdb type TYPE to the gcc type GCC_TYPE. It is ok for a - given type to be inserted more than once, provided that the exact - same association is made each time. This simplifies how type - caching works elsewhere in this file -- see how struct type caching - is handled. */ +/* See compile-internal.h. */ + +bool +compile_instance::get_cached_type (struct type *type, gcc_type &ret) const +{ + struct type_map_instance inst, *found; + + inst.type = type; + found = (struct type_map_instance *) htab_find (m_type_map, &inst); + if (found != NULL) + { + ret = found->gcc_type_handle; + return true; + } + + return false; +} + +/* See compile-internal.h. */ -static void -insert_type (struct compile_c_instance *context, struct type *type, - gcc_type gcc_type) +void +compile_instance::insert_type (struct type *type, gcc_type gcc_type) { struct type_map_instance inst, *add; void **slot; inst.type = type; inst.gcc_type_handle = gcc_type; - slot = htab_find_slot (context->type_map, &inst, INSERT); + slot = htab_find_slot (m_type_map, &inst, INSERT); add = (struct type_map_instance *) *slot; /* The type might have already been inserted in order to handle @@ -95,28 +119,28 @@ insert_type (struct compile_c_instance *context, struct type *type, /* Convert a pointer type to its gcc representation. */ static gcc_type -convert_pointer (struct compile_c_instance *context, struct type *type) +convert_pointer (compile_c_instance *context, struct type *type) { - gcc_type target = convert_type (context, TYPE_TARGET_TYPE (type)); + gcc_type target = context->convert_type (TYPE_TARGET_TYPE (type)); - return context->c_plugin->build_pointer_type (target); + return context->plugin ().build_pointer_type (target); } /* Convert an array type to its gcc representation. */ static gcc_type -convert_array (struct compile_c_instance *context, struct type *type) +convert_array (compile_c_instance *context, struct type *type) { gcc_type element_type; struct type *range = TYPE_INDEX_TYPE (type); - element_type = convert_type (context, TYPE_TARGET_TYPE (type)); + element_type = context->convert_type (TYPE_TARGET_TYPE (type)); if (TYPE_LOW_BOUND_KIND (range) != PROP_CONST) - return context->c_plugin->error (_("array type with non-constant" + return context->plugin ().error (_("array type with non-constant" " lower bound is not supported")); if (TYPE_LOW_BOUND (range) != 0) - return context->c_plugin->error (_("cannot convert array type with " + return context->plugin ().error (_("cannot convert array type with " "non-zero lower bound to C")); if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR @@ -125,12 +149,12 @@ convert_array (struct compile_c_instance *context, struct type *type) gcc_type result; if (TYPE_VECTOR (type)) - return context->c_plugin->error (_("variably-sized vector type" + return context->plugin ().error (_("variably-sized vector type" " is not supported")); std::string upper_bound = c_get_range_decl_name (&TYPE_RANGE_DATA (range)->high); - result = context->c_plugin->build_vla_array_type (element_type, + result = context->plugin ().build_vla_array_type (element_type, upper_bound.c_str ()); return result; } @@ -147,15 +171,15 @@ convert_array (struct compile_c_instance *context, struct type *type) } if (TYPE_VECTOR (type)) - return context->c_plugin->build_vector_type (element_type, count); - return context->c_plugin->build_array_type (element_type, count); + return context->plugin ().build_vector_type (element_type, count); + return context->plugin ().build_array_type (element_type, count); } } /* Convert a struct or union type to its gcc representation. */ static gcc_type -convert_struct_or_union (struct compile_c_instance *context, struct type *type) +convert_struct_or_union (compile_c_instance *context, struct type *type) { int i; gcc_type result; @@ -163,54 +187,52 @@ 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 = context->c_plugin->build_record_type (); + result = context->plugin ().build_record_type (); else { gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION); - result = context->c_plugin->build_union_type (); + result = context->plugin ().build_union_type (); } - insert_type (context, type, result); + context->insert_type (type, result); for (i = 0; i < TYPE_NFIELDS (type); ++i) { gcc_type field_type; unsigned long bitsize = TYPE_FIELD_BITSIZE (type, i); - field_type = convert_type (context, TYPE_FIELD_TYPE (type, i)); + field_type = context->convert_type (TYPE_FIELD_TYPE (type, i)); if (bitsize == 0) bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i)); - context->c_plugin->build_add_field (result, + context->plugin ().build_add_field (result, TYPE_FIELD_NAME (type, i), field_type, bitsize, TYPE_FIELD_BITPOS (type, i)); } - context->c_plugin->finish_record_or_union (result, TYPE_LENGTH (type)); + context->plugin ().finish_record_or_union (result, TYPE_LENGTH (type)); return result; } /* Convert an enum type to its gcc representation. */ static gcc_type -convert_enum (struct compile_c_instance *context, struct type *type) +convert_enum (compile_c_instance *context, struct type *type) { gcc_type int_type, result; int i; - const gcc_c_plugin *plugin = context->c_plugin; - int_type = plugin->int_type_v0 (TYPE_UNSIGNED (type), - TYPE_LENGTH (type)); + int_type = context->plugin ().int_type_v0 (TYPE_UNSIGNED (type), + TYPE_LENGTH (type)); - result = plugin->build_enum_type (int_type); + result = context->plugin ().build_enum_type (int_type); for (i = 0; i < TYPE_NFIELDS (type); ++i) { - plugin->build_add_enum_constant (result, - TYPE_FIELD_NAME (type, i), - TYPE_FIELD_ENUMVAL (type, i)); + context->plugin ().build_add_enum_constant + (result, TYPE_FIELD_NAME (type, i), TYPE_FIELD_ENUMVAL (type, i)); } - plugin->finish_enum_type (result); + context->plugin ().finish_enum_type (result); return result; } @@ -218,7 +240,7 @@ convert_enum (struct compile_c_instance *context, struct type *type) /* Convert a function type to its gcc representation. */ static gcc_type -convert_func (struct compile_c_instance *context, struct type *type) +convert_func (compile_c_instance *context, struct type *type) { int i; gcc_type result, return_type; @@ -243,14 +265,14 @@ convert_func (struct compile_c_instance *context, struct type *type) /* This approach means we can't make self-referential function types. Those are impossible in C, though. */ - return_type = convert_type (context, target_type); + return_type = context->convert_type (target_type); array.n_elements = TYPE_NFIELDS (type); array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (type)); for (i = 0; i < TYPE_NFIELDS (type); ++i) - array.elements[i] = convert_type (context, TYPE_FIELD_TYPE (type, i)); + array.elements[i] = context->convert_type (TYPE_FIELD_TYPE (type, i)); - result = context->c_plugin->build_function_type (return_type, + result = context->plugin ().build_function_type (return_type, &array, is_varargs); xfree (array.elements); @@ -260,62 +282,62 @@ convert_func (struct compile_c_instance *context, struct type *type) /* Convert an integer type to its gcc representation. */ static gcc_type -convert_int (struct compile_c_instance *context, struct type *type) +convert_int (compile_c_instance *context, struct type *type) { - if (context->c_plugin->version () >= GCC_C_FE_VERSION_1) + if (context->plugin ().version () >= GCC_C_FE_VERSION_1) { if (TYPE_NOSIGN (type)) { gdb_assert (TYPE_LENGTH (type) == 1); - return context->c_plugin->char_type (); + return context->plugin ().char_type (); } - return context->c_plugin->int_type (TYPE_UNSIGNED (type), + return context->plugin ().int_type (TYPE_UNSIGNED (type), TYPE_LENGTH (type), TYPE_NAME (type)); } else - return context->c_plugin->int_type_v0 (TYPE_UNSIGNED (type), + return context->plugin ().int_type_v0 (TYPE_UNSIGNED (type), TYPE_LENGTH (type)); } /* Convert a floating-point type to its gcc representation. */ static gcc_type -convert_float (struct compile_c_instance *context, struct type *type) +convert_float (compile_c_instance *context, struct type *type) { - if (context->c_plugin->version () >= GCC_C_FE_VERSION_1) - return context->c_plugin->float_type (TYPE_LENGTH (type), + if (context->plugin ().version () >= GCC_C_FE_VERSION_1) + return context->plugin ().float_type (TYPE_LENGTH (type), TYPE_NAME (type)); else - return context->c_plugin->float_type_v0 (TYPE_LENGTH (type)); + return context->plugin ().float_type_v0 (TYPE_LENGTH (type)); } /* Convert the 'void' type to its gcc representation. */ static gcc_type -convert_void (struct compile_c_instance *context, struct type *type) +convert_void (compile_c_instance *context, struct type *type) { - return context->c_plugin->void_type (); + return context->plugin ().void_type (); } /* Convert a boolean type to its gcc representation. */ static gcc_type -convert_bool (struct compile_c_instance *context, struct type *type) +convert_bool (compile_c_instance *context, struct type *type) { - return context->c_plugin->bool_type (); + return context->plugin ().bool_type (); } /* Convert a qualified type to its gcc representation. */ static gcc_type -convert_qualified (struct compile_c_instance *context, struct type *type) +convert_qualified (compile_c_instance *context, struct type *type) { struct type *unqual = make_unqualified_type (type); gcc_type unqual_converted; gcc_qualifiers_flags quals = 0; - unqual_converted = convert_type (context, unqual); + unqual_converted = context->convert_type (unqual); if (TYPE_CONST (type)) quals |= GCC_QUALIFIER_CONST; @@ -324,17 +346,17 @@ convert_qualified (struct compile_c_instance *context, struct type *type) if (TYPE_RESTRICT (type)) quals |= GCC_QUALIFIER_RESTRICT; - return context->c_plugin->build_qualified_type (unqual_converted, quals); + return context->plugin ().build_qualified_type (unqual_converted, quals); } /* Convert a complex type to its gcc representation. */ static gcc_type -convert_complex (struct compile_c_instance *context, struct type *type) +convert_complex (compile_c_instance *context, struct type *type) { - gcc_type base = convert_type (context, TYPE_TARGET_TYPE (type)); + gcc_type base = context->convert_type (TYPE_TARGET_TYPE (type)); - return context->c_plugin->build_complex_type (base); + return context->plugin ().build_complex_type (base); } /* A helper function which knows how to convert most types from their @@ -343,7 +365,7 @@ convert_complex (struct compile_c_instance *context, struct type *type) returns the gcc type. */ static gcc_type -convert_type_basic (struct compile_c_instance *context, struct type *type) +convert_type_basic (compile_c_instance *context, struct type *type) { /* If we are converting a qualified type, first convert the unqualified type and then apply the qualifiers. */ @@ -401,75 +423,38 @@ convert_type_basic (struct compile_c_instance *context, struct type *type) } } - return context->c_plugin->error (_("cannot convert gdb type to gcc type")); + return context->plugin ().error (_("cannot convert gdb type to gcc type")); } -/* See compile-internal.h. */ +/* Default compile flags for C. */ + +const char *compile_c_instance::m_default_cflags = "-std=gnu11" + /* Otherwise the .o file may need + "_Unwind_Resume" and + "__gcc_personality_v0". */ + " -fno-exceptions" + " -Wno-implicit-function-declaration"; + +/* See compile-c.h. */ gcc_type -convert_type (struct compile_c_instance *context, struct type *type) +compile_c_instance::convert_type (struct type *type) { - struct type_map_instance inst, *found; - gcc_type result; - /* We don't ever have to deal with typedefs in this code, because those are only needed as symbols by the C compiler. */ type = check_typedef (type); - inst.type = type; - found = (struct type_map_instance *) htab_find (context->type_map, &inst); - if (found != NULL) - return found->gcc_type_handle; + gcc_type result; + if (get_cached_type (type, result)) + return result; - result = convert_type_basic (context, type); - insert_type (context, type, result); + result = convert_type_basic (this, type); + insert_type (type, result); return result; } -/* Delete the compiler instance C. */ - -static void -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); - xfree (context); -} - -/* See compile-internal.h. */ - -struct compile_instance * -new_compile_instance (struct gcc_c_context *fe) -{ - struct compile_c_instance *result = XCNEW (struct compile_c_instance); - - result->base.fe = &fe->base; - result->base.destroy = delete_instance; - result->base.gcc_target_options = ("-std=gnu11" - /* Otherwise the .o file may need - "_Unwind_Resume" and - "__gcc_personality_v0". */ - " -fno-exceptions"); - - result->type_map = htab_create_alloc (10, hash_type_map_instance, - eq_type_map_instance, - xfree, xcalloc, xfree); - - 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__) diff --git a/gdb/compile/compile-c.h b/gdb/compile/compile-c.h index ffa58021e28..4dece9cf6ca 100644 --- a/gdb/compile/compile-c.h +++ b/gdb/compile/compile-c.h @@ -19,7 +19,6 @@ #include "common/enum-flags.h" #include "gcc-c-plugin.h" -#include "hashtab.h" /* enum-flags wrapper. */ @@ -36,20 +35,30 @@ extern gcc_c_symbol_address_function gcc_symbol_address; /* A subclass of compile_instance that is specific to the C front end. */ -struct compile_c_instance +class compile_c_instance : public compile_instance { - /* Base class. Note that the base class vtable actually points to a - gcc_c_fe_vtable. */ - struct compile_instance base; +public: + explicit compile_c_instance (struct gcc_c_context *gcc_c) + : compile_instance (&gcc_c->base, m_default_cflags), + m_plugin (gcc_c) + { + m_plugin.set_callbacks (gcc_convert_symbol, gcc_symbol_address, this); + } - /* Map from gdb types to gcc types. */ - htab_t type_map; + /* Convert a gdb type, TYPE, to a GCC type. - /* Map from gdb symbols to gcc error messages to emit. */ - htab_t symbol_err_map; + The new GCC type is returned. */ + gcc_type convert_type (struct type *type); - /* GCC C plugin. */ - gcc_c_plugin *c_plugin; + /* Return a handle for the GCC plug-in. */ + gcc_c_plugin &plugin () { return m_plugin; } + +private: + /* Default compiler flags for C. */ + static const char *m_default_cflags; + + /* The GCC plug-in. */ + gcc_c_plugin m_plugin; }; /* Emit code to compute the address for all the local variables in @@ -59,7 +68,7 @@ struct compile_c_instance extern gdb::unique_xmalloc_ptr generate_c_for_variable_locations - (struct compile_c_instance *compiler, + (compile_instance *compiler, string_file &stream, struct gdbarch *gdbarch, const struct block *block, diff --git a/gdb/compile/compile-internal.h b/gdb/compile/compile-internal.h index afe20e5141d..89dd1e58f27 100644 --- a/gdb/compile/compile-internal.h +++ b/gdb/compile/compile-internal.h @@ -28,28 +28,117 @@ struct block; /* An object of this type holds state associated with a given compilation job. */ -struct compile_instance +class compile_instance { - /* The GCC front end. */ +public: + compile_instance (struct gcc_base_context *gcc_fe, const char *options); - struct gcc_base_context *fe; + virtual ~compile_instance () + { + m_gcc_fe->ops->destroy (m_gcc_fe); + htab_delete (m_type_map); + if (m_symbol_err_map != NULL) + htab_delete (m_symbol_err_map); + } - /* The "scope" of this compilation. */ + /* Returns the GCC options to be passed during compilation. */ + const std::string &gcc_target_options () const + { + return m_gcc_target_options; + } - enum compile_i_scope_types scope; + /* Query the type cache for TYPE, returning the compiler's + type for it in RET. */ + bool get_cached_type (struct type *type, gcc_type &ret) const; - /* The block in which an expression is being parsed. */ + /* Insert GCC_TYPE into the type cache for TYPE. + + It is ok for a given type to be inserted more than once, provided that + the exact same association is made each time. */ + void insert_type (struct type *type, gcc_type gcc_type); + + /* Associate SYMBOL with some error text. */ + void insert_symbol_error (const struct symbol *sym, const char *text); + + /* Emit the error message corresponding to SYM, if one exists, and + arrange for it not to be emitted again. */ + void error_symbol_once (const struct symbol *sym); + + /* These currently just forward to the underlying ops + vtable. */ + + /* Set the plug-in print callback. */ + void set_print_callback (void (*print_function) (void *, const char *), + void *datum); + + /* Return the plug-in's front-end version. */ + unsigned int version () const; + + /* Set the plug-in's verbosity level. Nop for GCC_FE_VERSION_0. */ + void set_verbose (int level); + + /* Set the plug-in driver program. Nop for GCC_FE_VERSION_0. */ + void set_driver_filename (const char *filename); + + /* Set the regular expression used to match the configury triplet + prefix to the compiler. Nop for GCC_FE_VERSION_0. */ + void set_triplet_regexp (const char *regexp); + + /* Set compilation arguments. REGEXP is only used for protocol + version GCC_FE_VERSION_0. */ + char *set_arguments (int argc, char **argv, const char *regexp = NULL); + + /* Set the filename of the program to compile. Nop for GCC_FE_VERSION_0. */ + void set_source_file (const char *filename); + + /* Compile the previously specified source file to FILENAME. + VERBOSE_LEVEL is only used for protocol version GCC_FE_VERSION_0. */ + bool compile (const char *filename, int verbose_level = -1); - const struct block *block; + /* Set the scope type for this compile. */ + void set_scope (enum compile_i_scope_types scope) + { + m_scope = scope; + } + + /* Return the scope type. */ + enum compile_i_scope_types scope () const + { + return m_scope; + } + + /* Set the block to be used for symbol searches. */ + void set_block (const struct block *block) + { + m_block = block; + } + + /* Return the search block. */ + const struct block *block () const + { + return m_block; + } + +protected: + + /* The GCC front end. */ + struct gcc_base_context *m_gcc_fe; + + /* The "scope" of this compilation. */ + enum compile_i_scope_types m_scope; + + /* The block in which an expression is being parsed. */ + const struct block *m_block; /* Specify "-std=gnu11", "-std=gnu++11" or similar. These options are put after CU's DW_AT_producer compilation options to override them. */ + std::string m_gcc_target_options; - const char *gcc_target_options; + /* Map from gdb types to gcc types. */ + htab_t m_type_map; - /* How to destroy this object. */ - - void (*destroy) (struct compile_instance *); + /* Map from gdb symbols to gcc error messages to emit. */ + htab_t m_symbol_err_map; }; /* Define header and footers for different scopes. */ @@ -79,18 +168,6 @@ extern std::string compile_register_name_mangled (struct gdbarch *gdbarch, extern int compile_register_name_demangle (struct gdbarch *gdbarch, const char *reg_name); -/* Convert a gdb type, TYPE, to a GCC type. CONTEXT is used to do the - actual conversion. The new GCC type is returned. */ - -struct type; -extern gcc_type convert_type (struct compile_c_instance *context, - struct type *type); - -/* Instantiate a GDB object holding state for the GCC context FE. The - new object is returned. */ - -extern struct compile_instance *new_compile_instance (struct gcc_c_context *fe); - /* Type used to hold and pass around the source and object file names to use for compilation. */ class compile_file_names diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c index 01c0bc4b391..845229b6ba1 100644 --- a/gdb/compile/compile.c +++ b/gdb/compile/compile.c @@ -415,7 +415,7 @@ filter_args (int *argcp, char **argv) generated above. */ static void -get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch, +get_args (const compile_instance *compiler, struct gdbarch *gdbarch, int *argcp, char ***argvp) { const char *cs_producer_options; @@ -437,7 +437,7 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch, freeargv (argv_producer); } - build_argc_argv (compiler->gcc_target_options, + build_argc_argv (compiler->gcc_target_options ().c_str (), &argc_compiler, &argv_compiler); append_args (argcp, argvp, argc_compiler, argv_compiler); freeargv (argv_compiler); @@ -445,16 +445,6 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch, append_args (argcp, argvp, compile_args_argc, compile_args_argv); } -/* A cleanup function to destroy a gdb_gcc_instance. */ - -static void -cleanup_compile_instance (void *arg) -{ - struct compile_instance *inst = (struct compile_instance *) arg; - - inst->destroy (inst); -} - /* A helper function suitable for use as the "print_callback" in the compiler object. */ @@ -472,8 +462,6 @@ static compile_file_names compile_to_object (struct command_line *cmd, const char *cmd_string, enum compile_i_scope_types scope) { - struct compile_instance *compiler; - struct cleanup *cleanup; const struct block *expr_block; CORE_ADDR trash_pc, expr_pc; int argc; @@ -481,7 +469,6 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, int ok; struct gdbarch *gdbarch = get_current_arch (); std::string triplet_rx; - char *error_message; if (!target_has_execution) error (_("The program must be running for the compile command to "\ @@ -494,13 +481,13 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, if (current_language->la_get_compile_instance == NULL) error (_("No compiler support for language %s."), current_language->la_name); - compiler = current_language->la_get_compile_instance (); - cleanup = make_cleanup (cleanup_compile_instance, compiler); - compiler->fe->ops->set_print_callback (compiler->fe, print_callback, NULL); - - compiler->scope = scope; - compiler->block = expr_block; + compile_instance *compiler_instance + = current_language->la_get_compile_instance (); + std::unique_ptr compiler (compiler_instance); + compiler->set_print_callback (print_callback, NULL); + compiler->set_scope (scope); + compiler->set_block (expr_block); /* From the provided expression, build a scope to pass to the compiler. */ @@ -526,21 +513,20 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, error (_("Neither a simple expression, or a multi-line specified.")); std::string code - = current_language->la_compute_program (compiler, input, gdbarch, + = current_language->la_compute_program (compiler.get (), input, gdbarch, expr_block, expr_pc); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code.c_str ()); - if (compiler->fe->ops->version >= GCC_FE_VERSION_1) - compiler->fe->ops->set_verbose (compiler->fe, compile_debug); + compiler->set_verbose (compile_debug); if (compile_gcc[0] != 0) { - if (compiler->fe->ops->version < GCC_FE_VERSION_1) + if (compiler->version () < GCC_FE_VERSION_1) error (_("Command 'set compile-gcc' requires GCC version 6 or higher " "(libcc1 interface version 1 or higher)")); - compiler->fe->ops->set_driver_filename (compiler->fe, compile_gcc); + compiler->set_driver_filename (compile_gcc); } else { @@ -549,27 +535,19 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, /* Allow triplets with or without vendor set. */ triplet_rx = std::string (arch_rx) + "(-[^-]*)?-" + os_rx; - - if (compiler->fe->ops->version >= GCC_FE_VERSION_1) - compiler->fe->ops->set_triplet_regexp (compiler->fe, - triplet_rx.c_str ()); + compiler->set_triplet_regexp (triplet_rx.c_str ()); } /* Set compiler command-line arguments. */ - get_args (compiler, gdbarch, &argc, &argv); + get_args (compiler.get (), gdbarch, &argc, &argv); gdb_argv argv_holder (argv); - if (compiler->fe->ops->version >= GCC_FE_VERSION_1) - error_message = compiler->fe->ops->set_arguments (compiler->fe, argc, argv); - else - error_message = compiler->fe->ops->set_arguments_v0 (compiler->fe, - triplet_rx.c_str (), - argc, argv); + gdb::unique_xmalloc_ptr error_message; + error_message.reset (compiler->set_arguments (argc, argv, + triplet_rx.c_str ())); + if (error_message != NULL) - { - make_cleanup (xfree, error_message); - error ("%s", error_message); - } + error ("%s", error_message.get ()); if (compile_debug) { @@ -601,13 +579,8 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, fnames.source_file ()); /* Call the compiler and start the compilation process. */ - compiler->fe->ops->set_source_file (compiler->fe, fnames.source_file ()); - - if (compiler->fe->ops->version >= GCC_FE_VERSION_1) - ok = compiler->fe->ops->compile (compiler->fe, fnames.object_file ()); - else - ok = compiler->fe->ops->compile_v0 (compiler->fe, fnames.object_file (), - compile_debug); + compiler->set_source_file (fnames.source_file ()); + ok = compiler->compile (fnames.object_file (), compile_debug); if (!ok) error (_("Compilation failed.")); @@ -617,9 +590,6 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, /* Keep the source file. */ source_remover->keep (); - - do_cleanups (cleanup); - return fnames; } @@ -691,6 +661,87 @@ compile_register_name_demangle (struct gdbarch *gdbarch, error (_("Cannot find gdbarch register \"%s\"."), regname); } +/* Forwards to the plug-in. */ + +#define FORWARD(OP,...) (m_gcc_fe->ops->OP (m_gcc_fe, ##__VA_ARGS__)) + +/* See compile-internal.h. */ + +void +compile_instance::set_print_callback + (void (*print_function) (void *, const char *), void *datum) +{ + FORWARD (set_print_callback, print_function, datum); +} + +/* See compile-internal.h. */ + +unsigned int +compile_instance::version () const +{ + return m_gcc_fe->ops->version; +} + +/* See compile-internal.h. */ + +void +compile_instance::set_verbose (int level) +{ + if (version () >= GCC_FE_VERSION_1) + FORWARD (set_verbose, level); +} + +/* See compile-internal.h. */ + +void +compile_instance::set_driver_filename (const char *filename) +{ + if (version () >= GCC_FE_VERSION_1) + FORWARD (set_driver_filename, filename); +} + +/* See compile-internal.h. */ + +void +compile_instance::set_triplet_regexp (const char *regexp) +{ + if (version () >= GCC_FE_VERSION_1) + FORWARD (set_triplet_regexp, regexp); +} + +/* See compile-internal.h. */ + +char * +compile_instance::set_arguments (int argc, char **argv, const char *regexp) +{ + if (version () >= GCC_FE_VERSION_1) + return FORWARD (set_arguments, argc, argv); + else + return FORWARD (set_arguments_v0, regexp, argc, argv); +} + +/* See compile-internal.h. */ + +void +compile_instance::set_source_file (const char *filename) +{ + FORWARD (set_source_file, filename); +} + +/* See compile-internal.h. */ + +bool +compile_instance::compile (const char *filename, int verbose_level) +{ + if (version () >= GCC_FE_VERSION_1) + return FORWARD (compile, filename); + else + return FORWARD (compile_v0, filename, verbose_level); +} + +#undef FORWARD + + void _initialize_compile (void) { diff --git a/gdb/language.h b/gdb/language.h index c4b7619d1b8..02a84ff9a2b 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -36,7 +36,7 @@ struct value_print_options; struct type_print_options; struct lang_varobj_ops; struct parser_state; -struct compile_instance; +class compile_instance; struct completion_match_for_lcd; #define MAX_FORTRAN_DIMS 7 /* Maximum number of F77 array dims. */ @@ -424,7 +424,7 @@ struct language_defn instance is owned by its caller and must be deallocated by calling its 'destroy' method. */ - struct compile_instance *(*la_get_compile_instance) (void); + compile_instance *(*la_get_compile_instance) (void); /* This method must be defined if 'la_get_gcc_context' is defined. If 'la_get_gcc_context' is not defined, then this method is @@ -440,7 +440,7 @@ struct language_defn parsed. EXPR_PC is the PC at which the expression is being parsed. */ - std::string (*la_compute_program) (struct compile_instance *inst, + std::string (*la_compute_program) (compile_instance *inst, const char *input, struct gdbarch *gdbarch, const struct block *expr_block, -- 2.30.2