diff mbox

[1/6] : Commonise various target-descriptions.c functions

Message ID CFD4D062-238A-456A-97B1-892FF8D32DF1@arm.com
State New
Headers show

Commit Message

Alan Hayward Jan. 16, 2018, 9:50 a.m. UTC
This patch simply moves functionality from target-descriptions.c
to the common files arch/tdesc.c and arch/tdesc.h.
No functionality is changed.
This will allow usage by gdbserver.
The "#ifndef GDBSERVER" around the functions in arch/tdesc.h will be removed
in the next patch.

Alan.


2018-01-16  Alan Hayward  <alan.hayward@arm.com>

	* Makefile.in: Add new common tdesc file.
	* arch/tdesc.c: New file.
	* arch/tdesc.h (struct tdesc_reg): Moved from target-descriptions.c
	(enum tdesc_type_kind): Likewise.
	(struct tdesc_type): Likewise.
	(struct tdesc_type_builtin): Likewise.
	(struct tdesc_type_vector): Likewise.
	(struct tdesc_type_field): Likewise.
	(struct tdesc_type_with_fields): Likewise.
	(struct tdesc_feature): Likewise.
	(struct tdesc_arch_reg): Likewise.
	* target-descriptions.c (struct target_desc): Move to arch/tdesc.c/h
	(type *tdesc_type_builtin::make_gdb_type): Likewise.
	(type *tdesc_type_vector::make_gdb_type): Likewise.
	(type *tdesc_type_with_fields::make_gdb_type_struct): Likewise.
	(type *tdesc_type_with_fields::make_gdb_type_union): Likewise.
	(type *tdesc_type_with_fields::make_gdb_type_flags): Likewise.
	(type *tdesc_type_with_fields::make_gdb_type_enum): Likewise.
	(type *tdesc_type_with_fields::make_gdb_type): Likewise.
	(tdesc_predefined_type): Likewise.
	(tdesc_named_type): Likewise.
	(tdesc_create_reg): Likewise.
	(tdesc_create_vector): Likewise.
	(tdesc_create_struct): Likewise.
	(tdesc_set_struct_size): Likewise.
	(tdesc_create_union): Likewise.
	(tdesc_create_flags): Likewise.
	(tdesc_create_enum): Likewise.
	(tdesc_add_field): Likewise.
	(tdesc_add_typed_bitfield): Likewise.
	(tdesc_add_bitfield): Likewise.
	(tdesc_add_flag): Likewise.
	(tdesc_add_enum_value): Likewise.

Comments

Yao Qi Jan. 19, 2018, 11:05 p.m. UTC | #1
On Tue, Jan 16, 2018 at 9:50 AM, Alan Hayward <Alan.Hayward@arm.com> wrote:
> This patch simply moves functionality from target-descriptions.c
> to the common files arch/tdesc.c and arch/tdesc.h.
> No functionality is changed.
> This will allow usage by gdbserver.
> The "#ifndef GDBSERVER" around the functions in arch/tdesc.h will be removed
> in the next patch.
>

It is not right to move everything to arch/ and remove unused bits.  GDB now
is able to visit different tdesc_element, you want to do the same in
GDBserver, and share the code in arch/.  However, tdesc stuff in GDB and
GDBserver are quite different, so the 1st step, IMO, is to make GDBserver
more similar to GDB.  You can change each tdesc-related struct in each
patch, and refactor GDBserver bits.  Then, only move *needed* structures
to arch/, and move one structure in one patch each, if possible.
Alan Hayward Jan. 22, 2018, 2:06 p.m. UTC | #2
> On 19 Jan 2018, at 23:05, Yao Qi <qiyaoltc@gmail.com> wrote:
> 
> On Tue, Jan 16, 2018 at 9:50 AM, Alan Hayward <Alan.Hayward@arm.com> wrote:
>> This patch simply moves functionality from target-descriptions.c
>> to the common files arch/tdesc.c and arch/tdesc.h.
>> No functionality is changed.
>> This will allow usage by gdbserver.
>> The "#ifndef GDBSERVER" around the functions in arch/tdesc.h will be removed
>> in the next patch.
>> 
> 
> It is not right to move everything to arch/ and remove unused bits.  GDB now
> is able to visit different tdesc_element, you want to do the same in
> GDBserver, and share the code in arch/.  However, tdesc stuff in GDB and
> GDBserver are quite different, so the 1st step, IMO, is to make GDBserver
> more similar to GDB.  You can change each tdesc-related struct in each
> patch, and refactor GDBserver bits.  Then, only move *needed* structures
> to arch/, and move one structure in one patch each, if possible.
> 

Did you want me to change the ordering of the patches in the series or did you
want me to reduce the amount of code that gets moved into arch/ ?

When I wrote the whole patch series, I only moved across the functions I needed
from gdb to arch/. It turns out that I needed to move a lot of functions. Without
complicating the code, I think I need everything I moved into arch/

After I had finished writing my code, I looked at the ways of splitting it up into a
series. The simplest method was to put all the moving of functions into the first
patch. I agree that this makes the first patch a little odd to review. My reasoning
was to keep changes to the moved code separate from the moving.

I can look at making a new version of 2/6 the first patch, and then follow with
smaller versions of this patch? The final change across the whole series would
be the same. 


Alan.
Yao Qi Jan. 22, 2018, 3:46 p.m. UTC | #3
Alan Hayward <Alan.Hayward@arm.com> writes:

> Did you want me to change the ordering of the patches in the series or did you
> want me to reduce the amount of code that gets moved into arch/ ?
>

Both.

> When I wrote the whole patch series, I only moved across the functions I needed
> from gdb to arch/. It turns out that I needed to move a lot of
> functions. Without
> complicating the code, I think I need everything I moved into arch/
>
> After I had finished writing my code, I looked at the ways of
> splitting it up into a
> series. The simplest method was to put all the moving of functions
> into the first
> patch. I agree that this makes the first patch a little odd to
> review. My reasoning
> was to keep changes to the moved code separate from the moving.
>

For some big patch series, the patches (order and contents) I posted for
review are different from the patches I wrote to get things done.  After
I get my branch working, I'll restart a new branch, to rewrite them
in a way which is more friendly for review/upstreaming, because you've
never know what changes are needed until you finish the work.  It
happens to me that I realize that I need to refactor some part after I
committed ten patches in my branch, so I have to stop, rebase my
patches, to put refactor patches first.

> I can look at making a new version of 2/6 the first patch, and then follow with
> smaller versions of this patch? The final change across the whole series would
> be the same. 

That will be very helpful.  Steps matter, take a look at page 6 of my
presentation,
https://gcc.gnu.org/wiki/cauldron2013?action=AttachFile&do=get&target=port-gdb-tic6x-qi.pdf
diff mbox

Patch

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 0a4a06b242e0423218648fe77d53fc192456cd2f..386ab5c117ebf34e1ae927b5fe78fd4618012945 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -669,6 +669,7 @@  ALL_TARGET_OBS = \
 	arch/arm-get-next-pcs.o \
 	arch/arm-linux.o \
 	arch/i386.o \
+	arch/tdesc.o \
 	arm-bsd-tdep.o \
 	arm-fbsd-tdep.o \
 	arm-linux-tdep.o \
diff --git a/gdb/arch/tdesc.h b/gdb/arch/tdesc.h
index cc11651dcaa7abe81598b69f509ef34ff0d94dbf..22da5efa48f8cf5e94c33c9eed4739127467c356 100644
--- a/gdb/arch/tdesc.h
+++ b/gdb/arch/tdesc.h
@@ -18,6 +18,12 @@ 
 #ifndef ARCH_TDESC_H
 #define ARCH_TDESC_H 1

+#ifdef GDBSERVER
+#include "server.h"
+#else
+#include "defs.h"
+#endif
+
 struct tdesc_feature;
 struct tdesc_type;
 struct tdesc_type_builtin;
