summaryrefslogtreecommitdiff
path: root/gdb/xml-tdesc.c
diff options
context:
space:
mode:
authorDoug Evans <dje@google.com>2016-03-15 14:37:29 -0700
committerDoug Evans <dje@google.com>2016-03-15 14:37:29 -0700
commit8151645076ce927e0ee866c598a19f192e68e103 (patch)
treeb9270d1643c875c060e7d55746c50c69ee2e24bd /gdb/xml-tdesc.c
parent54157a25aa28ba78e1da1dfa06e6c988d75e88f1 (diff)
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.
Diffstat (limited to 'gdb/xml-tdesc.c')
-rw-r--r--gdb/xml-tdesc.c182
1 files changed, 134 insertions, 48 deletions
diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c
index adfe9fddba..a0fd08acf8 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 },