Extend flags to support multibit and enum bitfields.

gdb/ChangeLog:

	Extend flags to support multibit and enum bitfields.
	NEWS: Document new features.
	* c-typeprint.c (c_type_print_varspec_prefix): Handle TYPE_CODE_FLAGS.
	(c_type_print_varspec_suffix, c_type_print_base): Ditto.
	* gdbtypes.c (arch_flags_type): Don't assume all fields are one bit.
	(append_flags_type_field): New function.
	(append_flags_type_flag): Call it.
	* gdbtypes.h (append_flags_type_field): Declare.
	* target-descriptions.c (struct tdesc_type_flag): Delete.
	(enum tdesc_type_kind) <TDESC_TYPE_BOOL>: New enum value.
	(enum tdesc_type_kind) <TDESC_TYPE_ENUM>: Ditto.
	(struct tdesc_type) <u.f>: Delete.
	(tdesc_predefined_types): Add "bool".
	(tdesc_predefined_type): New function.
	(tdesc_gdb_type): Handle TDESC_TYPE_BOOL, TDESC_TYPE_ENUM.
	Update TDESC_TYPE_FLAGS support.
	(tdesc_free_type): Handle TDESC_TYPE_ENUM.  Update TDESC_TYPE_FLAGS.
	(tdesc_create_flags): Update.
	(tdesc_create_enum): New function.
	(tdesc_add_field): Initialize start,end to -1.
	(tdesc_add_typed_bitfield): New function.
	(tdesc_add_bitfield): Call it.
	(tdesc_add_flag): Allow TDESC_TYPE_STRUCT.  Update.
	(tdesc_add_enum_value): New function.
	(maint_print_c_tdesc_cmd): Fold TDESC_TYPE_FLAGS support into
	TDESC_TYPE_STRUCT.  Handle TDESC_TYPE_ENUM.
	* target-descriptions.h (tdesc_create_enum): Declare.
	(tdesc_add_typed_bitfield, tdesc_add_enum_value): Declare.
	* valprint.c (generic_val_print_enum_1): New function.
	(generic_val_print_enum): Call it.
	(val_print_type_code_flags): Make static.  Handle multibit bitfields
	and enum bitfields.
	* valprint.h (val_print_type_code_flags): Delete.
	* xml-tdesc.c (struct tdesc_parsing_data) <current_type_is_flags>:
	Delete.  All uses removed.
	(tdesc_start_enum): New function.
	(tdesc_start_field): Handle multibit and enum bitfields.
	(tdesc_start_enum_value): New function.
	(enum_value_attributes, enum_children, enum_attributes): New static
	globals.
	(feature_children): Add "enum".
	* features/gdb-target.dtd (enum, evalue): New elements.

gdb/doc/ChangeLog:

	* gdb.texinfo (Target Descriptions): New menu item "Enum Target Types".
	(Target Description Format): Mention enum types.  Update docs on
	flags types.
	(Predefined Target Types): Add "bool".
	(Enum Target Types): New node.

gdb/testsuite/ChangeLog:

	* gdb.xml/extra-regs.xml: Add enum, mixed_flags values.
	* gdb.xml/tdesc-regs.exp (load_description): New arg xml_file.
	All callers updated.  Add tests for enums, mixed flags register.
This commit is contained in:
Doug Evans 2016-03-15 14:37:29 -07:00
parent 54157a25aa
commit 8151645076
16 changed files with 735 additions and 220 deletions

View File

@ -1,3 +1,48 @@
2016-03-15 Doug Evans <dje@google.com>
Extend flags to support multibit and enum bitfields.
NEWS: Document new features.
* c-typeprint.c (c_type_print_varspec_prefix): Handle TYPE_CODE_FLAGS.
(c_type_print_varspec_suffix, c_type_print_base): Ditto.
* gdbtypes.c (arch_flags_type): Don't assume all fields are one bit.
(append_flags_type_field): New function.
(append_flags_type_flag): Call it.
* gdbtypes.h (append_flags_type_field): Declare.
* target-descriptions.c (struct tdesc_type_flag): Delete.
(enum tdesc_type_kind) <TDESC_TYPE_BOOL>: New enum value.
(enum tdesc_type_kind) <TDESC_TYPE_ENUM>: Ditto.
(struct tdesc_type) <u.f>: Delete.
(tdesc_predefined_types): Add "bool".
(tdesc_predefined_type): New function.
(tdesc_gdb_type): Handle TDESC_TYPE_BOOL, TDESC_TYPE_ENUM.
Update TDESC_TYPE_FLAGS support.
(tdesc_free_type): Handle TDESC_TYPE_ENUM. Update TDESC_TYPE_FLAGS.
(tdesc_create_flags): Update.
(tdesc_create_enum): New function.
(tdesc_add_field): Initialize start,end to -1.
(tdesc_add_typed_bitfield): New function.
(tdesc_add_bitfield): Call it.
(tdesc_add_flag): Allow TDESC_TYPE_STRUCT. Update.
(tdesc_add_enum_value): New function.
(maint_print_c_tdesc_cmd): Fold TDESC_TYPE_FLAGS support into
TDESC_TYPE_STRUCT. Handle TDESC_TYPE_ENUM.
* target-descriptions.h (tdesc_create_enum): Declare.
(tdesc_add_typed_bitfield, tdesc_add_enum_value): Declare.
* valprint.c (generic_val_print_enum_1): New function.
(generic_val_print_enum): Call it.
(val_print_type_code_flags): Make static. Handle multibit bitfields
and enum bitfields.
* valprint.h (val_print_type_code_flags): Delete.
* xml-tdesc.c (struct tdesc_parsing_data) <current_type_is_flags>:
Delete. All uses removed.
(tdesc_start_enum): New function.
(tdesc_start_field): Handle multibit and enum bitfields.
(tdesc_start_enum_value): New function.
(enum_value_attributes, enum_children, enum_attributes): New static
globals.
(feature_children): Add "enum".
* features/gdb-target.dtd (enum, evalue): New elements.
2016-03-15 Doug Evans <dje@google.com>
* target-descriptions.c (struct tdesc_type) <u.u.size>: Change type

View File

@ -3,6 +3,9 @@
*** Changes since GDB 7.11
* GDB now supports multibit bitfields and enums in target register
descriptions.
* New Python-based convenience function $_as_string(val), which returns
the textual representation of a value. This function is especially
useful to obtain the text label of an enum value.

View File

