Introduce type_allocator
authorTom Tromey <tom@tromey.com>
Mon, 13 Mar 2023 14:51:34 +0000 (08:51 -0600)
committerTom Tromey <tom@tromey.com>
Sat, 18 Mar 2023 17:12:37 +0000 (11:12 -0600)
This introduces a new type_allocator class.  This class will be used
to abstract out the placement of new types, so that type-creation code
can be simplified and shared.

Reviewed-By: Simon Marchi <simon.marchi@efficios.com>
gdb/gdbtypes.c
gdb/gdbtypes.h

index cfd0a1b62c7a090eae869bf5f135a75c926d98d6..5bb49063d5af40c9b68bc23f3e09313ea8894f0c 100644 (file)
@@ -173,6 +173,64 @@ show_strict_type_checking (struct ui_file *file, int from_tty,
 }
 
 \f
+/* Helper function to initialize a newly allocated type.  Set type code
+   to CODE and initialize the type-specific fields accordingly.  */
+
+static void
+set_type_code (struct type *type, enum type_code code)
+{
+  type->set_code (code);
+
+  switch (code)
+    {
+      case TYPE_CODE_STRUCT:
+      case TYPE_CODE_UNION:
+      case TYPE_CODE_NAMESPACE:
+       INIT_CPLUS_SPECIFIC (type);
+       break;
+      case TYPE_CODE_FLT:
+       TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_FLOATFORMAT;
+       break;
+      case TYPE_CODE_FUNC:
+       INIT_FUNC_SPECIFIC (type);
+       break;
+      case TYPE_CODE_FIXED_POINT:
+       INIT_FIXED_POINT_SPECIFIC (type);
+       break;
+    }
+}
+
+/* See gdbtypes.h.  */
+
+type *
+type_allocator::new_type ()
+{
+  if (m_smash)
+    return m_data.type;
+
+  obstack *obstack = (m_is_objfile
+                     ? &m_data.objfile->objfile_obstack
+                     : gdbarch_obstack (m_data.gdbarch));
+
+  /* Alloc the structure and start off with all fields zeroed.  */
+  struct type *type = OBSTACK_ZALLOC (obstack, struct type);
+  TYPE_MAIN_TYPE (type) = OBSTACK_ZALLOC (obstack, struct main_type);
+
+  if (m_is_objfile)
+    {
+      OBJSTAT (m_data.objfile, n_types++);
+      type->set_owner (m_data.objfile);
+    }
+  else
+    type->set_owner (m_data.gdbarch);
+
+  /* Initialize the fields that might not be zero.  */
+  type->set_code (TYPE_CODE_UNDEF);
+  TYPE_CHAIN (type) = type;    /* Chain back to itself.  */
+
+  return type;
+}
+
 /* Allocate a new OBJFILE-associated type structure and fill it
    with some defaults.  Space for the type structure is allocated
    on the objfile's objfile_obstack.  */
@@ -241,6 +299,39 @@ alloc_type_copy (const struct type *type)
 
 /* See gdbtypes.h.  */
 
+type *
+type_allocator::new_type (enum type_code code, int bit, const char *name)
+{
+  struct type *type = new_type ();
+  set_type_code (type, code);
+  gdb_assert ((bit % TARGET_CHAR_BIT) == 0);
+  type->set_length (bit / TARGET_CHAR_BIT);
+
+  if (name != nullptr)
+    {
+      obstack *obstack = (m_is_objfile
+                         ? &m_data.objfile->objfile_obstack
+                         : gdbarch_obstack (m_data.gdbarch));
+      type->set_name (obstack_strdup (obstack, name));
+    }
+
+  return type;
+}
+
+/* See gdbtypes.h.  */
+
+gdbarch *
+type_allocator::arch ()
+{
+  if (m_smash)
+    return m_data.type->arch ();
+  if (m_is_objfile)
+    return m_data.objfile->arch ();
+  return m_data.gdbarch;
+}
+
+/* See gdbtypes.h.  */
+
 gdbarch *
 type::arch () const
 {
@@ -3344,33 +3435,6 @@ allocate_gnat_aux_type (struct type *type)
   *(TYPE_GNAT_SPECIFIC (type)) = gnat_aux_default;
 }
 
-/* Helper function to initialize a newly allocated type.  Set type code
-   to CODE and initialize the type-specific fields accordingly.  */
-
-static void
-set_type_code (struct type *type, enum type_code code)
-{
-  type->set_code (code);
-
-  switch (code)
-    {
-      case TYPE_CODE_STRUCT:
-      case TYPE_CODE_UNION:
-      case TYPE_CODE_NAMESPACE:
-       INIT_CPLUS_SPECIFIC (type);
-       break;
-      case TYPE_CODE_FLT:
-       TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_FLOATFORMAT;
-       break;
-      case TYPE_CODE_FUNC:
-       INIT_FUNC_SPECIFIC (type);
-       break;
-      case TYPE_CODE_FIXED_POINT:
-       INIT_FIXED_POINT_SPECIFIC (type);
-       break;
-    }
-}
-
 /* Helper function to verify floating-point format and size.
    BIT is the type size in bits; if BIT equals -1, the size is
    determined by the floatformat.  Returns size to be used.  */
index 52475d5afb40c488d2ecda74b7b89e58961622a4..613c22d676bd177b34102fe50d5fffafc0828629 100644 (file)
@@ -2205,6 +2205,104 @@ extern struct type *get_target_type (struct type *type);
 
 extern unsigned int type_length_units (struct type *type);
 
+/* An object of this type is passed when allocating certain types.  It
+   determines where the new type is allocated.  Ultimately a type is
+   either allocated on a on an objfile obstack or on a gdbarch
+   obstack.  However, it's also possible to request that a new type be
+   allocated on the same obstack as some existing type, or that a
+   "new" type instead overwrite a supplied type object.  */
+
+class type_allocator
+{
+public:
+
+  /* Create new types on OBJFILE.  */
+  explicit type_allocator (objfile *objfile)
+    : m_is_objfile (true)
+  {
+    m_data.objfile = objfile;
+  }
+
+  /* Create new types on GDBARCH.  */
+  explicit type_allocator (gdbarch *gdbarch)
+  {
+    m_data.gdbarch = gdbarch;
+  }
+
+  /* This determines whether a passed-in type should be rewritten in
+     place, or whether it should simply determine where the new type
+     is created.  */
+  enum type_allocator_kind
+  {
+    /* Allocate on same obstack as existing type.  */
+    SAME = 0,
+    /* Smash the existing type.  */
+    SMASH = 1,
+  };
+
+  /* Create new types either on the same obstack as TYPE; or if SMASH
+     is passed, overwrite TYPE.  */
+  explicit type_allocator (struct type *type,
+                          type_allocator_kind kind = SAME)
+  {
+    if (kind == SAME)
+      {
+       if (type->is_objfile_owned ())
+         {
+           m_data.objfile = type->objfile_owner ();
+           m_is_objfile = true;
+         }
+       else
+         m_data.gdbarch = type->arch_owner ();
+      }
+    else
+      {
+       m_smash = true;
+       m_data.type = type;
+      }
+  }
+
+  /* Create new types on the same obstack as TYPE.  */
+  explicit type_allocator (const struct type *type)
+    : m_is_objfile (type->is_objfile_owned ())
+  {
+    if (type->is_objfile_owned ())
+      m_data.objfile = type->objfile_owner ();
+    else
+      m_data.gdbarch = type->arch_owner ();
+  }
+
+  /* Create a new type on the desired obstack.  Note that a "new" type
+     is not created if type-smashing was selected at construction.  */
+  type *new_type ();
+
+  /* Create a new type on the desired obstack, and fill in its code,
+     length, and name.  If NAME is non-null, it is copied to the
+     destination obstack first.  Note that a "new" type is not created
+     if type-smashing was selected at construction.  */
+  type *new_type (enum type_code code, int bit, const char *name);
+
+  /* Return the architecture associated with this allocator.  This
+     comes from whatever object was supplied to the constructor.  */
+  gdbarch *arch ();
+
+private:
+
+  /* Where the type should wind up.  */
+  union
+  {
+    struct objfile *objfile;
+    struct gdbarch *gdbarch;
+    struct type *type;
+  } m_data {};
+
+  /* True if this allocator uses the objfile field above.  */
+  bool m_is_objfile = false;
+  /* True if this allocator uses the type field above, indicating that
+     the "allocation" should be done in-place.  */
+  bool m_smash = false;
+};
+
 /* * Helper function to construct objfile-owned types.  */
 
 extern struct type *init_type (struct objfile *, enum type_code, int,