@@ -25,6 +31,271 @@  struct tdesc_type_vector;
 struct tdesc_type_with_fields;
 struct tdesc_reg;
 struct target_desc;
+struct type;
+
+#ifndef GDBSERVER
+
+/* The interface to visit different elements of target description.  */
+
+class tdesc_element_visitor
+{
+public:
+  virtual void visit_pre (const target_desc *e) = 0;
+  virtual void visit_post (const target_desc *e) = 0;
+
+  virtual void visit_pre (const tdesc_feature *e) = 0;
+  virtual void visit_post (const tdesc_feature *e) = 0;
+
+  virtual void visit (const tdesc_type_builtin *e) = 0;
+  virtual void visit (const tdesc_type_vector *e) = 0;
+  virtual void visit (const tdesc_type_with_fields *e) = 0;
+
+  virtual void visit (const tdesc_reg *e) = 0;
+};
+
+class tdesc_element
+{
+public:
+  virtual void accept (tdesc_element_visitor &v) const = 0;
+};
+
+/* An individual register from a target description.  */
+
+struct tdesc_reg : tdesc_element
+{
+  tdesc_reg (struct tdesc_feature *feature, const std::string &name_,
+	     int regnum, int save_restore_, const char *group_,
+	     int bitsize_, const char *type_);
+
+  virtual ~tdesc_reg () = default;
+
+  DISABLE_COPY_AND_ASSIGN (tdesc_reg);
+
+  /* The name of this register.  In standard features, it may be
+     recognized by the architecture support code, or it may be purely
+     for the user.  */
+  std::string name;
+
+  /* The register number used by this target to refer to this
+     register.  This is used for remote p/P packets and to determine
+     the ordering of registers in the remote g/G packets.  */
+  long target_regnum;
+
+  /* If this flag is set, GDB should save and restore this register
+     around calls to an inferior function.  */
+  int save_restore;
+
+  /* The name of the register group containing this register, or empty
+     if the group should be automatically determined from the
+     register's type.  If this is "general", "float", or "vector", the
+     corresponding "info" command should display this register's
+     value.  It can be an arbitrary string, but should be limited to
+     alphanumeric characters and internal hyphens.  Currently other
+     strings are ignored (treated as empty).  */
+  std::string group;
+
+  /* The size of the register, in bits.  */
+  int bitsize;
+
+  /* The type of the register.  This string corresponds to either
+     a named type from the target description or a predefined
+     type from GDB.  */
+  std::string type;
+
+  /* The target-described type corresponding to TYPE, if found.  */
+  struct tdesc_type *tdesc_type;
+
+  void accept (tdesc_element_visitor &v) const override;
+
+  bool operator== (const tdesc_reg &other) const;
+
+  bool operator!= (const tdesc_reg &other) const
+  {
+    return !(*this == other);
+  }
+};
+
+typedef std::unique_ptr<tdesc_reg> tdesc_reg_up;
+
+enum tdesc_type_kind
+{
+  /* Predefined types.  */
+  TDESC_TYPE_BOOL,
+  TDESC_TYPE_INT8,
+  TDESC_TYPE_INT16,
+  TDESC_TYPE_INT32,
+  TDESC_TYPE_INT64,
+  TDESC_TYPE_INT128,
+  TDESC_TYPE_UINT8,
+  TDESC_TYPE_UINT16,
+  TDESC_TYPE_UINT32,
+  TDESC_TYPE_UINT64,
+  TDESC_TYPE_UINT128,
+  TDESC_TYPE_CODE_PTR,
+  TDESC_TYPE_DATA_PTR,
+  TDESC_TYPE_IEEE_SINGLE,
+  TDESC_TYPE_IEEE_DOUBLE,
+  TDESC_TYPE_ARM_FPA_EXT,
+  TDESC_TYPE_I387_EXT,
+
+  /* Types defined by a target feature.  */
+  TDESC_TYPE_VECTOR,
+  TDESC_TYPE_STRUCT,
+  TDESC_TYPE_UNION,
+  TDESC_TYPE_FLAGS,
+  TDESC_TYPE_ENUM
+};
+
+struct tdesc_type : tdesc_element
+{
+  tdesc_type (const std::string &name_, enum tdesc_type_kind kind_)
+    : name (name_), kind (kind_)
+  {}
+
+  virtual ~tdesc_type () = default;
+
+  DISABLE_COPY_AND_ASSIGN (tdesc_type);
+
+  /* The name of this type.   */
+  std::string name;
+
+  /* Identify the kind of this type.  */
+  enum tdesc_type_kind kind;
+
+  bool operator== (const tdesc_type &other) const
+  {
+    return name == other.name && kind == other.kind;
+  }
+
+  bool operator!= (const tdesc_type &other) const
+  {
+    return !(*this == other);
+  }
+
+  /* Construct, if necessary, and return the GDB type implementing this
+     target type for architecture GDBARCH.  */
+
+  virtual type *make_gdb_type (struct gdbarch *gdbarch) const = 0;
+};
+
+struct tdesc_type_builtin : tdesc_type
+{
+  tdesc_type_builtin (const std::string &name, enum tdesc_type_kind kind)
+  : tdesc_type (name, kind)
+  {}
+
+  void accept (tdesc_element_visitor &v) const override;
+
+  type *make_gdb_type (struct gdbarch *gdbarch) const override;
+};
+
+/* tdesc_type for vector types.  */
+
+struct tdesc_type_vector : tdesc_type
+{
+  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_)
+  {}
+
+  void accept (tdesc_element_visitor &v) const override;
+
+  type *make_gdb_type (struct gdbarch *gdbarch) const override;
+
+  struct tdesc_type *element_type;
+  int count;
+};
+
+/* A named type from a target description.  */
+
+struct tdesc_type_field
+{
+  tdesc_type_field (const std::string &name_, tdesc_type *type_,
+		    int start_, int end_)
+  : name (name_), type (type_), start (start_), end (end_)
+  {}
+
+  std::string name;
+  struct tdesc_type *type;
+  /* For non-enum-values, either both are -1 (non-bitfield), or both are
+     not -1 (bitfield).  For enum values, start is the value (which could be
+     -1), end is -1.  */
+  int start, end;
+};
+
+/* tdesc_type for struct, union, flags, and enum types.  */
+
+struct tdesc_type_with_fields : tdesc_type
+{
+  tdesc_type_with_fields (const std::string &name, tdesc_type_kind kind,
+			  int size_ = 0)
+  : tdesc_type (name, kind), size (size_)
+  {}
+
+  void accept (tdesc_element_visitor &v) const override;
+
+  type *make_gdb_type_struct (struct gdbarch *gdbarch) const;
+  type *make_gdb_type_union (struct gdbarch *gdbarch) const;
+  type *make_gdb_type_flags (struct gdbarch *gdbarch) const;
+  type *make_gdb_type_enum (struct gdbarch *gdbarch) const;
+  type *make_gdb_type (struct gdbarch *gdbarch) const override;
+
+  std::vector<tdesc_type_field> fields;
+  int size;
+};
+
+typedef std::unique_ptr<tdesc_type> tdesc_type_up;
+
+/* A feature from a target description.  Each feature is a collection
+   of other elements, e.g. registers and types.  */
+
+struct tdesc_feature : tdesc_element
+{
+  tdesc_feature (const std::string &name_)
+    : name (name_)
+  {}
+
+  virtual ~tdesc_feature () = default;
+
+  DISABLE_COPY_AND_ASSIGN (tdesc_feature);
+
+  /* The name of this feature.  It may be recognized by the architecture
+     support code.  */
+  std::string name;
+
+  /* The registers associated with this feature.  */
+  std::vector<tdesc_reg_up> registers;
+
+  /* The types associated with this feature.  */
+  std::vector<tdesc_type_up> types;
+
+  void accept (tdesc_element_visitor &v) const override;
+
+  bool operator== (const tdesc_feature &other) const;
+
+  bool operator!= (const tdesc_feature &other) const
+  {
+    return !(*this == other);
+  }
+};
+
+typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
+
+/* Per-architecture data associated with a target description.  The
+   target description may be shared by multiple architectures, but
+   this data is private to one gdbarch.  */
+
+struct tdesc_arch_reg
+{
+  tdesc_arch_reg (tdesc_reg *reg_, struct type *type_)
+  : reg (reg_), type (type_)
+  {}
+
+  struct tdesc_reg *reg;
+  struct type *type;
+};
+
+#endif

 /* Allocate a new target_desc.  */
 target_desc *allocate_target_description (void);