@ -371,6 +371,7 @@ c_type_print_varspec_prefix (struct type *type,
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
case TYPE_CODE_ENUM:
case TYPE_CODE_FLAGS:
case TYPE_CODE_INT:
case TYPE_CODE_FLT:
case TYPE_CODE_VOID:
@ -748,6 +749,7 @@ c_type_print_varspec_suffix (struct type *type,
case TYPE_CODE_UNDEF:
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
case TYPE_CODE_FLAGS:
case TYPE_CODE_ENUM:
case TYPE_CODE_INT:
case TYPE_CODE_FLT:
@ -1402,6 +1404,54 @@ c_type_print_base (struct type *type, struct ui_file *stream,
}
break;
case TYPE_CODE_FLAGS:
{
struct type_print_options local_flags = *flags;
local_flags.local_typedefs = NULL;
c_type_print_modifier (type, stream, 0, 1);
fprintf_filtered (stream, "flag ");
print_name_maybe_canonical (TYPE_NAME (type), flags, stream);
if (show > 0)
{
fputs_filtered (" ", stream);
fprintf_filtered (stream, "{\n");
if (TYPE_NFIELDS (type) == 0)
{
if (TYPE_STUB (type))
fprintfi_filtered (level + 4, stream,
_("<incomplete type>\n"));
else
fprintfi_filtered (level + 4, stream,
_("<no data fields>\n"));
}
len = TYPE_NFIELDS (type);
for (i = 0; i < len; i++)
{
QUIT;
print_spaces_filtered (level + 4, stream);
/* We pass "show" here and not "show - 1" to get enum types
printed. There's no other way to see them. */
c_print_type (TYPE_FIELD_TYPE (type, i),
TYPE_FIELD_NAME (type, i),
stream, show, level + 4,
&local_flags);
fprintf_filtered (stream, " @%d",
TYPE_FIELD_BITPOS (type, i));
if (TYPE_FIELD_BITSIZE (type, i) > 1)
{
fprintf_filtered (stream, "-%d",
TYPE_FIELD_BITPOS (type, i)
+ TYPE_FIELD_BITSIZE (type, i) - 1);
}
fprintf_filtered (stream, ";\n");
}
fprintfi_filtered (level, stream, "}");
}
}
break;
case TYPE_CODE_VOID:
fprintf_filtered (stream, "void");
break;

View File

@ -1,3 +1,11 @@
2016-03-15 Doug Evans <dje@google.com>
* gdb.texinfo (Target Descriptions): New menu item "Enum Target Types".
(Target Description Format): Mention enum types. Update docs on
flags types.
(Predefined Target Types): Add "bool".
(Enum Target Types): New node.
2016-03-15 Pedro Alves <palves@redhat.com>
* gdb.texinfo (Tracepoint Actions): Fix typo.

View File

@ -40359,6 +40359,7 @@ target descriptions. @xref{Expat}.
* Target Description Format:: The contents of a target description.
* Predefined Target Types:: Standard types available for target
descriptions.
* Enum Target Types:: How to define enum target types.
* Standard Target Features:: Features @value{GDBN} knows about.
@end menu
@ -40559,7 +40560,8 @@ Any register's value is a collection of bits which @value{GDBN} must
interpret. The default interpretation is a two's complement integer,
but other types can be requested by name in the register description.
Some predefined types are provided by @value{GDBN} (@pxref{Predefined
Target Types}), and the description can define additional composite types.
Target Types}), and the description can define additional composite
and enum types.
Each type element must have an @samp{id} attribute, which gives
a unique (within the containing @samp{<feature>}) name to the type.
@ -40589,24 +40591,15 @@ each of which has a @var{name} and a @var{type}:
@end smallexample
@cindex <struct>
@cindex <flags>
If a register's value is composed from several separate values, define
it with a structure type. There are two forms of the @samp{<struct>}
element; a @samp{<struct>} element must either contain only bitfields
or contain no bitfields. If the structure contains only bitfields,
its total size in bytes must be specified, each bitfield must have an
explicit start and end, and bitfields are automatically assigned an
integer type. The field's @var{start} should be less than or
equal to its @var{end}, and zero represents the least significant bit.
it with either a structure type or a flags type.
A flags type may only contain bitfields.
A structure type may either contain only bitfields or contain no bitfields.
If the value contains only bitfields, its total size in bytes must be
specified.
@smallexample
<struct id="@var{id}" size="@var{size}">
<field name="@var{name}" start="@var{start}" end="@var{end}"/>
@dots{}
</struct>
@end smallexample
If the structure contains no bitfields, then each field has an
explicit type, and no implicit padding is added.
Non-bitfield values have a @var{name} and @var{type}.
@smallexample
<struct id="@var{id}">
@ -40615,20 +40608,67 @@ explicit type, and no implicit padding is added.
</struct>
@end smallexample
@cindex <flags>
If a register's value is a series of single-bit flags, define it with
a flags type. The @samp{<flags>} element has an explicit @var{size}
and contains one or more @samp{<field>} elements. Each field has a
@var{name}, a @var{start}, and an @var{end}. Only single-bit flags
are supported.
Both @var{name} and @var{type} values are required.
No implicit padding is added.
Bitfield values have a @var{name}, @var{start}, @var{end} and @var{type}.
@smallexample
<struct id="@var{id}" size="@var{size}">
<field name="@var{name}" start="@var{start}" end="@var{end}" type="@var{type}"/>
@dots{}
</struct>
@end smallexample
@smallexample
<flags id="@var{id}" size="@var{size}">
<field name="@var{name}" start="@var{start}" end="@var{end}"/>
<field name="@var{name}" start="@var{start}" end="@var{end}" type="@var{type}"/>
@dots{}
</flags>
@end smallexample
The @var{name} value is required.
Bitfield values may be named with the empty string, @samp{""},
in which case the field is ``filler'' and its value is not printed.
Not all bits need to be specified, so ``filler'' fields are optional.
The @var{start} value is required, and @var{end} and @var{type}
are optional.
The field's @var{start} must be less than or equal to its @var{end},
and zero represents the least significant bit.
The default value of @var{end} is @var{start}, a single bit field.
The default value of @var{type} depends on whether the
@var{end} was specified. If @var{end} is specified then the default
value of @var{type} is an unsigned integer. If @var{end} is unspecified
then the default value of @var{type} is @code{bool}.
Which to choose? Structures or flags?
Registers defined with @samp{flags} have these advantages over
defining them with @samp{struct}:
@itemize @bullet
@item
Arithmetic may be performed on them as if they were integers.
@item
They are printed in a more readable fashion.
@end itemize
Registers defined with @samp{struct} have one advantage over
defining them with @samp{flags}:
@itemize @bullet
@item
One can fetch individual fields like in @samp{C}.
@smallexample
(gdb) print $my_struct_reg.field3
$1 = 42
@end smallexample
@end itemize
@subsection Registers
@cindex <reg>
@ -40697,6 +40737,9 @@ types. The currently supported types are:
@table @code
@item bool
Boolean type, occupying a single bit.
@item int8
@itemx int16
@itemx int32
@ -40739,6 +40782,44 @@ The 10-byte extended precision format used by x87 registers.
@end table
@node Enum Target Types
@section Enum Target Types
@cindex target descriptions, enum types
Enum target types are useful in @samp{struct} and @samp{flags}
register descriptions. @xref{Target Description Format}.
Enum types have a name, size and a list of name/value pairs.
@smallexample
<enum id="@var{id}" size="@var{size}">
<evalue name="@var{name}" value="@var{value}"/>
@dots{}
</enum>
@end smallexample
Enums must be defined before they are used.
@smallexample
<enum id="levels_type" size="4">
<evalue name="low" value="0"/>
<evalue name="high" value="1"/>
</enum>
<flags id="flags_type" size="4">
<field name="X" start="0"/>
<field name="LEVEL" start="1" end="1" type="levels_type"/>
</flags>
<reg name="flags" bitsize="32" type="flags_type"/>
@end smallexample
Given that description, a value of 3 for the @samp{flags} register
would be printed as:
@smallexample
(gdb) info register flags
flags 0x3 [ X LEVEL=high ]
@end smallexample
@node Standard Target Features
@section Standard Target Features
@cindex target descriptions, standard features

