diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6873ee5073..e70a503d48 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 e961826407..b7bf08992b 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 41fead9ad1..d77c7d9625 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 abd829838b..b60b8ddcc9 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 228966f738..bfc6ccf1bb 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. */ -static void -insert_type (struct compile_c_instance *context, struct type *type, - gcc_type gcc_type) +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. */ + +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 ffa58021e2..4dece9cf6c 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 afe20e5141..89dd1e58f2 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); + } + + /* Returns the GCC options to be passed during compilation. */ + const std::string &gcc_target_options () const + { + return m_gcc_target_options; + } + + /* 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; + + /* 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); + + /* 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 scope; + enum compile_i_scope_types m_scope; /* The block in which an expression is being parsed. */ - - const struct block *block; + 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 01c0bc4b39..845229b6ba 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 c4b7619d1b..02a84ff9a2 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,