Extend flags to support multibit and enum bitfields.

gdb/ChangeLog:

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

gdb/doc/ChangeLog:

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

gdb/testsuite/ChangeLog:

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

View File

@@ -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,