View File

@ -45,6 +45,11 @@
id CDATA #REQUIRED
size CDATA #REQUIRED>
<!ELEMENT enum (evalue+)>
<!ATTLIST enum
id CDATA #REQUIRED
size CDATA #REQUIRED>
<!ELEMENT struct (field+)>
<!ATTLIST struct
id CDATA #REQUIRED
@ -61,5 +66,10 @@
start CDATA #IMPLIED
end CDATA #IMPLIED>
<!ELEMENT evalue EMPTY>
<!ATTLIST evalue
name CDATA #REQUIRED
value CDATA #REQUIRED>
<!ENTITY % xinclude SYSTEM "xinclude.dtd">
%xinclude;

View File

@ -4715,38 +4715,55 @@ arch_complex_type (struct gdbarch *gdbarch,
struct type *
arch_flags_type (struct gdbarch *gdbarch, char *name, int length)
{
int nfields = length * TARGET_CHAR_BIT;
int max_nfields = length * TARGET_CHAR_BIT;
struct type *type;
type = arch_type (gdbarch, TYPE_CODE_FLAGS, length, name);
TYPE_UNSIGNED (type) = 1;
TYPE_NFIELDS (type) = nfields;
TYPE_NFIELDS (type) = 0;
/* Pre-allocate enough space assuming every field is one bit. */
TYPE_FIELDS (type)
= (struct field *) TYPE_ZALLOC (type, nfields * sizeof (struct field));
= (struct field *) TYPE_ZALLOC (type, max_nfields * sizeof (struct field));
return type;
}
/* Add field to TYPE_CODE_FLAGS type TYPE to indicate the bit at
position BITPOS is called NAME. Pass NAME as "" for fields that
should not be printed. */
void
append_flags_type_field (struct type *type, int start_bitpos, int nr_bits,
struct type *field_type, char *name)
{
int type_bitsize = TYPE_LENGTH (type) * TARGET_CHAR_BIT;
int field_nr = TYPE_NFIELDS (type);
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLAGS);
gdb_assert (TYPE_NFIELDS (type) + 1 <= type_bitsize);
gdb_assert (start_bitpos >= 0 && start_bitpos < type_bitsize);
gdb_assert (nr_bits >= 1 && nr_bits <= type_bitsize);
gdb_assert (name != NULL);
TYPE_FIELD_NAME (type, field_nr) = xstrdup (name);
TYPE_FIELD_TYPE (type, field_nr) = field_type;
SET_FIELD_BITPOS (TYPE_FIELD (type, field_nr), start_bitpos);
TYPE_FIELD_BITSIZE (type, field_nr) = nr_bits;
++TYPE_NFIELDS (type);
}
/* Special version of append_flags_type_field to add a flag field.
Add field to TYPE_CODE_FLAGS type TYPE to indicate the bit at
position BITPOS is called NAME. */
void
append_flags_type_flag (struct type *type, int bitpos, char *name)
{
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLAGS);
gdb_assert (bitpos < TYPE_NFIELDS (type));
gdb_assert (bitpos >= 0);
struct gdbarch *gdbarch = get_type_arch (type);
if (name)
{
TYPE_FIELD_NAME (type, bitpos) = xstrdup (name);
SET_FIELD_BITPOS (TYPE_FIELD (type, bitpos), bitpos);
}
else
{
/* Don't show this field to the user. */
SET_FIELD_BITPOS (TYPE_FIELD (type, bitpos), -1);
}
append_flags_type_field (type, bitpos, 1,
builtin_type (gdbarch)->builtin_bool,
name);
}
/* Allocate a TYPE_CODE_STRUCT or TYPE_CODE_UNION type structure (as

View File

@ -1704,9 +1704,12 @@ struct field *append_composite_type_field_raw (struct type *t, char *name,
/* Helper functions to construct a bit flags type. An initially empty
type is created using arch_flag_type(). Flags are then added using
append_flag_type_flag(). */
append_flag_type_field() and append_flag_type_flag(). */
extern struct type *arch_flags_type (struct gdbarch *gdbarch,
char *name, int length);
extern void append_flags_type_field (struct type *type,
int start_bitpos, int nr_bits,
struct type *field_type, char *name);
extern void append_flags_type_flag (struct type *type, int bitpos, char *name);
extern void make_vector_type (struct type *array_type);

View File

