diff mbox

Introduce linked list for dynamic attributes

Message ID 54F5BA7A.2090308@linux.intel.com
State New
Headers show

Commit Message

Keven Boell March 3, 2015, 1:43 p.m. UTC
Hi Joel,

Here is the updated patch.

Thanks,
Keven

---

From: Keven Boell <keven.boell@intel.com>
Date: Mon, 23 Feb 2015 15:45:06 +0100
Subject: [PATCH] Introduce linked list for dynamic attributes

This patch introduces a linked list for dynamic
attributes of a type. This is a pre-work for
the Fortran dynamic array support. The Fortran
dynamic array support will add more dynamic
attributes to a type. As only a few types
will have such dynamic attributes set, a linked
list is more efficient in terms of memory
consumption than adding multiple attributes
to main_type.

Transformed the data_location dynamic attribute
to use the linked list.

2015-02-23  Keven Boell  <keven.boell@intel.com>

	* gdbtypes.c (resolve_dynamic_type_internal):
	Adapt data_location usage to linked list.
	(resolve_dynamic_type_internal): Adapt
	data_location usage to linked list.
	(get_dyn_prop): New function.
	(add_dyn_prop): New function.
	(copy_dynamic_prop_list): New function.
	(copy_type_recursive): Add copy of linked
	list.
	(copy_type): Add copy of linked list.
	* gdbtypes.h (enum dynamic_prop_node_kind):
	Kind of the dynamic attribute in linked list.
	(struct dynamic_prop_list): Dynamic list
	node.
	* dwarf2read.c (set_die_type): Add data_location
	data to linked list using helper functions.
---
 gdb/dwarf2read.c |    6 +---
 gdb/gdbtypes.c   |   86 +++++++++++++++++++++++++++++++++++++++++-------------
 gdb/gdbtypes.h   |   48 ++++++++++++++++++++++++++----
 3 files changed, 108 insertions(+), 32 deletions(-)

Comments

Joel Brobecker March 3, 2015, 3:54 p.m. UTC | #1
> Here is the updated patch.

Thanks. This is looking very good, if I may say so myself ;-)

> From: Keven Boell <keven.boell@intel.com>
> Date: Mon, 23 Feb 2015 15:45:06 +0100
> Subject: [PATCH] Introduce linked list for dynamic attributes
> 
> This patch introduces a linked list for dynamic
> attributes of a type. This is a pre-work for
> the Fortran dynamic array support. The Fortran
> dynamic array support will add more dynamic
> attributes to a type. As only a few types
> will have such dynamic attributes set, a linked
> list is more efficient in terms of memory
> consumption than adding multiple attributes
> to main_type.
> 
> Transformed the data_location dynamic attribute
> to use the linked list.
> 
> 2015-02-23  Keven Boell  <keven.boell@intel.com>
> 
> 	* gdbtypes.c (resolve_dynamic_type_internal):
> 	Adapt data_location usage to linked list.
> 	(resolve_dynamic_type_internal): Adapt
> 	data_location usage to linked list.
> 	(get_dyn_prop): New function.
> 	(add_dyn_prop): New function.
> 	(copy_dynamic_prop_list): New function.
> 	(copy_type_recursive): Add copy of linked
> 	list.
> 	(copy_type): Add copy of linked list.
> 	* gdbtypes.h (enum dynamic_prop_node_kind):
> 	Kind of the dynamic attribute in linked list.
> 	(struct dynamic_prop_list): Dynamic list
> 	node.
> 	* dwarf2read.c (set_die_type): Add data_location
> 	data to linked list using helper functions.

A few more comments, but I hope that the next revision will
be approved.

One thing I should ask: I assume that you've run the testsuite
before and after your change to confirm there are no regressions,
right? Can you tell us what platform you tested on, just for
the record?

