From 8151645076ce927e0ee866c598a19f192e68e103 Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Tue, 15 Mar 2016 14:37:29 -0700 Subject: 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) : New enum value. (enum tdesc_type_kind) : Ditto. (struct tdesc_type) : 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) : 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. --- gdb/xml-tdesc.c | 182 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 134 insertions(+), 48 deletions(-) (limited to 'gdb/xml-tdesc.c') 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 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 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 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 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 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 }, -- cgit v1.1