@ -90,20 +90,17 @@ typedef struct tdesc_type_field
{
char *name;
struct tdesc_type *type;
/* For non-enum-values, either both are -1 (non-bitfield), or both are
not -1 (bitfield). For enum values, start is the value (which could be
-1), end is -1. */
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);
enum tdesc_type_kind
{
/* Predefined types. */
TDESC_TYPE_BOOL,
TDESC_TYPE_INT8,
TDESC_TYPE_INT16,
TDESC_TYPE_INT32,
@ -125,7 +122,8 @@ enum tdesc_type_kind
TDESC_TYPE_VECTOR,
TDESC_TYPE_STRUCT,
TDESC_TYPE_UNION,
TDESC_TYPE_FLAGS
TDESC_TYPE_FLAGS,
TDESC_TYPE_ENUM
};
typedef struct tdesc_type
@ -146,19 +144,12 @@ typedef struct tdesc_type
int count;
} v;
/* Struct or union type. */
/* Struct, union, flags, or enum type. */
struct
{
VEC(tdesc_type_field) *fields;
int size;
} u;
/* Flags type. */
struct
{
VEC(tdesc_type_flag) *flags;
int size;
} f;
} u;
} *tdesc_type_p;
DEF_VEC_P(tdesc_type_p);
@ -527,6 +518,7 @@ tdesc_feature_name (const struct tdesc_feature *feature)
/* Predefined types. */
static struct tdesc_type tdesc_predefined_types[] =
{
{ "bool", TDESC_TYPE_BOOL },
{ "int8", TDESC_TYPE_INT8 },
{ "int16", TDESC_TYPE_INT16 },
{ "int32", TDESC_TYPE_INT32 },
@ -545,6 +537,21 @@ static struct tdesc_type tdesc_predefined_types[] =
{ "i387_ext", TDESC_TYPE_I387_EXT }
};
/* Lookup a predefined type. */
static struct tdesc_type *
tdesc_predefined_type (enum tdesc_type_kind kind)
{
int ix;
struct tdesc_type *type;
for (ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
if (tdesc_predefined_types[ix].kind == kind)
return &tdesc_predefined_types[ix];
gdb_assert_not_reached ("bad predefined tdesc type");
}
/* Return the type associated with ID in the context of FEATURE, or
NULL if none. */
@ -602,6 +609,9 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
switch (tdesc_type->kind)
{
/* Predefined types. */
case TDESC_TYPE_BOOL:
return builtin_type (gdbarch)->builtin_bool;
case TDESC_TYPE_INT8:
return builtin_type (gdbarch)->builtin_int8;
@ -690,17 +700,18 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, ix, f);
ix++)
{
if (f->type == NULL)
if (f->start != -1 && f->end != -1)
{
/* Bitfield. */
struct field *fld;
struct type *field_type;
int bitsize, total_size;
/* This invariant should be preserved while creating
types. */
/* This invariant should be preserved while creating types. */
gdb_assert (tdesc_type->u.u.size != 0);
if (tdesc_type->u.u.size > 4)
if (f->type != NULL)
field_type = tdesc_gdb_type (gdbarch, f->type);
else if (tdesc_type->u.u.size > 4)
field_type = builtin_type (gdbarch)->builtin_uint64;
else
field_type = builtin_type (gdbarch)->builtin_uint32;
@ -725,6 +736,7 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
}
else
{
gdb_assert (f->start == -1 && f->end == -1);
field_type = tdesc_gdb_type (gdbarch, f->type);
append_composite_type_field (type, xstrdup (f->name),
field_type);
@ -763,19 +775,45 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
case TDESC_TYPE_FLAGS:
{
struct tdesc_type_flag *f;
struct tdesc_type_field *f;
int ix;
type = arch_flags_type (gdbarch, tdesc_type->name,
tdesc_type->u.f.size);
tdesc_type->u.u.size);
for (ix = 0;
VEC_iterate (tdesc_type_flag, tdesc_type->u.f.flags, ix, f);
VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, 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 ? f->name : NULL);
{
struct type *field_type;
int bitsize = f->end - f->start + 1;
gdb_assert (f->type != NULL);
field_type = tdesc_gdb_type (gdbarch, f->type);
append_flags_type_field (type, f->start, bitsize,
field_type, f->name);
}
return type;
}
case TDESC_TYPE_ENUM:
{
struct tdesc_type_field *f;
int ix;
type = arch_type (gdbarch, TYPE_CODE_ENUM,
tdesc_type->u.u.size, tdesc_type->name);
TYPE_UNSIGNED (type) = 1;
for (ix = 0;
VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, ix, f);
ix++)
{
struct field *fld
= append_composite_type_field_raw (type, xstrdup (f->name),
NULL);
SET_FIELD_BITPOS (fld[0], f->start);
}
return type;
}
@ -1266,6 +1304,11 @@ tdesc_create_reg (struct tdesc_feature *feature, const char *name,
VEC_safe_push (tdesc_reg_p, feature->registers, reg);
}
/* Subroutine of tdesc_free_feature to simplify it.
Note: We do not want to free any referenced types here (e.g., types of
fields of a struct). All types of a feature are recorded in
feature->types and are freed that way. */
static void
tdesc_free_type (struct tdesc_type *type)
{
@ -1273,6 +1316,8 @@ tdesc_free_type (struct tdesc_type *type)
{
case TDESC_TYPE_STRUCT:
case TDESC_TYPE_UNION:
case TDESC_TYPE_FLAGS:
case TDESC_TYPE_ENUM:
{
struct tdesc_type_field *f;
int ix;
@ -1286,20 +1331,6 @@ 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;
}
@ -1369,15 +1400,29 @@ tdesc_create_flags (struct tdesc_feature *feature, const char *name,
type->name = xstrdup (name);
type->kind = TDESC_TYPE_FLAGS;
type->u.f.size = size;
type->u.u.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). */
struct tdesc_type *
tdesc_create_enum (struct tdesc_feature *feature, const char *name,
int size)
{
struct tdesc_type *type = XCNEW (struct tdesc_type);
gdb_assert (size > 0);
type->name = xstrdup (name);
type->kind = TDESC_TYPE_ENUM;
type->u.u.size = size;
VEC_safe_push (tdesc_type_p, feature->types, type);
return type;
}
/* Add a new field to TYPE. */
void
tdesc_add_field (struct tdesc_type *type, const char *field_name,
@ -1390,39 +1435,88 @@ tdesc_add_field (struct tdesc_type *type, const char *field_name,
f.name = xstrdup (field_name);
f.type = field_type;
/* Initialize these values so we know this is not a bit-field
when we print-c-tdesc. */
f.start = -1;
f.end = -1;
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
}
/* Add a new bitfield. */
/* Add a new typed bitfield to TYPE. */
void
tdesc_add_typed_bitfield (struct tdesc_type *type, const char *field_name,
int start, int end, struct tdesc_type *field_type)
{
struct tdesc_type_field f = { 0 };
gdb_assert (type->kind == TDESC_TYPE_STRUCT
|| type->kind == TDESC_TYPE_FLAGS);
gdb_assert (start >= 0 && end >= start);
f.name = xstrdup (field_name);
f.start = start;
f.end = end;
f.type = field_type;
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
}
/* Add a new untyped bitfield to TYPE.
Untyped bitfields become either uint32 or uint64 depending on the size
of the underlying type. */
void
tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
int start, int end)
{
struct tdesc_type_field f = { 0 };
struct tdesc_type *field_type;
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
gdb_assert (start >= 0 && end >= start);
f.name = xstrdup (field_name);
f.start = start;
f.end = end;
if (type->u.u.size > 4)
field_type = tdesc_predefined_type (TDESC_TYPE_UINT64);
else
field_type = tdesc_predefined_type (TDESC_TYPE_UINT32);
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
tdesc_add_typed_bitfield (type, field_name, start, end, field_type);
}
/* A flag is just a typed(bool) single-bit bitfield.
This function is kept to minimize changes in generated files. */
void
tdesc_add_flag (struct tdesc_type *type, int start,
const char *flag_name)
{
struct tdesc_type_flag f = { 0 };
struct tdesc_type_field f = { 0 };
gdb_assert (type->kind == TDESC_TYPE_FLAGS);
gdb_assert (type->kind == TDESC_TYPE_FLAGS
|| type->kind == TDESC_TYPE_STRUCT);
f.name = xstrdup (flag_name);
f.start = start;
f.end = start;
f.type = tdesc_predefined_type (TDESC_TYPE_BOOL);
VEC_safe_push (tdesc_type_flag, type->u.f.flags, &f);
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
}
void
tdesc_add_enum_value (struct tdesc_type *type, int value,
const char *name)
{
struct tdesc_type_field f = { 0 };
gdb_assert (type->kind == TDESC_TYPE_ENUM);
f.name = xstrdup (name);
f.start = value;
f.end = -1;
f.type = tdesc_predefined_type (TDESC_TYPE_INT32);
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
}
static void
@ -1623,7 +1717,6 @@ maint_print_c_tdesc_cmd (char *args, int from_tty)
struct tdesc_reg *reg;
struct tdesc_type *type;
struct tdesc_type_field *f;
struct tdesc_type_flag *flag;
int ix, ix2, ix3;
int printed_field_type = 0;
@ -1686,11 +1779,11 @@ maint_print_c_tdesc_cmd (char *args, int from_tty)
printed_field_type = 1;
}
if (((type->kind == TDESC_TYPE_UNION
|| type->kind == TDESC_TYPE_STRUCT)
&& VEC_length (tdesc_type_field, type->u.u.fields) > 0)
|| (type->kind == TDESC_TYPE_FLAGS
&& VEC_length (tdesc_type_flag, type->u.f.flags) > 0))
if ((type->kind == TDESC_TYPE_UNION
|| type->kind == TDESC_TYPE_STRUCT
|| type->kind == TDESC_TYPE_FLAGS
|| type->kind == TDESC_TYPE_ENUM)
&& VEC_length (tdesc_type_field, type->u.u.fields) > 0)
{
printf_unfiltered (" struct tdesc_type *type;\n");
printed_desc_type = 1;
@ -1761,33 +1854,77 @@ feature = tdesc_create_feature (result, \"%s\");\n",
type->name, type->u.v.count);
break;
case TDESC_TYPE_STRUCT:
printf_unfiltered
(" type = tdesc_create_struct (feature, \"%s\");\n",
type->name);
if (type->u.u.size != 0)
printf_unfiltered
(" tdesc_set_struct_size (type, %s);\n",
plongest (type->u.u.size));
case TDESC_TYPE_FLAGS:
if (type->kind == TDESC_TYPE_STRUCT)
{
printf_unfiltered
(" type = tdesc_create_struct (feature, \"%s\");\n",
type->name);
if (type->u.u.size != 0)
printf_unfiltered
(" tdesc_set_struct_size (type, %d);\n",
type->u.u.size);
}
else
{
printf_unfiltered
(" type = tdesc_create_flags (feature, \"%s\", %d);\n",
type->name, type->u.u.size);
}
for (ix3 = 0;
VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f);
ix3++)
{
/* Going first for implicitly sized types, else part handles
bitfields. As reported on xml-tdesc.c implicitly sized types
cannot contain a bitfield. */
if (f->type != NULL)
const char *type_name;
gdb_assert (f->type != NULL);
type_name = f->type->name;
/* To minimize changes to generated files, don't emit type
info for fields that have defaulted types. */
if (f->start != -1)
{
gdb_assert (f->end != -1);
if (f->type->kind == TDESC_TYPE_BOOL)
{
gdb_assert (f->start == f->end);
printf_unfiltered
(" tdesc_add_flag (type, %d, \"%s\");\n",
f->start, f->name);
}
else if ((type->u.u.size == 4
&& f->type->kind == TDESC_TYPE_UINT32)
|| (type->u.u.size == 8
&& f->type->kind == TDESC_TYPE_UINT64))
{
printf_unfiltered
(" tdesc_add_bitfield (type, \"%s\", %d, %d);\n",
f->name, f->start, f->end);
}
else
{
printf_unfiltered
(" field_type = tdesc_named_type (feature,"
" \"%s\");\n",
type_name);
printf_unfiltered
(" tdesc_add_typed_bitfield (type, \"%s\","
" %d, %d, field_type);\n",
f->name, f->start, f->end);
}
}
else /* Not a bitfield. */
{
gdb_assert (f->end == -1);
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
printf_unfiltered
(" field_type = tdesc_named_type (feature, \"%s\");\n",
f->type->name);
(" field_type = tdesc_named_type (feature,"
" \"%s\");\n",
type_name);
printf_unfiltered
(" tdesc_add_field (type, \"%s\", field_type);\n",
f->name);
}
else
printf_unfiltered
(" tdesc_add_bitfield (type, \"%s\", %d, %d);\n",
f->name, f->start, f->end);
}
break;
case TDESC_TYPE_UNION:
@ -1806,17 +1943,16 @@ feature = tdesc_create_feature (result, \"%s\");\n",
f->name);
}
break;
case TDESC_TYPE_FLAGS:
case TDESC_TYPE_ENUM:
printf_unfiltered
(" type = tdesc_create_flags (feature, \"%s\", %d);\n",
type->name, (int) type->u.f.size);
(" type = tdesc_create_enum (feature, \"%s\", %d);\n",
type->name, type->u.u.size);
for (ix3 = 0;
VEC_iterate (tdesc_type_flag, type->u.f.flags, ix3,
flag);
VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f);
ix3++)
printf_unfiltered
(" tdesc_add_flag (type, %d, \"%s\");\n",
flag->start, flag->name);
(" tdesc_add_enum_value (type, %d, \"%s\");\n",
f->start, f->name);
break;
default:
error (_("C output is not supported type \"%s\"."), type->name);