diff --git a/gdb/arch/tdesc.c b/gdb/arch/tdesc.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6005a75a7264bba4cd177e4ec1efd90809e25c8
--- /dev/null
+++ b/gdb/arch/tdesc.c
@@ -0,0 +1,325 @@ 
+/* Target description support for GDB.
+
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef GDBSERVER
+#include "server.h"
+
+typedef const char * (gdbarch_register_name_ftype) (struct gdbarch *gdbarch, int regnr);
+typedef struct type * (gdbarch_register_type_ftype) (struct gdbarch *gdbarch, int reg_nr);
+
+#else
+#include "defs.h"
+#endif
+
+#include "tdesc.h"
+
+tdesc_reg::tdesc_reg (struct tdesc_feature *feature, const std::string &name_,
+		      int regnum, int save_restore_, const char *group_,
+		      int bitsize_, const char *type_)
+  : name (name_), target_regnum (regnum),
+    save_restore (save_restore_),
+    group (group_ != NULL ? group_ : ""),
+    bitsize (bitsize_),
+    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 ());
+}
+
+void tdesc_reg::accept (tdesc_element_visitor &v) const
+{
+  v.visit (this);
+}
+
+bool tdesc_reg::operator== (const tdesc_reg &other) const
+{
+  return (name == other.name
+	  && target_regnum == other.target_regnum
+	  && save_restore == other.save_restore
+	  && bitsize == other.bitsize
+	  && group == other.group
+	  && type == other.type);
+}
+
+/* Predefined types.  */
+static tdesc_type_builtin tdesc_predefined_types[] =
+{
+  { "bool", TDESC_TYPE_BOOL },
+  { "int8", TDESC_TYPE_INT8 },
+  { "int16", TDESC_TYPE_INT16 },
+  { "int32", TDESC_TYPE_INT32 },
+  { "int64", TDESC_TYPE_INT64 },
+  { "int128", TDESC_TYPE_INT128 },
+  { "uint8", TDESC_TYPE_UINT8 },
+  { "uint16", TDESC_TYPE_UINT16 },
+  { "uint32", TDESC_TYPE_UINT32 },
+  { "uint64", TDESC_TYPE_UINT64 },
+  { "uint128", TDESC_TYPE_UINT128 },
+  { "code_ptr", TDESC_TYPE_CODE_PTR },
+  { "data_ptr", TDESC_TYPE_DATA_PTR },
+  { "ieee_single", TDESC_TYPE_IEEE_SINGLE },
+  { "ieee_double", TDESC_TYPE_IEEE_DOUBLE },
+  { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT },
+  { "i387_ext", TDESC_TYPE_I387_EXT }
+};
+
+void tdesc_type_builtin::accept (tdesc_element_visitor &v) const
+{
+  v.visit (this);
+}
+
+void tdesc_type_vector::accept (tdesc_element_visitor &v) const
+{
+  v.visit (this);
+}
+
+void tdesc_type_with_fields::accept (tdesc_element_visitor &v) const
+{
+  v.visit (this);
+}
+
+void tdesc_feature::accept (tdesc_element_visitor &v) const
+{
+  v.visit_pre (this);
+
+  for (const tdesc_type_up &type : types)
+    type->accept (v);
+
+  for (const tdesc_reg_up &reg : registers)
+    reg->accept (v);
+
+  v.visit_post (this);
+}
+
+bool tdesc_feature::operator== (const tdesc_feature &other) const
+{
+  if (name != other.name)
+    return false;
+
+  if (registers.size () != other.registers.size ())
+    return false;
+
+  for (int ix = 0; ix < registers.size (); ix++)
+    {
+      const tdesc_reg_up &reg1 = registers[ix];
+      const tdesc_reg_up &reg2 = other.registers[ix];
+
+      if (reg1 != reg2 && *reg1 != *reg2)
+	return false;
+      }
+
+  if (types.size () != other.types.size ())
+    return false;
+
+  for (int ix = 0; ix < types.size (); ix++)
+    {
+      const tdesc_type_up &type1 = types[ix];
+      const tdesc_type_up &type2 = other.types[ix];
+
+      if (type1 != type2 && *type1 != *type2)
+	return false;
+    }
+
+  return true;
+}
+
+/* Lookup a predefined type.  */
+
+static struct tdesc_type *
+tdesc_predefined_type (enum tdesc_type_kind kind)
+{
+  for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
+    if (tdesc_predefined_types[ix].kind == kind)
+      return &tdesc_predefined_types[ix];
+
+  gdb_assert_not_reached ("bad predefined tdesc type");
+}
+
+/* See arch/tdesc.h.  */
+
+struct tdesc_type *
+tdesc_named_type (const struct tdesc_feature *feature, const char *id)
+{
+  /* First try target-defined types.  */
+  for (const tdesc_type_up &type : feature->types)
+    if (type->name == id)
+      return type.get ();
+
+  /* Next try the predefined types.  */
+  for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
+    if (tdesc_predefined_types[ix].name == id)
+      return &tdesc_predefined_types[ix];
+
+  return NULL;
+}
+
+/* See arch/tdesc.h.  */
+
+void
+tdesc_create_reg (struct tdesc_feature *feature, const char *name,
+		  int regnum, int save_restore, const char *group,
+		  int bitsize, const char *type)
+{
+  tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore,
+				  group, bitsize, type);
+
+  feature->registers.emplace_back (reg);
+}
+
+/* See arch/tdesc.h.  */
+
+struct tdesc_type *
+tdesc_create_vector (struct tdesc_feature *feature, const char *name,
+		     struct tdesc_type *field_type, int count)
+{
+  tdesc_type_vector *type = new tdesc_type_vector (name, field_type, count);
+  feature->types.emplace_back (type);
+
+  return type;
+}
+
+/* See arch/tdesc.h.  */
+
+tdesc_type_with_fields *
+tdesc_create_struct (struct tdesc_feature *feature, const char *name)
+{
+  tdesc_type_with_fields *type
+    = new tdesc_type_with_fields (name, TDESC_TYPE_STRUCT);
+  feature->types.emplace_back (type);
+
+  return type;
+}
+
+/* See arch/tdesc.h.  */
+
+void
+tdesc_set_struct_size (tdesc_type_with_fields *type, int size)
+{
+  gdb_assert (type->kind == TDESC_TYPE_STRUCT);
+  gdb_assert (size > 0);
+  type->size = size;
+}
+
+/* See arch/tdesc.h.  */
+
+tdesc_type_with_fields *
+tdesc_create_union (struct tdesc_feature *feature, const char *name)
+{
+  tdesc_type_with_fields *type
+    = new tdesc_type_with_fields (name, TDESC_TYPE_UNION);
+  feature->types.emplace_back (type);
+
+  return type;
+}
+
+/* See arch/tdesc.h.  */
+
+tdesc_type_with_fields *
+tdesc_create_flags (struct tdesc_feature *feature, const char *name,
+		    int size)
+{
+  gdb_assert (size > 0);
+
+  tdesc_type_with_fields *type
+    = new tdesc_type_with_fields (name, TDESC_TYPE_FLAGS, size);
+  feature->types.emplace_back (type);
+
+  return type;
+}
+
+tdesc_type_with_fields *
+tdesc_create_enum (struct tdesc_feature *feature, const char *name,
+		   int size)
+{
+  gdb_assert (size > 0);
+
+  tdesc_type_with_fields *type
+    = new tdesc_type_with_fields (name, TDESC_TYPE_ENUM, size);
+  feature->types.emplace_back (type);
+
+  return type;
+}
+
+/* See arch/tdesc.h.  */
+
+void
+tdesc_add_field (tdesc_type_with_fields *type, const char *field_name,
+		 struct tdesc_type *field_type)
+{
+  gdb_assert (type->kind == TDESC_TYPE_UNION
+	      || type->kind == TDESC_TYPE_STRUCT);
+
+  /* Initialize start and end so we know this is not a bit-field
+     when we print-c-tdesc.  */
+  type->fields.emplace_back (field_name, field_type, -1, -1);
+}
+
+void
+tdesc_add_typed_bitfield (tdesc_type_with_fields *type, const char *field_name,
+			  int start, int end, struct tdesc_type *field_type)
+{
+  gdb_assert (type->kind == TDESC_TYPE_STRUCT
+	      || type->kind == TDESC_TYPE_FLAGS);
+  gdb_assert (start >= 0 && end >= start);
+
+  type->fields.emplace_back (field_name, field_type, start, end);
+}
+
+/* See arch/tdesc.h.  */
+
+void
+tdesc_add_bitfield (tdesc_type_with_fields *type, const char *field_name,
+		    int start, int end)
+{
+  struct tdesc_type *field_type;
+
+  gdb_assert (start >= 0 && end >= start);
+
+  if (type->size > 4)
+    field_type = tdesc_predefined_type (TDESC_TYPE_UINT64);
+  else
+    field_type = tdesc_predefined_type (TDESC_TYPE_UINT32);
+
+  tdesc_add_typed_bitfield (type, field_name, start, end, field_type);
+}
+
+/* See arch/tdesc.h.  */
+
+void
+tdesc_add_flag (tdesc_type_with_fields *type, int start,
+		const char *flag_name)
+{
+  gdb_assert (type->kind == TDESC_TYPE_FLAGS
+	      || type->kind == TDESC_TYPE_STRUCT);
+
+  type->fields.emplace_back (flag_name,
+			     tdesc_predefined_type (TDESC_TYPE_BOOL),
+			     start, start);
+}
+
+void
+tdesc_add_enum_value (tdesc_type_with_fields *type, int value,
+		      const char *name)
+{
+  gdb_assert (type->kind == TDESC_TYPE_ENUM);
+  type->fields.emplace_back (name,
+			     tdesc_predefined_type (TDESC_TYPE_INT32),
+			     value, -1);
+}
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 1b20a12d769718e591dea6df8183c2e9ecfac990..cef65a8fe61e22362e0bc4e6dbd7e3c0a0f4d1b4 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -38,30 +38,6 @@ 
 #include "completer.h"
 #include "readline/tilde.h" /* tilde_expand */

-/* The interface to visit different elements of target description.  */
-
-class tdesc_element_visitor
-{
-public:
-  virtual void visit_pre (const target_desc *e) = 0;
-  virtual void visit_post (const target_desc *e) = 0;
-
-  virtual void visit_pre (const tdesc_feature *e) = 0;
-  virtual void visit_post (const tdesc_feature *e) = 0;
-
-  virtual void visit (const tdesc_type_builtin *e) = 0;
-  virtual void visit (const tdesc_type_vector *e) = 0;
-  virtual void visit (const tdesc_type_with_fields *e) = 0;
-
-  virtual void visit (const tdesc_reg *e) = 0;
-};
-
-class tdesc_element
-{
-public:
-  virtual void accept (tdesc_element_visitor &v) const = 0;
-};
-
 /* Types.  */

 struct property
@@ -74,41 +50,20 @@  struct property
   std::string value;
 };

-/* An individual register from a target description.  */
+/* A target description.  */

-struct tdesc_reg : tdesc_element
+struct target_desc : tdesc_element
 {
-  tdesc_reg (struct tdesc_feature *feature, const std::string &name_,
-	     int regnum, int save_restore_, const char *group_,
-	     int bitsize_, const char *type_)
-    : name (name_), target_regnum (regnum),
-      save_restore (save_restore_),
-      group (group_ != NULL ? group_ : ""),
-      bitsize (bitsize_),
-      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 ());
-  }
-
-  virtual ~tdesc_reg () = default;
-
-  DISABLE_COPY_AND_ASSIGN (tdesc_reg);
+  target_desc ()
+  {}

-  /* The name of this register.  In standard features, it may be
-     recognized by the architecture support code, or it may be purely
-     for the user.  */
-  std::string name;
+  virtual ~target_desc () = default;

-  /* The register number used by this target to refer to this
-     register.  This is used for remote p/P packets and to determine
-     the ordering of registers in the remote g/G packets.  */
-  long target_regnum;
+  target_desc (const target_desc &) = delete;
+  void operator= (const target_desc &) = delete;

-  /* If this flag is set, GDB should save and restore this register
-     around calls to an inferior function.  */
-  int save_restore;
+  /* The architecture reported by the target, if any.  */
+  const struct bfd_arch_info *arch = NULL;

   /* The name of the register group containing this register, or empty
      if the group should be automatically determined from the register's
@@ -118,554 +73,290 @@  struct tdesc_reg : tdesc_element
      limited to alphanumeric characters and internal hyphens.  */
   std::string group;

-  /* The size of the register, in bits.  */
-  int bitsize;
+  /* The osabi reported by the target, if any; GDB_OSABI_UNKNOWN
+     otherwise.  */
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
+
+  /* The list of compatible architectures reported by the target.  */
+  std::vector<const bfd_arch_info *> compatible;

-  /* The type of the register.  This string corresponds to either
-     a named type from the target description or a predefined
-     type from GDB.  */
-  std::string type;
+  /* Any architecture-specific properties specified by the target.  */
+  std::vector<property> properties;

-  /* The target-described type corresponding to TYPE, if found.  */
-  struct tdesc_type *tdesc_type;
+  /* The features associated with this target.  */
+  std::vector<tdesc_feature_up> features;

   void accept (tdesc_element_visitor &v) const override
   {
-    v.visit (this);
-  }
+    v.visit_pre (this);

-  bool operator== (const tdesc_reg &other) const
-  {
-    return (name == other.name
-	    && target_regnum == other.target_regnum
-	    && save_restore == other.save_restore
-	    && bitsize == other.bitsize
-	    && group == other.group
-	    && type == other.type);
-  }
+    for (const tdesc_feature_up &feature : features)
+      feature->accept (v);

-  bool operator!= (const tdesc_reg &other) const
-  {
-    return !(*this == other);
+    v.visit_post (this);
   }
-};
-
-typedef std::unique_ptr<tdesc_reg> tdesc_reg_up;
-
-/* A named type from a target description.  */
-
-struct tdesc_type_field
-{
-  tdesc_type_field (const std::string &name_, tdesc_type *type_,
-		    int start_, int end_)
-  : name (name_), type (type_), start (start_), end (end_)
-  {}
-
-  std::string name;
-  struct tdesc_type *type;
-  /* For non-enum-values, either both are -1 (non-bitfield), or both are
-     not -1 (bitfield).  For enum values, start is the value (which could be
-     -1), end is -1.  */
-  int start, end;
-};
-
-enum tdesc_type_kind
-{
-  /* Predefined types.  */
-  TDESC_TYPE_BOOL,
-  TDESC_TYPE_INT8,
-  TDESC_TYPE_INT16,
-  TDESC_TYPE_INT32,
-  TDESC_TYPE_INT64,
-  TDESC_TYPE_INT128,
-  TDESC_TYPE_UINT8,
-  TDESC_TYPE_UINT16,
-  TDESC_TYPE_UINT32,
-  TDESC_TYPE_UINT64,
-  TDESC_TYPE_UINT128,
-  TDESC_TYPE_CODE_PTR,
-  TDESC_TYPE_DATA_PTR,
-  TDESC_TYPE_IEEE_SINGLE,
-  TDESC_TYPE_IEEE_DOUBLE,
-  TDESC_TYPE_ARM_FPA_EXT,
-  TDESC_TYPE_I387_EXT,
-
-  /* Types defined by a target feature.  */
-  TDESC_TYPE_VECTOR,
-  TDESC_TYPE_STRUCT,
-  TDESC_TYPE_UNION,
-  TDESC_TYPE_FLAGS,
-  TDESC_TYPE_ENUM
-};

