public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] Use registry in gdbarch
@ 2022-08-04 19:33 Tom Tromey
  0 siblings, 0 replies; only message in thread
From: Tom Tromey @ 2022-08-04 19:33 UTC (permalink / raw)
  To: gdb-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cb275538dbddfbb3c2c372a665ac48e6f617ea33

commit cb275538dbddfbb3c2c372a665ac48e6f617ea33
Author: Tom Tromey <tom@tromey.com>
Date:   Wed Jun 1 15:31:15 2022 -0600

    Use registry in gdbarch
    
    gdbarch implements its own registry-like approach.  This patch changes
    it to instead use registry.h.  It's a rather large patch but largely
    uninteresting -- it's mostly a straightforward conversion from the old
    approach to the new one.
    
    The main benefit of this change is that it introduces type safety to
    the gdbarch registry.  It also removes a bunch of code.
    
    One possible drawback is that, previously, the gdbarch registry
    differentiated between pre- and post-initialization setup.  This
    doesn't seem very important to me, though.

Diff:
---
 gdb/arch-utils.c          | 112 ++--------------------------------------------
 gdb/bsd-uthread.c         |  37 +++++++--------
 gdb/d-lang.c              |  21 +++++----
 gdb/d-lang.h              |  48 ++++++++++----------
 gdb/dwarf2/expr.c         |  32 +++----------
 gdb/dwarf2/frame.c        |  58 +++++++++++-------------
 gdb/f-lang.c              |  18 +++++---
 gdb/f-lang.h              |  32 ++++++-------
 gdb/fbsd-tdep.c           |  25 +++--------
 gdb/frame-base.c          |  38 ++++++----------
 gdb/frame-unwind.c        |  39 ++++++++--------
 gdb/gdbarch.c             |   4 +-
 gdb/gdbarch.h             |  34 ++++----------
 gdb/gdbarch.py            |   4 +-
 gdb/gdbtypes.c            |  29 ++++++------
 gdb/gdbtypes.h            |  94 +++++++++++++++++++-------------------
 gdb/gnu-v3-abi.c          |  42 +++++++++--------
 gdb/go-lang.c             |  21 +++++----
 gdb/go-lang.h             |  36 +++++++--------
 gdb/guile/scm-arch.c      |  45 ++++++++-----------
 gdb/guile/scm-symbol.c    |  34 +++++---------
 gdb/ia64-libunwind-tdep.c |  23 +++-------
 gdb/ia64-libunwind-tdep.h |  10 ++---
 gdb/jit.c                 |  37 +++++----------
 gdb/language.c            |  39 ++++++++--------
 gdb/linux-tdep.c          |  22 ++++-----
 gdb/m2-lang.c             |  24 +++++-----
 gdb/m2-lang.h             |  10 ++---
 gdb/netbsd-tdep.c         |  25 +++--------
 gdb/python/py-arch.c      |  24 +++++-----
 gdb/python/py-registers.c |  31 ++++---------
 gdb/python/py-unwind.c    |  18 +++-----
 gdb/regcache.c            |  36 ++++++++-------
 gdb/reggroups.c           |  54 +++++++++++-----------
 gdb/remote.c              |  31 ++++++-------
 gdb/rs6000-tdep.c         |   2 +-
 gdb/solib-svr4.c          |  32 +++++--------
 gdb/solib.c               |  26 +++--------
 gdb/target-descriptions.c |  52 +++++++++------------
 gdb/user-regs.c           |  44 +++++++++---------
 gdb/windows-tdep.c        |  25 ++++-------
 41 files changed, 532 insertions(+), 836 deletions(-)

diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index 295dfc2aaf7..9c6b9268a69 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -1092,10 +1092,6 @@ default_read_core_file_mappings
 {
 }
 
-/* Static function declarations */
-
-static void alloc_gdbarch_data (struct gdbarch *);
-
 /* Non-zero if we want to trace architecture code.  */
 
 #ifndef GDBARCH_DEBUG
@@ -1204,114 +1200,12 @@ gdbarch_tdep_1 (struct gdbarch *gdbarch)
   return gdbarch->tdep;
 }
 
-/* Keep a registry of per-architecture data-pointers required by GDB
-   modules.  */
-
-struct gdbarch_data
-{
-  unsigned index;
-  int init_p;
-  gdbarch_data_pre_init_ftype *pre_init;
-  gdbarch_data_post_init_ftype *post_init;
-};
-
-struct gdbarch_data_registration
-{
-  struct gdbarch_data *data;
-  struct gdbarch_data_registration *next;
-};
-
-struct gdbarch_data_registry
-{
-  unsigned nr;
-  struct gdbarch_data_registration *registrations;
-};
-
-static struct gdbarch_data_registry gdbarch_data_registry =
-{
-  0, NULL,
-};
-
-static struct gdbarch_data *
-gdbarch_data_register (gdbarch_data_pre_init_ftype *pre_init,
-		       gdbarch_data_post_init_ftype *post_init)
-{
-  struct gdbarch_data_registration **curr;
-
-  /* Append the new registration.  */
-  for (curr = &gdbarch_data_registry.registrations;
-       (*curr) != NULL;
-       curr = &(*curr)->next);
-  (*curr) = XNEW (struct gdbarch_data_registration);
-  (*curr)->next = NULL;
-  (*curr)->data = XNEW (struct gdbarch_data);
-  (*curr)->data->index = gdbarch_data_registry.nr++;
-  (*curr)->data->pre_init = pre_init;
-  (*curr)->data->post_init = post_init;
-  (*curr)->data->init_p = 1;
-  return (*curr)->data;
-}
-
-struct gdbarch_data *
-gdbarch_data_register_pre_init (gdbarch_data_pre_init_ftype *pre_init)
-{
-  return gdbarch_data_register (pre_init, NULL);
-}
-
-struct gdbarch_data *
-gdbarch_data_register_post_init (gdbarch_data_post_init_ftype *post_init)
-{
-  return gdbarch_data_register (NULL, post_init);
-}
-
-/* Create/delete the gdbarch data vector.  */
-
-static void
-alloc_gdbarch_data (struct gdbarch *gdbarch)
-{
-  gdb_assert (gdbarch->data == NULL);
-  gdbarch->nr_data = gdbarch_data_registry.nr;
-  gdbarch->data = GDBARCH_OBSTACK_CALLOC (gdbarch, gdbarch->nr_data, void *);
-}
-
-/* Return the current value of the specified per-architecture
-   data-pointer.  */
-
-void *
-gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *data)
+registry<gdbarch> *
+registry_accessor<gdbarch>::get (gdbarch *arch)
 {
-  gdb_assert (data->index < gdbarch->nr_data);
-  if (gdbarch->data[data->index] == NULL)
-    {
-      /* The data-pointer isn't initialized, call init() to get a
-	 value.  */
-      if (data->pre_init != NULL)
-	/* Mid architecture creation: pass just the obstack, and not
-	   the entire architecture, as that way it isn't possible for
-	   pre-init code to refer to undefined architecture
-	   fields.  */
-	gdbarch->data[data->index] = data->pre_init (&gdbarch->obstack);
-      else if (gdbarch->initialized_p
-	       && data->post_init != NULL)
-	/* Post architecture creation: pass the entire architecture
-	   (as all fields are valid), but be careful to also detect
-	   recursive references.  */
-	{
-	  gdb_assert (data->init_p);
-	  data->init_p = 0;
-	  gdbarch->data[data->index] = data->post_init (gdbarch);
-	  data->init_p = 1;
-	}
-      else
-	internal_error (__FILE__, __LINE__,
-			_("gdbarch post-init data field can only be used "
-			  "after gdbarch is fully initialised"));
-      gdb_assert (gdbarch->data[data->index] != NULL);
-    }
-  return gdbarch->data[data->index];
+  return &arch->registry_fields;
 }
 
-
 /* Keep a registry of the architectures known by GDB.  */
 
 struct gdbarch_registration
diff --git a/gdb/bsd-uthread.c b/gdb/bsd-uthread.c
index 759b562cdd0..c230cb90326 100644
--- a/gdb/bsd-uthread.c
+++ b/gdb/bsd-uthread.c
@@ -70,24 +70,24 @@ static bsd_uthread_target bsd_uthread_ops;
 
 /* Architecture-specific operations.  */
 
-/* Per-architecture data key.  */
-static struct gdbarch_data *bsd_uthread_data;
-
 struct bsd_uthread_ops
 {
   /* Supply registers for an inactive thread to a register cache.  */
-  void (*supply_uthread)(struct regcache *, int, CORE_ADDR);
+  void (*supply_uthread)(struct regcache *, int, CORE_ADDR) = nullptr;
 
   /* Collect registers for an inactive thread from a register cache.  */
-  void (*collect_uthread)(const struct regcache *, int, CORE_ADDR);
+  void (*collect_uthread)(const struct regcache *, int, CORE_ADDR) = nullptr;
 };
 
