aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog45
-rw-r--r--gdb/NEWS3
-rw-r--r--gdb/c-typeprint.c50
-rw-r--r--gdb/doc/ChangeLog8
-rw-r--r--gdb/doc/gdb.texinfo125
-rw-r--r--gdb/features/gdb-target.dtd10
-rw-r--r--gdb/gdbtypes.c49
-rw-r--r--gdb/gdbtypes.h5
-rw-r--r--gdb/target-descriptions.c302
-rw-r--r--gdb/target-descriptions.h8
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.xml/extra-regs.xml25
-rw-r--r--gdb/testsuite/gdb.xml/tdesc-regs.exp20
-rw-r--r--gdb/valprint.c91
-rw-r--r--gdb/valprint.h4
-rw-r--r--gdb/xml-tdesc.c182
16 files changed, 724 insertions, 209 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1d59888..d78f2cc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,50 @@
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
from LONGEST to int.
(struct tdesc_type) <u.f.size>: Ditto.
diff --git a/gdb/NEWS b/gdb/NEWS
index 928f70c..34c5a8d 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -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.
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index 6b9e6b3..ed16fc3 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -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;
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index a48d1c4..c34c4f3 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -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.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 71657b0..2f4da84 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -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,46 +40591,84 @@ 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.
+
+Non-bitfield values have a @var{name} and @var{type}.
@smallexample
-<struct id="@var{id}" size="@var{size}">
- <field name="@var{name}" start="@var{start}" end="@var{end}"/>
+<struct id="@var{id}">
+ <field name="@var{name}" type="@var{type}"/>
@dots{}
</struct>
@end smallexample
-If the structure contains no bitfields, then each field has an
-explicit type, and no implicit padding is added.
+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}">
- <field name="@var{name}" type="@var{type}"/>
+<struct id="@var{id}" size="@var{size}">
+ <field name="@var{name}" start="@var{start}" end="@var{end}" type="@var{type}"/>
@dots{}
</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.
-
@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
diff --git a/gdb/features/gdb-target.dtd b/gdb/features/gdb-target.dtd
index 3fd61c2..a6f0b07 100644
--- a/gdb/features/gdb-target.dtd
+++ b/gdb/features/gdb-target.dtd
@@ -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;
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 1af6fff..65758bf 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -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
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index e775a1d..1518a7a 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -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);
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index ac6e3a2..40f0478 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -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_field, tdesc_type->u.u.fields, ix, f);
+ ix++)
+ {
+ 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_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 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_bitfield (struct tdesc_type *type, const char *field_name,
- int start, int end)
+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);
+ 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_type;
+
+ gdb_assert (start >= 0 && end >= start);
+
+ if (type->u.u.size > 4)
+ field_type = tdesc_predefined_type (TDESC_TYPE_UINT64);
+ else
+ field_type = tdesc_predefined_type (TDESC_TYPE_UINT32);
+
+ 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);
diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h
index f777a92..ef97d1d 100644
--- a/gdb/target-descriptions.h
+++ b/gdb/target-descriptions.h
@@ -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);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 177b2d1..25154c6 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,11 @@
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.
* gdb.base/skip.exp: Remove hand calling test_skip_file_and_function.
diff --git a/gdb/testsuite/gdb.xml/extra-regs.xml b/gdb/testsuite/gdb.xml/extra-regs.xml
index f0db04e..cbbaf76 100644
--- a/gdb/testsuite/gdb.xml/extra-regs.xml
+++ b/gdb/testsuite/gdb.xml/extra-regs.xml
@@ -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>
diff --git a/gdb/testsuite/gdb.xml/tdesc-regs.exp b/gdb/testsuite/gdb.xml/tdesc-regs.exp
index 80e1008..48204cd 100644
--- a/gdb/testsuite/gdb.xml/tdesc-regs.exp
+++ b/gdb/testsuite/gdb.xml/tdesc-regs.exp
@@ -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"
diff --git a/gdb/valprint.c b/gdb/valprint.c
index a9b03ec..720942b 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -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,
diff --git a/gdb/valprint.h b/gdb/valprint.h
index bb03024..1a83cb5 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -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 *,
diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c
index adfe9fd..a0fd08a 100644
--- a/gdb/xml-tdesc.c
+++ b/gdb/xml-tdesc.c
@@ -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)
@@ -297,12 +292,34 @@ 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,65 +378,107 @@ tdesc_start_field (struct gdb_xml_parser *parser,
else
end = -1;
- if (field_type_id != NULL)
- {
- 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)
- gdb_xml_error (parser,
- _("Explicitly sized type can not "
- "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\""),
- field_name, field_type_id);
-
- tdesc_add_field (data->current_type, field_name, field_type);
- }
- else if (start != -1 && end != -1)
+ if (start != -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,
+ _("Bitfields must live in explicitly sized types"));
+
+ if (field_type_id != NULL
+ && strcmp (field_type_id, "bool") == 0
+ && !(start == end || end == -1))
{
- if (data->current_type_size == 0)
- gdb_xml_error (parser,
- _("Implicitly sized type can "
- "not contain bitfield \"%s\""),
- field_name);
+ 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 >= 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"
+ 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);
+ 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);
+
+ if (field_type == NULL)
+ gdb_xml_error (parser, _("Field \"%s\" references undefined "
+ "type \"%s\""),
+ field_name, field_type_id);
+
+ tdesc_add_field (data->current_type, field_name, field_type);
}
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 },