* gdbtypes.c (append_composite_type_field_raw): New.

(append_composite_type_field_aligned): Use the new function.
	* gdbtypes.h (append_composite_type_field_raw): Declare.
	* target-descriptions.c (struct tdesc_type_field): Add start and end.
	(struct tdesc_type_flag): New type.
	(struct tdesc_type): Add TDESC_TYPE_STRUCT and TDESC_TYPE_FLAGS to
	kind.  Add size to u.u.  Add u.f for flags.
	(tdesc_gdb_type): Handle TDESC_TYPE_STRUCT and TDESC_TYPE_FLAGS.
	(tdesc_free_type): Likewise.
	(tdesc_create_struct, tdesc_set_struct_size, tdesc_create_flags): New.
	(tdesc_add_field): Handle TDESC_TYPE_STRUCT.
	(tdesc_add_bitfield, tdesc_add_flag): New.
	* target-descriptions.h (tdesc_create_struct, tdesc_set_struct_size)
	(tdesc_create_flags, tdesc_add_bitfield, tdesc_add_flag): Declare.
	* xml-tdesc.c (struct tdesc_parsing_data): Rename current_union to
	current_type.  Add current_type_size and current_type_is_flags.
	(tdesc_start_union): Clear the new fields.
	(tdesc_start_struct, tdesc_start_flags): New.
	(tdesc_start_field): Handle struct fields, including bitfields.
	(field_attributes): Make type optional.  Add start and end.
	(union_children): Rename to struct_union_children.
	(union_attributes): Rename to struct_union_attributes.  Add optional
	size.
	(flags_attributes): New.
	(feature_children): Add struct and flags.
	* features/gdb-target.dtd: Add flags and struct to features.
	Make field type optional.  Add field start and end.

	doc/
	* gdb.texinfo (Types): Describe <struct> and <flags>.

	testsuite/
	* gdb.xml/extra-regs.xml: Add struct1, struct2, and flags
	types.  Add structreg, bitfields, and flags registers.
	* gdb.xml/tdesc-regs.exp: Test structreg and bitfields
	registers.
This commit is contained in:
Daniel Jacobowitz
2010-03-01 17:19:23 +00:00
parent bd56defd73
commit f5dff77744
12 changed files with 483 additions and 26 deletions

View File