> ---
>  gdb/dwarf2read.c |    6 +---
>  gdb/gdbtypes.c   |   86 +++++++++++++++++++++++++++++++++++++++++-------------
>  gdb/gdbtypes.h   |   48 ++++++++++++++++++++++++++----
>  3 files changed, 108 insertions(+), 32 deletions(-)
> 
> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index 071f97b..370143d 100644
> --- a/gdb/dwarf2read.c
> +++ b/gdb/dwarf2read.c
> @@ -22084,11 +22084,7 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
>    /* Read DW_AT_data_location and set in type.  */
>    attr = dwarf2_attr (die, DW_AT_data_location, cu);
>    if (attr_to_dynamic_prop (attr, die, cu, &prop))
> -    {
> -      TYPE_DATA_LOCATION (type)
> -        = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));
> -      *TYPE_DATA_LOCATION (type) = prop;
> -    }
> +    add_dyn_prop (DYN_ATTR_DATA_LOCATION, prop, type, objfile);
>  
>    if (dwarf2_per_objfile->die_type_hash == NULL)
>      {
> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 24f64be..20bdc20 100644
> --- a/gdb/gdbtypes.c
> +++ b/gdb/gdbtypes.c
> @@ -2025,7 +2025,7 @@ resolve_dynamic_type_internal (struct type *type,
>  {
>    struct type *real_type = check_typedef (type);
>    struct type *resolved_type = type;
> -  const struct dynamic_prop *prop;
> +  struct dynamic_prop *prop;
>    CORE_ADDR value;
>  
>    if (!is_dynamic_type_internal (real_type, top_level))
> @@ -2080,13 +2080,11 @@ resolve_dynamic_type_internal (struct type *type,
>  
>    /* Resolve data_location attribute.  */
>    prop = TYPE_DATA_LOCATION (resolved_type);
> -  if (dwarf2_evaluate_property (prop, addr_stack, &value))
> +  if (prop != NULL && dwarf2_evaluate_property (prop, addr_stack, &value))
>      {
> -      TYPE_DATA_LOCATION_ADDR (resolved_type) = value;
> -      TYPE_DATA_LOCATION_KIND (resolved_type) = PROP_CONST;
> +      TYPE_DYN_PROP_ADDR (prop) = value;
> +      TYPE_DYN_PROP_KIND (prop) = PROP_CONST;
>      }
> -  else
> -    TYPE_DATA_LOCATION (resolved_type) = NULL;
>  
>    return resolved_type;
>  }
> @@ -2101,6 +2099,41 @@ resolve_dynamic_type (struct type *type, CORE_ADDR addr)
>    return resolve_dynamic_type_internal (type, &pinfo, 1);
>  }
>  
> +/* See gdbtypes.h  */
> +
> +struct dynamic_prop *
> +get_dyn_prop (enum dynamic_prop_node_kind prop_kind, const struct type *type)
> +{
> +  struct dynamic_prop_list *node
> +    = TYPE_DYN_PROP_LIST (type);

You can join these two lines into one.

> +
> +  while (node != NULL)
> +    {
> +      if (node->prop_kind == prop_kind)
> +        return node->prop;
> +      node = node->next;
> +    }
> +  return NULL;
> +}
> +
> +/* See gdbtypes.h  */
> +
> +void
> +add_dyn_prop (enum dynamic_prop_node_kind prop_kind, struct dynamic_prop prop,
> +              struct type *type, struct objfile *objfile)
> +{
> +  struct dynamic_prop_list *temp
> +    = obstack_alloc (&objfile->objfile_obstack,
> +              sizeof (struct dynamic_prop_list));

The formatting is a little off on this one (the "sizeof" is missalined).

Also, I forgot in the previous review to ask that we add an assert
to make sure that the type is objfile-owned. Would you mind doing
that? Otherwise, what we might be doing is allocating memory on
an obstack whose lifetime is independent of the type's thus potentially
creating a dangling pointer, which is always hard to track down after
the fact.

> +  temp->prop = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));
> +  *temp->prop = prop;
> +  temp->prop_kind = prop_kind;
> +
> +  temp->next = TYPE_DYN_PROP_LIST (type);
> +  TYPE_DYN_PROP_LIST (type) = temp;
> +}
> +
> +
>  /* Find the real type of TYPE.  This function returns the real type,
>     after removing all layers of typedefs, and completing opaque or stub
>     types.  Completion changes the TYPE argument, but stripping of
> @@ -4222,6 +4255,25 @@ create_copied_types_hash (struct objfile *objfile)
>  			       dummy_obstack_deallocate);
>  }
>  
> +/* Recursively copy (deep copy) a dynamic attribute list of a type.  */
> +
> +struct dynamic_prop_list *
> +copy_dynamic_prop_list (struct dynamic_prop_list *list)
> +{

I think this function can be made static.

> +  struct dynamic_prop_list *copy;
> +
> +  copy = xmalloc (sizeof (struct dynamic_prop_list));
> +  *copy = *list;
> +
> +  copy->prop = xmalloc (sizeof (struct dynamic_prop));

xmalloc is the wrong function to be using, as we're allocating
the dynamic properties on the type's obfile instead.  Otherwise,
we'd be creating a memory leak. So I guess this function needs
to be given an obstack as parameter.

> +  *(copy->prop) = *(list->prop);

Looks like you forgot to copy the prop kind?

> +
> +  if (list->next != NULL)
> +    copy->next = copy_dynamic_prop_list (list->next);

I am reluctant to use recursion, here, as this is theoretically
open-ended, and can lead to stack over-consumption. Better to
use a simple loop, IMO. Less elegant, but I think it will protect
GDB's stack a little more.

> +
> +  return copy;
> +}
> +
>  /* Recursively copy (deep copy) TYPE, if it is associated with
>     OBJFILE.  Return a new type allocated using malloc, a saved type if
>     we have already visited TYPE (using COPIED_TYPES), or TYPE if it is
> @@ -4325,14 +4377,10 @@ copy_type_recursive (struct objfile *objfile,
>        *TYPE_RANGE_DATA (new_type) = *TYPE_RANGE_DATA (type);
>      }
>  
> -  /* Copy the data location information.  */
> -  if (TYPE_DATA_LOCATION (type) != NULL)
> -    {
> -      TYPE_DATA_LOCATION (new_type)
> -	= TYPE_ALLOC (new_type, sizeof (struct dynamic_prop));
> -      memcpy (TYPE_DATA_LOCATION (new_type), TYPE_DATA_LOCATION (type),
> -	      sizeof (struct dynamic_prop));
> -    }
> +  if (TYPE_DYN_PROP_LIST (type) != NULL)
> +    TYPE_DYN_PROP_LIST (new_type)
> +      = copy_dynamic_prop_list (TYPE_DYN_PROP_LIST (type));
> +
>  
>    /* Copy pointers to other types.  */
>    if (TYPE_TARGET_TYPE (type))
> @@ -4396,13 +4444,9 @@ copy_type (const struct type *type)
>    TYPE_LENGTH (new_type) = TYPE_LENGTH (type);
>    memcpy (TYPE_MAIN_TYPE (new_type), TYPE_MAIN_TYPE (type),
>  	  sizeof (struct main_type));
> -  if (TYPE_DATA_LOCATION (type) != NULL)
> -    {
> -      TYPE_DATA_LOCATION (new_type)
> -	= TYPE_ALLOC (new_type, sizeof (struct dynamic_prop));
> -      memcpy (TYPE_DATA_LOCATION (new_type), TYPE_DATA_LOCATION (type),
> -	      sizeof (struct dynamic_prop));
> -    }
> +  if (TYPE_DYN_PROP_LIST (type) != NULL)
> +    TYPE_DYN_PROP_LIST (new_type)
> +      = copy_dynamic_prop_list (TYPE_DYN_PROP_LIST (type));
>  
>    return new_type;
>  }
> diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> index 2c5ccf4..c852c5d 100644
> --- a/gdb/gdbtypes.h
> +++ b/gdb/gdbtypes.h
> @@ -434,6 +434,21 @@ struct dynamic_prop
>    union dynamic_prop_data data;
>  };
>  
> +/* * Define a type's dynamic property node kind.  */
> +enum dynamic_prop_node_kind
> +{
> +  /* A property providing a type's data location.
> +     Evaluating this field yields to the location of an object's data.  */
> +  DYN_ATTR_DATA_LOCATION,
> +};
> +
> +/* * List for dynamic type attributes.  */
> +struct dynamic_prop_list
> +{
> +  enum dynamic_prop_node_kind prop_kind;
> +  struct dynamic_prop *prop;
> +  struct dynamic_prop_list *next;
> +};

