return pc;
}
+static void
+default_fetch_tdesc_parameter (struct gdbarch *gdbarch,
+ readable_regcache *regcache,
+ unsigned int parameter_id)
+{
+ error (_("Architecture \"%s\" doesn't support target description parameters"),
+ gdbarch_bfd_arch_info (get_current_arch ())->printable_name);
+}
+
/* Non-zero if we want to trace architecture code. */
#ifndef GDBARCH_DEBUG
#include "gdbsupport/underlying.h"
#include "gdbsupport/byte-vector.h"
#include "extract-store-integer.h"
+#include "target-descriptions.h"
static struct value *dwarf2_evaluate_loc_desc_full
(struct type *type, const frame_info_ptr &frame, const gdb_byte *data,
}
}
break;
+
+ case PROP_TDESC_PARAMETER:
+ {
+ gdbarch *gdbarch = get_frame_arch (frame);
+ auto [feature, param_name, element_length] = prop->tdesc_parameter ();
+ std::optional<unsigned int> param_id = tdesc_parameter_id (gdbarch,
+ feature,
+ param_name);
+ if (!param_id.has_value ())
+ return false;
+
+ return read_frame_tdesc_parameter_unsigned (frame, *param_id, value);
+ }
+ break;
}
return false;
<!ELEMENT compatible (#PCDATA)>
<!ELEMENT feature
- ((vector | flags | struct | union )*, reg*)>
+ (parameter*, (vector | flags | struct | union )*, reg*)>
<!ATTLIST feature
name ID #REQUIRED>
+<!ELEMENT parameter EMPTY>
+<!ATTLIST parameter
+ name CDATA #REQUIRED
+ type CDATA #REQUIRED>
+
<!ELEMENT reg (description*)>
<!ATTLIST reg
name CDATA #REQUIRED
/* See frame-unwind.h. */
+struct value *
+frame_unwind_legacy::prev_tdesc_parameter (const frame_info_ptr &this_frame,
+ void **this_prologue_cache,
+ unsigned int parameter_id) const
+{
+ if (m_prev_tdesc_parameter == nullptr)
+ return frame_unwind::prev_tdesc_parameter (this_frame, this_prologue_cache,
+ parameter_id);
+ return m_prev_tdesc_parameter (this_frame, this_prologue_cache, parameter_id);
+}
+
+/* See frame-unwind.h. */
+
int
frame_unwind_legacy::sniff (const frame_info_ptr &this_frame,
void **this_prologue_cache) const
void **this_prologue_cache,
int regnum);
+typedef value *(frame_prev_tdesc_parameter_ftype)
+ (const frame_info_ptr &this_frame, void **this_prologue_cache,
+ unsigned int parameter);
+
/* Deallocate extra memory associated with the frame cache if any. */
typedef void (frame_dealloc_cache_ftype) (frame_info *self,
void **this_prologue_cache,
int regnum) const = 0;
+ /* Get the value of a target description parameter in a previous frame. */
+
+ virtual value *prev_tdesc_parameter (const frame_info_ptr &this_frame,
+ void **this_prologue_cache,
+ unsigned int parameter) const
+ { return nullptr; }
+
/* Properly deallocate the cache. */
virtual void dealloc_cache (frame_info *self, void *this_cache) const
const struct frame_data *data,
frame_sniffer_ftype *sniffer_func,
frame_dealloc_cache_ftype *dealloc_cache_func = nullptr,
- frame_prev_arch_ftype *prev_arch_func = nullptr)
+ frame_prev_arch_ftype *prev_arch_func = nullptr,
+ frame_prev_tdesc_parameter_ftype *prev_tdesc_parameter_func = nullptr)
: frame_unwind (name, type, uclass, data), m_stop_reason (stop_reason_func),
m_this_id (this_id_func), m_prev_register (prev_register_func),
m_sniffer (sniffer_func), m_dealloc_cache (dealloc_cache_func),
- m_prev_arch (prev_arch_func)
+ m_prev_arch (prev_arch_func),
+ m_prev_tdesc_parameter (prev_tdesc_parameter_func)
{ }
/* This method just passes the parameters to the callback pointer. */
struct gdbarch *prev_arch (const frame_info_ptr &this_frame,
void **this_prologue_cache) const override;
+ /* This method just passes the parameters to the callback pointer. */
+
+ value *prev_tdesc_parameter (const frame_info_ptr &this_frame,
+ void **this_prologue_cache,
+ unsigned int parameter) const override;
+
private:
frame_unwind_stop_reason_ftype *m_stop_reason;
frame_sniffer_ftype *m_sniffer;
frame_dealloc_cache_ftype *m_dealloc_cache;
frame_prev_arch_ftype *m_prev_arch;
+ frame_prev_tdesc_parameter_ftype *m_prev_tdesc_parameter;
};
/* Register a frame unwinder, _prepending_ it to the front of the
#include "valprint.h"
#include "cli/cli-option.h"
#include "dwarf2/loc.h"
+#include "target-descriptions.h"
/* The sentinel frame terminates the innermost end of the frame chain.
If unwound, it returns the information needed to construct an
}
}
+value *
+frame_unwind_tdesc_parameter_value (const frame_info_ptr &next_frame,
+ unsigned int parameter)
+{
+ FRAME_SCOPED_DEBUG_ENTER_EXIT;
+
+ gdb_assert (next_frame != nullptr);
+ gdbarch *gdbarch = frame_unwind_arch (next_frame);
+
+ /* Find the unwinder. */
+ if (next_frame->unwind == NULL)
+ frame_unwind_find_by_frame (next_frame, &next_frame->prologue_cache);
+
+ /* Ask this frame to unwind its register. */
+ value *value
+ = next_frame->unwind->prev_tdesc_parameter (next_frame,
+ &next_frame->prologue_cache,
+ parameter);
+ if (value == nullptr)
+ {
+ auto maybe_param_name = tdesc_parameter_name (gdbarch, parameter);
+ const char *feature, *param_name;
+ if (maybe_param_name.has_value ())
+ {
+ feature = maybe_param_name->first;
+ param_name = maybe_param_name->second;
+ }
+ else
+ {
+ feature = "unknown";
+ param_name = "unknown";
+ }
+
+ error (_("Can't unwind value of parameter %d (%s:%s)"), parameter,
+ feature, param_name);
+ }
+
+ return value;
+}
+
+value *
+get_frame_tdesc_parameter_value (const frame_info_ptr &frame,
+ unsigned int parameter)
+{
+ return frame_unwind_tdesc_parameter_value (frame_info_ptr (frame->next),
+ parameter);
+}
+
+bool
+read_frame_tdesc_parameter_unsigned (const frame_info_ptr &frame,
+ unsigned int parameter, ULONGEST *val)
+{
+ value *value = get_frame_tdesc_parameter_value (frame, parameter);
+
+ if (!value->entirely_available ())
+ return false;
+
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+ *val = extract_unsigned_integer (value->contents (), byte_order);
+ return true;
+}
+
/* Create a sentinel frame.
See frame_id_build_sentinel for the description of STACK_ADDR and
int regnum, CORE_ADDR offset,
gdb::array_view<const gdb_byte> buffer);
+/* FIXME: Document. */
+extern value *frame_unwind_tdesc_parameter_value
+ (const frame_info_ptr &next_frame, unsigned int parameter);
+
+/* FIXME: Document. */
+extern value *get_frame_tdesc_parameter_value (const frame_info_ptr &frame,
+ unsigned int parameter);
+
+/* FIXME: Document. */
+extern bool read_frame_tdesc_parameter_unsigned (const frame_info_ptr &frame,
+ unsigned int parameter,
+ ULONGEST *val);
+
/* Unwind the PC. Strictly speaking return the resume address of the
calling frame. For GDB, `pc' is the resume address and not a
specific register. */
gdbarch_read_core_file_mappings_ftype *read_core_file_mappings = default_read_core_file_mappings;
gdbarch_use_target_description_from_corefile_notes_ftype *use_target_description_from_corefile_notes = default_use_target_description_from_corefile_notes;
gdbarch_core_parse_exec_context_ftype *core_parse_exec_context = default_core_parse_exec_context;
+ gdbarch_fetch_tdesc_parameter_ftype *fetch_tdesc_parameter = default_fetch_tdesc_parameter;
};
/* Create a new ``struct gdbarch'' based on information provided by
/* Skip verify of read_core_file_mappings, invalid_p == 0. */
/* Skip verify of use_target_description_from_corefile_notes, invalid_p == 0. */
/* Skip verify of core_parse_exec_context, invalid_p == 0. */
+ /* Skip verify of fetch_tdesc_parameter, invalid_p == 0. */
if (!log.empty ())
internal_error (_("verify_gdbarch: the following are invalid ...%s"),
log.c_str ());
gdb_printf (file,
"gdbarch_dump: core_parse_exec_context = <%s>\n",
host_address_to_string (gdbarch->core_parse_exec_context));
+ gdb_printf (file,
+ "gdbarch_dump: fetch_tdesc_parameter = <%s>\n",
+ host_address_to_string (gdbarch->fetch_tdesc_parameter));
if (gdbarch->dump_tdep != NULL)
gdbarch->dump_tdep (gdbarch, file);
}
{
gdbarch->core_parse_exec_context = core_parse_exec_context;
}
+
+void
+gdbarch_fetch_tdesc_parameter (struct gdbarch *gdbarch, readable_regcache *regcache, unsigned int parameter_id)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->fetch_tdesc_parameter != NULL);
+ if (gdbarch_debug >= 2)
+ gdb_printf (gdb_stdlog, "gdbarch_fetch_tdesc_parameter called\n");
+ gdbarch->fetch_tdesc_parameter (gdbarch, regcache, parameter_id);
+}
+
+void
+set_gdbarch_fetch_tdesc_parameter (struct gdbarch *gdbarch,
+ gdbarch_fetch_tdesc_parameter_ftype fetch_tdesc_parameter)
+{
+ gdbarch->fetch_tdesc_parameter = fetch_tdesc_parameter;
+}
typedef core_file_exec_context (gdbarch_core_parse_exec_context_ftype) (struct gdbarch *gdbarch, bfd *cbfd);
extern core_file_exec_context gdbarch_core_parse_exec_context (struct gdbarch *gdbarch, bfd *cbfd);
extern void set_gdbarch_core_parse_exec_context (struct gdbarch *gdbarch, gdbarch_core_parse_exec_context_ftype *core_parse_exec_context);
+
+/* Obtain or calculate target description parameter. */
+
+typedef void (gdbarch_fetch_tdesc_parameter_ftype) (struct gdbarch *gdbarch, readable_regcache *regcache, unsigned int parameter_id);
+extern void gdbarch_fetch_tdesc_parameter (struct gdbarch *gdbarch, readable_regcache *regcache, unsigned int parameter_id);
+extern void set_gdbarch_fetch_tdesc_parameter (struct gdbarch *gdbarch, gdbarch_fetch_tdesc_parameter_ftype *fetch_tdesc_parameter);
predefault="default_core_parse_exec_context",
invalid=False,
)
+
+Method(
+ comment="""
+Obtain or calculate target description parameter.
+""",
+ type="void",
+ name="fetch_tdesc_parameter",
+ params=[
+ ("readable_regcache *", "regcache"),
+ ("unsigned int", "parameter_id"),
+ ],
+ predefault="default_fetch_tdesc_parameter",
+ invalid=False,
+)
static struct type *
create_dynamic_range_type (type_allocator &alloc, struct type *index_type,
+ ULONGEST element_length,
const char *parameter_feature,
const char *length_parameter)
{
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;
+ std::tuple<const char *, const char *, ULONGEST> *parameter
+ = new std::tuple<const char *, const char *, ULONGEST> (parameter_feature,
+ length_parameter,
+ element_length);
high.set_tdesc_parameter (parameter);
return create_range_type (alloc, index_type, &low, &high, 0);
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,
+ range_type = create_dynamic_range_type (alloc, index_type, element_type->length (),
+ parameter_feature,
length_parameter);
return create_array_type (alloc, element_type, range_type);
}
if (dwarf2_evaluate_property (prop, frame, addr_stack, &value,
{ (CORE_ADDR) rank }))
{
+ /* In the case of a vector with tdesc parameter in the range, we
+ should evaluate it to the number of elements in the vector. */
+ if (prop->kind () == PROP_TDESC_PARAMETER)
+ {
+ ULONGEST element_length = std::get<ULONGEST> (prop->tdesc_parameter ());
+
+ if (element_length != ULONGEST_MAX)
+ value /= element_length;
+ value -= 1;
+
+ if (low_bound.kind () == PROP_CONST)
+ value += low_bound.const_val ();
+ }
high_bound.set_const_val (value);
if (dyn_range_type->bounds ()->flag_upper_bound_is_count)
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;
+ /* The first element is the feature name, the second is the parameter
+ name and the third is the size of an element in the vector,
+ or ULONGEST_MAX if it should be ignored. */
+ std::tuple<const char *,const char *,ULONGEST> *tdesc_parameter;
};
/* * Used to store a dynamic property. */
m_data.variable_name = name;
}
- std::pair<const char *, const char *> tdesc_parameter () const
+ std::tuple<const char *,const char *,ULONGEST> 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)
+ void set_tdesc_parameter (std::tuple<const char *,const char *,ULONGEST> *parameter)
{
m_kind = PROP_TDESC_PARAMETER;
m_data.tdesc_parameter = parameter;
#include "gdbsupport/unordered_map.h"
#include <unordered_map>
#include "cli/cli-cmds.h"
+#include "target-descriptions.h"
/*
* DATA STRUCTURE
/* Cached table containing the type of each register. */
struct type **register_type = nullptr;
+
+ /* Offset of each target description parameter. */
+ std::vector<long> tdesc_parameter_offset;
+
+ /* Size of target description parameters buffer. */
+ long sizeof_tdesc_parameters = 0;
};
static const registry<gdbarch>::key<struct regcache_descr>
descr->sizeof_fixed_size_cooked_registers = offset;
}
+ /* Initialize list of target description parameter offsets. */
+ long offset = 0;
+ descr->tdesc_parameter_offset.resize (tdesc_num_parameters (gdbarch));
+ for (i = 0; i < descr->tdesc_parameter_offset.size (); i++)
+ {
+ descr->tdesc_parameter_offset[i] = offset;
+ offset += tdesc_parameter_size (gdbarch, i);
+ }
+ descr->sizeof_tdesc_parameters = offset;
+
return descr;
}
m_register_status.reset
(new register_status[gdbarch_num_regs (gdbarch)] ());
}
+
+ m_tdesc_parameter_status.resize (tdesc_num_parameters (gdbarch), REG_UNKNOWN);
+ m_tdesc_parameters.resize (m_descr->sizeof_tdesc_parameters, 0);
}
regcache::regcache (inferior *inf_for_target_calls, gdbarch *gdbarch)
return m_descr->has_variable_size_registers;
}
+/* See regcache.h. */
+
+gdb::array_view<gdb_byte>
+reg_buffer::tdesc_parameter_buffer (unsigned int param_id)
+{
+ gdb_assert (param_id < m_descr->tdesc_parameter_offset.size ());
+ gdb_byte *start;
+
+ start = &m_tdesc_parameters[m_descr->tdesc_parameter_offset[param_id]];
+
+ ULONGEST size = tdesc_parameter_size (m_descr->gdbarch, param_id);
+ return gdb::array_view<gdb_byte> (start, size);
+}
+
+/* See regcache.h. */
+
+enum register_status
+reg_buffer::get_tdesc_parameter_status (unsigned int param_id) const
+{
+ gdb_assert (param_id < m_tdesc_parameter_status.size ());
+ return m_tdesc_parameter_status[param_id];
+}
+
+/* See regcache.h. */
+
+void
+reg_buffer::invalidate_tdesc_parameter (unsigned int param_id)
+{
+ gdb_assert (param_id < m_tdesc_parameter_status.size ());
+ m_tdesc_parameter_status[param_id] = REG_UNKNOWN;
+}
+
+/* See regcache.h. */
+
+void
+reg_buffer::supply_parameter (unsigned int param_id,
+ gdb::array_view<const gdb_byte> src)
+{
+ gdb_assert (param_id < m_tdesc_parameter_status.size ());
+
+ gdb::array_view<gdb_byte> dst = tdesc_parameter_buffer (param_id);
+
+ if (src.data () != nullptr)
+ {
+ copy (src, dst);
+ m_tdesc_parameter_status[param_id] = REG_VALID;
+ }
+ else
+ {
+ /* This memset not strictly necessary, but better than garbage
+ in case the parameter value manages to escape somewhere (due
+ to a bug, no less). */
+ memset (dst.data (), 0, dst.size ());
+ m_tdesc_parameter_status[param_id] = REG_UNAVAILABLE;
+ }
+}
+
/* Helper for reg_buffer::register_buffer. */
template<typename ElemType>
/* See regcache.h. */
+void
+readable_regcache::update_tdesc_parameter (unsigned int param_id)
+{
+ gdb_assert (param_id < m_tdesc_parameter_status.size ());
+
+ if (get_tdesc_parameter_status (param_id) == REG_UNKNOWN)
+ {
+ gdbarch_fetch_tdesc_parameter (m_descr->gdbarch, this, param_id);
+
+ if (m_tdesc_parameter_status[param_id] == REG_UNKNOWN)
+ m_tdesc_parameter_status[param_id] = REG_UNAVAILABLE;
+ }
+}
+
+/* See regcache.h. */
+
+register_status
+readable_regcache::tdesc_parameter_value (unsigned int param_id,
+ gdb::array_view<gdb_byte> dst)
+{
+ gdb_assert (param_id < m_tdesc_parameter_status.size ());
+
+ ULONGEST size = tdesc_parameter_size (m_descr->gdbarch, param_id);
+ gdb_assert (dst.size () == size);
+
+ update_tdesc_parameter (param_id);
+
+ if (m_tdesc_parameter_status[param_id] == REG_VALID)
+ copy (tdesc_parameter_buffer (param_id), dst);
+ else
+ memset (dst.data (), 0, dst.size ());
+
+ return m_tdesc_parameter_status[param_id];
+}
+
+value *
+readable_regcache::tdesc_parameter_value (unsigned int param_id)
+{
+ value *result = value::allocate (tdesc_parameter_type (m_descr->gdbarch,
+ param_id));
+
+ if (tdesc_parameter_value (param_id,
+ result->contents_raw ()) == REG_UNAVAILABLE)
+ result->mark_bytes_unavailable (0, result->type ()->length ());
+
+ return result;
+}
+
+/* See regcache.h. */
+
void
regcache::cooked_write_part (int regnum, int offset,
gdb::array_view<const gdb_byte> src)
/* See gdbsupport/common-regcache.h. */
int register_size (int regnum) const override;
+ /* FIXME: Document.
+ Assumes SRC contains an integer in target byte order. */
+ void supply_parameter (unsigned int param_id,
+ gdb::array_view<const gdb_byte> src);
+
+ /* FIXME: Document. */
+ enum register_status get_tdesc_parameter_status (unsigned int param_id) const;
+
+ /* FIXME: Document. */
+ void invalidate_tdesc_parameter (unsigned int param_id);
+
protected:
/* Assert on the range of REGNUM. */
void assert_regnum (int regnum) const;
gdb::array_view<const gdb_byte> register_buffer (int regnum) const;
gdb::array_view<gdb_byte> register_buffer (int regnum);
+ /* Return a view on target desc parameter PARAM_ID's buffer cache. */
+ gdb::array_view<gdb_byte> tdesc_parameter_buffer (unsigned int param_id_id);
+
/* Save a register cache. The set of registers saved into the
regcache determined by the save_reggroup. COOKED_READ returns
zero iff the register's value can't be returned. */
/* The offset of resolved types for variable-size registers (if any). */
std::vector<long> m_variable_size_register_offset;
+ /* The target description parameters buffers (if any). */
+ std::vector<gdb_byte> m_tdesc_parameters;
+
+ /* Target description parameter cache status. */
+ std::vector<register_status> m_tdesc_parameter_status;
+
friend class regcache;
friend class detached_regcache;
};
will call mark_value_bytes_unavailable as appropriate. */
struct value *cooked_read_value (int regnum);
+ /* FIXME: Document. */
+ void update_tdesc_parameter (unsigned int param_id);
+
+ /* FIXME: Document. */
+ register_status tdesc_parameter_value (unsigned int param_id,
+ gdb::array_view<gdb_byte> dst);
+
+ /* FIXME: Document. */
+ value *tdesc_parameter_value (unsigned int param_id);
+
protected:
/* Perform a partial register transfer using a read, modify, write
return cache->regcache->arch ();
}
+static value *
+sentinel_frame_prev_tdesc_parameter (const frame_info_ptr &this_frame,
+ void **this_prologue_cache,
+ unsigned int parameter)
+{
+ frame_unwind_cache *cache = (frame_unwind_cache *) *this_prologue_cache;
+
+ return cache->regcache->tdesc_parameter_value (parameter);
+}
+
const struct frame_unwind_legacy sentinel_frame_unwind (
"sentinel",
SENTINEL_FRAME,
NULL,
NULL,
NULL,
- sentinel_frame_prev_arch
+ sentinel_frame_prev_arch,
+ sentinel_frame_prev_tdesc_parameter
);
return;
type *element_gdb_type = make_gdb_type (m_gdbarch, e->element_type);
- if (e->bitsize_parameter.length () == 0)
+ if (e->bitsize_parameter == nullptr)
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 ());
+ // Probably not. e->name is duplicated below. OTOH, I think target
+ // descriptions and their associated objects are never destroyed.
+ m_type = init_vector_type (element_gdb_type,
+ e->bitsize_parameter->feature.c_str (),
+ e->bitsize_parameter->name.c_str ());
m_type->set_name (xstrdup (e->name.c_str ()));
return;
}
struct type *type;
};
+struct tdesc_arch_parameter
+{
+ tdesc_arch_parameter (const tdesc_parameter *parameter_)
+ : parameter (parameter_)
+ {}
+
+ const tdesc_parameter *parameter;
+
+ struct type *type = nullptr;
+};
+
struct tdesc_arch_data
{
/* A list of register/type pairs, indexed by GDB's internal register number.
gdbarch_register_name_ftype *pseudo_register_name = NULL;
gdbarch_register_type_ftype *pseudo_register_type = NULL;
gdbarch_register_reggroup_p_ftype *pseudo_register_reggroup_p = NULL;
+
+ std::vector<tdesc_arch_parameter> parameters;
};
/* A handle for architecture-specific data associated with the
return feature->name.c_str ();
}
+/* See target-descriptions.h. */
+
+std::optional<unsigned int>
+tdesc_parameter_id (gdbarch *gdbarch, const char *feature,
+ const char *param_name)
+{
+ struct tdesc_arch_data *data = get_arch_data (gdbarch);
+
+ for (int i = 0; i < data->parameters.size (); i++)
+ {
+ const tdesc_arch_parameter &arch_param = data->parameters[i];
+ if (arch_param.parameter->feature == feature
+ && arch_param.parameter->name == param_name)
+ return i;
+ }
+
+ return {};
+}
+
+/* See target-descriptions.h. */
+
+const tdesc_parameter *
+tdesc_feature_parameter (const tdesc_feature &feature, const char *parameter)
+{
+ for (int i = 0; i < feature.parameters.size (); i++)
+ if (feature.parameters[i]->name == parameter)
+ return feature.parameters[i].get ();
+
+ return nullptr;
+}
+
+/* See target-descriptions.h. */
+
+std::optional<std::pair<const char *,const char *>>
+tdesc_parameter_name (gdbarch *gdbarch, unsigned int param_id)
+{
+ struct tdesc_arch_data *data = get_arch_data (gdbarch);
+
+ if (param_id < data->parameters.size ())
+ {
+ const tdesc_arch_parameter ¶m = data->parameters[param_id];
+ return std::pair<const char *,const char *>
+ { param.parameter->feature.c_str (), param.parameter->name.c_str () };
+ }
+ else
+ return {};
+}
+
+/* See target-descriptions.h. */
+
+type *
+tdesc_parameter_type (gdbarch *gdbarch, unsigned int param_id)
+{
+ tdesc_arch_data *data = get_arch_data (gdbarch);
+
+ gdb_assert (param_id < data->parameters.size ());
+ tdesc_arch_parameter &arch_parameter = data->parameters[param_id];
+ const tdesc_parameter *parameter = arch_parameter.parameter;
+
+ if (arch_parameter.type == nullptr)
+ {
+ arch_parameter.type = make_gdb_type (gdbarch, parameter->type);
+ if (arch_parameter.type == nullptr)
+ internal_error ("Register \"%s\" has an unknown type \"%s\"",
+ parameter->name.c_str (),
+ parameter->type->name.c_str ());
+ }
+
+ return arch_parameter.type;
+}
+
+/* See target-descriptions.h. */
+
+ULONGEST
+tdesc_parameter_size (gdbarch *gdbarch, unsigned int param_id)
+{
+ return tdesc_parameter_type (gdbarch, param_id)->length ();
+}
+
+unsigned int
+tdesc_num_parameters (gdbarch *gdbarch)
+{
+ return get_arch_data (gdbarch)->parameters.size ();
+}
+
+/* See target-descriptions.h. */
+
+void
+tdesc_setup_parameters (gdbarch *gdbarch, const target_desc *target_desc)
+{
+ struct tdesc_arch_data *data = get_arch_data (gdbarch);
+
+ /* Ensure this is done only once. */
+ gdb_assert (data->parameters.size () == 0);
+
+ for (const tdesc_feature_up &feature : target_desc->features)
+ for (const tdesc_parameter_up ¶meter: feature->parameters)
+ data->parameters.emplace_back (parameter.get ());
+}
+
/* Lookup type associated with ID. */
struct type *
gdb_printf
(" element_type = tdesc_named_type (feature, \"%s\");\n",
type->element_type->name.c_str ());
- if (type->bitsize_parameter.length () != 0)
+ if (type->bitsize_parameter != nullptr)
gdb_printf
- (" tdesc_create_vector (feature, \"%s\", element_type, \"%s\");\n",
- type->name.c_str (), type->bitsize_parameter.c_str ());
+ (" tdesc_create_vector (feature, \"%s\", element_type, param_%s);\n",
+ type->name.c_str (), type->bitsize_parameter->name.c_str ());
else
gdb_printf
(" tdesc_create_vector (feature, \"%s\", element_type, %d);\n",
gdb_printf ("\"%s\", ", reg->group.c_str ());
else
gdb_printf ("NULL, ");
- if (reg->bitsize_parameter.length () != 0)
- gdb_printf ("\"%s\", \"%s\");\n", reg->bitsize_parameter.c_str (),
- reg->type.c_str ());
+ if (reg->bitsize_parameter != nullptr)
+ gdb_printf ("param_%s, ", reg->bitsize_parameter->name.c_str ());
else
- gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ());
+ gdb_printf ("%d, ", reg->bitsize);
+ gdb_printf ("\"%s\");\n", reg->type.c_str ());
+ }
+
+ void visit (const tdesc_parameter *p) override
+ {
+ if (!m_printed_param_type)
+ {
+ gdb_printf (" tdesc_type *param_type;\n");
+ m_printed_param_type = true;
+ }
+
+ gdb_printf (" param_type = tdesc_named_type (feature, \"%s\");\n",
+ p->type->name.c_str ());
+ gdb_printf
+ (" const tdesc_parameter ¶m_%s = tdesc_create_parameter (*feature, \"%s\", param_type);\n",
+ p->name.c_str (), p->name.c_str ());
}
protected:
/* Did we print "struct tdesc_type *field_type;" yet? */
bool m_printed_field_type = false;
+
+ /* Did we print "struct tdesc_type *param_type;" yet? */
+ bool m_printed_param_type = false;
};
/* Print target description feature in C. */
gdb_printf ("\"%s\", ", reg->group.c_str ());
else
gdb_printf ("NULL, ");
- if (reg->bitsize_parameter.length () != 0)
- gdb_printf ("\"%s\", \"%s\");\n", reg->bitsize_parameter.c_str (),
- reg->type.c_str ());
+ if (reg->bitsize_parameter != nullptr)
+ gdb_printf ("param_%s, ", reg->bitsize_parameter->name.c_str ());
else
- gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ());
+ gdb_printf ("%d, ", reg->bitsize);
+ gdb_printf ("\"%s\");\n", reg->type.c_str ());
m_next_regnum++;
}
const char *tdesc_feature_name (const struct tdesc_feature *feature);
+/* FIXME: Document. */
+
+std::optional<unsigned int> tdesc_parameter_id (gdbarch *gdbarch,
+ const char *feature,
+ const char *param_name);
+
+/* FIXME: Document. */
+
+const tdesc_parameter *tdesc_feature_parameter (const tdesc_feature &feature,
+ const char *parameter);
+
+/* FIXME: Document. */
+
+std::optional<std::pair<const char *,const char *>> tdesc_parameter_name
+ (gdbarch *gdbarch, unsigned int param_id);
+
+/* FIXME: Document. */
+
+type *tdesc_parameter_type (gdbarch *gdbarch, unsigned int param_id);
+
+/* FIXME: Document. */
+
+ULONGEST tdesc_parameter_size (gdbarch *gdbarch, unsigned int param_id);
+
+/* FIXME: Document. */
+
+unsigned int tdesc_num_parameters (gdbarch *gdbarch);
+
+/* Update TARGET_DESC to use parameters with GDBARCH. */
+
+void tdesc_setup_parameters (struct gdbarch *gdbarch,
+ const struct target_desc *target_desc);
+
/* Return the name of register REGNO, from the target description or
from an architecture-provided pseudo_register_name method. */
if (bitsize_attr[0] == '$')
{
- // FIXME: Check whether the bitsize parameter is valid.
+ const char *parameter_name = &bitsize_attr[1];
+ const tdesc_parameter *parameter
+ = tdesc_feature_parameter (*data->current_feature, parameter_name);
+
+ if (parameter == nullptr)
+ gdb_xml_error (parser,
+ _("Register bitsize references non-existent parameter \"%s\""),
+ parameter_name);
+
tdesc_create_reg (data->current_feature, name, regnum, save_restore,
- group, &bitsize_attr[1], type);
+ group, *parameter, type);
}
else
{
}
else if (!strcmp (attributes[2].name, "bitsize"))
{
- char *bitsize = (char *) attributes[2].value.get ();
+ const char *bitsize = (const char *) attributes[2].value.get ();
if (bitsize[0] != '$')
- gdb_xml_error (parser, _ ("Vector bitsize \"%s\" isn't a parameter"),
+ 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]);
+ const char *parameter_name = &bitsize[1];
+ const tdesc_parameter *parameter
+ = tdesc_feature_parameter (*data->current_feature, parameter_name);
+
+ if (parameter == nullptr)
+ gdb_xml_error (parser,
+ _("Vector bitsize references non-existent parameter \"%s\""),
+ parameter_name);
+
+ tdesc_create_vector (data->current_feature, id, field_type, *parameter);
}
else
- gdb_xml_error (parser, _ ("Vector doesn't have count nor size attribute"));
+ gdb_xml_error (parser, _("Vector doesn't have count nor bitsize attribute"));
+}
+
+/* Handle the start of a <parameter> element. Initialize the type and
+ record it with the current feature. */
+
+static void
+tdesc_start_parameter (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element, void *user_data,
+ std::vector<gdb_xml_value> &attributes)
+{
+ struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data;
+
+ const char *name = (const char *) attributes[0].value.get ();
+ const char *type_id = (const char *) attributes[1].value.get ();
+
+ tdesc_type *type = tdesc_named_type (data->current_feature, type_id);
+ if (type == nullptr)
+ gdb_xml_error (parser, _("Parameter \"%s\" references undefined type \"%s\""),
+ name, type_id);
+
+ if (data->current_feature->has_parameter (name))
+ gdb_xml_error (parser, _("Parameter \"%s\" duplicated in feature \"%s\""),
+ name, data->current_feature->name.c_str ());
+
+ tdesc_create_parameter (*data->current_feature, name, type);
}
/* The elements and attributes of an XML target description. */
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
+static const struct gdb_xml_attribute parameter_attributes[] = {
+ { "name", GDB_XML_AF_NONE, NULL, NULL },
+ { "type", GDB_XML_AF_NONE, NULL, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
static const struct gdb_xml_attribute feature_attributes[] = {
{ "name", GDB_XML_AF_NONE, NULL, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
{ "vector", vector_attributes, NULL,
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
tdesc_start_vector, NULL },
+ { "parameter", parameter_attributes, NULL,
+ GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
+ tdesc_start_parameter, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
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_)
+ const tdesc_parameter &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_),
+ 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. */
{
v.visit_pre (this);
+ for (const tdesc_parameter_up ¶meter : parameters)
+ parameter->accept (v);
+
for (const tdesc_type_up &type : types)
type->accept (v);
/* See gdbsupport/tdesc.h. */
+bool
+tdesc_feature::has_parameter (const char *parameter) const
+{
+ for (int i = 0; i < this->parameters.size (); i++)
+ if (this->parameters[i]->name == parameter)
+ return true;
+
+ return false;
+}
+
+/* See gdbsupport/tdesc.h. */
+
+const tdesc_parameter &
+tdesc_create_parameter (tdesc_feature &feature, const char *parameter,
+ tdesc_type *type)
+{
+ gdb_assert (!feature.has_parameter (parameter));
+
+ feature.parameters.emplace_back (new tdesc_parameter (feature.name,
+ parameter, type));
+
+ return *feature.parameters.back ().get ();
+}
+
+/* See gdbsupport/tdesc.h. */
+
void
tdesc_create_reg (struct tdesc_feature *feature, const char *name,
int regnum, int save_restore, const char *group,
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)
+ const tdesc_parameter &bitsize_parameter, const char *type)
{
tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore,
group, bitsize_parameter, type);
struct tdesc_type *
tdesc_create_vector (struct tdesc_feature *feature, const char *name,
struct tdesc_type *field_type,
- const char *bitsize_parameter)
+ const tdesc_parameter &bitsize_parameter)
{
tdesc_type_vector *type = new tdesc_type_vector (name, field_type,
- feature->name,
bitsize_parameter);
feature->types.emplace_back (type);
void print_xml_feature::visit (const tdesc_type_vector *t)
{
- if (t->bitsize_parameter.length () != 0)
+ if (t->bitsize_parameter != nullptr)
add_line ("<vector id=\"%s\" type=\"%s\" bitsize=\"$%s\"/>", t->name.c_str (),
- t->element_type->name.c_str (), t->bitsize_parameter.c_str ());
+ t->element_type->name.c_str (), t->bitsize_parameter->name.c_str ());
else
add_line ("<vector id=\"%s\" type=\"%s\" count=\"%d\"/>", t->name.c_str (),
t->element_type->name.c_str (), t->count);
{
std::string tmp;
- if (r->bitsize_parameter.length () != 0)
+ if (r->bitsize_parameter != nullptr)
string_appendf (tmp,
"<reg name=\"%s\" bitsize=\"$%s\" type=\"%s\" regnum=\"%ld\"",
- r->name.c_str (), r->bitsize_parameter.c_str(),
+ r->name.c_str (), r->bitsize_parameter->name.c_str(),
r->type.c_str (), r->target_regnum);
else
string_appendf (tmp,
add_line ("</target>");
}
+void print_xml_feature::visit (const tdesc_parameter *p)
+{
+ add_line ("<parameter name=\"%s\" type=\"%s\"/>", p->name.c_str (),
+ p->type->name.c_str ());
+}
+
/* See gdbsupport/tdesc.h. */
void
struct tdesc_type_vector;
struct tdesc_type_with_fields;
struct tdesc_reg;
+struct tdesc_parameter;
struct target_desc;
/* The interface to visit different elements of target description. */
virtual void visit (const tdesc_reg *e)
{}
+
+ virtual void visit (const tdesc_parameter *e)
+ {}
};
class tdesc_element
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_);
+ const tdesc_parameter &bitsize_parameter_, const char *type_);
virtual ~tdesc_reg () = default;
std::string group;
/* The size of the register, in bits.
- Ignored if BITSIZE_PARAMETER isn't empty. */
+ Ignored if BITSIZE_PARAMETER isn't nullptr. */
int bitsize;
- std::string feature, bitsize_parameter;
+ /* FIXME: Document. */
+ const tdesc_parameter *bitsize_parameter = nullptr;
/* The type of the register. This string corresponds to either
a named type from the target description or a predefined
&& save_restore == other.save_restore
&& bitsize == other.bitsize
&& group == other.group
+ && bitsize_parameter == other.bitsize_parameter
&& type == other.type);
}
: name (name_), kind (kind_)
{}
+ tdesc_type (tdesc_type &&other)
+ { *this = std::move (other); }
+
virtual ~tdesc_type () = default;
DISABLE_COPY_AND_ASSIGN (tdesc_type);
{
return !(*this == other);
}
+
+ tdesc_type &operator= (tdesc_type &&other)
+ {
+ this->name = std::move (other.name);
+ this->kind = other.kind;
+ return *this;
+ }
};
typedef std::unique_ptr<tdesc_type> tdesc_type_up;
+/* A parameter from a target description. */
+
+struct tdesc_parameter : tdesc_element
+{
+ tdesc_parameter (const std::string &feature_, const std::string &name_,
+ tdesc_type *type_)
+ : feature (feature_), name (name_), type (type_)
+ {}
+
+ tdesc_parameter (tdesc_parameter &&other)
+ : type (other.type)
+ {
+ *this = std::move (other);
+ }
+
+ virtual ~tdesc_parameter () = default;
+
+ DISABLE_COPY_AND_ASSIGN (tdesc_parameter);
+
+ /* FIXME: Document. */
+ std::string feature;
+
+ /* The name of this parameter. In standard features, it may be
+ recognized by the architecture support code. */
+ std::string name;
+
+ /* The type of the parameter. */
+ tdesc_type *type;
+
+ void accept (tdesc_element_visitor &v) const override
+ {
+ v.visit (this);
+ }
+
+ bool operator== (const tdesc_parameter &other) const
+ {
+ return (name == other.name
+ && feature == other.feature
+ && type == other.type);
+ }
+
+ bool operator!= (const tdesc_parameter &other) const
+ {
+ return !(*this == other);
+ }
+
+ tdesc_parameter &operator= (tdesc_parameter &&other)
+ {
+ if (this != &other)
+ {
+ this->feature = std::move (other.feature);
+ this->name = std::move (other.name);
+ this->type = other.type;
+ }
+
+ return *this;
+ }
+};
+
+typedef std::unique_ptr<tdesc_parameter> tdesc_parameter_up;
+
struct tdesc_type_builtin : tdesc_type
{
tdesc_type_builtin (const std::string &name, enum tdesc_type_kind kind)
tdesc_type_vector (const std::string &name, tdesc_type *element_type_,
int count_)
: tdesc_type (name, TDESC_TYPE_VECTOR),
- element_type (element_type_), count (count_)
+ element_type (element_type_), count (count_), bitsize_parameter (nullptr)
{}
tdesc_type_vector (const std::string &name, tdesc_type *element_type_,
- const std::string &feature_,
- const std::string &bitsize_parameter_)
+ const tdesc_parameter &bitsize_parameter_)
: tdesc_type (name, TDESC_TYPE_VECTOR), element_type (element_type_),
- count (TDESC_REG_VARIABLE_SIZE), feature (feature_),
- bitsize_parameter (bitsize_parameter_)
+ count (TDESC_REG_VARIABLE_SIZE), bitsize_parameter (&bitsize_parameter_)
{}
void accept (tdesc_element_visitor &v) const override
struct tdesc_type *element_type;
- /* Ignored if BITSIZE_PARAMETER isn't empty. */
+ /* Ignored if BITSIZE_PARAMETER isn't nullptr. */
int count;
/* Target description parameter providing total vector size. */
- std::string feature, bitsize_parameter;
+ const tdesc_parameter *bitsize_parameter;
};
/* A named type from a target description. */
/* The types associated with this feature. */
std::vector<tdesc_type_up> types;
+ /* Paremeters defined in this feature. */
+ std::vector<tdesc_parameter_up> parameters;
+
void accept (tdesc_element_visitor &v) const override;
+ bool has_parameter (const char *parameter) const;
+
bool operator== (const tdesc_feature &other) const;
bool operator!= (const tdesc_feature &other) const
struct tdesc_type *tdesc_create_vector (struct tdesc_feature *feature,
const char *name,
struct tdesc_type *field_type,
- const char *bitsize_parameter);
+ const tdesc_parameter &bitsize_parameter);
/* Return the created struct tdesc_type named NAME in FEATURE. */
tdesc_type_with_fields *tdesc_create_struct (struct tdesc_feature *feature,
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);
+ const tdesc_parameter &bitsize_parameter,
+ const char *type);
+
+/* Return internal ID of PARAMETER from FEATURE. */
+
+std::optional<unsigned int> tdesc_parameter_id (const target_desc *target_desc,
+ const char *feature,
+ const char *parameter);
+
+/* Add PARAMETER to FEATURE. */
+
+const tdesc_parameter & tdesc_create_parameter (tdesc_feature &feature,
+ const char *parameter,
+ tdesc_type *type);
/* Return the tdesc in string XML format. */
void visit (const tdesc_type_vector *type) override;
void visit (const tdesc_type_with_fields *type) override;
void visit (const tdesc_reg *reg) override;
+ void visit (const tdesc_parameter *p) override;
private: