From: Tom Tromey Date: Mon, 13 Mar 2023 14:51:34 +0000 (-0600) Subject: Introduce type_allocator X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6a4d297c62ce68a833814b9cf84626c42fc0cf78;p=binutils-gdb.git Introduce type_allocator 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 --- diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index cfd0a1b62c7..5bb49063d5a 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -173,6 +173,64 @@ show_strict_type_checking (struct ui_file *file, int from_tty, } +/* 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. */ diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 52475d5afb4..613c22d676b 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -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,