-struct tdesc_type : tdesc_element
-{
-  tdesc_type (const std::string &name_, enum tdesc_type_kind kind_)
-    : name (name_), kind (kind_)
-  {}
+  bool operator== (const target_desc &other) const
+  {
+    if (arch != other.arch)
+      return false;

-  virtual ~tdesc_type () = default;
+    if (osabi != other.osabi)
+      return false;

-  DISABLE_COPY_AND_ASSIGN (tdesc_type);
+    if (features.size () != other.features.size ())
+      return false;

-  /* The name of this type.   */
-  std::string name;
+    for (int ix = 0; ix < features.size (); ix++)
+      {
+	const tdesc_feature_up &feature1 = features[ix];
+	const tdesc_feature_up &feature2 = other.features[ix];

-  /* Identify the kind of this type.  */
-  enum tdesc_type_kind kind;
+	if (feature1 != feature2 && *feature1 != *feature2)
+	  return false;
+      }

-  bool operator== (const tdesc_type &other) const
-  {
-    return name == other.name && kind == other.kind;
+    return true;
   }

-  bool operator!= (const tdesc_type &other) const
+  bool operator!= (const target_desc &other) const
   {
     return !(*this == other);
   }
-
-  /* Construct, if necessary, and return the GDB type implementing this
-     target type for architecture GDBARCH.  */
-
-  virtual type *make_gdb_type (struct gdbarch *gdbarch) const = 0;
 };

-typedef std::unique_ptr<tdesc_type> tdesc_type_up;
-
-struct tdesc_type_builtin : tdesc_type
-{
-  tdesc_type_builtin (const std::string &name, enum tdesc_type_kind kind)
-  : tdesc_type (name, kind)
-  {}

-  void accept (tdesc_element_visitor &v) const override
-  {
-    v.visit (this);
-  }

-  type *make_gdb_type (struct gdbarch *gdbarch) const override
-  {
-    switch (this->kind)
-      {
-      /* Predefined types.  */
-      case TDESC_TYPE_BOOL:
-        return builtin_type (gdbarch)->builtin_bool;
+type *tdesc_type_builtin::make_gdb_type (struct gdbarch *gdbarch) const
+{
+  switch (this->kind)
+    {
+    /* Predefined types.  */
+    case TDESC_TYPE_BOOL:
+      return builtin_type (gdbarch)->builtin_bool;

-      case TDESC_TYPE_INT8:
-        return builtin_type (gdbarch)->builtin_int8;
+    case TDESC_TYPE_INT8:
+      return builtin_type (gdbarch)->builtin_int8;

-      case TDESC_TYPE_INT16:
-        return builtin_type (gdbarch)->builtin_int16;
+    case TDESC_TYPE_INT16:
+      return builtin_type (gdbarch)->builtin_int16;

-      case TDESC_TYPE_INT32:
-        return builtin_type (gdbarch)->builtin_int32;
+    case TDESC_TYPE_INT32:
+      return builtin_type (gdbarch)->builtin_int32;

-      case TDESC_TYPE_INT64:
-        return builtin_type (gdbarch)->builtin_int64;
+    case TDESC_TYPE_INT64:
+      return builtin_type (gdbarch)->builtin_int64;

-      case TDESC_TYPE_INT128:
-        return builtin_type (gdbarch)->builtin_int128;
+    case TDESC_TYPE_INT128:
+      return builtin_type (gdbarch)->builtin_int128;

-      case TDESC_TYPE_UINT8:
-        return builtin_type (gdbarch)->builtin_uint8;
+    case TDESC_TYPE_UINT8:
+      return builtin_type (gdbarch)->builtin_uint8;

-      case TDESC_TYPE_UINT16:
-        return builtin_type (gdbarch)->builtin_uint16;
+    case TDESC_TYPE_UINT16:
+      return builtin_type (gdbarch)->builtin_uint16;

-      case TDESC_TYPE_UINT32:
-        return builtin_type (gdbarch)->builtin_uint32;
+    case TDESC_TYPE_UINT32:
+      return builtin_type (gdbarch)->builtin_uint32;

-      case TDESC_TYPE_UINT64:
-        return builtin_type (gdbarch)->builtin_uint64;
+    case TDESC_TYPE_UINT64:
+      return builtin_type (gdbarch)->builtin_uint64;

-      case TDESC_TYPE_UINT128:
-        return builtin_type (gdbarch)->builtin_uint128;
+    case TDESC_TYPE_UINT128:
+      return builtin_type (gdbarch)->builtin_uint128;

-      case TDESC_TYPE_CODE_PTR:
-        return builtin_type (gdbarch)->builtin_func_ptr;
+    case TDESC_TYPE_CODE_PTR:
+      return builtin_type (gdbarch)->builtin_func_ptr;

-      case TDESC_TYPE_DATA_PTR:
-        return builtin_type (gdbarch)->builtin_data_ptr;
-      }
+    case TDESC_TYPE_DATA_PTR:
+      return builtin_type (gdbarch)->builtin_data_ptr;
+    }

-    type *gdb_type = tdesc_find_type (gdbarch, this->name.c_str ());
-    if (gdb_type != NULL)
-      return gdb_type;
+  type *gdb_type = tdesc_find_type (gdbarch, this->name.c_str ());
+  if (gdb_type != NULL)
+    return gdb_type;

-    switch (this->kind)
-      {
-      case TDESC_TYPE_IEEE_SINGLE:
-        return arch_float_type (gdbarch, -1, "builtin_type_ieee_single",
-				floatformats_ieee_single);
+  switch (this->kind)
+    {
+    case TDESC_TYPE_IEEE_SINGLE:
+      return arch_float_type (gdbarch, -1, "builtin_type_ieee_single",
+			      floatformats_ieee_single);

-      case TDESC_TYPE_IEEE_DOUBLE:
-        return arch_float_type (gdbarch, -1, "builtin_type_ieee_double",
-				floatformats_ieee_double);
+    case TDESC_TYPE_IEEE_DOUBLE:
+      return arch_float_type (gdbarch, -1, "builtin_type_ieee_double",
+			      floatformats_ieee_double);

-      case TDESC_TYPE_ARM_FPA_EXT:
-        return arch_float_type (gdbarch, -1, "builtin_type_arm_ext",
-				floatformats_arm_ext);
+    case TDESC_TYPE_ARM_FPA_EXT:
+      return arch_float_type (gdbarch, -1, "builtin_type_arm_ext",
+			      floatformats_arm_ext);

-      case TDESC_TYPE_I387_EXT:
-        return arch_float_type (gdbarch, -1, "builtin_type_i387_ext",
-				floatformats_i387_ext);
-      }
+    case TDESC_TYPE_I387_EXT:
+      return arch_float_type (gdbarch, -1, "builtin_type_i387_ext",
+			      floatformats_i387_ext);
+    }

-    internal_error (__FILE__, __LINE__,
-		    "Type \"%s\" has an unknown kind %d",
-		    this->name.c_str (), this->kind);
+  internal_error (__FILE__, __LINE__,
+  		  "Type \"%s\" has an unknown kind %d",
+		  this->name.c_str (), this->kind);

-    return NULL;
-  }
-};
-
-/* tdesc_type for vector types.  */
+  return NULL;
+}

-struct tdesc_type_vector : tdesc_type
+type *tdesc_type_vector::make_gdb_type (struct gdbarch *gdbarch) const
 {
-  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_)
-  {}
-
-  void accept (tdesc_element_visitor &v) const override
-  {
-    v.visit (this);
-  }
-
-  type *make_gdb_type (struct gdbarch *gdbarch) const override
-  {
-    type *vector_gdb_type = tdesc_find_type (gdbarch, this->name.c_str ());
-    if (vector_gdb_type != NULL)
-      return vector_gdb_type;
-
-    type *element_gdb_type = this->element_type->make_gdb_type (gdbarch);
-    vector_gdb_type = init_vector_type (element_gdb_type, this->count);
-    TYPE_NAME (vector_gdb_type) = xstrdup (this->name.c_str ());
-
+  type *vector_gdb_type = tdesc_find_type (gdbarch, this->name.c_str ());
+  if (vector_gdb_type != NULL)
     return vector_gdb_type;
-  }
-
-  struct tdesc_type *element_type;
-  int count;
-};