View File

@ -235,12 +235,20 @@ struct tdesc_type *tdesc_create_union (struct tdesc_feature *feature,
struct tdesc_type *tdesc_create_flags (struct tdesc_feature *feature,
const char *name,
int size);
struct tdesc_type *tdesc_create_enum (struct tdesc_feature *feature,
const char *name,
int size);
void tdesc_add_field (struct tdesc_type *type, const char *field_name,
struct tdesc_type *field_type);
void tdesc_add_typed_bitfield (struct tdesc_type *type, const char *field_name,
int start, int end,
struct tdesc_type *field_type);
void tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
int start, int end);
void tdesc_add_flag (struct tdesc_type *type, int start,
const char *flag_name);
void tdesc_add_enum_value (struct tdesc_type *type, int value,
const char *name);
void tdesc_create_reg (struct tdesc_feature *feature, const char *name,
int regnum, int save_restore, const char *group,
int bitsize, const char *type);

View File

@ -1,3 +1,9 @@
2016-03-15 Doug Evans <dje@google.com>
* gdb.xml/extra-regs.xml: Add enum, mixed_flags values.
* gdb.xml/tdesc-regs.exp (load_description): New arg xml_file.
All callers updated. Add tests for enums, mixed flags register.
2016-03-15 Doug Evans <dje@google.com>
* gdb.base/skip.c (main): Call test_skip_file_and_function.

View File

@ -23,6 +23,30 @@
<field name="Y" start="2" end="2"/>
</flags>
<enum id="Z_values" size="4">
<evalue name="yes" value="1"/>
<evalue name="no" value="0"/>
<evalue name="maybe" value="2"/>
<evalue name="so" value="3"/>
</enum>
<flags id="mixed_flags" size="4">
<!-- Elided end and type. -->
<field name="A" start="0"/>
<!-- Elided end, unsigned int. -->
<field name="B" start="1" type="uint32"/>
<!-- Elided end, bool. -->
<field name="C" start="2" type="bool"/>
<!-- Elided type, single bitfield. -->
<field name="D" start="3" end="3"/>
<!-- Anonymous field. -->
<field name="" start="4" end="5"/>
<!-- Multi-bit bitfield, elided type. -->
<field name="E" start="6" end="7"/>
<!-- Enum bitfield. -->
<field name="Z" start="8" end="9" type="Z_values"/>
</flags>
<reg name="extrareg" bitsize="32"/>
<reg name="uintreg" bitsize="32" type="uint32"/>
<reg name="vecreg" bitsize="32" type="v4int8"/>
@ -30,5 +54,6 @@
<reg name="structreg" bitsize="64" type="struct1"/>
<reg name="bitfields" bitsize="64" type="struct2"/>
<reg name="flags" bitsize="32" type="flags"/>
<reg name="mixed_flags" bitsize="32" type="mixed_flags"/>
</feature>
</target>

View File

