<!ATTLIST vector
id CDATA #REQUIRED
type CDATA #REQUIRED
- count CDATA #REQUIRED>
+ count CDATA #IMPLIED
+ bitsize CDATA #IMPLIED>
<!ELEMENT flags (field+)>
<!ATTLIST flags
return result_type;
}
+/* Create a range type using ALLOC.
+
+ Indices will be of type INDEX_TYPE, and will range from 0 to the value
+ calculated from the array length given by the given target description
+ parameter. */
+
+static struct type *
+create_dynamic_range_type (type_allocator &alloc, struct type *index_type,
+ const char *parameter_feature,
+ const char *length_parameter)
+{
+ struct dynamic_prop low, high;
+
+ low.set_const_val (0);
+ // FIXME: Leaks memory.
+ std::pair<const char *, const char *> *parameter
+ = new std::pair<const char *, const char *>;
+ // FIXME: Is the lifetime of the following strings longer than of this
+ // object?
+ parameter->first = parameter_feature;
+ parameter->second = length_parameter;
+ high.set_tdesc_parameter (parameter);
+
+ return create_range_type (alloc, index_type, &low, &high, 0);
+}
+
/* Predicate tests whether BOUNDS are static. Returns 1 if all bounds values
are static, otherwise returns 0. */
return create_array_type (alloc, element_type, range_type);
}
+/* Create type for array ranges where the low bound is 0 and the high bound is
+ calculated from the array length found in the given target description
+ parameter. */
+
+static struct type *
+lookup_array_range_type (struct type *element_type,
+ const char *parameter_feature,
+ const char *length_parameter)
+{
+ type_allocator alloc (element_type);
+ struct type *index_type, *range_type;
+
+ index_type = builtin_type (element_type->arch ())->builtin_unsigned_int;
+ range_type = create_dynamic_range_type (alloc, index_type, parameter_feature,
+ length_parameter);
+ return create_array_type (alloc, element_type, range_type);
+}
+
/* See gdbtypes.h. */
struct type *
return array_type;
}
+/* Create vector type of elements of type ELT_TYPE, where its total length is
+ given by the given target description parameter. */
+
+struct type *
+init_vector_type (struct type *elt_type, const char *parameter_feature,
+ const char *length_parameter)
+{
+ struct type *array_type = lookup_array_range_type (elt_type,
+ parameter_feature,
+ length_parameter);
+ make_vector_type (array_type);
+ return array_type;
+}
+
/* Internal routine called by TYPE_SELF_TYPE to return the type that TYPE
belongs to. In c++ this is the class of "this", but TYPE_THIS_TYPE is too
confusing. "self" is a common enough replacement for "this".
PROP_TYPE, /* Type. */
PROP_VARIABLE_NAME, /* Variable name. */
PROP_OPTIMIZED_OUT, /* Optimized out. */
+ PROP_TDESC_PARAMETER, /* Parameter from target description. */
};
union dynamic_prop_data
this property. */
const char *variable_name;
+
+ /* The first element is the feature name and the second is the parameter
+ name. */
+ std::pair<const char *, const char *> *tdesc_parameter;
};
/* * Used to store a dynamic property. */
m_data.variable_name = name;
}
+ std::pair<const char *, const char *> tdesc_parameter () const
+ {
+ gdb_assert (m_kind == PROP_TDESC_PARAMETER);
+ return *m_data.tdesc_parameter;
+ }
+
+ void set_tdesc_parameter (std::pair<const char *,const char *> *parameter)
+ {
+ m_kind = PROP_TDESC_PARAMETER;
+ m_data.tdesc_parameter = parameter;
+ }
+
/* Determine which field of the union dynamic_prop.data is used. */
enum dynamic_prop_kind m_kind;
extern void make_vector_type (struct type *array_type);
extern struct type *init_vector_type (struct type *elt_type, int n);
+extern struct type *init_vector_type (struct type *elt_type,
+ const char *parameter_feature,
+ const char *length_parameter);
extern struct type *lookup_reference_type (struct type *, enum type_code);
extern struct type *lookup_lvalue_reference_type (struct type *);
return;
type *element_gdb_type = make_gdb_type (m_gdbarch, e->element_type);
- m_type = init_vector_type (element_gdb_type, e->count);
+ if (e->bitsize_parameter.length () == 0)
+ m_type = init_vector_type (element_gdb_type, e->count);
+ else
+ // FIXME: Is the lifetime of feature and tdesc_parameter correct?
+ // Probably not. e->name is duplicated below.
+ m_type = init_vector_type (element_gdb_type, e->feature.c_str (),
+ e->bitsize_parameter.c_str ());
m_type->set_name (xstrdup (e->name.c_str ()));
return;
}
gdb_printf
(" element_type = tdesc_named_type (feature, \"%s\");\n",
type->element_type->name.c_str ());
- gdb_printf
- (" tdesc_create_vector (feature, \"%s\", element_type, %d);\n",
- type->name.c_str (), type->count);
+ if (type->bitsize_parameter.length () != 0)
+ gdb_printf
+ (" tdesc_create_vector (feature, \"%s\", element_type, \"%s\");\n",
+ type->name.c_str (), type->bitsize_parameter.c_str ());
+ else
+ gdb_printf
+ (" tdesc_create_vector (feature, \"%s\", element_type, %d);\n",
+ type->name.c_str (), type->count);
gdb_printf ("\n");
}
gdb_printf ("\"%s\", ", reg->group.c_str ());
else
gdb_printf ("NULL, ");
- gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ());
+ if (reg->bitsize_parameter.length () != 0)
+ gdb_printf ("\"%s\", \"%s\");\n", reg->bitsize_parameter.c_str (),
+ reg->type.c_str ());
+ else
+ gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ());
}
protected:
gdb_printf ("\"%s\", ", reg->group.c_str ());
else
gdb_printf ("NULL, ");
- gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ());
+ if (reg->bitsize_parameter.length () != 0)
+ gdb_printf ("\"%s\", \"%s\");\n", reg->bitsize_parameter.c_str (),
+ reg->type.c_str ());
+ else
+ gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ());
m_next_regnum++;
}
{
struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data;
int ix = 0;
- char *name, *group;
+ char *name, *group, *bitsize_attr;
const char *type;
- int bitsize, regnum, save_restore;
+ int regnum, save_restore;
int length = attributes.size ();
name = (char *) attributes[ix++].value.get ();
- bitsize = * (ULONGEST *) attributes[ix++].value.get ();
+ bitsize_attr = (char *) attributes[ix++].value.get ();
if (ix < length && strcmp (attributes[ix].name, "regnum") == 0)
regnum = * (ULONGEST *) attributes[ix++].value.get ();
gdb_xml_error (parser, _("Register \"%s\" has unknown type \"%s\""),
name, type);
- tdesc_create_reg (data->current_feature, name, regnum, save_restore, group,
- bitsize, type);
+ if (bitsize_attr[0] == '$')
+ {
+ // FIXME: Check whether the bitsize parameter is valid.
+ tdesc_create_reg (data->current_feature, name, regnum, save_restore,
+ group, &bitsize_attr[1], type);
+ }
+ else
+ {
+ int bitsize = (int) gdb_xml_parse_ulongest (parser, bitsize_attr);
+
+ tdesc_create_reg (data->current_feature, name, regnum, save_restore,
+ group, bitsize, type);
+ }
data->next_regnum = regnum + 1;
}
struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data;
struct tdesc_type *field_type;
char *id, *field_type_id;
- ULONGEST count;
id = (char *) attributes[0].value.get ();
field_type_id = (char *) attributes[1].value.get ();
- count = * (ULONGEST *) attributes[2].value.get ();
-
- if (count > MAX_VECTOR_SIZE)
- {
- gdb_xml_error (parser,
- _("Vector size %s is larger than maximum (%d)"),
- pulongest (count), MAX_VECTOR_SIZE);
- }
field_type = tdesc_named_type (data->current_feature, field_type_id);
if (field_type == NULL)
gdb_xml_error (parser, _("Vector \"%s\" references undefined type \"%s\""),
id, field_type_id);
- tdesc_create_vector (data->current_feature, id, field_type, count);
+ if (!strcmp (attributes[2].name, "count"))
+ {
+ ULONGEST count = * (ULONGEST *) attributes[2].value.get ();
+
+ if (count > MAX_VECTOR_SIZE)
+ gdb_xml_error (parser, _ ("Vector size %s is larger than maximum (%d)"),
+ pulongest (count), MAX_VECTOR_SIZE);
+
+ tdesc_create_vector (data->current_feature, id, field_type, count);
+ }
+ else if (!strcmp (attributes[2].name, "bitsize"))
+ {
+ char *bitsize = (char *) attributes[2].value.get ();
+
+ if (bitsize[0] != '$')
+ gdb_xml_error (parser, _ ("Vector bitsize \"%s\" isn't a parameter"),
+ bitsize);
+
+ // FIXME: Check whether the parameter exists.
+ tdesc_create_vector (data->current_feature, id, field_type, &bitsize[1]);
+ }
+ else
+ gdb_xml_error (parser, _ ("Vector doesn't have count nor size attribute"));
}
/* The elements and attributes of an XML target description. */
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 },
+ { "bitsize", GDB_XML_AF_NONE, NULL, NULL },
{ "regnum", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
{ "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
{ "group", GDB_XML_AF_OPTIONAL, NULL, NULL },
static const struct gdb_xml_attribute vector_attributes[] = {
{ "id", GDB_XML_AF_NONE, NULL, NULL },
{ "type", GDB_XML_AF_NONE, NULL, NULL },
- { "count", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { "count", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+ { "bitsize", GDB_XML_AF_OPTIONAL, NULL, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
tdesc_type = tdesc_named_type (feature, type.c_str ());
}
+tdesc_reg::tdesc_reg (struct tdesc_feature *feature_, const std::string &name_,
+ int regnum, int save_restore_, const char *group_,
+ const std::string &bitsize_parameter_, const char *type_)
+ : name (name_), target_regnum (regnum),
+ save_restore (save_restore_),
+ group (group_ != NULL ? group_ : ""),
+ bitsize (TDESC_REG_VARIABLE_SIZE),
+ bitsize_parameter (bitsize_parameter_),
+ type (type_ != NULL ? type_ : "<unknown>")
+{
+ /* If the register's type is target-defined, look it up now. We may not
+ have easy access to the containing feature when we want it later. */
+ tdesc_type = tdesc_named_type (feature_, type.c_str ());
+ feature = feature_->name;
+}
+
/* Predefined types. */
static tdesc_type_builtin tdesc_predefined_types[] =
{
/* See gdbsupport/tdesc.h. */
+void
+tdesc_create_reg (struct tdesc_feature *feature, const char *name,
+ int regnum, int save_restore, const char *group,
+ const char *bitsize_parameter, const char *type)
+{
+ tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore,
+ group, bitsize_parameter, type);
+
+ feature->registers.emplace_back (reg);
+}
+
+/* See gdbsupport/tdesc.h. */
+
struct tdesc_type *
tdesc_create_vector (struct tdesc_feature *feature, const char *name,
struct tdesc_type *field_type, int count)
/* See gdbsupport/tdesc.h. */
+struct tdesc_type *
+tdesc_create_vector (struct tdesc_feature *feature, const char *name,
+ struct tdesc_type *field_type,
+ const char *bitsize_parameter)
+{
+ tdesc_type_vector *type = new tdesc_type_vector (name, field_type,
+ feature->name,
+ bitsize_parameter);
+ feature->types.emplace_back (type);
+
+ return type;
+}
+
+/* See gdbsupport/tdesc.h. */
+
tdesc_type_with_fields *
tdesc_create_struct (struct tdesc_feature *feature, const char *name)
{
void print_xml_feature::visit (const tdesc_type_vector *t)
{
- add_line ("<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
- t->name.c_str (), t->element_type->name.c_str (), t->count);
+ if (t->bitsize_parameter.length () != 0)
+ add_line ("<vector id=\"%s\" type=\"%s\" bitsize=\"$%s\"/>", t->name.c_str (),
+ t->element_type->name.c_str (), t->bitsize_parameter.c_str ());
+ else
+ add_line ("<vector id=\"%s\" type=\"%s\" count=\"%d\"/>", t->name.c_str (),
+ t->element_type->name.c_str (), t->count);
}
void print_xml_feature::visit (const tdesc_type_with_fields *t)
{
std::string tmp;
- string_appendf (tmp,
- "<reg name=\"%s\" bitsize=\"%d\" type=\"%s\" regnum=\"%ld\"",
- r->name.c_str (), r->bitsize, r->type.c_str (),
- r->target_regnum);
+ if (r->bitsize_parameter.length () != 0)
+ string_appendf (tmp,
+ "<reg name=\"%s\" bitsize=\"$%s\" type=\"%s\" regnum=\"%ld\"",
+ r->name.c_str (), r->bitsize_parameter.c_str(),
+ r->type.c_str (), r->target_regnum);
+ else
+ string_appendf (tmp,
+ "<reg name=\"%s\" bitsize=\"%d\" type=\"%s\" regnum=\"%ld\"",
+ r->name.c_str (), r->bitsize, r->type.c_str (),
+ r->target_regnum);
if (r->group.length () > 0)
string_appendf (tmp, " group=\"%s\"", r->group.c_str ());
virtual void accept (tdesc_element_visitor &v) const = 0;
};
+/* Used in vector type element count or register bitsize to indicate that the
+ corresponding value is derived from a target description parameter. */
+
+#define TDESC_REG_VARIABLE_SIZE -1
+
/* An individual register from a target description. */
struct tdesc_reg : tdesc_element
int regnum, int save_restore_, const char *group_,
int bitsize_, const char *type_);
+ tdesc_reg (struct tdesc_feature *feature, const std::string &name_,
+ int regnum, int save_restore_, const char *group_,
+ const std::string &bitsize_parameter_, const char *type_);
+
virtual ~tdesc_reg () = default;
DISABLE_COPY_AND_ASSIGN (tdesc_reg);
strings are ignored (treated as empty). */
std::string group;
- /* The size of the register, in bits. */
+ /* The size of the register, in bits.
+ Ignored if BITSIZE_PARAMETER isn't empty. */
int bitsize;
+ std::string feature, bitsize_parameter;
+
/* The type of the register. This string corresponds to either
a named type from the target description or a predefined
type from GDB. */
element_type (element_type_), count (count_)
{}
+ tdesc_type_vector (const std::string &name, tdesc_type *element_type_,
+ const std::string &feature_,
+ const std::string &bitsize_parameter_)
+ : tdesc_type (name, TDESC_TYPE_VECTOR), element_type (element_type_),
+ count (TDESC_REG_VARIABLE_SIZE), feature (feature_),
+ bitsize_parameter (bitsize_parameter_)
+ {}
+
void accept (tdesc_element_visitor &v) const override
{
v.visit (this);
}
struct tdesc_type *element_type;
+
+ /* Ignored if BITSIZE_PARAMETER isn't empty. */
int count;
+
+ /* Target description parameter providing total vector size. */
+ std::string feature, bitsize_parameter;
};
/* A named type from a target description. */
struct tdesc_type *field_type,
int count);
+/* Return the created vector tdesc_type named NAME in FEATURE,
+ with number of elements derived by the given BITSIZE_PARAMETER. */
+struct tdesc_type *tdesc_create_vector (struct tdesc_feature *feature,
+ const char *name,
+ struct tdesc_type *field_type,
+ const char *bitsize_parameter);
+
/* Return the created struct tdesc_type named NAME in FEATURE. */
tdesc_type_with_fields *tdesc_create_struct (struct tdesc_feature *feature,
const char *name);
int regnum, int save_restore, const char *group,
int bitsize, const char *type);
+/* Create a register in feature FEATURE with size given by
+ BITSIZE_PARAMETER. */
+void tdesc_create_reg (struct tdesc_feature *feature, const char *name,
+ int regnum, int save_restore, const char *group,
+ const char *bitsize_parameter, const char *type);
+
/* Return the tdesc in string XML format. */
const char *tdesc_get_features_xml (const target_desc *tdesc);