OK with keeping it a pointer for now.

>  
>  /* * Determine which field of the union main_type.fields[x].loc is
>     used.  */
> @@ -719,10 +734,8 @@ struct main_type
>  
>    union type_specific type_specific;
>  
> -  /* * Contains a location description value for the current type. Evaluating
> -     this field yields to the location of the data for an object.  */
> -
> -  struct dynamic_prop *data_location;
> +  /* * Contains all dynamic type properties.  */
> +  struct dynamic_prop_list *dyn_prop_list;
>  };
>  
>  /* * A ``struct type'' describes a particular instance of a type, with
> @@ -1238,9 +1251,9 @@ extern void allocate_gnat_aux_type (struct type *);
>  #define TYPE_LOW_BOUND_KIND(range_type) \
>    TYPE_RANGE_DATA(range_type)->low.kind
>  
> -/* Attribute accessors for the type data location.  */
> +/* Property accessors for the type data location.  */
>  #define TYPE_DATA_LOCATION(thistype) \
> -  TYPE_MAIN_TYPE(thistype)->data_location
> +  get_dyn_prop (DYN_ATTR_DATA_LOCATION, thistype)
>  #define TYPE_DATA_LOCATION_BATON(thistype) \
>    TYPE_DATA_LOCATION (thistype)->data.baton
>  #define TYPE_DATA_LOCATION_ADDR(thistype) \
> @@ -1248,6 +1261,17 @@ extern void allocate_gnat_aux_type (struct type *);
>  #define TYPE_DATA_LOCATION_KIND(thistype) \
>    TYPE_DATA_LOCATION (thistype)->kind
>  
> +/* Attribute accessors for dynamic properties.  */
> +#define TYPE_DYN_PROP_LIST(thistype) \
> +  TYPE_MAIN_TYPE(thistype)->dyn_prop_list
> +#define TYPE_DYN_PROP_BATON(dynprop) \
> +  dynprop->data.baton
> +#define TYPE_DYN_PROP_ADDR(dynprop) \
> +  dynprop->data.const_val
> +#define TYPE_DYN_PROP_KIND(dynprop) \
> +  dynprop->kind
> +
> +
>  /* Moto-specific stuff for FORTRAN arrays.  */
>  
>  #define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \
> @@ -1767,6 +1791,18 @@ extern struct type *resolve_dynamic_type (struct type *type, CORE_ADDR addr);
>  /* * Predicate if the type has dynamic values, which are not resolved yet.  */
>  extern int is_dynamic_type (struct type *type);
>  
> +/* * Fetch a dynamic property of a type from the dynamic attribute
> +   list.  */
> +extern struct dynamic_prop *get_dyn_prop
> +  (enum dynamic_prop_node_kind kind, const struct type *type);
> +
> +/* * Add a dynamic property to a type.  */
> +extern void add_dyn_prop (enum dynamic_prop_node_kind kind,
> +  struct dynamic_prop prop, struct type *type, struct objfile *objfile);