-static void *
-bsd_uthread_init (struct obstack *obstack)
-{
-  struct bsd_uthread_ops *ops;
+/* Per-architecture data key.  */
+static const registry<gdbarch>::key<struct bsd_uthread_ops> bsd_uthread_data;
 
-  ops = OBSTACK_ZALLOC (obstack, struct bsd_uthread_ops);
+static struct bsd_uthread_ops *
+get_bsd_uthread (struct gdbarch *gdbarch)
+{
+  struct bsd_uthread_ops *ops = bsd_uthread_data.get (gdbarch);
+  if (ops == nullptr)
+    ops = bsd_uthread_data.emplace (gdbarch);
   return ops;
 }
 
@@ -99,8 +99,7 @@ bsd_uthread_set_supply_uthread (struct gdbarch *gdbarch,
 				void (*supply_uthread) (struct regcache *,
 							int, CORE_ADDR))
 {
-  struct bsd_uthread_ops *ops
-    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
+  struct bsd_uthread_ops *ops = get_bsd_uthread (gdbarch);
 
   ops->supply_uthread = supply_uthread;
 }
@@ -113,8 +112,7 @@ bsd_uthread_set_collect_uthread (struct gdbarch *gdbarch,
 			 void (*collect_uthread) (const struct regcache *,
 						  int, CORE_ADDR))
 {
-  struct bsd_uthread_ops *ops
-    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
+  struct bsd_uthread_ops *ops = get_bsd_uthread (gdbarch);
 
   ops->collect_uthread = collect_uthread;
 }
@@ -196,8 +194,7 @@ static int
 bsd_uthread_activate (struct objfile *objfile)
 {
   struct gdbarch *gdbarch = target_gdbarch ();
-  struct bsd_uthread_ops *ops
-    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
+  struct bsd_uthread_ops *ops = get_bsd_uthread (gdbarch);
 
   /* Skip if the thread stratum has already been activated.  */
   if (bsd_uthread_active)
@@ -317,8 +314,7 @@ void
 bsd_uthread_target::fetch_registers (struct regcache *regcache, int regnum)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  struct bsd_uthread_ops *uthread_ops
-    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
+  struct bsd_uthread_ops *uthread_ops = get_bsd_uthread (gdbarch);
   ptid_t ptid = regcache->ptid ();
   CORE_ADDR addr = ptid.tid ();
   CORE_ADDR active_addr;
@@ -349,8 +345,7 @@ void
 bsd_uthread_target::store_registers (struct regcache *regcache, int regnum)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  struct bsd_uthread_ops *uthread_ops
-    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
+  struct bsd_uthread_ops *uthread_ops = get_bsd_uthread (gdbarch);
   ptid_t ptid = regcache->ptid ();
   CORE_ADDR addr = ptid.tid ();
   CORE_ADDR active_addr;
@@ -549,8 +544,6 @@ void _initialize_bsd_uthread ();
 void
 _initialize_bsd_uthread ()
 {
-  bsd_uthread_data = gdbarch_data_register_pre_init (bsd_uthread_init);
-
   gdb::observers::inferior_created.attach (bsd_uthread_inferior_created,
 					   "bsd-uthread");
   gdb::observers::solib_loaded.attach (bsd_uthread_solib_loaded,
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index ce6dc058412..d9591997c87 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -188,11 +188,10 @@ static d_language d_language_defn;
 
 /* Build all D language types for the specified architecture.  */
 
-static void *
+static struct builtin_d_type *
 build_d_types (struct gdbarch *gdbarch)
 {
-  struct builtin_d_type *builtin_d_type
-    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_d_type);
+  struct builtin_d_type *builtin_d_type = new struct builtin_d_type;
 
   /* Basic types.  */
   builtin_d_type->builtin_void
@@ -265,19 +264,19 @@ build_d_types (struct gdbarch *gdbarch)
   return builtin_d_type;
 }
 
-static struct gdbarch_data *d_type_data;
+static const registry<gdbarch>::key<struct builtin_d_type> d_type_data;
 
 /* Return the D type table for the specified architecture.  */
 
 const struct builtin_d_type *
 builtin_d_type (struct gdbarch *gdbarch)
 {
-  return (const struct builtin_d_type *) gdbarch_data (gdbarch, d_type_data);
-}
+  struct builtin_d_type *result = d_type_data.get (gdbarch);
+  if (result == nullptr)
+    {
+      result = build_d_types (gdbarch);
+      d_type_data.set (gdbarch, result);
+    }
 
-void _initialize_d_language ();
-void
-_initialize_d_language ()
-{
-  d_type_data = gdbarch_data_register_post_init (build_d_types);
+  return result;
 }
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
index 56e418d7255..967a9b4deb8 100644
--- a/gdb/d-lang.h
+++ b/gdb/d-lang.h
@@ -28,30 +28,30 @@
 
 struct builtin_d_type
 {
-  struct type *builtin_void;
-  struct type *builtin_bool;
-  struct type *builtin_byte;
-  struct type *builtin_ubyte;
-  struct type *builtin_short;
-  struct type *builtin_ushort;
-  struct type *builtin_int;
-  struct type *builtin_uint;
-  struct type *builtin_long;
-  struct type *builtin_ulong;
-  struct type *builtin_cent;
-  struct type *builtin_ucent;
-  struct type *builtin_float;
-  struct type *builtin_double;
-  struct type *builtin_real;
-  struct type *builtin_ifloat;
-  struct type *builtin_idouble;
-  struct type *builtin_ireal;
-  struct type *builtin_cfloat;
-  struct type *builtin_cdouble;
-  struct type *builtin_creal;
-  struct type *builtin_char;
-  struct type *builtin_wchar;
-  struct type *builtin_dchar;
+  struct type *builtin_void = nullptr;
+  struct type *builtin_bool = nullptr;
+  struct type *builtin_byte = nullptr;
+  struct type *builtin_ubyte = nullptr;
+  struct type *builtin_short = nullptr;
+  struct type *builtin_ushort = nullptr;
+  struct type *builtin_int = nullptr;
+  struct type *builtin_uint = nullptr;
+  struct type *builtin_long = nullptr;
+  struct type *builtin_ulong = nullptr;
+  struct type *builtin_cent = nullptr;
+  struct type *builtin_ucent = nullptr;
+  struct type *builtin_float = nullptr;
+  struct type *builtin_double = nullptr;
+  struct type *builtin_real = nullptr;
+  struct type *builtin_ifloat = nullptr;
+  struct type *builtin_idouble = nullptr;
+  struct type *builtin_ireal = nullptr;
+  struct type *builtin_cfloat = nullptr;
+  struct type *builtin_cdouble = nullptr;
+  struct type *builtin_creal = nullptr;
+  struct type *builtin_char = nullptr;
+  struct type *builtin_wchar = nullptr;
+  struct type *builtin_dchar = nullptr;
 };
 
 /* Defined in d-exp.y.  */
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index 99862583336..3549745df04 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -34,30 +34,17 @@
 #include "gdbarch.h"
 #include "objfiles.h"
 
-/* Cookie for gdbarch data.  */
-
-static struct gdbarch_data *dwarf_arch_cookie;
-
 /* This holds gdbarch-specific types used by the DWARF expression
    evaluator.  See comments in execute_stack_op.  */
 
 struct dwarf_gdbarch_types
 {
-  struct type *dw_types[3];
+  struct type *dw_types[3] {};
 };
 
-/* Allocate and fill in dwarf_gdbarch_types for an arch.  */
-
-static void *
-dwarf_gdbarch_types_init (struct gdbarch *gdbarch)
-{
-  struct dwarf_gdbarch_types *types
-    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct dwarf_gdbarch_types);
-
-  /* The types themselves are lazily initialized.  */
+/* Cookie for gdbarch data.  */
 
-  return types;
-}
+static const registry<gdbarch>::key<dwarf_gdbarch_types> dwarf_arch_cookie;
 
 /* Ensure that a FRAME is defined, throw an exception otherwise.  */
 
@@ -701,8 +688,9 @@ struct type *
 dwarf_expr_context::address_type () const
 {
   gdbarch *arch = this->m_per_objfile->objfile->arch ();
-  dwarf_gdbarch_types *types
-    = (dwarf_gdbarch_types *) gdbarch_data (arch, dwarf_arch_cookie);
+  dwarf_gdbarch_types *types = dwarf_arch_cookie.get (arch);
+  if (types == nullptr)
+    types = dwarf_arch_cookie.emplace (arch);
   int ndx;
 
   if (this->m_addr_size == 2)
@@ -2398,11 +2386,3 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
   this->m_recursion_depth--;
   gdb_assert (this->m_recursion_depth >= 0);
 }
-
-void _initialize_dwarf2expr ();
-void
-_initialize_dwarf2expr ()
-{
-  dwarf_arch_cookie
-    = gdbarch_data_register_post_init (dwarf_gdbarch_types_init);
-}
diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c
index 387a2bc7515..0e681f006cd 100644
--- a/gdb/dwarf2/frame.c
+++ b/gdb/dwarf2/frame.c
@@ -580,23 +580,39 @@ execute_cfa_program_test (struct gdbarch *gdbarch)
 
 /* Architecture-specific operations.  */
 
-/* Per-architecture data key.  */
-static struct gdbarch_data *dwarf2_frame_data;
+static void dwarf2_frame_default_init_reg (struct gdbarch *gdbarch,
+					   int regnum,
+					   struct dwarf2_frame_state_reg *reg,
+					   struct frame_info *this_frame);
 
 struct dwarf2_frame_ops
 {
   /* Pre-initialize the register state REG for register REGNUM.  */
   void (*init_reg) (struct gdbarch *, int, struct dwarf2_frame_state_reg *,
-		    struct frame_info *);
+		    struct frame_info *)
+    = dwarf2_frame_default_init_reg;
 
   /* Check whether the THIS_FRAME is a signal trampoline.  */
-  int (*signal_frame_p) (struct gdbarch *, struct frame_info *);
+  int (*signal_frame_p) (struct gdbarch *, struct frame_info *) = nullptr;
 
   /* Convert .eh_frame register number to DWARF register number, or
      adjust .debug_frame register number.  */
-  int (*adjust_regnum) (struct gdbarch *, int, int);
+  int (*adjust_regnum) (struct gdbarch *, int, int) = nullptr;
 };
 
+/* Per-architecture data key.  */
+static const registry<gdbarch>::key<dwarf2_frame_ops> dwarf2_frame_data;
+
+/* Get or initialize the frame ops.  */
+static dwarf2_frame_ops *
+get_frame_ops (struct gdbarch *gdbarch)
+{
+  dwarf2_frame_ops *result = dwarf2_frame_data.get (gdbarch);
+  if (result == nullptr)
+    result = dwarf2_frame_data.emplace (gdbarch);
+  return result;
+}
+
 /* Default architecture-specific register state initialization
    function.  */
 
@@ -637,18 +653,6 @@ dwarf2_frame_default_init_reg (struct gdbarch *gdbarch, int regnum,
     reg->how = DWARF2_FRAME_REG_CFA;
 }
 
-/* Return a default for the architecture-specific operations.  */
-
-static void *
-dwarf2_frame_init (struct obstack *obstack)
-{
-  struct dwarf2_frame_ops *ops;
-  
-  ops = OBSTACK_ZALLOC (obstack, struct dwarf2_frame_ops);
-  ops->init_reg = dwarf2_frame_default_init_reg;
-  return ops;
-}
-
 /* Set the architecture-specific register state initialization
    function for GDBARCH to INIT_REG.  */
 
@@ -658,8 +662,7 @@ dwarf2_frame_set_init_reg (struct gdbarch *gdbarch,
 					     struct dwarf2_frame_state_reg *,
 					     struct frame_info *))
 {
-  struct dwarf2_frame_ops *ops
-    = (struct dwarf2_frame_ops *) gdbarch_data (gdbarch, dwarf2_frame_data);
+  struct dwarf2_frame_ops *ops = get_frame_ops (gdbarch);
 
   ops->init_reg = init_reg;
 }
@@ -671,8 +674,7 @@ dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
 		       struct dwarf2_frame_state_reg *reg,
 		       struct frame_info *this_frame)
 {
-  struct dwarf2_frame_ops *ops
-    = (struct dwarf2_frame_ops *) gdbarch_data (gdbarch, dwarf2_frame_data);
+  struct dwarf2_frame_ops *ops = get_frame_ops (gdbarch);
 
   ops->init_reg (gdbarch, regnum, reg, this_frame);
 }
@@ -685,8 +687,7 @@ dwarf2_frame_set_signal_frame_p (struct gdbarch *gdbarch,
 				 int (*signal_frame_p) (struct gdbarch *,
 							struct frame_info *))
 {
-  struct dwarf2_frame_ops *ops
-    = (struct dwarf2_frame_ops *) gdbarch_data (gdbarch, dwarf2_frame_data);
+  struct dwarf2_frame_ops *ops = get_frame_ops (gdbarch);
 
   ops->signal_frame_p = signal_frame_p;
 }
