/* Convert types from GDB to GCC
- Copyright (C) 2014-2018 Free Software Foundation, Inc.
+ Copyright (C) 2014-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "gdbtypes.h"
#include "compile-internal.h"
+#include "compile-c.h"
#include "objfiles.h"
-/* An object that maps a gdb type to a gcc type. */
-
-struct type_map_instance
-{
- /* The gdb type. */
-
- struct type *type;
-
- /* The corresponding gcc type handle. */
-
- gcc_type gcc_type_handle;
-};
-
-/* Hash a type_map_instance. */
-
-static hashval_t
-hash_type_map_instance (const void *p)
-{
- const struct type_map_instance *inst = (const struct type_map_instance *) p;
-
- return htab_hash_pointer (inst->type);
-}
-
-/* Check two type_map_instance objects for equality. */
-
-static int
-eq_type_map_instance (const void *a, const void *b)
-{
- const struct type_map_instance *insta = (const struct type_map_instance *) a;
- const struct type_map_instance *instb = (const struct type_map_instance *) b;
-
- return insta->type == instb->type;
-}
-
-\f
-
-/* 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. */
-
-static void
-insert_type (struct compile_c_instance *context, 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);
-
- add = (struct type_map_instance *) *slot;
- /* The type might have already been inserted in order to handle
- recursive types. */
- if (add != NULL && add->gcc_type_handle != gcc_type)
- error (_("Unexpected type id from GCC, check you use recent enough GCC."));
-
- if (add == NULL)
- {
- add = XNEW (struct type_map_instance);
- *add = inst;
- *slot = add;
- }
-}
-
/* 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 C_CTX (context)->c_ops->build_pointer_type (C_CTX (context),
- 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);
+ struct type *range = type->index_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 C_CTX (context)->c_ops->error (C_CTX (context),
- _("array type with non-constant"
- " lower bound is not supported"));
+ return context->plugin ().error (_("array type with non-constant"
+ " lower bound is not supported"));
if (TYPE_LOW_BOUND (range) != 0)
- return C_CTX (context)->c_ops->error (C_CTX (context),
- _("cannot convert array type with "
- "non-zero lower bound to C"));
+ return context->plugin ().error (_("cannot convert array type with "
+ "non-zero lower bound to C"));
if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR
|| TYPE_HIGH_BOUND_KIND (range) == PROP_LOCLIST)
gcc_type result;
if (TYPE_VECTOR (type))
- return C_CTX (context)->c_ops->error (C_CTX (context),
- _("variably-sized vector type"
- " is not supported"));
+ 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 = C_CTX (context)->c_ops->build_vla_array_type (C_CTX (context),
- element_type,
- upper_bound.c_str ());
+ result = context->plugin ().build_vla_array_type (element_type,
+ upper_bound.c_str ());
return result;
}
else
}
if (TYPE_VECTOR (type))
- return C_CTX (context)->c_ops->build_vector_type (C_CTX (context),
- element_type,
- count);
- return C_CTX (context)->c_ops->build_array_type (C_CTX (context),
- 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;
/* 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 = C_CTX (context)->c_ops->build_record_type (C_CTX (context));
+ if (type->code () == TYPE_CODE_STRUCT)
+ result = context->plugin ().build_record_type ();
else
{
- gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
- result = C_CTX (context)->c_ops->build_union_type (C_CTX (context));
+ gdb_assert (type->code () == TYPE_CODE_UNION);
+ result = context->plugin ().build_union_type ();
}
- insert_type (context, type, result);
+ context->insert_type (type, result);
- for (i = 0; i < TYPE_NFIELDS (type); ++i)
+ for (i = 0; i < type->num_fields (); ++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 (i).type ());
if (bitsize == 0)
- bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
- C_CTX (context)->c_ops->build_add_field (C_CTX (context), result,
- TYPE_FIELD_NAME (type, i),
- field_type,
- bitsize,
- TYPE_FIELD_BITPOS (type, i));
+ bitsize = 8 * TYPE_LENGTH (type->field (i).type ());
+ context->plugin ().build_add_field (result,
+ TYPE_FIELD_NAME (type, i),
+ field_type,
+ bitsize,
+ TYPE_FIELD_BITPOS (type, i));
}
- C_CTX (context)->c_ops->finish_record_or_union (C_CTX (context), 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;
- struct gcc_c_context *ctx = C_CTX (context);
- int_type = ctx->c_ops->int_type_v0 (ctx,
- TYPE_UNSIGNED (type),
- TYPE_LENGTH (type));
+ int_type = context->plugin ().int_type_v0 (TYPE_UNSIGNED (type),
+ TYPE_LENGTH (type));
- result = ctx->c_ops->build_enum_type (ctx, int_type);
- for (i = 0; i < TYPE_NFIELDS (type); ++i)
+ result = context->plugin ().build_enum_type (int_type);
+ for (i = 0; i < type->num_fields (); ++i)
{
- ctx->c_ops->build_add_enum_constant (ctx,
- 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));
}
- ctx->c_ops->finish_enum_type (ctx, result);
+ context->plugin ().finish_enum_type (result);
return result;
}
/* 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;
/* 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.n_elements = type->num_fields ();
+ array.elements = XNEWVEC (gcc_type, type->num_fields ());
+ for (i = 0; i < type->num_fields (); ++i)
+ array.elements[i] = context->convert_type (type->field (i).type ());
- result = C_CTX (context)->c_ops->build_function_type (C_CTX (context),
- return_type,
- &array, is_varargs);
+ result = context->plugin ().build_function_type (return_type,
+ &array, is_varargs);
xfree (array.elements);
return result;
/* 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)
{
- return C_CTX (context)->c_ops->int_type_v0 (C_CTX (context),
- TYPE_UNSIGNED (type),
- TYPE_LENGTH (type));
+ if (context->plugin ().version () >= GCC_C_FE_VERSION_1)
+ {
+ if (TYPE_NOSIGN (type))
+ {
+ gdb_assert (TYPE_LENGTH (type) == 1);
+ return context->plugin ().char_type ();
+ }
+ return context->plugin ().int_type (TYPE_UNSIGNED (type),
+ TYPE_LENGTH (type),
+ type->name ());
+ }
+ else
+ 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)
{
- return C_CTX (context)->c_ops->float_type_v0 (C_CTX (context),
- TYPE_LENGTH (type));
+ if (context->plugin ().version () >= GCC_C_FE_VERSION_1)
+ return context->plugin ().float_type (TYPE_LENGTH (type),
+ type->name ());
+ else
+ 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 C_CTX (context)->c_ops->void_type (C_CTX (context));
+ 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 C_CTX (context)->c_ops->bool_type (C_CTX (context));
+ 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;
if (TYPE_RESTRICT (type))
quals |= GCC_QUALIFIER_RESTRICT;
- return C_CTX (context)->c_ops->build_qualified_type (C_CTX (context),
- 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 C_CTX (context)->c_ops->build_complex_type (C_CTX (context), base);
+ return context->plugin ().build_complex_type (base);
}
/* A helper function which knows how to convert most types from their
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. */
| TYPE_INSTANCE_FLAG_RESTRICT)) != 0)
return convert_qualified (context, type);
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_PTR:
return convert_pointer (context, type);
}
}
- return C_CTX (context)->c_ops->error (C_CTX (context),
- _("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;
}
\f
-/* 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);
- 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);
-
- fe->c_ops->set_callbacks (fe, 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__)
+#define GCC_METHOD0(R, N) \
+ R gcc_c_plugin::N () const \
+ { return FORWARD (N); }
+#define GCC_METHOD1(R, N, A) \
+ R gcc_c_plugin::N (A a) const \
+ { return FORWARD (N, a); }
+#define GCC_METHOD2(R, N, A, B) \
+ R gcc_c_plugin::N (A a, B b) const \
+ { return FORWARD (N, a, b); }
+#define GCC_METHOD3(R, N, A, B, C) \
+ R gcc_c_plugin::N (A a, B b, C c) const \
+ { return FORWARD (N, a, b, c); }
+#define GCC_METHOD4(R, N, A, B, C, D) \
+ R gcc_c_plugin::N (A a, B b, C c, D d) const \
+ { return FORWARD (N, a, b, c, d); }
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+ R gcc_c_plugin::N (A a, B b, C c, D d, E e) const \
+ { return FORWARD (N, a, b, c, d, e); }
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+ R gcc_c_plugin::N (A a, B b, C c, D d, E e, F f, G g) const \
+ { return FORWARD (N, a, b, c, d, e, f, g); }
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
+#undef FORWARD