extern void add_dyn_prop
  (enum dynamic_prop_node_kind kind, struct dynamic_prop prop,
   struct type *type, struct objfile *objfile);

> +
> +extern struct dynamic_prop_list *copy_dynamic_prop_list
> +  (struct dynamic_prop_list *list);

You'll be able to delete this declaration.

> +
>  extern struct type *check_typedef (struct type *);
>  
>  #define CHECK_TYPEDEF(TYPE)			\
> -- 
> 1.7.9.5
diff mbox

Patch

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 071f97b..370143d 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -22084,11 +22084,7 @@  set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   /* Read DW_AT_data_location and set in type.  */
   attr = dwarf2_attr (die, DW_AT_data_location, cu);
   if (attr_to_dynamic_prop (attr, die, cu, &prop))
-    {
-      TYPE_DATA_LOCATION (type)
-        = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));
-      *TYPE_DATA_LOCATION (type) = prop;
-    }
+    add_dyn_prop (DYN_ATTR_DATA_LOCATION, prop, type, objfile);
 
   if (dwarf2_per_objfile->die_type_hash == NULL)
     {
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 24f64be..20bdc20 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -2025,7 +2025,7 @@  resolve_dynamic_type_internal (struct type *type,
 {
   struct type *real_type = check_typedef (type);
   struct type *resolved_type = type;
-  const struct dynamic_prop *prop;
+  struct dynamic_prop *prop;
   CORE_ADDR value;
 
   if (!is_dynamic_type_internal (real_type, top_level))
@@ -2080,13 +2080,11 @@  resolve_dynamic_type_internal (struct type *type,
 
   /* Resolve data_location attribute.  */
   prop = TYPE_DATA_LOCATION (resolved_type);
-  if (dwarf2_evaluate_property (prop, addr_stack, &value))
+  if (prop != NULL && dwarf2_evaluate_property (prop, addr_stack, &value))
     {
-      TYPE_DATA_LOCATION_ADDR (resolved_type) = value;
-      TYPE_DATA_LOCATION_KIND (resolved_type) = PROP_CONST;
+      TYPE_DYN_PROP_ADDR (prop) = value;
+      TYPE_DYN_PROP_KIND (prop) = PROP_CONST;
     }
-  else
-    TYPE_DATA_LOCATION (resolved_type) = NULL;
 
   return resolved_type;
 }
@@ -2101,6 +2099,41 @@  resolve_dynamic_type (struct type *type, CORE_ADDR addr)
   return resolve_dynamic_type_internal (type, &pinfo, 1);
 }
 
+/* See gdbtypes.h  */
+
+struct dynamic_prop *
+get_dyn_prop (enum dynamic_prop_node_kind prop_kind, const struct type *type)
+{
+  struct dynamic_prop_list *node
+    = TYPE_DYN_PROP_LIST (type);
+
+  while (node != NULL)
+    {
+      if (node->prop_kind == prop_kind)
+        return node->prop;
+      node = node->next;
+    }
+  return NULL;
+}
+
+/* See gdbtypes.h  */
+
+void
+add_dyn_prop (enum dynamic_prop_node_kind prop_kind, struct dynamic_prop prop,
+              struct type *type, struct objfile *objfile)
+{
+  struct dynamic_prop_list *temp
+    = obstack_alloc (&objfile->objfile_obstack,
+              sizeof (struct dynamic_prop_list));
+  temp->prop = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));
+  *temp->prop = prop;
+  temp->prop_kind = prop_kind;
+
+  temp->next = TYPE_DYN_PROP_LIST (type);
+  TYPE_DYN_PROP_LIST (type) = temp;
+}
+
+
 /* Find the real type of TYPE.  This function returns the real type,
    after removing all layers of typedefs, and completing opaque or stub
    types.  Completion changes the TYPE argument, but stripping of
@@ -4222,6 +4255,25 @@  create_copied_types_hash (struct objfile *objfile)
 			       dummy_obstack_deallocate);
 }
 
+/* Recursively copy (deep copy) a dynamic attribute list of a type.  */
+
+struct dynamic_prop_list *
+copy_dynamic_prop_list (struct dynamic_prop_list *list)
+{
+  struct dynamic_prop_list *copy;
+
+  copy = xmalloc (sizeof (struct dynamic_prop_list));
+  *copy = *list;
+
+  copy->prop = xmalloc (sizeof (struct dynamic_prop));
+  *(copy->prop) = *(list->prop);
+
+  if (list->next != NULL)
+    copy->next = copy_dynamic_prop_list (list->next);
+
+  return copy;
+}
+
 /* Recursively copy (deep copy) TYPE, if it is associated with
    OBJFILE.  Return a new type allocated using malloc, a saved type if
    we have already visited TYPE (using COPIED_TYPES), or TYPE if it is
@@ -4325,14 +4377,10 @@  copy_type_recursive (struct objfile *objfile,
       *TYPE_RANGE_DATA (new_type) = *TYPE_RANGE_DATA (type);
     }
 
-  /* Copy the data location information.  */
-  if (TYPE_DATA_LOCATION (type) != NULL)
-    {
-      TYPE_DATA_LOCATION (new_type)
-	= TYPE_ALLOC (new_type, sizeof (struct dynamic_prop));
-      memcpy (TYPE_DATA_LOCATION (new_type), TYPE_DATA_LOCATION (type),
-	      sizeof (struct dynamic_prop));
-    }
+  if (TYPE_DYN_PROP_LIST (type) != NULL)
+    TYPE_DYN_PROP_LIST (new_type)
+      = copy_dynamic_prop_list (TYPE_DYN_PROP_LIST (type));
+
 
   /* Copy pointers to other types.  */
   if (TYPE_TARGET_TYPE (type))