@@ -698,8 +699,7 @@ static int
 dwarf2_frame_signal_frame_p (struct gdbarch *gdbarch,
 			     struct frame_info *this_frame)
 {
-  struct dwarf2_frame_ops *ops
-    = (struct dwarf2_frame_ops *) gdbarch_data (gdbarch, dwarf2_frame_data);
+  struct dwarf2_frame_ops *ops = get_frame_ops (gdbarch);
 
   if (ops->signal_frame_p == NULL)
     return 0;
@@ -714,8 +714,7 @@ dwarf2_frame_set_adjust_regnum (struct gdbarch *gdbarch,
 				int (*adjust_regnum) (struct gdbarch *,
 						      int, int))
 {
-  struct dwarf2_frame_ops *ops
-    = (struct dwarf2_frame_ops *) gdbarch_data (gdbarch, dwarf2_frame_data);
+  struct dwarf2_frame_ops *ops = get_frame_ops (gdbarch);
 
   ops->adjust_regnum = adjust_regnum;
 }
@@ -727,8 +726,7 @@ static int
 dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch,
 			    int regnum, int eh_frame_p)
 {
-  struct dwarf2_frame_ops *ops
-    = (struct dwarf2_frame_ops *) gdbarch_data (gdbarch, dwarf2_frame_data);
+  struct dwarf2_frame_ops *ops = get_frame_ops (gdbarch);
 
   if (ops->adjust_regnum == NULL)
     return regnum;
@@ -2201,8 +2199,6 @@ void _initialize_dwarf2_frame ();
 void
 _initialize_dwarf2_frame ()
 {
-  dwarf2_frame_data = gdbarch_data_register_pre_init (dwarf2_frame_init);
-
   add_setshow_boolean_cmd ("unwinders", class_obscure,
 			   &dwarf2_frame_unwinders_enabled_p , _("\
 Set whether the DWARF stack frame unwinders are used."), _("\
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 0f3de163c90..4b15950187e 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -1720,11 +1720,10 @@ f_language::get_symbol_name_matcher_inner
 
 static f_language f_language_defn;
 
-static void *
+static struct builtin_f_type *
 build_fortran_types (struct gdbarch *gdbarch)
 {
-  struct builtin_f_type *builtin_f_type
-    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_f_type);
+  struct builtin_f_type *builtin_f_type = new struct builtin_f_type;
 
   builtin_f_type->builtin_void
     = arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, "void");
@@ -1794,12 +1793,19 @@ build_fortran_types (struct gdbarch *gdbarch)
   return builtin_f_type;
 }
 
-static struct gdbarch_data *f_type_data;
+static const registry<gdbarch>::key<struct builtin_f_type> f_type_data;
 
 const struct builtin_f_type *
 builtin_f_type (struct gdbarch *gdbarch)
 {
-  return (const struct builtin_f_type *) gdbarch_data (gdbarch, f_type_data);
+  struct builtin_f_type *result = f_type_data.get (gdbarch);
+  if (result == nullptr)
+    {
+      result = build_fortran_types (gdbarch);
+      f_type_data.set (gdbarch, result);
+    }
+
+  return result;
 }
 
 /* Command-list for the "set/show fortran" prefix command.  */
@@ -1810,8 +1816,6 @@ void _initialize_f_language ();
 void
 _initialize_f_language ()
 {
-  f_type_data = gdbarch_data_register_post_init (build_fortran_types);
-
   add_setshow_prefix_cmd
     ("fortran", no_class,
      _("Prefix command for changing Fortran-specific settings."),
diff --git a/gdb/f-lang.h b/gdb/f-lang.h
index aebd45db94a..181f837f1db 100644
--- a/gdb/f-lang.h
+++ b/gdb/f-lang.h
@@ -317,22 +317,22 @@ extern int calc_f77_array_dims (struct type *);
 
 struct builtin_f_type
 {
-  struct type *builtin_character;
-  struct type *builtin_integer_s1;
-  struct type *builtin_integer_s2;
-  struct type *builtin_integer;
-  struct type *builtin_integer_s8;
-  struct type *builtin_logical_s1;
-  struct type *builtin_logical_s2;
-  struct type *builtin_logical;
-  struct type *builtin_logical_s8;
-  struct type *builtin_real;
-  struct type *builtin_real_s8;
-  struct type *builtin_real_s16;
-  struct type *builtin_complex;
-  struct type *builtin_complex_s8;
-  struct type *builtin_complex_s16;
-  struct type *builtin_void;
+  struct type *builtin_character = nullptr;
+  struct type *builtin_integer_s1 = nullptr;
+  struct type *builtin_integer_s2 = nullptr;
+  struct type *builtin_integer = nullptr;
+  struct type *builtin_integer_s8 = nullptr;
+  struct type *builtin_logical_s1 = nullptr;
+  struct type *builtin_logical_s2 = nullptr;
+  struct type *builtin_logical = nullptr;
+  struct type *builtin_logical_s8 = nullptr;
+  struct type *builtin_real = nullptr;
+  struct type *builtin_real_s8 = nullptr;
+  struct type *builtin_real_s16 = nullptr;
+  struct type *builtin_complex = nullptr;
+  struct type *builtin_complex_s8 = nullptr;
+  struct type *builtin_complex_s16 = nullptr;
+  struct type *builtin_void = nullptr;
 };
 
 /* Return the Fortran type table for the specified architecture.  */
diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
index f2f961b5486..3a2dbbe6f88 100644
--- a/gdb/fbsd-tdep.c
+++ b/gdb/fbsd-tdep.c
@@ -484,24 +484,21 @@ const struct kinfo_proc_layout kinfo_proc_layout_64 =
     .ru_majflt = 0x48,
   };
 
-static struct gdbarch_data *fbsd_gdbarch_data_handle;
-
 struct fbsd_gdbarch_data
   {
-    struct type *siginfo_type;
+    struct type *siginfo_type = nullptr;
   };
 
-static void *
-init_fbsd_gdbarch_data (struct gdbarch *gdbarch)
-{
-  return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct fbsd_gdbarch_data);
-}
+static const registry<gdbarch>::key<fbsd_gdbarch_data>
+     fbsd_gdbarch_data_handle;
 
 static struct fbsd_gdbarch_data *
 get_fbsd_gdbarch_data (struct gdbarch *gdbarch)
 {
-  return ((struct fbsd_gdbarch_data *)
-	  gdbarch_data (gdbarch, fbsd_gdbarch_data_handle));
+  struct fbsd_gdbarch_data *result = fbsd_gdbarch_data_handle.get (gdbarch);
+  if (result == nullptr)
+    result = fbsd_gdbarch_data_handle.emplace (gdbarch);
+  return result;
 }
 
 struct fbsd_pspace_data
@@ -2392,11 +2389,3 @@ fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_xml_syscall_file_name (gdbarch, "syscalls/freebsd.xml");
   set_gdbarch_get_syscall_number (gdbarch, fbsd_get_syscall_number);
 }
-
-void _initialize_fbsd_tdep ();
-void
-_initialize_fbsd_tdep ()
-{
-  fbsd_gdbarch_data_handle =
-    gdbarch_data_register_post_init (init_fbsd_gdbarch_data);
-}
diff --git a/gdb/frame-base.c b/gdb/frame-base.c
index 91af24b4f74..06c6af4b8c7 100644
--- a/gdb/frame-base.c
+++ b/gdb/frame-base.c
@@ -53,8 +53,6 @@ const struct frame_base default_frame_base = {
   default_frame_args_address
 };
 
-static struct gdbarch_data *frame_base_data;
-
 struct frame_base_table_entry
 {
   frame_base_sniffer_ftype *sniffer;
@@ -63,19 +61,19 @@ struct frame_base_table_entry
 
 struct frame_base_table
 {
-  struct frame_base_table_entry *head;
-  struct frame_base_table_entry **tail;
-  const struct frame_base *default_base;
+  struct frame_base_table_entry *head = nullptr;
+  struct frame_base_table_entry **tail = &head;
+  const struct frame_base *default_base = &default_frame_base;
 };
 
-static void *
-frame_base_init (struct obstack *obstack)
-{
-  struct frame_base_table *table
-    = OBSTACK_ZALLOC (obstack, struct frame_base_table);
+static const registry<gdbarch>::key<struct frame_base_table> frame_base_data;
 
-  table->tail = &table->head;
-  table->default_base = &default_frame_base;
+static struct frame_base_table *
+get_frame_base_table (struct gdbarch *gdbarch)
+{
+  struct frame_base_table *table = frame_base_data.get (gdbarch);
+  if (table == nullptr)
+    table = frame_base_data.emplace (gdbarch);
   return table;
 }
 
@@ -83,8 +81,7 @@ void
 frame_base_append_sniffer (struct gdbarch *gdbarch,
 			   frame_base_sniffer_ftype *sniffer)
 {
-  struct frame_base_table *table
-    = (struct frame_base_table *) gdbarch_data (gdbarch, frame_base_data);
+  struct frame_base_table *table = get_frame_base_table (gdbarch);
 
   (*table->tail)
     = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_base_table_entry);
@@ -96,8 +93,7 @@ void
 frame_base_set_default (struct gdbarch *gdbarch,
 			const struct frame_base *default_base)
 {
-  struct frame_base_table *table
-    = (struct frame_base_table *) gdbarch_data (gdbarch, frame_base_data);
+  struct frame_base_table *table = get_frame_base_table (gdbarch);
 
   table->default_base = default_base;
 }
@@ -106,8 +102,7 @@ const struct frame_base *
 frame_base_find_by_frame (struct frame_info *this_frame)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
-  struct frame_base_table *table
-    = (struct frame_base_table *) gdbarch_data (gdbarch, frame_base_data);
+  struct frame_base_table *table = get_frame_base_table (gdbarch);
   struct frame_base_table_entry *entry;
 
   for (entry = table->head; entry != NULL; entry = entry->next)
@@ -120,10 +115,3 @@ frame_base_find_by_frame (struct frame_info *this_frame)
     }
   return table->default_base;
 }
-
-void _initialize_frame_base ();
-void
-_initialize_frame_base ()
-{
-  frame_base_data = gdbarch_data_register_pre_init (frame_base_init);
-}
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index 302ce1efb99..78fc8dd4bcf 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -29,8 +29,6 @@
 #include "gdbarch.h"
 #include "dwarf2/frame-tailcall.h"
 
-static struct gdbarch_data *frame_unwind_data;
-
 struct frame_unwind_table_entry
 {
   const struct frame_unwind *unwinder;
@@ -39,11 +37,14 @@ struct frame_unwind_table_entry
 
 struct frame_unwind_table
 {
-  struct frame_unwind_table_entry *list;
+  struct frame_unwind_table_entry *list = nullptr;
   /* The head of the OSABI part of the search list.  */
-  struct frame_unwind_table_entry **osabi_head;
+  struct frame_unwind_table_entry **osabi_head = nullptr;
 };
 
+static const registry<gdbarch>::key<struct frame_unwind_table>
+     frame_unwind_data;
+
 /* A helper function to add an unwinder to a list.  LINK says where to
    install the new unwinder.  The new link is returned.  */
 
@@ -56,16 +57,20 @@ add_unwinder (struct obstack *obstack, const struct frame_unwind *unwinder,
   return &(*link)->next;
 }
 
-static void *
-frame_unwind_init (struct obstack *obstack)
+static struct frame_unwind_table *
+get_frame_unwind_table (struct gdbarch *gdbarch)
 {
-  struct frame_unwind_table *table
-    = OBSTACK_ZALLOC (obstack, struct frame_unwind_table);
+  struct frame_unwind_table *table = frame_unwind_data.get (gdbarch);
+  if (table != nullptr)
+    return table;
+
+  table = new frame_unwind_table;
 
   /* Start the table out with a few default sniffers.  OSABI code
      can't override this.  */
   struct frame_unwind_table_entry **link = &table->list;
 
+  struct obstack *obstack = gdbarch_obstack (gdbarch);
   link = add_unwinder (obstack, &dummy_frame_unwind, link);
   /* The DWARF tailcall sniffer must come before the inline sniffer.
      Otherwise, we can end up in a situation where a DWARF frame finds
@@ -79,6 +84,8 @@ frame_unwind_init (struct obstack *obstack)
 
   /* The insertion point for OSABI sniffers.  */
   table->osabi_head = link;
+  frame_unwind_data.set (gdbarch, table);
+
   return table;
 }
 
@@ -86,8 +93,7 @@ void
 frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
 				const struct frame_unwind *unwinder)
 {
-  struct frame_unwind_table *table
-    = (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data);
+  struct frame_unwind_table *table = get_frame_unwind_table (gdbarch);
   struct frame_unwind_table_entry *entry;
 
   /* Insert the new entry at the start of the list.  */
@@ -101,8 +107,7 @@ void
 frame_unwind_append_unwinder (struct gdbarch *gdbarch,
 			      const struct frame_unwind *unwinder)
 {
-  struct frame_unwind_table *table
-    = (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data);
+  struct frame_unwind_table *table = get_frame_unwind_table (gdbarch);
   struct frame_unwind_table_entry **ip;
 
   /* Find the end of the list and insert the new entry there.  */
@@ -182,8 +187,7 @@ frame_unwind_find_by_frame (struct frame_info *this_frame, void **this_cache)
   frame_debug_printf ("this_frame=%d", frame_relative_level (this_frame));
 
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
-  struct frame_unwind_table *table
-    = (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data);
+  struct frame_unwind_table *table = get_frame_unwind_table (gdbarch);
   struct frame_unwind_table_entry *entry;
   const struct frame_unwind *unwinder_from_target;
 
@@ -333,10 +337,3 @@ frame_unwind_got_address (struct frame_info *frame, int regnum,
 	     register_type (gdbarch, regnum), addr);
   return reg_val;
 }
-
-void _initialize_frame_unwind ();
-void
-_initialize_frame_unwind ()
-{
-  frame_unwind_data = gdbarch_data_register_pre_init (frame_unwind_init);
-}
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 15897172f10..0edae7f6f0a 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -34,6 +34,8 @@ struct gdbarch
 
   /* An obstack bound to the lifetime of the architecture.  */
   auto_obstack obstack;
+  /* Registry.  */
+  registry<gdbarch> registry_fields;
 
   /* basic architectural information.  */
   const struct bfd_arch_info * bfd_arch_info;
@@ -264,8 +266,6 @@ gdbarch_alloc (const struct gdbarch_info *info,
 
   gdbarch = new struct gdbarch;
 
-  alloc_gdbarch_data (gdbarch);
-
   gdbarch->tdep = tdep;
 
   gdbarch->bfd_arch_info = info->bfd_arch_info;
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 324958469a7..2c431a34735 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -29,6 +29,7 @@
 #include "osabi.h"
 #include "displaced-stepping.h"
 #include "gdbsupport/gdb-checked-static-cast.h"
+#include "registry.h"
 
 struct floatformat;
 struct ui_file;
@@ -351,32 +352,13 @@ extern struct gdbarch *gdbarch_find_by_info (struct gdbarch_info info);
 extern void set_target_gdbarch (struct gdbarch *gdbarch);
 
 
-/* Register per-architecture data-pointer.
-
-   Reserve space for a per-architecture data-pointer.  An identifier
-   for the reserved data-pointer is returned.  That identifer should
-   be saved in a local static variable.
-
-   Memory for the per-architecture data shall be allocated using
-   gdbarch_obstack_zalloc.  That memory will be deleted when the
-   corresponding architecture object is deleted.
-
-   When a previously created architecture is re-selected, the
-   per-architecture data-pointer for that previous architecture is
-   restored.  INIT() is not re-called.
-
-   Multiple registrarants for any architecture are allowed (and
-   strongly encouraged).  */
-
-struct gdbarch_data;
-
-typedef void *(gdbarch_data_pre_init_ftype) (struct obstack *obstack);
-extern struct gdbarch_data *gdbarch_data_register_pre_init (gdbarch_data_pre_init_ftype *init);
-typedef void *(gdbarch_data_post_init_ftype) (struct gdbarch *gdbarch);
-extern struct gdbarch_data *gdbarch_data_register_post_init (gdbarch_data_post_init_ftype *init);
-
-extern void *gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *);
-
+/* A registry adaptor for gdbarch.  This arranges to store the
+   registry in the gdbarch.  */
+template<>
+struct registry_accessor<gdbarch>
+{
+  static registry<gdbarch> *get (gdbarch *arch);
+};
 
 /* Set the dynamic target-system-dependent parameters (architecture,
    byte-order, ...) using information found in the BFD.  */
diff --git a/gdb/gdbarch.py b/gdb/gdbarch.py
index 5a261ba572b..696b3028e6f 100755
--- a/gdb/gdbarch.py
+++ b/gdb/gdbarch.py
@@ -261,6 +261,8 @@ with open("gdbarch.c", "w") as f:
     print(file=f)
     print("  /* An obstack bound to the lifetime of the architecture.  */", file=f)
     print("  auto_obstack obstack;", file=f)
+    print("  /* Registry.  */", file=f)
+    print("  registry<gdbarch> registry_fields;", file=f)
     print(file=f)
     print("  /* basic architectural information.  */", file=f)
     for c in filter(info, components):
@@ -296,8 +298,6 @@ with open("gdbarch.c", "w") as f:
     print("", file=f)
     print("  gdbarch = new struct gdbarch;", file=f)
     print(file=f)
-    print("  alloc_gdbarch_data (gdbarch);", file=f)
-    print(file=f)
     print("  gdbarch->tdep = tdep;", file=f)
     print(file=f)
     for c in filter(info, components):
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 8ab0a898ba6..8c2558dd7ac 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -6147,19 +6147,12 @@ type::fixed_point_scaling_factor ()
 
 \f
 
-static struct gdbarch_data *gdbtypes_data;
+static const registry<gdbarch>::key<struct builtin_type> gdbtypes_data;
 
-const struct builtin_type *
-builtin_type (struct gdbarch *gdbarch)
+static struct builtin_type *
+create_gdbtypes_data (struct gdbarch *gdbarch)
 {
-  return (const struct builtin_type *) gdbarch_data (gdbarch, gdbtypes_data);
-}
-
-static void *
-gdbtypes_post_init (struct gdbarch *gdbarch)
-{
-  struct builtin_type *builtin_type
-    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_type);
+  struct builtin_type *builtin_type = new struct builtin_type;
 
   /* Basic types.  */
   builtin_type->builtin_void
@@ -6302,6 +6295,18 @@ gdbtypes_post_init (struct gdbarch *gdbarch)
   return builtin_type;
 }
 
+const struct builtin_type *
+builtin_type (struct gdbarch *gdbarch)
+{
+  struct builtin_type *result = gdbtypes_data.get (gdbarch);
+  if (result == nullptr)
+    {
+      result = create_gdbtypes_data (gdbarch);
+      gdbtypes_data.set (gdbarch, result);
+    }
+  return result;
+}
+
 /* This set of objfile-based types is intended to be used by symbol
    readers as basic types.  */
 
@@ -6439,8 +6444,6 @@ void _initialize_gdbtypes ();
 void
 _initialize_gdbtypes ()
 {
-  gdbtypes_data = gdbarch_data_register_post_init (gdbtypes_post_init);
-
   add_setshow_zuinteger_cmd ("overload", no_class, &overload_debug,
 			     _("Set debugging of C++ overloading."),
 			     _("Show debugging of C++ overloading."),
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index cb989228222..8ffcafc6a29 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -2310,65 +2310,65 @@ struct builtin_type
   /* Integral types.  */
 
   /* Implicit size/sign (based on the architecture's ABI).  */
-  struct type *builtin_void;
-  struct type *builtin_char;
-  struct type *builtin_short;
-  struct type *builtin_int;
-  struct type *builtin_long;
-  struct type *builtin_signed_char;
-  struct type *builtin_unsigned_char;
-  struct type *builtin_unsigned_short;
-  struct type *builtin_unsigned_int;
-  struct type *builtin_unsigned_long;
-  struct type *builtin_bfloat16;
-  struct type *builtin_half;
-  struct type *builtin_float;
-  struct type *builtin_double;
-  struct type *builtin_long_double;
-  struct type *builtin_complex;
-  struct type *builtin_double_complex;
-  struct type *builtin_string;
-  struct type *builtin_bool;
-  struct type *builtin_long_long;
-  struct type *builtin_unsigned_long_long;
-  struct type *builtin_decfloat;
-  struct type *builtin_decdouble;
-  struct type *builtin_declong;
+  struct type *builtin_void = nullptr;
+  struct type *builtin_char = nullptr;
+  struct type *builtin_short = nullptr;
+  struct type *builtin_int = nullptr;
+  struct type *builtin_long = nullptr;
+  struct type *builtin_signed_char = nullptr;
+  struct type *builtin_unsigned_char = nullptr;
+  struct type *builtin_unsigned_short = nullptr;
+  struct type *builtin_unsigned_int = nullptr;
+  struct type *builtin_unsigned_long = nullptr;
+  struct type *builtin_bfloat16 = nullptr;
+  struct type *builtin_half = nullptr;
+  struct type *builtin_float = nullptr;
+  struct type *builtin_double = nullptr;
+  struct type *builtin_long_double = nullptr;
+  struct type *builtin_complex = nullptr;
+  struct type *builtin_double_complex = nullptr;
+  struct type *builtin_string = nullptr;
+  struct type *builtin_bool = nullptr;
+  struct type *builtin_long_long = nullptr;
+  struct type *builtin_unsigned_long_long = nullptr;
+  struct type *builtin_decfloat = nullptr;
+  struct type *builtin_decdouble = nullptr;
+  struct type *builtin_declong = nullptr;
 
   /* "True" character types.
       We use these for the '/c' print format, because c_char is just a
       one-byte integral type, which languages less laid back than C
       will print as ... well, a one-byte integral type.  */
-  struct type *builtin_true_char;
-  struct type *builtin_true_unsigned_char;
+  struct type *builtin_true_char = nullptr;
+  struct type *builtin_true_unsigned_char = nullptr;
 
   /* Explicit sizes - see C9X <intypes.h> for naming scheme.  The "int0"
      is for when an architecture needs to describe a register that has
      no size.  */
-  struct type *builtin_int0;
-  struct type *builtin_int8;
-  struct type *builtin_uint8;
-  struct type *builtin_int16;
-  struct type *builtin_uint16;
-  struct type *builtin_int24;
-  struct type *builtin_uint24;
-  struct type *builtin_int32;
-  struct type *builtin_uint32;
-  struct type *builtin_int64;
-  struct type *builtin_uint64;
-  struct type *builtin_int128;
-  struct type *builtin_uint128;
+  struct type *builtin_int0 = nullptr;
+  struct type *builtin_int8 = nullptr;
+  struct type *builtin_uint8 = nullptr;
+  struct type *builtin_int16 = nullptr;
+  struct type *builtin_uint16 = nullptr;
+  struct type *builtin_int24 = nullptr;
+  struct type *builtin_uint24 = nullptr;
+  struct type *builtin_int32 = nullptr;
+  struct type *builtin_uint32 = nullptr;
+  struct type *builtin_int64 = nullptr;
+  struct type *builtin_uint64 = nullptr;
+  struct type *builtin_int128 = nullptr;
+  struct type *builtin_uint128 = nullptr;
 
   /* Wide character types.  */
-  struct type *builtin_char16;
-  struct type *builtin_char32;
-  struct type *builtin_wchar;
+  struct type *builtin_char16 = nullptr;
+  struct type *builtin_char32 = nullptr;
+  struct type *builtin_wchar = nullptr;
 
   /* Pointer types.  */
 
   /* * `pointer to data' type.  Some target platforms use an implicitly
      {sign,zero} -extended 32-bit ABI pointer on a 64-bit ISA.  */
-  struct type *builtin_data_ptr;
+  struct type *builtin_data_ptr = nullptr;
 
   /* * `pointer to function (returning void)' type.  Harvard
      architectures mean that ABI function and code pointers are not
@@ -2379,21 +2379,21 @@ struct builtin_type
      However, all function pointer types are interconvertible, so void
      (*) () can server as a generic function pointer.  */
 
-  struct type *builtin_func_ptr;
+  struct type *builtin_func_ptr = nullptr;
 
   /* * `function returning pointer to function (returning void)' type.
      The final void return type is not significant for it.  */
 
-  struct type *builtin_func_func;
+  struct type *builtin_func_func = nullptr;
 
   /* Special-purpose types.  */
 
   /* * This type is used to represent a GDB internal function.  */
 
-  struct type *internal_fn;
+  struct type *internal_fn = nullptr;
 
   /* * This type is used to represent an xmethod.  */
-  struct type *xmethod;
+  struct type *xmethod = nullptr;
 };
 
 /* * Return the type table for the specified architecture.  */
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index 953645e7411..61666f2353c 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -38,7 +38,7 @@ static struct cp_abi_ops gnu_v3_abi_ops;
 /* A gdbarch key for std::type_info, in the event that it can't be
    found in the debug info.  */
 
-static struct gdbarch_data *std_type_info_gdbarch_data;
+static const registry<gdbarch>::key<struct type> std_type_info_gdbarch_data;
 
 
 static int
@@ -91,7 +91,7 @@ gnuv3_is_operator_name (const char *name)
    vtable_type_gdbarch_data is a gdbarch per-architecture data pointer
    which refers to the struct type * for this structure, laid out
    appropriately for the architecture.  */
-static struct gdbarch_data *vtable_type_gdbarch_data;
+static const registry<gdbarch>::key<struct type> vtable_type_gdbarch_data;
 
 
 /* Human-readable names for the numbers of the fields above.  */
@@ -108,13 +108,17 @@ enum {
 
    We use this function as the gdbarch per-architecture data
    initialization function.  */
-static void *
-build_gdb_vtable_type (struct gdbarch *arch)
+static struct type *
+get_gdb_vtable_type (struct gdbarch *arch)
 {
   struct type *t;
   struct field *field_list, *field;
   int offset;
 
+  struct type *result = vtable_type_gdbarch_data.get (arch);
+  if (result != nullptr)
+    return result;
+
   struct type *void_ptr_type
     = builtin_type (arch)->builtin_data_ptr;
   struct type *ptr_to_void_fn_type
@@ -171,7 +175,9 @@ build_gdb_vtable_type (struct gdbarch *arch)
   t->set_name ("gdb_gnu_v3_abi_vtable");
   INIT_CPLUS_SPECIFIC (t);
 
-  return make_type_with_address_space (t, TYPE_INSTANCE_FLAG_CODE_SPACE);
+  result = make_type_with_address_space (t, TYPE_INSTANCE_FLAG_CODE_SPACE);
+  vtable_type_gdbarch_data.set (arch, result);
+  return result;
 }
 
 
@@ -179,8 +185,7 @@ build_gdb_vtable_type (struct gdbarch *arch)
 static struct type *
 vtable_ptrdiff_type (struct gdbarch *gdbarch)
 {
-  struct type *vtable_type
-    = (struct type *) gdbarch_data (gdbarch, vtable_type_gdbarch_data);
+  struct type *vtable_type = get_gdb_vtable_type (gdbarch);
 
   /* The "offset_to_top" field has the appropriate (ptrdiff_t) type.  */
   return vtable_type->field (vtable_field_offset_to_top).type ();
@@ -192,8 +197,7 @@ vtable_ptrdiff_type (struct gdbarch *gdbarch)
 static int
 vtable_address_point_offset (struct gdbarch *gdbarch)
 {
-  struct type *vtable_type
-    = (struct type *) gdbarch_data (gdbarch, vtable_type_gdbarch_data);
+  struct type *vtable_type = get_gdb_vtable_type (gdbarch);
 
   return (vtable_type->field (vtable_field_virtual_functions).loc_bitpos ()
 	  / TARGET_CHAR_BIT);
@@ -253,8 +257,7 @@ static struct value *
 gnuv3_get_vtable (struct gdbarch *gdbarch,
 		  struct type *container_type, CORE_ADDR container_addr)
 {
-  struct type *vtable_type
-    = (struct type *) gdbarch_data (gdbarch, vtable_type_gdbarch_data);
+  struct type *vtable_type = get_gdb_vtable_type (gdbarch);
   struct type *vtable_pointer_type;
   struct value *vtable_pointer;
   CORE_ADDR vtable_address;
@@ -1016,7 +1019,7 @@ gnuv3_print_vtable (struct value *value)
    We use this function as the gdbarch per-architecture data
    initialization function.  */
 
-static void *
+static struct type *
 build_std_type_info_type (struct gdbarch *arch)
 {
   struct type *t;
@@ -1069,8 +1072,14 @@ gnuv3_get_typeid_type (struct gdbarch *gdbarch)
   typeinfo = lookup_symbol ("std::type_info", NULL, STRUCT_DOMAIN,
 			    NULL).symbol;
   if (typeinfo == NULL)
-    typeinfo_type
-      = (struct type *) gdbarch_data (gdbarch, std_type_info_gdbarch_data);
+    {
+      typeinfo_type = std_type_info_gdbarch_data.get (gdbarch);
+      if (typeinfo_type == nullptr)
+	{
+	  typeinfo_type = build_std_type_info_type (gdbarch);
+	  std_type_info_gdbarch_data.set (gdbarch, typeinfo_type);
+	}
+    }
   else
     typeinfo_type = typeinfo->type ();
 
@@ -1560,11 +1569,6 @@ gnuv3_pass_by_reference (struct type *type)
 static void
 init_gnuv3_ops (void)
 {
-  vtable_type_gdbarch_data
-    = gdbarch_data_register_post_init (build_gdb_vtable_type);
-  std_type_info_gdbarch_data
-    = gdbarch_data_register_post_init (build_std_type_info_type);
-
   gnu_v3_abi_ops.shortname = "gnu-v3";
   gnu_v3_abi_ops.longname = "GNU G++ Version 3 ABI";
   gnu_v3_abi_ops.doc = "G++ Version 3 ABI";
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 844f743e83d..c56db238525 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -481,11 +481,10 @@ go_language::language_arch_info (struct gdbarch *gdbarch,
 
 static go_language go_language_defn;
 
-static void *
+static struct builtin_go_type *
 build_go_types (struct gdbarch *gdbarch)
 {
-  struct builtin_go_type *builtin_go_type
-    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_go_type);
+  struct builtin_go_type *builtin_go_type = new struct builtin_go_type;
 
   builtin_go_type->builtin_void
     = arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, "void");
@@ -527,17 +526,17 @@ build_go_types (struct gdbarch *gdbarch)
   return builtin_go_type;
 }
 
-static struct gdbarch_data *go_type_data;
+static const registry<gdbarch>::key<struct builtin_go_type> go_type_data;
 
 const struct builtin_go_type *
 builtin_go_type (struct gdbarch *gdbarch)
 {
-  return (const struct builtin_go_type *) gdbarch_data (gdbarch, go_type_data);
-}
+  struct builtin_go_type *result = go_type_data.get (gdbarch);
+  if (result == nullptr)
+    {
+      result = build_go_types (gdbarch);
+      go_type_data.set (gdbarch, result);
+    }
 
-void _initialize_go_language ();
-void
-_initialize_go_language ()
-{
-  go_type_data = gdbarch_data_register_post_init (build_go_types);
+  return result;
 }
diff --git a/gdb/go-lang.h b/gdb/go-lang.h
index fb57dd7dacc..523501bba4c 100644
--- a/gdb/go-lang.h
+++ b/gdb/go-lang.h
@@ -30,24 +30,24 @@ struct parser_state;
 
 struct builtin_go_type
 {
-  struct type *builtin_void;
-  struct type *builtin_char;
-  struct type *builtin_bool;
-  struct type *builtin_int;
-  struct type *builtin_uint;
-  struct type *builtin_uintptr;
-  struct type *builtin_int8;
-  struct type *builtin_int16;
-  struct type *builtin_int32;
-  struct type *builtin_int64;
-  struct type *builtin_uint8;
-  struct type *builtin_uint16;
-  struct type *builtin_uint32;
-  struct type *builtin_uint64;
-  struct type *builtin_float32;
-  struct type *builtin_float64;
-  struct type *builtin_complex64;
-  struct type *builtin_complex128;
+  struct type *builtin_void = nullptr;
+  struct type *builtin_char = nullptr;
+  struct type *builtin_bool = nullptr;
+  struct type *builtin_int = nullptr;
+  struct type *builtin_uint = nullptr;
+  struct type *builtin_uintptr = nullptr;
+  struct type *builtin_int8 = nullptr;
+  struct type *builtin_int16 = nullptr;
+  struct type *builtin_int32 = nullptr;
+  struct type *builtin_int64 = nullptr;
+  struct type *builtin_uint8 = nullptr;
+  struct type *builtin_uint16 = nullptr;
+  struct type *builtin_uint32 = nullptr;
+  struct type *builtin_uint64 = nullptr;
+  struct type *builtin_float32 = nullptr;
+  struct type *builtin_float64 = nullptr;
+  struct type *builtin_complex64 = nullptr;
+  struct type *builtin_complex128 = nullptr;
 };
 
 enum go_type
diff --git a/gdb/guile/scm-arch.c b/gdb/guile/scm-arch.c
index 529043a0084..4c636aa2d5a 100644
--- a/gdb/guile/scm-arch.c
+++ b/gdb/guile/scm-arch.c
@@ -41,7 +41,10 @@ static const char arch_smob_name[] = "gdb:arch";
 /* The tag Guile knows the arch smob by.  */
 static scm_t_bits arch_smob_tag;
 
-static struct gdbarch_data *arch_object_data = NULL;
+/* Use a 'void *' here because it isn't guaranteed that SCM is a
+   pointer.  */
+static const registry<gdbarch>::key<void, gdb::noop_deleter<void>>
+     arch_object_data;
 
 static int arscm_is_arch (SCM);
 \f
@@ -105,30 +108,28 @@ gdbscm_arch_p (SCM scm)
   return scm_from_bool (arscm_is_arch (scm));
 }
 
-/* Associates an arch_object with GDBARCH as gdbarch_data via the gdbarch
-   post init registration mechanism (gdbarch_data_register_post_init).  */
-
-static void *
-arscm_object_data_init (struct gdbarch *gdbarch)
-{
-  SCM arch_scm = arscm_make_arch_smob (gdbarch);
-
-  /* This object lasts the duration of the GDB session, so there is no
-     call to scm_gc_unprotect_object for it.  */
-  scm_gc_protect_object (arch_scm);
-
-  return (void *) arch_scm;
-}
-
 /* Return the <gdb:arch> object corresponding to GDBARCH.
    The object is cached in GDBARCH so this is simple.  */
 
 SCM
 arscm_scm_from_arch (struct gdbarch *gdbarch)
 {
-  SCM a_scm = (SCM) gdbarch_data (gdbarch, arch_object_data);
+  SCM arch_scm;
+  void *data = arch_object_data.get (gdbarch);
+  if (data == nullptr)
+    {
+      arch_scm = arscm_make_arch_smob (gdbarch);
 
-  return a_scm;
+      /* This object lasts the duration of the GDB session, so there
+	 is no call to scm_gc_unprotect_object for it.  */
+      scm_gc_protect_object (arch_scm);
+
+      arch_object_data.set (gdbarch, (void *) arch_scm);
+    }
+  else
+    arch_scm = (SCM) data;
+
+  return arch_scm;
 }
 
 /* Return the <gdb:arch> smob in SELF.
@@ -651,11 +652,3 @@ gdbscm_initialize_arches (void)
 
   gdbscm_define_functions (arch_functions, 1);
 }
-
-void _initialize_scm_arch ();
-void
-_initialize_scm_arch ()
-{
-  arch_object_data
-    = gdbarch_data_register_post_init (arscm_object_data_init);
-}
diff --git a/gdb/guile/scm-symbol.c b/gdb/guile/scm-symbol.c
index 78917bdbed0..4344a633334 100644
--- a/gdb/guile/scm-symbol.c
+++ b/gdb/guile/scm-symbol.c
@@ -78,13 +78,14 @@ struct syscm_deleter
 
 static const registry<objfile>::key<htab, syscm_deleter>
      syscm_objfile_data_key;
-static struct gdbarch_data *syscm_gdbarch_data_key;
 
 struct syscm_gdbarch_data
 {
   /* Hash table to implement eqable gdbarch symbols.  */
   htab_t htab;
 };
+
+static const registry<gdbarch>::key<syscm_gdbarch_data> syscm_gdbarch_data_key;
 \f
 /* Administrivia for symbol smobs.  */
 
@@ -110,17 +111,6 @@ syscm_eq_symbol_smob (const void *ap, const void *bp)
 	  && a->symbol != NULL);
 }
 
-static void *
-syscm_init_arch_symbols (struct gdbarch *gdbarch)
-{
-  struct syscm_gdbarch_data *data
-    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct syscm_gdbarch_data);
-
-  data->htab = gdbscm_create_eqable_gsmob_ptr_map (syscm_hash_symbol_smob,
-						   syscm_eq_symbol_smob);
-  return data;
-}
-
 /* Return the struct symbol pointer -> SCM mapping table.
    It is created if necessary.  */
 
@@ -144,9 +134,14 @@ syscm_get_symbol_map (struct symbol *symbol)
   else
     {
       struct gdbarch *gdbarch = symbol->arch ();
-      struct syscm_gdbarch_data *data
-	= (struct syscm_gdbarch_data *) gdbarch_data (gdbarch,
-						      syscm_gdbarch_data_key);
+      struct syscm_gdbarch_data *data = syscm_gdbarch_data_key.get (gdbarch);
+      if (data == nullptr)
+	{
+	  data = syscm_gdbarch_data_key.emplace (gdbarch);
+	  data->htab
+	    = gdbscm_create_eqable_gsmob_ptr_map (syscm_hash_symbol_smob,
+						  syscm_eq_symbol_smob);
+	}
 
       htab = data->htab;
     }
@@ -817,12 +812,3 @@ gdbscm_initialize_symbols (void)
   domain_keyword = scm_from_latin1_keyword ("domain");
   frame_keyword = scm_from_latin1_keyword ("frame");
 }
-
-void _initialize_scm_symbol ();
-void
-_initialize_scm_symbol ()
-{
-  /* Arch-specific symbol data.  */
-  syscm_gdbarch_data_key
-    = gdbarch_data_register_post_init (syscm_init_arch_symbols);
-}
diff --git a/gdb/ia64-libunwind-tdep.c b/gdb/ia64-libunwind-tdep.c
index a2a236a4667..4c788f20956 100644
--- a/gdb/ia64-libunwind-tdep.c
+++ b/gdb/ia64-libunwind-tdep.c
@@ -56,7 +56,7 @@
 #endif
 
 static int libunwind_initialized;
-static struct gdbarch_data *libunwind_descr_handle;
+static const registry<gdbarch>::key<libunwind_descr> libunwind_descr_handle;
 
 /* Required function pointers from libunwind.  */
 typedef int (unw_get_reg_p_ftype) (unw_cursor_t *, unw_regnum_t, unw_word_t *);
@@ -127,17 +127,10 @@ static const char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
 static struct libunwind_descr *
 libunwind_descr (struct gdbarch *gdbarch)
 {
-  return ((struct libunwind_descr *)
-	  gdbarch_data (gdbarch, libunwind_descr_handle));
-}
-
-static void *
-libunwind_descr_init (struct obstack *obstack)
-{
-  struct libunwind_descr *descr
-    = OBSTACK_ZALLOC (obstack, struct libunwind_descr);
-
-  return descr;
+  struct libunwind_descr *result = libunwind_descr_handle.get (gdbarch);
+  if (result == nullptr)
+    result = libunwind_descr_handle.emplace (gdbarch);
+  return result;
 }
 
 void
@@ -148,8 +141,7 @@ libunwind_frame_set_descr (struct gdbarch *gdbarch,
 
   gdb_assert (gdbarch != NULL);
 
-  arch_descr = ((struct libunwind_descr *)
-		gdbarch_data (gdbarch, libunwind_descr_handle));
+  arch_descr = libunwind_descr (gdbarch);
   gdb_assert (arch_descr != NULL);
 
   /* Copy new descriptor info into arch descriptor.  */
@@ -587,8 +579,5 @@ void _initialize_libunwind_frame ();
 void
 _initialize_libunwind_frame ()
 {
-  libunwind_descr_handle
-    = gdbarch_data_register_pre_init (libunwind_descr_init);
-
   libunwind_initialized = libunwind_load ();
 }
diff --git a/gdb/ia64-libunwind-tdep.h b/gdb/ia64-libunwind-tdep.h
index 2484ea81de3..56425d0d754 100644
--- a/gdb/ia64-libunwind-tdep.h
+++ b/gdb/ia64-libunwind-tdep.h
@@ -40,11 +40,11 @@ struct frame_unwind;
 
 struct libunwind_descr
 {
-  int (*gdb2uw) (int);
-  int (*uw2gdb) (int);
-  int (*is_fpreg) (int);
-  void *accessors;
-  void *special_accessors;
+  int (*gdb2uw) (int) = nullptr;
+  int (*uw2gdb) (int) = nullptr;
+  int (*is_fpreg) (int) = nullptr;
+  void *accessors = nullptr;
+  void *special_accessors = nullptr;
 };
 
 int libunwind_frame_sniffer (const struct frame_unwind *self,
diff --git a/gdb/jit.c b/gdb/jit.c
index 167ea8cad81..6d8acc40225 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -52,12 +52,6 @@ static const char jit_descriptor_name[] = "__jit_debug_descriptor";
 static void jit_inferior_created_hook (inferior *inf);
 static void jit_inferior_exit_hook (struct inferior *inf);
 
-/* An unwinder is registered for every gdbarch.  This key is used to
-   remember if the unwinder has been registered for a particular
-   gdbarch.  */
-
-static struct gdbarch_data *jit_gdbarch_data;
-
 /* True if we want to see trace of jit level stuff.  */
 
 static bool jit_debug = false;
@@ -1127,19 +1121,25 @@ static const struct frame_unwind jit_frame_unwind =
 
 struct jit_gdbarch_data_type
 {
-  /* Has the (pseudo) unwinder been prepended? */
-  int unwinder_registered;
+  /* Has the (pseudo) unwinder been pretended? */
+  int unwinder_registered = 0;
 };
 
+/* An unwinder is registered for every gdbarch.  This key is used to
+   remember if the unwinder has been registered for a particular
+   gdbarch.  */
+
+static const registry<gdbarch>::key<jit_gdbarch_data_type> jit_gdbarch_data;
+
 /* Check GDBARCH and prepend the pseudo JIT unwinder if needed.  */
 
 static void
 jit_prepend_unwinder (struct gdbarch *gdbarch)
 {
-  struct jit_gdbarch_data_type *data;
+  struct jit_gdbarch_data_type *data = jit_gdbarch_data.get (gdbarch);
+  if (data == nullptr)
+    data = jit_gdbarch_data.emplace (gdbarch);
 
-  data
-    = (struct jit_gdbarch_data_type *) gdbarch_data (gdbarch, jit_gdbarch_data);
   if (!data->unwinder_registered)
     {
       frame_unwind_prepend_unwinder (gdbarch, &jit_frame_unwind);
@@ -1285,20 +1285,6 @@ jit_event_handler (gdbarch *gdbarch, objfile *jiter)
     }
 }
 
-/* Initialize the jit_gdbarch_data slot with an instance of struct
-   jit_gdbarch_data_type */
-
-static void *
-jit_gdbarch_data_init (struct obstack *obstack)
-{
-  struct jit_gdbarch_data_type *data =
-    XOBNEW (obstack, struct jit_gdbarch_data_type);
-
-  data->unwinder_registered = 0;
-
-  return data;
-}
-
 void _initialize_jit ();
 void
 _initialize_jit ()
@@ -1322,7 +1308,6 @@ _initialize_jit ()
   gdb::observers::inferior_exit.attach (jit_inferior_exit_hook, "jit");
   gdb::observers::breakpoint_deleted.attach (jit_breakpoint_deleted, "jit");
 
-  jit_gdbarch_data = gdbarch_data_register_pre_init (jit_gdbarch_data_init);
   if (is_dl_available ())
     {
       struct cmd_list_element *c;
diff --git a/gdb/language.c b/gdb/language.c
index af58a374dd6..c185a009a72 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -918,24 +918,28 @@ static unknown_language unknown_language_defn;
 \f
 /* Per-architecture language information.  */
 
-static struct gdbarch_data *language_gdbarch_data;
-
 struct language_gdbarch
 {
   /* A vector of per-language per-architecture info.  Indexed by "enum
      language".  */
-  struct language_arch_info arch_info[nr_languages];
+  struct language_arch_info arch_info[nr_languages] {};
 };
 
-static void *
-language_gdbarch_post_init (struct gdbarch *gdbarch)
+static const registry<gdbarch>::key<language_gdbarch> language_gdbarch_data;
+
+static language_gdbarch *
+get_language_gdbarch (struct gdbarch *gdbarch)
 {
-  struct language_gdbarch *l
-    = obstack_new<struct language_gdbarch> (gdbarch_obstack (gdbarch));
-  for (const auto &lang : language_defn::languages)
+  struct language_gdbarch *l = language_gdbarch_data.get (gdbarch);
+  if (l == nullptr)
     {
-      gdb_assert (lang != nullptr);
-      lang->language_arch_info (gdbarch, &l->arch_info[lang->la_language]);
+      l = new struct language_gdbarch;
+      for (const auto &lang : language_defn::languages)
+	{
+	  gdb_assert (lang != nullptr);
+	  lang->language_arch_info (gdbarch, &l->arch_info[lang->la_language]);
+	}
+      language_gdbarch_data.set (gdbarch, l);
     }
 
   return l;
@@ -947,8 +951,7 @@ struct type *
 language_string_char_type (const struct language_defn *la,
 			   struct gdbarch *gdbarch)
 {
-  struct language_gdbarch *ld
-    = (struct language_gdbarch *) gdbarch_data (gdbarch, language_gdbarch_data);
+  struct language_gdbarch *ld = get_language_gdbarch (gdbarch);
   return ld->arch_info[la->la_language].string_char_type ();
 }
 
@@ -958,8 +961,7 @@ struct type *
 language_bool_type (const struct language_defn *la,
 		    struct gdbarch *gdbarch)
 {
-  struct language_gdbarch *ld
-    = (struct language_gdbarch *) gdbarch_data (gdbarch, language_gdbarch_data);
+  struct language_gdbarch *ld = get_language_gdbarch (gdbarch);
   return ld->arch_info[la->la_language].bool_type ();
 }
 
@@ -1067,8 +1069,7 @@ language_lookup_primitive_type_1 (const struct language_defn *la,
 				  struct gdbarch *gdbarch,
 				  T arg)
 {
-  struct language_gdbarch *ld =
-    (struct language_gdbarch *) gdbarch_data (gdbarch, language_gdbarch_data);
+  struct language_gdbarch *ld = get_language_gdbarch (gdbarch);
   return ld->arch_info[la->la_language].lookup_primitive_type (arg);
 }
 
@@ -1099,8 +1100,7 @@ language_lookup_primitive_type_as_symbol (const struct language_defn *la,
 					  struct gdbarch *gdbarch,
 					  const char *name)
 {
-  struct language_gdbarch *ld
-    = (struct language_gdbarch *) gdbarch_data (gdbarch, language_gdbarch_data);
+  struct language_gdbarch *ld = get_language_gdbarch (gdbarch);
   struct language_arch_info *lai = &ld->arch_info[la->la_language];
 
   if (symbol_lookup_debug)
@@ -1135,9 +1135,6 @@ _initialize_language ()
   static const char *const case_sensitive_names[]
     = { "on", "off", "auto", NULL };
 
-  language_gdbarch_data
-    = gdbarch_data_register_post_init (language_gdbarch_post_init);
-
   /* GDB commands for language specific stuff.  */
 
   set_show_commands setshow_check_cmds
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 4e6a48b1d20..5fe6be16c31 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -193,25 +193,22 @@ enum
     LINUX_SIGRTMAX = 64,
   };
 
-static struct gdbarch_data *linux_gdbarch_data_handle;
-
 struct linux_gdbarch_data
 {
-  struct type *siginfo_type;
-  int num_disp_step_buffers;
+  struct type *siginfo_type = nullptr;
+  int num_disp_step_buffers = 0;
 };
 
-static void *
-init_linux_gdbarch_data (struct obstack *obstack)
-{
-  return obstack_zalloc<linux_gdbarch_data> (obstack);
-}
+static const registry<gdbarch>::key<linux_gdbarch_data>
+     linux_gdbarch_data_handle;
 
 static struct linux_gdbarch_data *
 get_linux_gdbarch_data (struct gdbarch *gdbarch)
 {
-  return ((struct linux_gdbarch_data *)
-	  gdbarch_data (gdbarch, linux_gdbarch_data_handle));
+  struct linux_gdbarch_data *result = linux_gdbarch_data_handle.get (gdbarch);
+  if (result == nullptr)
+    result = linux_gdbarch_data_handle.emplace (gdbarch);
+  return result;
 }
 
 /* Linux-specific cached data.  This is used by GDB for caching
@@ -2752,9 +2749,6 @@ void _initialize_linux_tdep ();
 void
 _initialize_linux_tdep ()
 {
-  linux_gdbarch_data_handle =
-    gdbarch_data_register_pre_init (init_linux_gdbarch_data);
-
   /* Observers used to invalidate the cache when needed.  */
   gdb::observers::inferior_exit.attach (invalidate_linux_cache_inf,
 					"linux-tdep");
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 17b21af5d95..6a243bd419c 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -275,11 +275,10 @@ m2_language::emitchar (int ch, struct type *chtype,
 /* Called during architecture gdbarch initialisation to create language
    specific types.  */
 
-static void *
+static struct builtin_m2_type *
 build_m2_types (struct gdbarch *gdbarch)
 {
-  struct builtin_m2_type *builtin_m2_type
-    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_m2_type);
+  struct builtin_m2_type *builtin_m2_type = new struct builtin_m2_type;
 
   /* Modula-2 "pervasive" types.  NOTE:  these can be redefined!!! */
   builtin_m2_type->builtin_int
@@ -297,20 +296,17 @@ build_m2_types (struct gdbarch *gdbarch)
   return builtin_m2_type;
 }
 
-static struct gdbarch_data *m2_type_data;
+static const registry<gdbarch>::key<struct builtin_m2_type> m2_type_data;
 
 const struct builtin_m2_type *
 builtin_m2_type (struct gdbarch *gdbarch)
 {
-  return (const struct builtin_m2_type *) gdbarch_data (gdbarch, m2_type_data);
-}
-
-
-/* Initialization for Modula-2 */
+  struct builtin_m2_type *result = m2_type_data.get (gdbarch);
+  if (result == nullptr)
+    {
+      result = build_m2_types (gdbarch);
+      m2_type_data.set (gdbarch, result);
+    }
 
-void _initialize_m2_language ();
-void
-_initialize_m2_language ()
-{
-  m2_type_data = gdbarch_data_register_post_init (build_m2_types);
+  return result;
 }
diff --git a/gdb/m2-lang.h b/gdb/m2-lang.h
index 86a093e5f1b..775312f3cb4 100644
--- a/gdb/m2-lang.h
+++ b/gdb/m2-lang.h
@@ -37,11 +37,11 @@ extern int get_long_set_bounds (struct type *type, LONGEST *low,
 
 struct builtin_m2_type
 {
-  struct type *builtin_char;
-  struct type *builtin_int;
-  struct type *builtin_card;
-  struct type *builtin_real;
-  struct type *builtin_bool;
+  struct type *builtin_char = nullptr;
+  struct type *builtin_int = nullptr;
+  struct type *builtin_card = nullptr;
+  struct type *builtin_real = nullptr;
+  struct type *builtin_bool = nullptr;
 };
 
 /* Return the Modula-2 type table for the specified architecture.  */
diff --git a/gdb/netbsd-tdep.c b/gdb/netbsd-tdep.c
index fbedb77f46e..2e30aaf52c4 100644
--- a/gdb/netbsd-tdep.c
+++ b/gdb/netbsd-tdep.c
@@ -373,24 +373,21 @@ nbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
     return find_solib_trampoline_target (get_current_frame (), pc);
 }
 
-static struct gdbarch_data *nbsd_gdbarch_data_handle;
-
 struct nbsd_gdbarch_data
 {
-  struct type *siginfo_type;
+  struct type *siginfo_type = nullptr;
 };
 
-static void *
-init_nbsd_gdbarch_data (struct gdbarch *gdbarch)
-{
-  return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct nbsd_gdbarch_data);
-}
+static const registry<gdbarch>::key<nbsd_gdbarch_data>
+     nbsd_gdbarch_data_handle;
 
 static struct nbsd_gdbarch_data *
 get_nbsd_gdbarch_data (struct gdbarch *gdbarch)
 {
-  return ((struct nbsd_gdbarch_data *)
-	  gdbarch_data (gdbarch, nbsd_gdbarch_data_handle));
+  struct nbsd_gdbarch_data *result = nbsd_gdbarch_data_handle.get (gdbarch);
+  if (result == nullptr)
+    result = nbsd_gdbarch_data_handle.emplace (gdbarch);
+  return result;
 }
 
 /* Implement the "get_siginfo_type" gdbarch method.  */
@@ -622,11 +619,3 @@ nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_xml_syscall_file_name (gdbarch, "syscalls/netbsd.xml");
   set_gdbarch_get_syscall_number (gdbarch, nbsd_get_syscall_number);
 }
-
-void _initialize_nbsd_tdep ();
-void
-_initialize_nbsd_tdep ()
-{
-  nbsd_gdbarch_data_handle
-    = gdbarch_data_register_post_init (init_nbsd_gdbarch_data);
-}
diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index 594e4ed4918..cf0978560f9 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -28,7 +28,8 @@ struct arch_object {
   struct gdbarch *gdbarch;
 };
 
-static struct gdbarch_data *arch_object_data = NULL;
+static const registry<gdbarch>::key<PyObject, gdb::noop_deleter<PyObject>>
+     arch_object_data;
 
 /* Require a valid Architecture.  */
 #define ARCHPY_REQUIRE_VALID(arch_obj, arch)			\
@@ -48,7 +49,7 @@ extern PyTypeObject arch_object_type
 /* Associates an arch_object with GDBARCH as gdbarch_data via the gdbarch
    post init registration mechanism (gdbarch_data_register_post_init).  */
 
-static void *
+static PyObject *
 arch_object_data_init (struct gdbarch *gdbarch)
 {
   arch_object *arch_obj = PyObject_New (arch_object, &arch_object_type);
@@ -58,7 +59,7 @@ arch_object_data_init (struct gdbarch *gdbarch)
 
   arch_obj->gdbarch = gdbarch;
 
-  return (void *) arch_obj;
+  return (PyObject *) arch_obj;
 }
 
 /* Returns the struct gdbarch value corresponding to the given Python
@@ -88,10 +89,14 @@ gdbpy_is_architecture (PyObject *obj)
 PyObject *
 gdbarch_to_arch_object (struct gdbarch *gdbarch)
 {
-  PyObject *new_ref = (PyObject *) gdbarch_data (gdbarch, arch_object_data);
+  PyObject *new_ref = arch_object_data.get (gdbarch);
+  if (new_ref == nullptr)
+    {
+      new_ref = arch_object_data_init (gdbarch);
+      arch_object_data.set (gdbarch, new_ref);
+    }
 
-  /* new_ref could be NULL if registration of arch_object with GDBARCH failed
-     in arch_object_data_init.  */
+  /* new_ref could be NULL if creation failed.  */
   Py_XINCREF (new_ref);
 
   return new_ref;
@@ -337,13 +342,6 @@ gdbpy_all_architecture_names (PyObject *self, PyObject *args)
  return list.release ();
 }
 
-void _initialize_py_arch ();
-void
-_initialize_py_arch ()
-{
-  arch_object_data = gdbarch_data_register_post_init (arch_object_data_init);
-}
-
 /* Initializes the Architecture class in the gdb module.  */
 
 int
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c
index bbb322f068c..f22575a28c2 100644
--- a/gdb/python/py-registers.c
+++ b/gdb/python/py-registers.c
@@ -25,8 +25,12 @@
 #include "user-regs.h"
 #include <unordered_map>
 
+/* Per-gdbarch data type.  */
+typedef std::vector<gdbpy_ref<>> gdbpy_register_type;
+
 /* Token to access per-gdbarch data related to register descriptors.  */
-static struct gdbarch_data *gdbpy_register_object_data = NULL;
+static const registry<gdbarch>::key<gdbpy_register_type>
+     gdbpy_register_object_data;
 
 /* Structure for iterator over register descriptors.  */
 struct register_descriptor_iterator_object {
@@ -85,16 +89,6 @@ struct reggroup_object {
 extern PyTypeObject reggroup_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("reggroup_object");
 
-/* Associates a vector of gdb.RegisterDescriptor objects with GDBARCH as
-   gdbarch_data via the gdbarch post init registration mechanism
-   (gdbarch_data_register_post_init).  */
-
-static void *
-gdbpy_register_object_data_init (struct gdbarch *gdbarch)
-{
-  return new std::vector<gdbpy_ref<>>;
-}
-
 /* Return a gdb.RegisterGroup object wrapping REGGROUP.  The register
    group objects are cached, and the same Python object will always be
    returned for the same REGGROUP pointer.  */
@@ -156,9 +150,10 @@ static gdbpy_ref<>
 gdbpy_get_register_descriptor (struct gdbarch *gdbarch,
 			       int regnum)
 {
-  auto &vec
-    = *(std::vector<gdbpy_ref<>> *) gdbarch_data (gdbarch,
-						  gdbpy_register_object_data);
+  gdbpy_register_type *vecp = gdbpy_register_object_data.get (gdbarch);
+  if (vecp == nullptr)
+    vecp = gdbpy_register_object_data.emplace (gdbarch);
+  gdbpy_register_type &vec = *vecp;
 
   /* Ensure that we have enough entries in the vector.  */
   if (vec.size () <= regnum)
@@ -422,14 +417,6 @@ gdbpy_parse_register_id (struct gdbarch *gdbarch, PyObject *pyo_reg_id,
   return false;
 }
 
-void _initialize_py_registers ();
-void
-_initialize_py_registers ()
-{
-  gdbpy_register_object_data
-    = gdbarch_data_register_post_init (gdbpy_register_object_data_init);
-}
-
 /* Initializes the new Python classes from this file in the gdb module.  */
 
 int
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index b2fd1402e93..fb9466102c4 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -117,8 +117,6 @@ extern PyTypeObject pending_frame_object_type
 extern PyTypeObject unwind_info_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("unwind_info_object");
 
-static struct gdbarch_data *pyuw_gdbarch_data;
-
 /* Convert gdb.Value instance to inferior's pointer.  Return 1 on success,
    0 on failure.  */
 
@@ -657,14 +655,10 @@ pyuw_dealloc_cache (struct frame_info *this_frame, void *cache)
 struct pyuw_gdbarch_data_type
 {
   /* Has the unwinder shim been prepended? */
-  int unwinder_registered;
+  int unwinder_registered = 0;
 };
 
-static void *
-pyuw_gdbarch_data_init (struct gdbarch *gdbarch)
-{
-  return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct pyuw_gdbarch_data_type);
-}
+static const registry<gdbarch>::key<pyuw_gdbarch_data_type> pyuw_gdbarch_data;
 
 /* New inferior architecture callback: register the Python unwinders
    intermediary.  */
@@ -672,9 +666,9 @@ pyuw_gdbarch_data_init (struct gdbarch *gdbarch)
 static void
 pyuw_on_new_gdbarch (struct gdbarch *newarch)
 {
-  struct pyuw_gdbarch_data_type *data
-    = (struct pyuw_gdbarch_data_type *) gdbarch_data (newarch,
-						      pyuw_gdbarch_data);
+  struct pyuw_gdbarch_data_type *data = pyuw_gdbarch_data.get (newarch);
+  if (data == nullptr)
+    data= pyuw_gdbarch_data.emplace (newarch);
 
   if (!data->unwinder_registered)
     {
@@ -706,8 +700,6 @@ _initialize_py_unwind ()
 	NULL,
 	show_pyuw_debug,
 	&setdebuglist, &showdebuglist);
-  pyuw_gdbarch_data
-    = gdbarch_data_register_post_init (pyuw_gdbarch_data_init);
 }
 
 /* Initialize unwind machinery.  */
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 6fd4f86f4bf..a22a839d902 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -41,19 +41,17 @@
 /* Per-architecture object describing the layout of a register cache.
    Computed once when the architecture is created.  */
 
-static struct gdbarch_data *regcache_descr_handle;
-
 struct regcache_descr
 {
   /* The architecture this descriptor belongs to.  */
-  struct gdbarch *gdbarch;
+  struct gdbarch *gdbarch = nullptr;
 
   /* The raw register cache.  Each raw (or hard) register is supplied
      by the target interface.  The raw cache should not contain
      redundant information - if the PC is constructed from two
      registers then those registers and not the PC lives in the raw
      cache.  */
-  long sizeof_raw_registers;
+  long sizeof_raw_registers = 0;
 
   /* The cooked register space.  Each cooked register in the range
      [0..NR_RAW_REGISTERS) is direct-mapped onto the corresponding raw
@@ -61,21 +59,24 @@ struct regcache_descr
      .. NR_COOKED_REGISTERS) (a.k.a. pseudo registers) are mapped onto
      both raw registers and memory by the architecture methods
      gdbarch_pseudo_register_read and gdbarch_pseudo_register_write.  */
-  int nr_cooked_registers;
-  long sizeof_cooked_registers;
+  int nr_cooked_registers = 0;
+  long sizeof_cooked_registers = 0;
 
   /* Offset and size (in 8 bit bytes), of each register in the
      register cache.  All registers (including those in the range
      [NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an
      offset.  */
-  long *register_offset;
-  long *sizeof_register;
+  long *register_offset = nullptr;
+  long *sizeof_register = nullptr;
 
   /* Cached table containing the type of each register.  */
-  struct type **register_type;
+  struct type **register_type = nullptr;
 };
 
-static void *
+static const registry<gdbarch>::key<struct regcache_descr>
+     regcache_descr_handle;
+
+static struct regcache_descr *
 init_regcache_descr (struct gdbarch *gdbarch)
 {
   int i;
@@ -83,7 +84,7 @@ init_regcache_descr (struct gdbarch *gdbarch)
   gdb_assert (gdbarch != NULL);
 
   /* Create an initial, zero filled, table.  */
-  descr = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct regcache_descr);
+  descr = new struct regcache_descr;
   descr->gdbarch = gdbarch;
 
   /* Total size of the register space.  The raw registers are mapped
@@ -140,8 +141,14 @@ init_regcache_descr (struct gdbarch *gdbarch)
 static struct regcache_descr *
 regcache_descr (struct gdbarch *gdbarch)
 {
-  return (struct regcache_descr *) gdbarch_data (gdbarch,
-						 regcache_descr_handle);
+  struct regcache_descr *result = regcache_descr_handle.get (gdbarch);
+  if (result == nullptr)
+    {
+      result = init_regcache_descr (gdbarch);
+      regcache_descr_handle.set (gdbarch, result);
+    }
+
+  return result;
 }
 
 /* Utility functions returning useful register attributes stored in
@@ -2119,9 +2126,6 @@ _initialize_regcache ()
 {
   struct cmd_list_element *c;
 
-  regcache_descr_handle
-    = gdbarch_data_register_post_init (init_regcache_descr);
-
   gdb::observers::target_changed.attach (regcache_observer_target_changed,
 					 "regcache");
   gdb::observers::thread_ptid_changed.attach (regcache_thread_ptid_changed,
diff --git a/gdb/reggroups.c b/gdb/reggroups.c
index 1a13cb2fba0..b81031b42ac 100644
--- a/gdb/reggroups.c
+++ b/gdb/reggroups.c
@@ -52,6 +52,20 @@ reggroup_gdbarch_new (struct gdbarch *gdbarch, const char *name,
 
 struct reggroups
 {
+  reggroups ()
+  {
+    /* Add the default groups.  */
+    add (general_reggroup);
+    add (float_reggroup);
+    add (system_reggroup);
+    add (vector_reggroup);
+    add (all_reggroup);
+    add (save_reggroup);
+    add (restore_reggroup);
+  }
+
+  DISABLE_COPY_AND_ASSIGN (reggroups);
+
   /* Add GROUP to the list of register groups.  */
 
   void add (const reggroup *group)
@@ -86,15 +100,25 @@ private:
 
 /* Key used to lookup register group data from a gdbarch.  */
 
-static struct gdbarch_data *reggroups_data;
+static const registry<gdbarch>::key<reggroups> reggroups_data;
+
+/* Get the reggroups for the architecture, creating if necessary.  */
+
+static reggroups *
+get_reggroups (struct gdbarch *gdbarch)
+{
+  struct reggroups *groups = reggroups_data.get (gdbarch);
+  if (groups == nullptr)
+    groups = reggroups_data.emplace (gdbarch);
+  return groups;
+}
 
 /* See reggroups.h.  */
 
 void
 reggroup_add (struct gdbarch *gdbarch, const reggroup *group)
 {
-  struct reggroups *groups
-    = (struct reggroups *) gdbarch_data (gdbarch, reggroups_data);
+  struct reggroups *groups = get_reggroups (gdbarch);
 
   gdb_assert (groups != nullptr);
   gdb_assert (group != nullptr);
@@ -102,31 +126,11 @@ reggroup_add (struct gdbarch *gdbarch, const reggroup *group)
   groups->add (group);
 }
 
-/* Called to initialize the per-gdbarch register group information.  */
-
-static void *
-reggroups_init (struct obstack *obstack)
-{
-  struct reggroups *groups = obstack_new<struct reggroups> (obstack);
-
-  /* Add the default groups.  */
-  groups->add (general_reggroup);
-  groups->add (float_reggroup);
-  groups->add (system_reggroup);
-  groups->add (vector_reggroup);
-  groups->add (all_reggroup);
-  groups->add (save_reggroup);
-  groups->add (restore_reggroup);
-
-  return groups;
-}
-
 /* See reggroups.h.  */
 const std::vector<const reggroup *> &
 gdbarch_reggroups (struct gdbarch *gdbarch)
 {
-  struct reggroups *groups
-    = (struct reggroups *) gdbarch_data (gdbarch, reggroups_data);
+  struct reggroups *groups = get_reggroups (gdbarch);
   gdb_assert (groups != nullptr);
   gdb_assert (groups->size () > 0);
   return groups->groups ();
@@ -252,8 +256,6 @@ void _initialize_reggroup ();
 void
 _initialize_reggroup ()
 {
-  reggroups_data = gdbarch_data_register_pre_init (reggroups_init);
-
   add_cmd ("reggroups", class_maintenance,
 	   maintenance_print_reggroups, _("\
 Print the internal register group names.\n\
diff --git a/gdb/remote.c b/gdb/remote.c
index 04b283fba52..70f918a7362 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -11989,26 +11989,29 @@ struct remote_g_packet_guess
   const struct target_desc *tdesc;
 };
 
-struct remote_g_packet_data : public allocate_on_obstack
+struct remote_g_packet_data
 {
   std::vector<remote_g_packet_guess> guesses;
 };
 
-static struct gdbarch_data *remote_g_packet_data_handle;
+static const registry<gdbarch>::key<struct remote_g_packet_data>
+     remote_g_packet_data_handle;
 
-static void *
-remote_g_packet_data_init (struct obstack *obstack)
+static struct remote_g_packet_data *
+get_g_packet_data (struct gdbarch *gdbarch)
 {
-  return new (obstack) remote_g_packet_data;
+  struct remote_g_packet_data *data
+    = remote_g_packet_data_handle.get (gdbarch);
+  if (data == nullptr)
+    data = remote_g_packet_data_handle.emplace (gdbarch);
+  return data;
 }
 
 void
 register_remote_g_packet_guess (struct gdbarch *gdbarch, int bytes,
 				const struct target_desc *tdesc)
 {
-  struct remote_g_packet_data *data
-    = ((struct remote_g_packet_data *)
-       gdbarch_data (gdbarch, remote_g_packet_data_handle));
+  struct remote_g_packet_data *data = get_g_packet_data (gdbarch);
 
   gdb_assert (tdesc != NULL);
 
@@ -12027,9 +12030,7 @@ register_remote_g_packet_guess (struct gdbarch *gdbarch, int bytes,
 static bool
 remote_read_description_p (struct target_ops *target)
 {
-  struct remote_g_packet_data *data
-    = ((struct remote_g_packet_data *)
-       gdbarch_data (target_gdbarch (), remote_g_packet_data_handle));
+  struct remote_g_packet_data *data = get_g_packet_data (target_gdbarch ());
 
   return !data->guesses.empty ();
 }
@@ -12037,9 +12038,7 @@ remote_read_description_p (struct target_ops *target)
 const struct target_desc *
 remote_target::read_description ()
 {
-  struct remote_g_packet_data *data
-    = ((struct remote_g_packet_data *)
-       gdbarch_data (target_gdbarch (), remote_g_packet_data_handle));
+  struct remote_g_packet_data *data = get_g_packet_data (target_gdbarch ());
 
   /* Do not try this during initial connection, when we do not know
      whether there is a running but stopped thread.  */
@@ -14955,10 +14954,6 @@ void _initialize_remote ();
 void
 _initialize_remote ()
 {
-  /* architecture specific data */
-  remote_g_packet_data_handle =
-    gdbarch_data_register_pre_init (remote_g_packet_data_init);
-
   add_target (remote_target_info, remote_target::open);
   add_target (extended_remote_target_info, extended_remote_target::open);
 
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 1be3e4d61cd..cccc8872da9 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -155,7 +155,7 @@ static const char *powerpc_vector_abi_string = "auto";
 
 /* PowerPC-related per-inferior data.  */
 
-static registry<inferior>::key<ppc_inferior_data> ppc_inferior_data_key;
+static const registry<inferior>::key<ppc_inferior_data> ppc_inferior_data_key;
 
 /* Get the per-inferior PowerPC data for INF.  */
 
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 6f8680f75b8..95a1e1eb722 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -2995,24 +2995,23 @@ svr4_relocate_section_addresses (struct so_list *so,
 
 /* Architecture-specific operations.  */
 
-/* Per-architecture data key.  */
-static struct gdbarch_data *solib_svr4_data;
-
 struct solib_svr4_ops
 {
   /* Return a description of the layout of `struct link_map'.  */
-  struct link_map_offsets *(*fetch_link_map_offsets)(void);
+  struct link_map_offsets *(*fetch_link_map_offsets)(void) = nullptr;
 };
 
+/* Per-architecture data key.  */
+static const registry<gdbarch>::key<struct solib_svr4_ops> solib_svr4_data;
+
 /* Return a default for the architecture-specific operations.  */
 
-static void *
-solib_svr4_init (struct obstack *obstack)
+static struct solib_svr4_ops *
+get_ops (struct gdbarch *gdbarch)
 {
-  struct solib_svr4_ops *ops;
-
-  ops = OBSTACK_ZALLOC (obstack, struct solib_svr4_ops);
-  ops->fetch_link_map_offsets = NULL;
+  struct solib_svr4_ops *ops = solib_svr4_data.get (gdbarch);
+  if (ops == nullptr)
+    ops = solib_svr4_data.emplace (gdbarch);
   return ops;
 }
 
@@ -3023,8 +3022,7 @@ void
 set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
 				       struct link_map_offsets *(*flmo) (void))
 {
-  struct solib_svr4_ops *ops
-    = (struct solib_svr4_ops *) gdbarch_data (gdbarch, solib_svr4_data);
+  struct solib_svr4_ops *ops = get_ops (gdbarch);
 
   ops->fetch_link_map_offsets = flmo;
 
@@ -3039,9 +3037,7 @@ set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
 static struct link_map_offsets *
 svr4_fetch_link_map_offsets (void)
 {
-  struct solib_svr4_ops *ops
-    = (struct solib_svr4_ops *) gdbarch_data (target_gdbarch (),
-					      solib_svr4_data);
+  struct solib_svr4_ops *ops = get_ops (target_gdbarch ());
 
   gdb_assert (ops->fetch_link_map_offsets);
   return ops->fetch_link_map_offsets ();
@@ -3052,9 +3048,7 @@ svr4_fetch_link_map_offsets (void)
 static int
 svr4_have_link_map_offsets (void)
 {
-  struct solib_svr4_ops *ops
-    = (struct solib_svr4_ops *) gdbarch_data (target_gdbarch (),
-					      solib_svr4_data);
+  struct solib_svr4_ops *ops = get_ops (target_gdbarch ());
 
   return (ops->fetch_link_map_offsets != NULL);
 }
@@ -3173,8 +3167,6 @@ void _initialize_svr4_solib ();
 void
 _initialize_svr4_solib ()
 {
-  solib_svr4_data = gdbarch_data_register_pre_init (solib_svr4_init);
-
   svr4_so_ops.relocate_section_addresses = svr4_relocate_section_addresses;
   svr4_so_ops.free_so = svr4_free_so;
   svr4_so_ops.clear_so = svr4_clear_so;
diff --git a/gdb/solib.c b/gdb/solib.c
index fc07f60a6d5..d889673dabf 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -57,25 +57,14 @@
 /* Architecture-specific operations.  */
 
 /* Per-architecture data key.  */
-static struct gdbarch_data *solib_data;
-
-static void *
-solib_init (struct obstack *obstack)
-{
-  struct target_so_ops **ops;
-
-  ops = OBSTACK_ZALLOC (obstack, struct target_so_ops *);
-  *ops = current_target_so_ops;
-  return ops;
-}
+static const registry<gdbarch>::key<const struct target_so_ops,
+			      gdb::noop_deleter<const struct target_so_ops>>
+     solib_data;
 
 static const struct target_so_ops *
 solib_ops (struct gdbarch *gdbarch)
 {
-  const struct target_so_ops **ops
-    = (const struct target_so_ops **) gdbarch_data (gdbarch, solib_data);
-
-  return *ops;
+  return solib_data.get (gdbarch);
 }
 
 /* Set the solib operations for GDBARCH to NEW_OPS.  */
@@ -83,10 +72,7 @@ solib_ops (struct gdbarch *gdbarch)
 void
 set_solib_ops (struct gdbarch *gdbarch, const struct target_so_ops *new_ops)
 {
-  const struct target_so_ops **ops
-    = (const struct target_so_ops **) gdbarch_data (gdbarch, solib_data);
-
-  *ops = new_ops;
+  solib_data.set (gdbarch, new_ops);
 }
 \f
 
@@ -1786,8 +1772,6 @@ void _initialize_solib ();
 void
 _initialize_solib ()
 {
-  solib_data = gdbarch_data_register_pre_init (solib_init);
-
   gdb::observers::free_objfile.attach (remove_user_added_objfile,
 				       "solib");
   gdb::observers::inferior_execd.attach ([] (inferior *inf)
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 85954ac2939..d5d795875c2 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -479,7 +479,17 @@ get_tdesc_info (struct inferior *inf)
 /* A handle for architecture-specific data associated with the
    target description (see struct tdesc_arch_data).  */
 
-static struct gdbarch_data *tdesc_data;
+static const registry<gdbarch>::key<tdesc_arch_data> tdesc_data;
+
+/* Get or create the tdesc_data.  */
+static tdesc_arch_data *
+get_arch_data (struct gdbarch *gdbarch)
+{
+  tdesc_arch_data *result = tdesc_data.get (gdbarch);
+  if (result == nullptr)
+    result = tdesc_data.emplace (gdbarch);
+  return result;
+}
 
 /* See target-descriptions.h.  */
 
@@ -562,8 +572,7 @@ target_find_description (void)
 	{
 	  struct tdesc_arch_data *data;
 
-	  data = ((struct tdesc_arch_data *)
-		  gdbarch_data (target_gdbarch (), tdesc_data));
+	  data = get_arch_data (target_gdbarch ());
 	  if (tdesc_has_registers (tdesc_info->tdesc)
 	      && data->arch_regs.empty ())
 	    warning (_("Target-supplied registers are not supported "
@@ -742,8 +751,7 @@ tdesc_feature_name (const struct tdesc_feature *feature)
 struct type *
 tdesc_find_type (struct gdbarch *gdbarch, const char *id)
 {
-  tdesc_arch_data *data
-    = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
+  tdesc_arch_data *data = get_arch_data (gdbarch);
 
   for (const tdesc_arch_reg &reg : data->arch_regs)
     {
@@ -761,15 +769,6 @@ tdesc_find_type (struct gdbarch *gdbarch, const char *id)
 
 /* Construct the per-gdbarch data.  */
 
-static void *
-tdesc_data_init (struct obstack *obstack)
-{
-  return obstack_new<tdesc_arch_data> (obstack);
-}
-
-/* Similar, but for the temporary copy used during architecture
-   initialization.  */
-
 tdesc_arch_data_up
 tdesc_data_alloc (void)
 {
@@ -867,9 +866,8 @@ tdesc_register_bitsize (const struct tdesc_feature *feature, const char *name)
 static struct tdesc_arch_reg *
 tdesc_find_arch_register (struct gdbarch *gdbarch, int regno)
 {
-  struct tdesc_arch_data *data;
+  struct tdesc_arch_data *data = get_arch_data (gdbarch);
 
-  data = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
   if (regno < data->arch_regs.size ())
     return &data->arch_regs[regno];
   else
@@ -898,8 +896,7 @@ tdesc_register_name (struct gdbarch *gdbarch, int regno)
 
   if (regno >= num_regs && regno < gdbarch_num_cooked_regs (gdbarch))
     {
-      struct tdesc_arch_data *data
-	= (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
+      struct tdesc_arch_data *data = get_arch_data (gdbarch);
 
       gdb_assert (data->pseudo_register_name != NULL);
       return data->pseudo_register_name (gdbarch, regno);
@@ -918,8 +915,7 @@ tdesc_register_type (struct gdbarch *gdbarch, int regno)
 
   if (reg == NULL && regno >= num_regs && regno < num_regs + num_pseudo_regs)
     {
-      struct tdesc_arch_data *data
-	= (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
+      struct tdesc_arch_data *data = get_arch_data (gdbarch);
 
       gdb_assert (data->pseudo_register_type != NULL);
       return data->pseudo_register_type (gdbarch, regno);
@@ -1036,8 +1032,7 @@ tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regno,
 
   if (regno >= num_regs && regno < num_regs + num_pseudo_regs)
     {
-      struct tdesc_arch_data *data
-	= (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
+      struct tdesc_arch_data *data = get_arch_data (gdbarch);
 
       if (data->pseudo_register_reggroup_p != NULL)
 	return data->pseudo_register_reggroup_p (gdbarch, regno, reggroup);
@@ -1058,8 +1053,7 @@ void
 set_tdesc_pseudo_register_name (struct gdbarch *gdbarch,
 				gdbarch_register_name_ftype *pseudo_name)
 {
-  struct tdesc_arch_data *data
-    = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
+  struct tdesc_arch_data *data = get_arch_data (gdbarch);
 
   data->pseudo_register_name = pseudo_name;
 }
@@ -1068,8 +1062,7 @@ void
 set_tdesc_pseudo_register_type (struct gdbarch *gdbarch,
 				gdbarch_register_type_ftype *pseudo_type)
 {
-  struct tdesc_arch_data *data
-    = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
+  struct tdesc_arch_data *data = get_arch_data (gdbarch);
 
   data->pseudo_register_type = pseudo_type;
 }
@@ -1079,8 +1072,7 @@ set_tdesc_pseudo_register_reggroup_p
   (struct gdbarch *gdbarch,
    gdbarch_register_reggroup_p_ftype *pseudo_reggroup_p)
 {
-  struct tdesc_arch_data *data
-    = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
+  struct tdesc_arch_data *data = get_arch_data (gdbarch);
 
   data->pseudo_register_reggroup_p = pseudo_reggroup_p;
 }
@@ -1102,7 +1094,7 @@ tdesc_use_registers (struct gdbarch *gdbarch,
      included.  */
   gdb_assert (tdesc_has_registers (target_desc));
 
-  data = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
+  data = get_arch_data (gdbarch);
   data->arch_regs = std::move (early_data->arch_regs);
 
   /* Build up a set of all registers, so that we can assign register
@@ -1962,8 +1954,6 @@ _initialize_target_descriptions ()
 {
   cmd_list_element *cmd;
 
-  tdesc_data = gdbarch_data_register_pre_init (tdesc_data_init);
-
   add_setshow_prefix_cmd ("tdesc", class_maintenance,
 			  _("Set target description specific variables."),
 			  _("Show target description specific variables."),
diff --git a/gdb/user-regs.c b/gdb/user-regs.c
index 8f1c6e62b97..4bc4685387f 100644
--- a/gdb/user-regs.c
+++ b/gdb/user-regs.c
@@ -57,8 +57,8 @@ struct user_reg
 
 struct gdb_user_regs
 {
-  struct user_reg *first;
-  struct user_reg **last;
+  struct user_reg *first = nullptr;
+  struct user_reg **last = nullptr;
 };
 
 static void
@@ -95,18 +95,26 @@ user_reg_add_builtin (const char *name, user_reg_read_ftype *xread,
 /* Per-architecture user registers.  Start with the builtin user
    registers and then, again, append.  */
 
-static struct gdbarch_data *user_regs_data;
+static const registry<gdbarch>::key<gdb_user_regs> user_regs_data;
 
-static void *
-user_regs_init (struct obstack *obstack)
+static gdb_user_regs *
+get_user_regs (struct gdbarch *gdbarch)
 {
-  struct user_reg *reg;
-  struct gdb_user_regs *regs = OBSTACK_ZALLOC (obstack, struct gdb_user_regs);
+  struct gdb_user_regs *regs = user_regs_data.get (gdbarch);
+  if (regs == nullptr)
+    {
+      regs = new struct gdb_user_regs;
+
+      struct obstack *obstack = gdbarch_obstack (gdbarch);
+      regs->last = &regs->first;
+      for (user_reg *reg = builtin_user_regs.first;
+	   reg != NULL;
+	   reg = reg->next)
+	append_user_reg (regs, reg->name, reg->xread, reg->baton,
+			 OBSTACK_ZALLOC (obstack, struct user_reg));
+      user_regs_data.set (gdbarch, regs);
+    }
 
-  regs->last = &regs->first;
-  for (reg = builtin_user_regs.first; reg != NULL; reg = reg->next)
-    append_user_reg (regs, reg->name, reg->xread, reg->baton,
-		     OBSTACK_ZALLOC (obstack, struct user_reg));
   return regs;
 }
 
@@ -114,8 +122,7 @@ void
 user_reg_add (struct gdbarch *gdbarch, const char *name,
 	      user_reg_read_ftype *xread, const void *baton)
 {
-  struct gdb_user_regs *regs
-    = (struct gdb_user_regs *) gdbarch_data (gdbarch, user_regs_data);
+  struct gdb_user_regs *regs = get_user_regs (gdbarch);
   gdb_assert (regs != NULL);
   append_user_reg (regs, name, xread, baton,
 		   GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_reg));
@@ -149,8 +156,7 @@ user_reg_map_name_to_regnum (struct gdbarch *gdbarch, const char *name,
 
   /* Search the user name space.  */
   {
-    struct gdb_user_regs *regs
-      = (struct gdb_user_regs *) gdbarch_data (gdbarch, user_regs_data);
+    struct gdb_user_regs *regs = get_user_regs (gdbarch);
     struct user_reg *reg;
     int nr;
 
@@ -169,8 +175,7 @@ user_reg_map_name_to_regnum (struct gdbarch *gdbarch, const char *name,
 static struct user_reg *
 usernum_to_user_reg (struct gdbarch *gdbarch, int usernum)
 {
-  struct gdb_user_regs *regs
-    = (struct gdb_user_regs *) gdbarch_data (gdbarch, user_regs_data);
+  struct gdb_user_regs *regs = get_user_regs (gdbarch);
   struct user_reg *reg;
 
   for (reg = regs->first; reg != NULL; reg = reg->next)
@@ -216,11 +221,10 @@ static void
 maintenance_print_user_registers (const char *args, int from_tty)
 {
   struct gdbarch *gdbarch = get_current_arch ();
-  struct gdb_user_regs *regs;
   struct user_reg *reg;
   int regnum;
 
-  regs = (struct gdb_user_regs *) gdbarch_data (gdbarch, user_regs_data);
+  struct gdb_user_regs *regs = get_user_regs (gdbarch);
   regnum = gdbarch_num_cooked_regs (gdbarch);
 
   gdb_printf (" %-11s %3s\n", "Name", "Nr");
@@ -232,8 +236,6 @@ void _initialize_user_regs ();
 void
 _initialize_user_regs ()
 {
-  user_regs_data = gdbarch_data_register_pre_init (user_regs_init);
-
   add_cmd ("user-registers", class_maintenance,
 	   maintenance_print_user_registers,
 	   _("List the names of the current user registers."),
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 2516e4ed058..a34ac5e5f0a 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -175,29 +175,25 @@ static const int FULL_TIB_SIZE = 0x1000;
 
 static bool maint_display_all_tib = false;
 
-static struct gdbarch_data *windows_gdbarch_data_handle;
-
 struct windows_gdbarch_data
 {
-  struct type *siginfo_type;
-  struct type *tib_ptr_type; /* Type of thread information block */
+  struct type *siginfo_type = nullptr;
+  /* Type of thread information block.  */
+  struct type *tib_ptr_type = nullptr;
 };
 
-/* Allocate windows_gdbarch_data for an arch.  */
-
-static void *
-init_windows_gdbarch_data (struct gdbarch *gdbarch)
-{
-  return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct windows_gdbarch_data);
-}
+static const registry<gdbarch>::key<windows_gdbarch_data>
+     windows_gdbarch_data_handle;
 
 /* Get windows_gdbarch_data of an arch.  */
 
 static struct windows_gdbarch_data *
 get_windows_gdbarch_data (struct gdbarch *gdbarch)
 {
-  return ((struct windows_gdbarch_data *)
-	  gdbarch_data (gdbarch, windows_gdbarch_data_handle));
+  windows_gdbarch_data *result = windows_gdbarch_data_handle.get (gdbarch);
+  if (result == nullptr)
+    result = windows_gdbarch_data_handle.emplace (gdbarch);
+  return result;
 }
 
 /* Define Thread Local Base pointer type.  */
@@ -1195,9 +1191,6 @@ void _initialize_windows_tdep ();
 void
 _initialize_windows_tdep ()
 {
-  windows_gdbarch_data_handle
-    = gdbarch_data_register_post_init (init_windows_gdbarch_data);
-
   init_w32_command_list ();
   cmd_list_element *info_w32_thread_information_block_cmd
     = add_cmd ("thread-information-block", class_info, display_tib,


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-08-04 19:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-04 19:33 [binutils-gdb] Use registry in gdbarch Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).