-/* tdesc_type for struct, union, flags, and enum types.  */
+  type *element_gdb_type = this->element_type->make_gdb_type (gdbarch);
+  vector_gdb_type = init_vector_type (element_gdb_type, this->count);
+  TYPE_NAME (vector_gdb_type) = xstrdup (this->name.c_str ());

-struct tdesc_type_with_fields : tdesc_type
-{
-  tdesc_type_with_fields (const std::string &name, tdesc_type_kind kind,
-			  int size_ = 0)
-  : tdesc_type (name, kind), size (size_)
-  {}
+  return vector_gdb_type;
+}

-  void accept (tdesc_element_visitor &v) const override
-  {
-    v.visit (this);
-  }

-  type *make_gdb_type_struct (struct gdbarch *gdbarch) const
-  {
-    type *struct_gdb_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
-    TYPE_NAME (struct_gdb_type) = xstrdup (this->name.c_str ());
-    TYPE_TAG_NAME (struct_gdb_type) = TYPE_NAME (struct_gdb_type);
+type *tdesc_type_with_fields::make_gdb_type_struct (struct gdbarch *gdbarch) const
+{
+  type *struct_gdb_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  TYPE_NAME (struct_gdb_type) = xstrdup (this->name.c_str ());
+  TYPE_TAG_NAME (struct_gdb_type) = TYPE_NAME (struct_gdb_type);

-    for (const tdesc_type_field &f : this->fields)
-      {
-	if (f.start != -1 && f.end != -1)
-	  {
-	    /* Bitfield.  */
-	    struct field *fld;
-	    struct type *field_gdb_type;
-	    int bitsize, total_size;
-
-	    /* This invariant should be preserved while creating types.  */
-	    gdb_assert (this->size != 0);
-	    if (f.type != NULL)
-	      field_gdb_type = f.type->make_gdb_type (gdbarch);
-	    else if (this->size > 4)
-	      field_gdb_type = builtin_type (gdbarch)->builtin_uint64;
-	    else
-	      field_gdb_type = builtin_type (gdbarch)->builtin_uint32;
-
-	    fld = append_composite_type_field_raw
-	      (struct_gdb_type, xstrdup (f.name.c_str ()), field_gdb_type);
-
-	    /* For little-endian, BITPOS counts from the LSB of
-	       the structure and marks the LSB of the field.  For
-	       big-endian, BITPOS counts from the MSB of the
-	       structure and marks the MSB of the field.  Either
-	       way, it is the number of bits to the "left" of the
-	       field.  To calculate this in big-endian, we need
-	       the total size of the structure.  */
-	    bitsize = f.end - f.start + 1;
-	    total_size = this->size * TARGET_CHAR_BIT;
-	    if (gdbarch_bits_big_endian (gdbarch))
-	      SET_FIELD_BITPOS (fld[0], total_size - f.start - bitsize);
-	    else
-	      SET_FIELD_BITPOS (fld[0], f.start);
-	    FIELD_BITSIZE (fld[0]) = bitsize;
-	  }
-	else
-	  {
-	    gdb_assert (f.start == -1 && f.end == -1);
-	    type *field_gdb_type = f.type->make_gdb_type (gdbarch);
-	    append_composite_type_field (struct_gdb_type,
-					 xstrdup (f.name.c_str ()),
-					 field_gdb_type);
-	  }
-      }
+  for (const tdesc_type_field &f : this->fields)
+    {
+      if (f.start != -1 && f.end != -1)
+      	{
+	  /* Bitfield.  */
+	  struct field *fld;
+	  struct type *field_gdb_type;
+	  int bitsize, total_size;
+
+	  /* This invariant should be preserved while creating types.  */
+	  gdb_assert (this->size != 0);
+	  if (f.type != NULL)
+	    field_gdb_type = f.type->make_gdb_type (gdbarch);
+	  else if (this->size > 4)
+	    field_gdb_type = builtin_type (gdbarch)->builtin_uint64;
+	  else
+	    field_gdb_type = builtin_type (gdbarch)->builtin_uint32;
+
+	  fld = append_composite_type_field_raw
+	    (struct_gdb_type, xstrdup (f.name.c_str ()), field_gdb_type);
+
+	  /* For little-endian, BITPOS counts from the LSB of
+	     the structure and marks the LSB of the field.  For
+	     big-endian, BITPOS counts from the MSB of the
+	     structure and marks the MSB of the field.  Either
+	     way, it is the number of bits to the "left" of the
+	     field.  To calculate this in big-endian, we need
+	     the total size of the structure.  */
+	  bitsize = f.end - f.start + 1;
+	  total_size = this->size * TARGET_CHAR_BIT;
+	  if (gdbarch_bits_big_endian (gdbarch))
+	    SET_FIELD_BITPOS (fld[0], total_size - f.start - bitsize);
+	  else
+	    SET_FIELD_BITPOS (fld[0], f.start);
+	  FIELD_BITSIZE (fld[0]) = bitsize;
+	}
+      else
+	{
+	  gdb_assert (f.start == -1 && f.end == -1);
+	  type *field_gdb_type = f.type->make_gdb_type (gdbarch);
+	  append_composite_type_field (struct_gdb_type,
+				       xstrdup (f.name.c_str ()),
+				       field_gdb_type);
+	}
+    }

-    if (this->size != 0)
-      TYPE_LENGTH (struct_gdb_type) = this->size;
+  if (this->size != 0)
+    TYPE_LENGTH (struct_gdb_type) = this->size;

-    return struct_gdb_type;
-  }
+  return struct_gdb_type;
+}

-  type *make_gdb_type_union (struct gdbarch *gdbarch) const
-  {
-    type *union_gdb_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION);
-    TYPE_NAME (union_gdb_type) = xstrdup (this->name.c_str ());
+type *tdesc_type_with_fields::make_gdb_type_union (struct gdbarch *gdbarch) const
+{
+  type *union_gdb_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION);
+  TYPE_NAME (union_gdb_type) = xstrdup (this->name.c_str ());

-    for (const tdesc_type_field &f : this->fields)
-      {
-	type* field_gdb_type = f.type->make_gdb_type (gdbarch);
-	append_composite_type_field (union_gdb_type, xstrdup (f.name.c_str ()),
+  for (const tdesc_type_field &f : this->fields)
+    {
+      type* field_gdb_type = f.type->make_gdb_type (gdbarch);
+      append_composite_type_field (union_gdb_type, xstrdup (f.name.c_str ()),
 				     field_gdb_type);

-	/* If any of the children of a union are vectors, flag the
-	   union as a vector also.  This allows e.g. a union of two
-	   vector types to show up automatically in "info vector".  */
-	if (TYPE_VECTOR (field_gdb_type))
-	  TYPE_VECTOR (union_gdb_type) = 1;
-      }
+      /* If any of the children of a union are vectors, flag the
+	 union as a vector also.  This allows e.g. a union of two
+	 vector types to show up automatically in "info vector".  */
+      if (TYPE_VECTOR (field_gdb_type))
+	TYPE_VECTOR (union_gdb_type) = 1;
+    }

-    return union_gdb_type;
-  }
+  return union_gdb_type;
+}