@@ -4396,13 +4444,9 @@  copy_type (const struct type *type)
   TYPE_LENGTH (new_type) = TYPE_LENGTH (type);
   memcpy (TYPE_MAIN_TYPE (new_type), TYPE_MAIN_TYPE (type),
 	  sizeof (struct main_type));
-  if (TYPE_DATA_LOCATION (type) != NULL)
-    {
-      TYPE_DATA_LOCATION (new_type)
-	= TYPE_ALLOC (new_type, sizeof (struct dynamic_prop));
-      memcpy (TYPE_DATA_LOCATION (new_type), TYPE_DATA_LOCATION (type),
-	      sizeof (struct dynamic_prop));
-    }
+  if (TYPE_DYN_PROP_LIST (type) != NULL)
+    TYPE_DYN_PROP_LIST (new_type)
+      = copy_dynamic_prop_list (TYPE_DYN_PROP_LIST (type));
 
   return new_type;
 }
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 2c5ccf4..c852c5d 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -434,6 +434,21 @@  struct dynamic_prop
   union dynamic_prop_data data;
 };
 
+/* * Define a type's dynamic property node kind.  */
+enum dynamic_prop_node_kind
+{
+  /* A property providing a type's data location.
+     Evaluating this field yields to the location of an object's data.  */
+  DYN_ATTR_DATA_LOCATION,
+};
+
+/* * List for dynamic type attributes.  */
+struct dynamic_prop_list
+{
+  enum dynamic_prop_node_kind prop_kind;
+  struct dynamic_prop *prop;
+  struct dynamic_prop_list *next;
+};
 
 /* * Determine which field of the union main_type.fields[x].loc is
    used.  */
