Extend flags to support multibit and enum bitfields.
authorDoug Evans <dje@google.com>
Tue, 15 Mar 2016 21:37:29 +0000 (14:37 -0700)
committerDoug Evans <dje@google.com>
Tue, 15 Mar 2016 21:37:29 +0000 (14:37 -0700)
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.

16 files changed:
gdb/ChangeLog
gdb/NEWS
gdb/c-typeprint.c
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/features/gdb-target.dtd
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/target-descriptions.c
gdb/target-descriptions.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.xml/extra-regs.xml
gdb/testsuite/gdb.xml/tdesc-regs.exp
gdb/valprint.c
gdb/valprint.h
gdb/xml-tdesc.c

index 1d59888e734803e83c90a30c321194d909a68f78..d78f2cc3d3e3ff715fa707d66268e6856dc31c90 100644 (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
index 928f70c55e75e4d0c20384743e1fbc03fecf05a9..34c5a8df3c564a86681ee0d99a571cf3ed85aa63 100644 (file)
--- 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.
index 6b9e6b3cf20c2ec7f560046282e26faf97b6bd23..ed16fc3b8d2e68bdac415ab8517f42a2c8b78160 100644 (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;
index a48d1c4f4875e1fa393812168b2b3c740c7d3994..c34c4f302d629e3f1446393166f5e1b03f574907 100644 (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.
index 71657b0ec2d8c2161553d5e5abe5bad41b0e05ee..2f4da8440b0d3705123611528693be5c65e145ea 100644 (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,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
index 3fd61c2557eb2c28022e377cfaa85aa38f0b97a6..a6f0b077bfae88fe9ab83ef57cf584db11428589 100644 (file)
        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
        start           CDATA   #IMPLIED
        end             CDATA   #IMPLIED>
 
+<!ELEMENT evalue       EMPTY>
+<!ATTLIST evalue
+       name            CDATA   #REQUIRED
+       value           CDATA   #REQUIRED>
+
 <!ENTITY % xinclude SYSTEM "xinclude.dtd">
 %xinclude;
index 1af6fff67f48b00cc2ceb1ed4176c1bb65f07a00..65758bf0dfcbb200070a375392fe67a852c165dc 100644 (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
index e775a1d6d135c8450328a66261338bdf27393d90..1518a7ad82bf468cd61a1d97b359071763a30aa6 100644 (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);
index ac6e3a23483c40e915f224269cef9eb0354b2826..40f04786b08613d59d94868e5a9c02b9c9df6520 100644 (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_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);
index f777a92ef9b5ecbe807ecbe6e08997a9446c03f5..ef97d1d5f76d80bad1a47c435fa1b7f3cb871d73 100644 (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);
index 177b2d1af94d818d94ec5c9191e5a01c8e2138b1..25154c682b7deb86762fae74875ed228f42c6e41 100644 (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.
index f0db04e6bc632fb8965499e13e7405f6591c5fc1..cbbaf76afc4d89bf160dd0de14a84da9a93d3144 100644 (file)
       <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>
index 80e100821310dac146734ee0e9fc03f728992380..48204cd9db987aba91cff7607e553ae199014bb7 100644 (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"
index a9b03ec0dc6fd3941e8b3ea8253f69c46cd1269a..720942b85e74d55561c98dba0ed344d5f26e57f4 100644 (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,
index bb03024c10add39a2003ce9313ce98248692e255..1a83cb519bd5c9492c41b7873b87b066b85dd7fa 100644 (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 *,
index adfe9fddbab472901bd7a40d5240d19ee55f427e..a0fd08acf863953e04ef1ac115d72452e1c41cbd 100644 (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,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 },