@ -106,7 +106,7 @@ foreach src ${core-regs} {
}
# Similarly, we need to copy files under test into the objdir.
proc load_description { file errmsg } {
proc load_description { file errmsg xml_file } {
global srcdir
global subdir
global gdb_prompt
@ -114,7 +114,7 @@ proc load_description { file errmsg } {
global architecture
global remote_filename
set regs_file [standard_output_file regs.xml]
set regs_file [standard_output_file $xml_file]
file delete $regs_file
set ifd [open "$srcdir/$subdir/$file" r]
@ -135,22 +135,18 @@ proc load_description { file errmsg } {
close $ofd
if {[is_remote host]} {
set regs_file [remote_download host "$subdir/regs.xml" "regs.xml"]
set regs_file [remote_download host "$subdir/$xml_file" $xml_file]
}
# Anchor the test output, so that error messages are detected.
set cmd "set tdesc filename [file tail $regs_file]"
set msg "set tdesc filename regs.xml - from $file"
set msg "set tdesc filename $xml_file - from $file"
set cmd_regex [string_to_regexp $cmd]
gdb_test_multiple $cmd $msg {
-re "^$cmd_regex\r\n$errmsg$gdb_prompt $" {
pass $msg
}
}
if {[is_remote host]} {
remote_file host delete "regs.xml"
}
}
if {![is_remote host]} {
@ -158,7 +154,7 @@ if {![is_remote host]} {
"cd to directory holding xml"
}
load_description "extra-regs.xml" ""
load_description "extra-regs.xml" "" "test-extra-regs.xml"
gdb_test "ptype \$extrareg" "type = (int|long|long long)"
gdb_test "ptype \$uintreg" "type = uint32_t"
gdb_test "ptype \$vecreg" "type = int8_t __attribute__ \\(\\(vector_size\\(4\\)\\)\\)"
@ -170,7 +166,11 @@ gdb_test "ptype \$structreg" \
gdb_test "ptype \$structreg.v4" "type = int8_t __attribute__ \\(\\(vector_size\\(4\\)\\)\\)"
gdb_test "ptype \$bitfields" \
"type = struct struct2 {\r\n *uint64_t f1 : 35;\r\n *uint64_t f2 : 1;\r\n}"
gdb_test "ptype \$flags" \
"type = flag flags {\r\n *uint32_t X @0;\r\n *uint32_t Y @2;\r\n}"
gdb_test "ptype \$mixed_flags" \
"type = flag mixed_flags {\r\n *bool A @0;\r\n *uint32_t B @1;\r\n *bool C @2;\r\n *uint32_t D @3;\r\n *uint32_t @4-5;\r\n *uint32_t E @6-7;\r\n *enum {yes = 1, no = 0, maybe = 2, so} Z @8-9;\r\n}"
load_description "core-only.xml" ""
load_description "core-only.xml" "" "test-regs.xml"
# The extra register from the previous description should be gone.
gdb_test "ptype \$extrareg" "type = void"

View File

@ -98,6 +98,10 @@ static void set_output_radix (char *, int, struct cmd_list_element *);
static void set_output_radix_1 (int, unsigned);
static void val_print_type_code_flags (struct type *type,
const gdb_byte *valaddr,
struct ui_file *stream);
void _initialize_valprint (void);
#define PRINT_MAX_DEFAULT 200 /* Start print_max off at this value. */
@ -526,28 +530,17 @@ generic_val_print_ref (struct type *type, const gdb_byte *valaddr,
}
}
/* generic_val_print helper for TYPE_CODE_ENUM. */
/* Helper function for generic_val_print_enum.
This is also used to print enums in TYPE_CODE_FLAGS values. */
static void
generic_val_print_enum (struct type *type, const gdb_byte *valaddr,
int embedded_offset, struct ui_file *stream,
const struct value *original_value,
const struct value_print_options *options)
generic_val_print_enum_1 (struct type *type, LONGEST val,
struct ui_file *stream)
{
unsigned int i;
unsigned int len;
LONGEST val;
struct gdbarch *gdbarch = get_type_arch (type);
int unit_size = gdbarch_addressable_memory_unit_size (gdbarch);
if (options->format)
{
val_print_scalar_formatted (type, valaddr, embedded_offset,
original_value, options, 0, stream);
return;
}
len = TYPE_NFIELDS (type);
val = unpack_long (type, valaddr + embedded_offset * unit_size);
for (i = 0; i < len; i++)
{
QUIT;
@ -597,6 +590,29 @@ generic_val_print_enum (struct type *type, const gdb_byte *valaddr,
print_longest (stream, 'd', 0, val);
}
/* generic_val_print helper for TYPE_CODE_ENUM. */
static void
generic_val_print_enum (struct type *type, const gdb_byte *valaddr,
int embedded_offset, struct ui_file *stream,
const struct value *original_value,
const struct value_print_options *options)
{
LONGEST val;
struct gdbarch *gdbarch = get_type_arch (type);
int unit_size = gdbarch_addressable_memory_unit_size (gdbarch);
if (options->format)
{
val_print_scalar_formatted (type, valaddr, embedded_offset,
original_value, options, 0, stream);
return;
}
val = unpack_long (type, valaddr + embedded_offset * unit_size);
generic_val_print_enum_1 (type, val, stream);
}
/* generic_val_print helper for TYPE_CODE_FLAGS. */
static void
@ -1162,26 +1178,51 @@ val_print_type_code_int (struct type *type, const gdb_byte *valaddr,
}
}
void
static void
val_print_type_code_flags (struct type *type, const gdb_byte *valaddr,
struct ui_file *stream)
{
ULONGEST val = unpack_long (type, valaddr);
int bitpos, nfields = TYPE_NFIELDS (type);
int field, nfields = TYPE_NFIELDS (type);
struct gdbarch *gdbarch = get_type_arch (type);
struct type *bool_type = builtin_type (gdbarch)->builtin_bool;
fputs_filtered ("[ ", stream);
for (bitpos = 0; bitpos < nfields; bitpos++)
fputs_filtered ("[", stream);
for (field = 0; field < nfields; field++)
{
if (TYPE_FIELD_BITPOS (type, bitpos) != -1
&& (val & ((ULONGEST)1 << bitpos)))
if (TYPE_FIELD_NAME (type, field)[0] != '\0')
{
if (TYPE_FIELD_NAME (type, bitpos))
fprintf_filtered (stream, "%s ", TYPE_FIELD_NAME (type, bitpos));
struct type *field_type = TYPE_FIELD_TYPE (type, field);
if (field_type == bool_type
/* We require boolean types here to be one bit wide. This is a
problematic place to notify the user of an internal error
though. Instead just fall through and print the field as an
int. */
&& TYPE_FIELD_BITSIZE (type, field) == 1)
{
if (val & ((ULONGEST)1 << TYPE_FIELD_BITPOS (type, field)))
fprintf_filtered (stream, " %s",
TYPE_FIELD_NAME (type, field));
}
else
fprintf_filtered (stream, "#%d ", bitpos);
{
unsigned field_len = TYPE_FIELD_BITSIZE (type, field);
ULONGEST field_val
= val >> (TYPE_FIELD_BITPOS (type, field) - field_len + 1);
if (field_len < sizeof (ULONGEST) * TARGET_CHAR_BIT)
field_val &= ((ULONGEST) 1 << field_len) - 1;
fprintf_filtered (stream, " %s=",
TYPE_FIELD_NAME (type, field));
if (TYPE_CODE (field_type) == TYPE_CODE_ENUM)
generic_val_print_enum_1 (field_type, field_val, stream);
else
print_longest (stream, 'd', 0, field_val);
}
}
}
fputs_filtered ("]", stream);
fputs_filtered (" ]", stream);
}
/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR,

View File

@ -124,10 +124,6 @@ extern void val_print_array_elements (struct type *, const gdb_byte *, int,
extern void val_print_type_code_int (struct type *, const gdb_byte *,
struct ui_file *);
extern void val_print_type_code_flags (struct type *type,
const gdb_byte *valaddr,
struct ui_file *stream);
extern void val_print_scalar_formatted (struct type *,
const gdb_byte *, int,
const struct value *,

View File

@ -91,12 +91,9 @@ struct tdesc_parsing_data
/* The struct or union we are currently parsing, or last parsed. */
struct tdesc_type *current_type;
/* The byte size of the current struct type, if specified. Zero
if not specified. */
/* The byte size of the current struct/flags type, if specified. Zero
if not specified. Flags values must specify a size. */
int current_type_size;
/* Whether the current type is a flags type. */
int current_type_is_flags;
};
/* Handle the end of an <architecture> element and its value. */
@ -240,7 +237,6 @@ tdesc_start_union (struct gdb_xml_parser *parser,
data->current_type = tdesc_create_union (data->current_feature, id);
data->current_type_size = 0;
data->current_type_is_flags = 0;
}
/* Handle the start of a <struct> element. Initialize the type and
@ -259,7 +255,6 @@ tdesc_start_struct (struct gdb_xml_parser *parser,
type = tdesc_create_struct (data->current_feature, id);
data->current_type = type;
data->current_type_size = 0;
data->current_type_is_flags = 0;
attr = xml_find_attribute (attributes, "size");
if (attr != NULL)
@ -296,13 +291,35 @@ tdesc_start_flags (struct gdb_xml_parser *parser,
}
type = tdesc_create_flags (data->current_feature, id, size);
data->current_type = type;
data->current_type_size = size;
}
static void
tdesc_start_enum (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
struct tdesc_parsing_data *data = user_data;
char *id = xml_find_attribute (attributes, "id")->value;
int size = * (ULONGEST *)
xml_find_attribute (attributes, "size")->value;
struct tdesc_type *type;
if (size > MAX_FIELD_SIZE)
{
gdb_xml_error (parser,
_("Enum size %s is larger than maximum (%d)"),
pulongest (size), MAX_FIELD_SIZE);
}
type = tdesc_create_enum (data->current_feature, id, size);
data->current_type = type;
data->current_type_size = 0;
data->current_type_is_flags = 1;
}
/* Handle the start of a <field> element. Attach the field to the
current struct or union. */
current struct, union or flags. */
static void
tdesc_start_field (struct gdb_xml_parser *parser,
@ -319,9 +336,15 @@ tdesc_start_field (struct gdb_xml_parser *parser,
attr = xml_find_attribute (attributes, "type");
if (attr != NULL)
field_type_id = (char *) attr->value;
{
field_type_id = (char *) attr->value;
field_type = tdesc_named_type (data->current_feature, field_type_id);
}
else
field_type_id = NULL;
{
field_type_id = NULL;
field_type = NULL;
}
attr = xml_find_attribute (attributes, "start");
if (attr != NULL)
@ -355,18 +378,66 @@ tdesc_start_field (struct gdb_xml_parser *parser,
else
end = -1;
if (field_type_id != NULL)
if (start != -1)
{
if (data->current_type_is_flags)
gdb_xml_error (parser, _("Cannot add typed field \"%s\" to flags"),
field_name);
if (data->current_type_size != 0)
struct tdesc_type *t = data->current_type;
if (data->current_type_size == 0)
gdb_xml_error (parser,
_("Explicitly sized type can not "
"contain non-bitfield \"%s\""),
_("Bitfields must live in explicitly sized types"));
if (field_type_id != NULL
&& strcmp (field_type_id, "bool") == 0
&& !(start == end || end == -1))
{
gdb_xml_error (parser,
_("Boolean fields must be one bit in size"));
}
if (end >= 64)
gdb_xml_error (parser,
_("Bitfield \"%s\" goes past "
"64 bits (unsupported)"),
field_name);
if (end != -1)
{
/* Assume that the bit numbering in XML is "lsb-zero". Most
architectures other than PowerPC use this ordering. In the
future, we can add an XML tag to indicate "msb-zero"
numbering. */
if (start > end)
gdb_xml_error (parser, _("Bitfield \"%s\" has start after end"),
field_name);
if (end >= data->current_type_size * TARGET_CHAR_BIT)
gdb_xml_error (parser,
_("Bitfield \"%s\" does not fit in struct"));
}
if (end == -1)
{
if (field_type != NULL)
tdesc_add_typed_bitfield (t, field_name, start, start, field_type);
else
tdesc_add_flag (t, start, field_name);
}
else if (field_type != NULL)
tdesc_add_typed_bitfield (t, field_name, start, end, field_type);
else
tdesc_add_bitfield (t, field_name, start, end);
}
else if (start == -1 && end != -1)
gdb_xml_error (parser, _("End specified but not start"));
else if (field_type_id != NULL)
{
/* TDESC_TYPE_FLAGS values are explicitly sized, so the following test
catches adding non-bitfield types to flags as well. */
if (data->current_type_size != 0)
gdb_xml_error (parser,
_("Explicitly sized type cannot "
"contain non-bitfield \"%s\""),
field_name);
field_type = tdesc_named_type (data->current_feature, field_type_id);
if (field_type == NULL)
gdb_xml_error (parser, _("Field \"%s\" references undefined "
"type \"%s\""),
@ -374,46 +445,40 @@ tdesc_start_field (struct gdb_xml_parser *parser,
tdesc_add_field (data->current_type, field_name, field_type);
}
else if (start != -1 && end != -1)
{
struct tdesc_type *t = data->current_type;
if (data->current_type_is_flags)
tdesc_add_flag (t, start, field_name);
else
{
if (data->current_type_size == 0)
gdb_xml_error (parser,
_("Implicitly sized type can "
"not contain bitfield \"%s\""),
field_name);
if (end >= 64)
gdb_xml_error (parser,
_("Bitfield \"%s\" goes past "
"64 bits (unsupported)"),
field_name);
/* Assume that the bit numbering in XML is "lsb-zero". Most
architectures other than PowerPC use this ordering. In
the future, we can add an XML tag to indicate "msb-zero"
numbering. */
if (start > end)
gdb_xml_error (parser, _("Bitfield \"%s\" has start after end"),
field_name);
if (end >= data->current_type_size * TARGET_CHAR_BIT)
gdb_xml_error (parser,
_("Bitfield \"%s\" does not fit in struct"));
tdesc_add_bitfield (t, field_name, start, end);
}
}
else
gdb_xml_error (parser, _("Field \"%s\" has neither type nor bit position"),
field_name);
}
/* Handle the start of an <evalue> element. Attach the value to the
current enum. */
static void
tdesc_start_enum_value (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data;
struct gdb_xml_value *attr;
char *field_name;
ULONGEST ul_value;
int value;
field_name = (char *) xml_find_attribute (attributes, "name")->value;
attr = xml_find_attribute (attributes, "value");
ul_value = * (ULONGEST *) attr->value;
if (ul_value > INT_MAX)
{
gdb_xml_error (parser,
_("Enum value %s is larger than maximum (%d)"),
pulongest (ul_value), INT_MAX);
}
value = ul_value;
tdesc_add_enum_value (data->current_type, value, field_name);
}
/* Handle the start of a <vector> element. Initialize the type and
record it with the current feature. */
@ -457,12 +522,24 @@ static const struct gdb_xml_attribute field_attributes[] = {
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_attribute enum_value_attributes[] = {
{ "name", GDB_XML_AF_NONE, NULL, NULL },
{ "value", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_element struct_union_children[] = {
{ "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
tdesc_start_field, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
static const struct gdb_xml_element enum_children[] = {
{ "evalue", enum_value_attributes, NULL, GDB_XML_EF_REPEATABLE,
tdesc_start_enum_value, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
static const struct gdb_xml_attribute reg_attributes[] = {
{ "name", GDB_XML_AF_NONE, NULL, NULL },
{ "bitsize", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
@ -486,6 +563,12 @@ static const struct gdb_xml_attribute flags_attributes[] = {
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_attribute enum_attributes[] = {
{ "id", GDB_XML_AF_NONE, NULL, NULL },
{ "size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL},
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_attribute vector_attributes[] = {
{ "id", GDB_XML_AF_NONE, NULL, NULL },
{ "type", GDB_XML_AF_NONE, NULL, NULL },
@ -511,6 +594,9 @@ static const struct gdb_xml_element feature_children[] = {
{ "flags", flags_attributes, struct_union_children,
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
tdesc_start_flags, NULL },
{ "enum", enum_attributes, enum_children,
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
tdesc_start_enum, NULL },
{ "vector", vector_attributes, NULL,
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
tdesc_start_vector, NULL },