virtual base class dwarf2 fix

Mike Stump mrs@windriver.com
Fri Oct 13 16:25:00 GMT 2000


g++ doesn't follow the dwarf2 standard for virtual bases for C++.  The
patch at the end fixes that.  The testcase is below.  The solution
adds a callback to the backend.  The C++ frontend is modified to use
that callback.  The callback is used to smuggle information from the
C++ frontend into the backend.  The information smuggled is the offset
in bytes to the pointer to the virtual base.  Another competing way
would for someone to add virtual bases to the backend more fully.
That would require far more work than I am able to contribute at the
moment.

The change results in the following type of change to the dwarf2
information:

< DW_AT_data_member_location: 2 byte block: 23 0  (DW_OP_plus_uconst: 0)
---
> DW_AT_data_member_location: 3 byte block: 23 8 6  (DW_OP_plus_uconst: 8)

Can I put this in?


extern "C" int printf(const char *...);

class  A
{
public:
    int	a;
};


class	B
{
public:
    int	b;
};


class	C
{
public:
    int	c;
};

class	D: public virtual A, public virtual B, virtual public C
{
    int	d;
public:
    D();
};

D::D() 
{ 
    printf("\n\nClass locations for D (virtual bases.)\n");
    printf("D::D this %p\n",this); 
    printf("D::A %p D::B %p D::C %p \n",(A *)this,(B *)this,(C *)this);
}

class	E: public A, public B, public C
{
    int e;
public:
    E();
};

E::E() 
{ 
    printf("Class locations for E (ordinary bases).\n");
    printf("E::E this %p\n",this);
    printf("E::A %p E::B %p E::C %p \n",(A *)this,(B *)this,(C *)this);
}

int main()
{
    D	*d1heap = new D;
    E	*e1heap = new E;
    
    printf("Classes: %x %x\n", d1heap, e1heap);
}

Doing diffs in .:
*** ./cp/class.c.~1~	Fri Oct 13 15:43:08 2000
--- ./cp/class.c	Fri Oct 13 15:43:27 2000
*************** pushclass (type, modify)
*** 5515,5520 ****
--- 5515,5536 ----
  
    pushlevel_class ();
  
+ int
+ find_vbase_pointer (base, for_type)
+      tree base, for_type;
+ {
+   tree decl;
+   char *name;
+   FORMAT_VBASE_NAME (name, BINFO_TYPE (base));
+   
+   decl = lookup_field (for_type, get_identifier (name), 0, 0);
+   my_friendly_assert (decl != 0, 999);
+   
+   decl = size_binop (FLOOR_DIV_EXPR, DECL_FIELD_BITPOS (decl), size_int (BITS_PER_UNIT));
+   my_friendly_assert (TREE_CODE (decl) == INTEGER_CST, 999);
+   return TREE_INT_CST_LOW (decl);
+ }
+ 
  #if 0
    if (CLASSTYPE_TEMPLATE_INFO (type))
      overload_template_name (type);
*** ./cp/lex.c.~1~	Fri Oct 13 15:43:13 2000
--- ./cp/lex.c	Fri Oct 13 15:43:27 2000
*************** lang_init_options ()
*** 275,280 ****
--- 275,283 ----
    set_message_prefixing_rule (DIAGNOSTICS_SHOW_PREFIX_ONCE);
  }
  
+ int find_vbase_pointer (tree, tree);
+ void set_find_vbase_pointer (int (*)(tree, tree));
+ 
  void
  lang_init ()
  {
*************** lang_init ()
*** 291,296 ****
--- 294,300 ----
  
    if (flag_gnu_xref) GNU_xref_begin (input_filename);
    init_repo (input_filename);
+   set_find_vbase_pointer (find_vbase_pointer);
  }
  
  void
*** ./dwarf2out.c.~1~	Fri Oct 13 15:42:52 2000
--- ./dwarf2out.c	Fri Oct 13 15:50:34 2000
*************** static unsigned HOST_WIDE_INT simple_typ
*** 3421,3427 ****
  static HOST_WIDE_INT field_byte_offset	PARAMS ((tree));
  static void add_AT_location_description	PARAMS ((dw_die_ref,
  						 enum dwarf_attribute, rtx));
! static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
  static void add_const_value_attribute	PARAMS ((dw_die_ref, rtx));
  static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
  static void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree));
--- 3421,3427 ----
  static HOST_WIDE_INT field_byte_offset	PARAMS ((tree));
  static void add_AT_location_description	PARAMS ((dw_die_ref,
  						 enum dwarf_attribute, rtx));
! static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree, tree));
  static void add_const_value_attribute	PARAMS ((dw_die_ref, rtx));
  static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
  static void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree));
*************** static void gen_field_die		PARAMS ((tree
*** 3468,3474 ****
  static void gen_ptr_to_mbr_type_die	PARAMS ((tree, dw_die_ref));
  static dw_die_ref gen_compile_unit_die	PARAMS ((const char *));
  static void gen_string_type_die		PARAMS ((tree, dw_die_ref));
! static void gen_inheritance_die		PARAMS ((tree, dw_die_ref));
  static void gen_member_die		PARAMS ((tree, dw_die_ref));
  static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref));
  static void gen_subroutine_type_die	PARAMS ((tree, dw_die_ref));