@ -90,9 +90,17 @@ typedef struct tdesc_type_field
{
char *name;
struct tdesc_type *type;
int start, end;
} tdesc_type_field;
DEF_VEC_O(tdesc_type_field);
typedef struct tdesc_type_flag
{
char *name;
int start;
} tdesc_type_flag;
DEF_VEC_O(tdesc_type_flag);
typedef struct tdesc_type
{
/* The name of this type. */
@ -123,7 +131,9 @@ typedef struct tdesc_type
/* Types defined by a target feature. */
TDESC_TYPE_VECTOR,
TDESC_TYPE_UNION
TDESC_TYPE_STRUCT,
TDESC_TYPE_UNION,
TDESC_TYPE_FLAGS
} kind;
/* Kind-specific data. */
@ -136,11 +146,19 @@ typedef struct tdesc_type
int count;
} v;
/* Union type. */
/* Struct or union type. */
struct
{
VEC(tdesc_type_field) *fields;
LONGEST size;
} u;
/* Flags type. */
struct
{
VEC(tdesc_type_flag) *flags;
LONGEST size;
} f;
} u;
} *tdesc_type_p;
DEF_VEC_P(tdesc_type_p);
@ -652,6 +670,66 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
return type;
}
case TDESC_TYPE_STRUCT:
{
struct type *type, *field_type;
struct tdesc_type_field *f;
int ix;
type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
TYPE_NAME (type) = xstrdup (tdesc_type->name);
TYPE_TAG_NAME (type) = TYPE_NAME (type);
for (ix = 0;
VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, ix, f);
ix++)
{
if (f->type == NULL)
{
/* Bitfield. */
struct field *fld;
struct type *field_type;
int bitsize, total_size;
/* This invariant should be preserved while creating
types. */
gdb_assert (tdesc_type->u.u.size != 0);
if (tdesc_type->u.u.size > 4)
field_type = builtin_type (gdbarch)->builtin_uint64;
else
field_type = builtin_type (gdbarch)->builtin_uint32;
fld = append_composite_type_field_raw (type, xstrdup (f->name),
field_type);
/* For little-endian, BITPOS counts from the LSB of
the structure and marks the LSB of the field. For
big-endian, BITPOS counts from the MSB of the
structure and marks the MSB of the field. Either
way, it is the number of bits to the "left" of the
field. To calculate this in big-endian, we need
the total size of the structure. */
bitsize = f->end - f->start + 1;
total_size = tdesc_type->u.u.size * TARGET_CHAR_BIT;
if (gdbarch_bits_big_endian (gdbarch))
FIELD_BITPOS (fld[0]) = total_size - f->start - bitsize;
else
FIELD_BITPOS (fld[0]) = f->start;
FIELD_BITSIZE (fld[0]) = bitsize;
}
else
{
field_type = tdesc_gdb_type (gdbarch, f->type);
append_composite_type_field (type, xstrdup (f->name),
field_type);
}
}
if (tdesc_type->u.u.size != 0)
TYPE_LENGTH (type) = tdesc_type->u.u.size;
return type;
}
case TDESC_TYPE_UNION:
{
struct type *type, *field_type;
@ -668,12 +746,30 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
field_type = tdesc_gdb_type (gdbarch, f->type);
append_composite_type_field (type, xstrdup (f->name), field_type);
/* If any of the children of this union are vectors, flag the
/* If any of the children of a union are vectors, flag the
union as a vector also. This allows e.g. a union of two
vector types to show up automatically in "info vector". */
if (TYPE_VECTOR (field_type))
TYPE_VECTOR (type) = 1;
}
return type;
}
case TDESC_TYPE_FLAGS:
{
struct type *type, *field_type;
struct tdesc_type_flag *f;
int ix;
type = arch_flags_type (gdbarch, xstrdup (tdesc_type->name),
tdesc_type->u.f.size);
for (ix = 0;
VEC_iterate (tdesc_type_flag, tdesc_type->u.f.flags, ix, f);
ix++)
/* Note that contrary to the function name, this call will
just set the properties of an already-allocated
field. */
append_flags_type_flag (type, f->start, f->name);
return type;
}
@ -1161,6 +1257,7 @@ tdesc_free_type (struct tdesc_type *type)
switch (type->kind)
{
case TDESC_TYPE_STRUCT:
case TDESC_TYPE_UNION:
{
struct tdesc_type_field *f;
@ -1175,6 +1272,20 @@ tdesc_free_type (struct tdesc_type *type)
}
break;
case TDESC_TYPE_FLAGS:
{
struct tdesc_type_flag *f;
int ix;
for (ix = 0;
VEC_iterate (tdesc_type_flag, type->u.f.flags, ix, f);
ix++)
xfree (f->name);
VEC_free (tdesc_type_flag, type->u.f.flags);
}
break;
default:
break;
}
@ -1198,6 +1309,29 @@ tdesc_create_vector (struct tdesc_feature *feature, const char *name,
return type;
}
struct tdesc_type *
tdesc_create_struct (struct tdesc_feature *feature, const char *name)
{
struct tdesc_type *type = XZALLOC (struct tdesc_type);
type->name = xstrdup (name);
type->kind = TDESC_TYPE_STRUCT;
VEC_safe_push (tdesc_type_p, feature->types, type);
return type;
}
/* Set the total length of TYPE. Structs which contain bitfields may
omit the reserved bits, so the end of the last field may not
suffice. */
void
tdesc_set_struct_size (struct tdesc_type *type, LONGEST size)
{
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
type->u.u.size = size;
}
struct tdesc_type *
tdesc_create_union (struct tdesc_feature *feature, const char *name)
{
@ -1210,13 +1344,32 @@ tdesc_create_union (struct tdesc_feature *feature, const char *name)
return type;
}
struct tdesc_type *
tdesc_create_flags (struct tdesc_feature *feature, const char *name,
LONGEST size)
{
struct tdesc_type *type = XZALLOC (struct tdesc_type);
type->name = xstrdup (name);
type->kind = TDESC_TYPE_FLAGS;
type->u.f.size = size;
VEC_safe_push (tdesc_type_p, feature->types, type);
return type;
}
/* Add a new field. Return a temporary pointer to the field, which
is only valid until the next call to tdesc_add_field (the vector
might be reallocated). */
void
tdesc_add_field (struct tdesc_type *type, const char *field_name,
struct tdesc_type *field_type)
{
struct tdesc_type_field f = { 0 };
gdb_assert (type->kind == TDESC_TYPE_UNION);
gdb_assert (type->kind == TDESC_TYPE_UNION
|| type->kind == TDESC_TYPE_STRUCT);
f.name = xstrdup (field_name);
f.type = field_type;
@ -1224,6 +1377,37 @@ tdesc_add_field (struct tdesc_type *type, const char *field_name,
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
}
/* Add a new bitfield. */
void
tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
int start, int end)
{
struct tdesc_type_field f = { 0 };
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
f.name = xstrdup (field_name);
f.start = start;
f.end = end;
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
}
void
tdesc_add_flag (struct tdesc_type *type, int start,
const char *flag_name)
{
struct tdesc_type_flag f = { 0 };
gdb_assert (type->kind == TDESC_TYPE_FLAGS);
f.name = xstrdup (flag_name);
f.start = start;
VEC_safe_push (tdesc_type_flag, type->u.f.flags, &f);
}
static void
tdesc_free_feature (struct tdesc_feature *feature)
{