-  type *make_gdb_type_flags (struct gdbarch *gdbarch) const
-  {
-    type *flags_gdb_type = arch_flags_type (gdbarch, this->name.c_str (),
+type *tdesc_type_with_fields::make_gdb_type_flags (struct gdbarch *gdbarch) const
+{
+  type *flags_gdb_type = arch_flags_type (gdbarch, this->name.c_str (),
 					  this->size * TARGET_CHAR_BIT);

-    for (const tdesc_type_field &f : this->fields)
-      {
+  for (const tdesc_type_field &f : this->fields)
+    {
       int bitsize = f.end - f.start + 1;

       gdb_assert (f.type != NULL);
       type *field_gdb_type = f.type->make_gdb_type (gdbarch);
       append_flags_type_field (flags_gdb_type, f.start, bitsize,
 			       field_gdb_type, f.name.c_str ());
-      }
+    }

-    return flags_gdb_type;
-  }
+  return flags_gdb_type;
+}

-  type *make_gdb_type_enum (struct gdbarch *gdbarch) const
-  {
-    type *enum_gdb_type = arch_type (gdbarch, TYPE_CODE_ENUM,
+type *tdesc_type_with_fields::make_gdb_type_enum (struct gdbarch *gdbarch) const
+{
+  type *enum_gdb_type = arch_type (gdbarch, TYPE_CODE_ENUM,
 				   this->size * TARGET_CHAR_BIT,
 				   this->name.c_str ());

-    TYPE_UNSIGNED (enum_gdb_type) = 1;
-    for (const tdesc_type_field &f : this->fields)
-      {
+  TYPE_UNSIGNED (enum_gdb_type) = 1;
+  for (const tdesc_type_field &f : this->fields)
+    {
       struct field *fld
 	= append_composite_type_field_raw (enum_gdb_type,
 					   xstrdup (f.name.c_str ()),
 					   NULL);

       SET_FIELD_BITPOS (fld[0], f.start);
-      }
-
-    return enum_gdb_type;
-  }
-
-  type *make_gdb_type (struct gdbarch *gdbarch) const override
-  {
-    type *gdb_type = tdesc_find_type (gdbarch, this->name.c_str ());
-    if (gdb_type != NULL)
-      return gdb_type;
-
-    switch (this->kind)
-    {
-      case TDESC_TYPE_STRUCT:
-	return make_gdb_type_struct (gdbarch);
-      case TDESC_TYPE_UNION:
-	return make_gdb_type_union (gdbarch);
-      case TDESC_TYPE_FLAGS:
-	return make_gdb_type_flags (gdbarch);
-      case TDESC_TYPE_ENUM:
-	return make_gdb_type_enum (gdbarch);
     }

-    internal_error (__FILE__, __LINE__,
-		    "Type \"%s\" has an unknown kind %d",
-		    this->name.c_str (), this->kind);
-
-    return NULL;
-  }
-
-  std::vector<tdesc_type_field> fields;
-  int size;
-};
-
-/* A feature from a target description.  Each feature is a collection
-   of other elements, e.g. registers and types.  */
-
-struct tdesc_feature : tdesc_element
-{
-  tdesc_feature (const std::string &name_)
-    : name (name_)
-  {}
-
-  virtual ~tdesc_feature () = default;
-
-  DISABLE_COPY_AND_ASSIGN (tdesc_feature);
-
-  /* The name of this feature.  It may be recognized by the architecture
-     support code.  */
-  std::string name;
-
-  /* The registers associated with this feature.  */
-  std::vector<tdesc_reg_up> registers;
-
-  /* The types associated with this feature.  */
-  std::vector<tdesc_type_up> types;
-
-  void accept (tdesc_element_visitor &v) const override
-  {
-    v.visit_pre (this);
-
-    for (const tdesc_type_up &type : types)
-      type->accept (v);
-
-    for (const tdesc_reg_up &reg : registers)
-      reg->accept (v);
-
-    v.visit_post (this);
-  }
-
-  bool operator== (const tdesc_feature &other) const
-  {
-    if (name != other.name)
-      return false;
-
-    if (registers.size () != other.registers.size ())
-      return false;
-
-    for (int ix = 0; ix < registers.size (); ix++)
-      {
-	const tdesc_reg_up &reg1 = registers[ix];
-	const tdesc_reg_up &reg2 = other.registers[ix];
-
-	if (reg1 != reg2 && *reg1 != *reg2)
-	  return false;
-      }
-
-    if (types.size () != other.types.size ())
-      return false;
-
-    for (int ix = 0; ix < types.size (); ix++)
-      {
-	const tdesc_type_up &type1 = types[ix];
-	const tdesc_type_up &type2 = other.types[ix];
-
-	if (type1 != type2 && *type1 != *type2)
-	  return false;
-      }
-
-    return true;
-  }
-
-  bool operator!= (const tdesc_feature &other) const
-  {
-    return !(*this == other);
-  }
-};
-
-typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
-
-/* A target description.  */
+  return enum_gdb_type;
+}

-struct target_desc : tdesc_element
+type *tdesc_type_with_fields::make_gdb_type (struct gdbarch *gdbarch) const
 {
-  target_desc ()
-  {}
-
-  virtual ~target_desc () = default;
-
-  target_desc (const target_desc &) = delete;
-  void operator= (const target_desc &) = delete;
-
-  /* The architecture reported by the target, if any.  */
-  const struct bfd_arch_info *arch = NULL;
-
-  /* The osabi reported by the target, if any; GDB_OSABI_UNKNOWN
-     otherwise.  */
-  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
-
-  /* The list of compatible architectures reported by the target.  */
-  std::vector<const bfd_arch_info *> compatible;
-
-  /* Any architecture-specific properties specified by the target.  */
-  std::vector<property> properties;
-
-  /* The features associated with this target.  */
-  std::vector<tdesc_feature_up> features;
-
-  void accept (tdesc_element_visitor &v) const override
-  {
-    v.visit_pre (this);
-
-    for (const tdesc_feature_up &feature : features)
-      feature->accept (v);
-
-    v.visit_post (this);
-  }
-
-  bool operator== (const target_desc &other) const
-  {
-    if (arch != other.arch)
-      return false;
-
-    if (osabi != other.osabi)
-      return false;
-
-    if (features.size () != other.features.size ())
-      return false;
-
-    for (int ix = 0; ix < features.size (); ix++)
-      {
-	const tdesc_feature_up &feature1 = features[ix];
-	const tdesc_feature_up &feature2 = other.features[ix];
-
-	if (feature1 != feature2 && *feature1 != *feature2)
-	  return false;
-      }
-
-    return true;
-  }
-
-  bool operator!= (const target_desc &other) const
-  {
-    return !(*this == other);
-  }
-};
+  type *gdb_type = tdesc_find_type (gdbarch, this->name.c_str ());
+  if (gdb_type != NULL)
+    return gdb_type;

-/* Per-architecture data associated with a target description.  The
-   target description may be shared by multiple architectures, but
-   this data is private to one gdbarch.  */
+  switch (this->kind)
+    {
+    case TDESC_TYPE_STRUCT:
+      return make_gdb_type_struct (gdbarch);
+    case TDESC_TYPE_UNION:
+      return make_gdb_type_union (gdbarch);
+    case TDESC_TYPE_FLAGS:
+      return make_gdb_type_flags (gdbarch);
+    case TDESC_TYPE_ENUM:
+      return make_gdb_type_enum (gdbarch);
+    }

-struct tdesc_arch_reg
-{
-  tdesc_arch_reg (tdesc_reg *reg_, struct type *type_)
-  : reg (reg_), type (type_)
-  {}
+  internal_error (__FILE__, __LINE__,
+		  "Type \"%s\" has an unknown kind %d",
+		  this->name.c_str (), this->kind);

-  struct tdesc_reg *reg;
-  struct type *type;
-};
+  return NULL;
+}

 struct tdesc_arch_data
 {
@@ -957,58 +648,6 @@  tdesc_feature_name (const struct tdesc_feature *feature)
   return feature->name.c_str ();
 }

-/* Predefined types.  */
-static tdesc_type_builtin tdesc_predefined_types[] =
-{
-  { "bool", TDESC_TYPE_BOOL },
-  { "int8", TDESC_TYPE_INT8 },
-  { "int16", TDESC_TYPE_INT16 },
-  { "int32", TDESC_TYPE_INT32 },
-  { "int64", TDESC_TYPE_INT64 },
-  { "int128", TDESC_TYPE_INT128 },
-  { "uint8", TDESC_TYPE_UINT8 },
-  { "uint16", TDESC_TYPE_UINT16 },
-  { "uint32", TDESC_TYPE_UINT32 },
-  { "uint64", TDESC_TYPE_UINT64 },
-  { "uint128", TDESC_TYPE_UINT128 },
-  { "code_ptr", TDESC_TYPE_CODE_PTR },
-  { "data_ptr", TDESC_TYPE_DATA_PTR },
-  { "ieee_single", TDESC_TYPE_IEEE_SINGLE },
-  { "ieee_double", TDESC_TYPE_IEEE_DOUBLE },
-  { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT },
-  { "i387_ext", TDESC_TYPE_I387_EXT }
-};
-
-/* Lookup a predefined type.  */
-
-static struct tdesc_type *
-tdesc_predefined_type (enum tdesc_type_kind kind)
-{
-  for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
-    if (tdesc_predefined_types[ix].kind == kind)
-      return &tdesc_predefined_types[ix];
-
-  gdb_assert_not_reached ("bad predefined tdesc type");
-}
-
-/* See arch/tdesc.h.  */
-
-struct tdesc_type *
-tdesc_named_type (const struct tdesc_feature *feature, const char *id)
-{
-  /* First try target-defined types.  */
-  for (const tdesc_type_up &type : feature->types)
-    if (type->name == id)
-      return type.get ();
-
-  /* Next try the predefined types.  */
-  for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
-    if (tdesc_predefined_types[ix].name == id)
-      return &tdesc_predefined_types[ix];
-
-  return NULL;
-}
-
 /* Lookup type associated with ID.  */

 struct type *
@@ -1440,161 +1079,6 @@  tdesc_use_registers (struct gdbarch *gdbarch,
 				      tdesc_remote_register_number);
   set_gdbarch_register_reggroup_p (gdbarch, tdesc_register_reggroup_p);
 }