--- 3468,3474 ----
  static void gen_ptr_to_mbr_type_die	PARAMS ((tree, dw_die_ref));
  static dw_die_ref gen_compile_unit_die	PARAMS ((const char *));
  static void gen_string_type_die		PARAMS ((tree, dw_die_ref));
! static void gen_inheritance_die		PARAMS ((tree, dw_die_ref, tree));
  static void gen_member_die		PARAMS ((tree, dw_die_ref));
  static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref));
  static void gen_subroutine_type_die	PARAMS ((tree, dw_die_ref));
*************** field_byte_offset (decl)
*** 7573,7578 ****
--- 7573,7598 ----
    return object_offset_in_bytes;
  }
  
+ static int
+ default_find_vbase_pointer (tree decl, tree for_type)
+ {
+   return tree_low_cst (BINFO_OFFSET (decl), 0);
+ }
+ 
+ int (*find_vbase_pointer_func)(tree,tree) = default_find_vbase_pointer;
+ 
+ void
+ set_find_vbase_pointer (int (*func)(tree, tree))
+ {
+   find_vbase_pointer_func = func;
+ }
+ 
+ static int
+ find_vbase_pointer (tree decl, tree for_type)
+ {
+   return (*find_vbase_pointer_func)(decl, for_type);
+ }
+ 
  /* The following routines define various Dwarf attributes and any data
     associated with them.  */
  
*************** add_AT_location_description (die, attr_k
*** 7635,7650 ****
     (See the `bit_offset_attribute' function below).  */
  
  static void
! add_data_member_location_attribute (die, decl)
       register dw_die_ref die;
!      register tree decl;
  {
    register unsigned long offset;
    register dw_loc_descr_ref loc_descr;
    register enum dwarf_location_atom op;
  
    if (TREE_CODE (decl) == TREE_VEC)
!     offset = tree_low_cst (BINFO_OFFSET (decl), 0);
    else
      offset = field_byte_offset (decl);
  
--- 7655,7675 ----
     (See the `bit_offset_attribute' function below).  */
  
  static void
! add_data_member_location_attribute (die, decl, for_type)
       register dw_die_ref die;
!      register tree decl, for_type;
  {
    register unsigned long offset;
    register dw_loc_descr_ref loc_descr;
    register enum dwarf_location_atom op;
  
    if (TREE_CODE (decl) == TREE_VEC)
!     {
!       if (TREE_VIA_VIRTUAL (decl))
! 	offset = find_vbase_pointer (decl, for_type);
!       else
! 	offset = tree_low_cst (BINFO_OFFSET (decl), 0);
!     }
    else
      offset = field_byte_offset (decl);
  
*************** add_data_member_location_attribute (die,
*** 7661,7666 ****
--- 7686,7695 ----
  #endif
  
    loc_descr = new_loc_descr (op, offset, 0);
+   if (TREE_VIA_VIRTUAL (decl))
+     {
+       add_loc_descr (&loc_descr, new_loc_descr (DW_OP_deref, 0, 0));
+     }
    add_AT_loc (die, DW_AT_data_member_location, loc_descr);
  }
  
*************** gen_field_die (decl, context_die)
*** 9557,9563 ****
      }
  
    if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE)
!     add_data_member_location_attribute (decl_die, decl);
  
    if (DECL_ARTIFICIAL (decl))
      add_AT_flag (decl_die, DW_AT_artificial, 1);
--- 9586,9592 ----
      }
  
    if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE)
!     add_data_member_location_attribute (decl_die, decl, 0);
  
    if (DECL_ARTIFICIAL (decl))
      add_AT_flag (decl_die, DW_AT_artificial, 1);
*************** gen_string_type_die (type, context_die)
*** 9694,9707 ****
  /* Generate the DIE for a base class.  */
  
  static void
! gen_inheritance_die (binfo, context_die)
!      register tree binfo;
       register dw_die_ref context_die;
  {
    dw_die_ref die = new_die (DW_TAG_inheritance, context_die);
  
    add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die);
!   add_data_member_location_attribute (die, binfo);
  
    if (TREE_VIA_VIRTUAL (binfo))
      add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
--- 9723,9736 ----
  /* Generate the DIE for a base class.  */
  
  static void
! gen_inheritance_die (binfo, context_die, for_type)
!      register tree binfo, for_type;
       register dw_die_ref context_die;
  {
    dw_die_ref die = new_die (DW_TAG_inheritance, context_die);
  
    add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die);
!   add_data_member_location_attribute (die, binfo, for_type);
  
    if (TREE_VIA_VIRTUAL (binfo))
      add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
*************** gen_member_die (type, context_die)
*** 9742,9748 ****
        register int i;
  
        for (i = 0; i < n_bases; i++)
! 	gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die);
      }
  
    /* Now output info about the data members and type members.  */
--- 9771,9777 ----
        register int i;
  
        for (i = 0; i < n_bases; i++)
! 	gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die, type);
      }
  
    /* Now output info about the data members and type members.  */
--------------


More information about the Gcc-patches mailing list