@@ -719,10 +734,8 @@  struct main_type
 
   union type_specific type_specific;
 
-  /* * Contains a location description value for the current type. Evaluating
-     this field yields to the location of the data for an object.  */
-
-  struct dynamic_prop *data_location;
+  /* * Contains all dynamic type properties.  */
+  struct dynamic_prop_list *dyn_prop_list;
 };
 
 /* * A ``struct type'' describes a particular instance of a type, with
@@ -1238,9 +1251,9 @@  extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_LOW_BOUND_KIND(range_type) \
   TYPE_RANGE_DATA(range_type)->low.kind
 
-/* Attribute accessors for the type data location.  */
+/* Property accessors for the type data location.  */
 #define TYPE_DATA_LOCATION(thistype) \
-  TYPE_MAIN_TYPE(thistype)->data_location
+  get_dyn_prop (DYN_ATTR_DATA_LOCATION, thistype)
 #define TYPE_DATA_LOCATION_BATON(thistype) \
   TYPE_DATA_LOCATION (thistype)->data.baton
 #define TYPE_DATA_LOCATION_ADDR(thistype) \
@@ -1248,6 +1261,17 @@  extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_DATA_LOCATION_KIND(thistype) \
   TYPE_DATA_LOCATION (thistype)->kind
 
+/* Attribute accessors for dynamic properties.  */
+#define TYPE_DYN_PROP_LIST(thistype) \
+  TYPE_MAIN_TYPE(thistype)->dyn_prop_list
+#define TYPE_DYN_PROP_BATON(dynprop) \
+  dynprop->data.baton
+#define TYPE_DYN_PROP_ADDR(dynprop) \
+  dynprop->data.const_val
+#define TYPE_DYN_PROP_KIND(dynprop) \
+  dynprop->kind
+
+
 /* Moto-specific stuff for FORTRAN arrays.  */
 
 #define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \
@@ -1767,6 +1791,18 @@  extern struct type *resolve_dynamic_type (struct type *type, CORE_ADDR addr);
 /* * Predicate if the type has dynamic values, which are not resolved yet.  */
 extern int is_dynamic_type (struct type *type);
 
+/* * Fetch a dynamic property of a type from the dynamic attribute
+   list.  */
+extern struct dynamic_prop *get_dyn_prop
+  (enum dynamic_prop_node_kind kind, const struct type *type);
+
+/* * Add a dynamic property to a type.  */
+extern void add_dyn_prop (enum dynamic_prop_node_kind kind,
+  struct dynamic_prop prop, struct type *type, struct objfile *objfile);
+
+extern struct dynamic_prop_list *copy_dynamic_prop_list
+  (struct dynamic_prop_list *list);
+
 extern struct type *check_typedef (struct type *);
 
 #define CHECK_TYPEDEF(TYPE)			\