-

-
-/* See arch/tdesc.h.  */
-
-void
-tdesc_create_reg (struct tdesc_feature *feature, const char *name,
-		  int regnum, int save_restore, const char *group,
-		  int bitsize, const char *type)
-{
-  tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore,
-				  group, bitsize, type);
-
-  feature->registers.emplace_back (reg);
-}
-
-/* See arch/tdesc.h.  */
-
-struct tdesc_type *
-tdesc_create_vector (struct tdesc_feature *feature, const char *name,
-		     struct tdesc_type *field_type, int count)
-{
-  tdesc_type_vector *type = new tdesc_type_vector (name, field_type, count);
-  feature->types.emplace_back (type);
-
-  return type;
-}
-
-/* See arch/tdesc.h.  */
-
-tdesc_type_with_fields *
-tdesc_create_struct (struct tdesc_feature *feature, const char *name)
-{
-  tdesc_type_with_fields *type
-    = new tdesc_type_with_fields (name, TDESC_TYPE_STRUCT);
-  feature->types.emplace_back (type);
-
-  return type;
-}
-
-/* See arch/tdesc.h.  */
-
-void
-tdesc_set_struct_size (tdesc_type_with_fields *type, int size)
-{
-  gdb_assert (type->kind == TDESC_TYPE_STRUCT);
-  gdb_assert (size > 0);
-  type->size = size;
-}
-
-/* See arch/tdesc.h.  */
-
-tdesc_type_with_fields *
-tdesc_create_union (struct tdesc_feature *feature, const char *name)
-{
-  tdesc_type_with_fields *type
-    = new tdesc_type_with_fields (name, TDESC_TYPE_UNION);
-  feature->types.emplace_back (type);
-
-  return type;
-}
-
-/* See arch/tdesc.h.  */
-
-tdesc_type_with_fields *
-tdesc_create_flags (struct tdesc_feature *feature, const char *name,
-		    int size)
-{
-  gdb_assert (size > 0);
-
-  tdesc_type_with_fields *type
-    = new tdesc_type_with_fields (name, TDESC_TYPE_FLAGS, size);
-  feature->types.emplace_back (type);
-
-  return type;
-}
-
-tdesc_type_with_fields *
-tdesc_create_enum (struct tdesc_feature *feature, const char *name,
-		   int size)
-{
-  gdb_assert (size > 0);
-
-  tdesc_type_with_fields *type
-    = new tdesc_type_with_fields (name, TDESC_TYPE_ENUM, size);
-  feature->types.emplace_back (type);
-
-  return type;
-}
-
-/* See arch/tdesc.h.  */
-
-void
-tdesc_add_field (tdesc_type_with_fields *type, const char *field_name,
-		 struct tdesc_type *field_type)
-{
-  gdb_assert (type->kind == TDESC_TYPE_UNION
-	      || type->kind == TDESC_TYPE_STRUCT);
-
-  /* Initialize start and end so we know this is not a bit-field
-     when we print-c-tdesc.  */
-  type->fields.emplace_back (field_name, field_type, -1, -1);
-}
-
-void
-tdesc_add_typed_bitfield (tdesc_type_with_fields *type, const char *field_name,
-			  int start, int end, struct tdesc_type *field_type)
-{
-  gdb_assert (type->kind == TDESC_TYPE_STRUCT
-	      || type->kind == TDESC_TYPE_FLAGS);
-  gdb_assert (start >= 0 && end >= start);
-
-  type->fields.emplace_back (field_name, field_type, start, end);
-}
-
-/* See arch/tdesc.h.  */
-
-void
-tdesc_add_bitfield (tdesc_type_with_fields *type, const char *field_name,
-		    int start, int end)
-{
-  struct tdesc_type *field_type;
-
-  gdb_assert (start >= 0 && end >= start);
-
-  if (type->size > 4)
-    field_type = tdesc_predefined_type (TDESC_TYPE_UINT64);
-  else
-    field_type = tdesc_predefined_type (TDESC_TYPE_UINT32);
-
-  tdesc_add_typed_bitfield (type, field_name, start, end, field_type);
-}
-
-/* See arch/tdesc.h.  */
-
-void
-tdesc_add_flag (tdesc_type_with_fields *type, int start,
-		const char *flag_name)
-{
-  gdb_assert (type->kind == TDESC_TYPE_FLAGS
-	      || type->kind == TDESC_TYPE_STRUCT);
-
-  type->fields.emplace_back (flag_name,
-			     tdesc_predefined_type (TDESC_TYPE_BOOL),
-			     start, start);
-}
-
-void
-tdesc_add_enum_value (tdesc_type_with_fields *type, int value,
-		      const char *name)
-{
-  gdb_assert (type->kind == TDESC_TYPE_ENUM);
-  type->fields.emplace_back (name,
-			     tdesc_predefined_type (TDESC_TYPE_INT32),
-			     value, -1);
-}

 /* See arch/tdesc.h.  */