Patch for IA64 32-bit function descriptors

Jessica Han jessica@cup.hp.com
Tue Jun 4 14:28:00 GMT 2002


I've updated the patch with Richard and Benjamin's comments. It contains two
parts: part 1 is for g++, part 2 is for libstdc++-v3, they have to go
together.   Pleaser review and check it in if ok. Thanks.

----
Jessica Han
Open Source Tools
Hewlett-Packard
(408) 447-6154

Part 1. g++
2002-06-04 Jessica Han <jessica@cup.hp.com>
	* config/ia64/hpux.h Use 4 word function descriptors, define
        TARGET_VTABLE_ENTRY_ALIGN, TARGET_VTABLE_DATA_ENTRY_DISTANCE for
        handling IA64 32-bit mode.
	* defaults.h Define TARGET_VTABLE_ENTRY_ALIGN and
        TARGET_VTABLE_DATA_ENTRY_DISTANCE.
	* cp/class.c Make IA64 32-bit vtable looks the same as 64-bit.
	* cp/rtti.c  Make IA64 32-bit vtable looks the same as 64-bit.
	* testsuite/g++.old-deja/g++.abi/vtabl2.C Test the IA64 32-bit vtable
        layout specially.
	* doc/tm.texi Define TARGET_VTABLE_ENTRY_ALIGN and
        TARGET_VTABLE_DATA_ENTRY_DISTANCE.

--- hpux.h.1.8	Tue Jun  4 12:04:29 2002
+++ hpux.h	Tue Jun  4 12:10:13 2002
@@ -121,3 +121,36 @@ Boston, MA 02111-1307, USA.  */

 #undef PAD_VARARGS_DOWN
 #define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
+
+/* Function descriptors are always 16 bytes */
+#undef TARGET_VTABLE_USES_DESCRIPTORS
+#define TARGET_VTABLE_USES_DESCRIPTORS  (TARGET_ILP32 ? 4 : 2)
+
+/* vtable entries are 8 byte aligned at 32-bit mode */
+#undef TARGET_VTABLE_ENTRY_ALIGN
+#define TARGET_VTABLE_ENTRY_ALIGN ( TARGET_ILP32 ? (POINTER_SIZE*2) :
POINTER_SIZE)
+
+/* at 32-bit mode, there are 4 bytes of zeros after each vtable entry */
+#undef TARGET_VTABLE_DATA_ENTRY_DISTANCE
+#define TARGET_VTABLE_DATA_ENTRY_DISTANCE ( TARGET_ILP32 ? 2 : 1)
+
+/* Output part N of a function descriptor for DECL.  For ia64, both
+   words are emitted with a single relocation, so ignore N > 0.  */
+
+#undef ASM_OUTPUT_FDESC
+#define ASM_OUTPUT_FDESC(FILE, DECL, PART)                              \
+do {                                                                    \
+  if ((PART) == 0)                                                      \
+    {                                                                   \
+      if (TARGET_ILP32)                                                 \
+        fputs ("\tdata8.ua @iplt(", FILE);                              \
+      else                                                              \
+        fputs ("\tdata16.ua @iplt(", FILE);                             \
+      assemble_name (FILE, XSTR (XEXP (DECL_RTL (DECL), 0), 0));        \
+      fputs (")\n", FILE);                                              \
+      if (TARGET_ILP32)                                                 \
+        fputs ("\tdata8.ua 0\n", FILE);                                 \
+    }                                                                   \
+} while (0)
+
+

--- defaults.h.1.76	Tue Jun  4 12:11:17 2002
+++ defaults.h	Tue Jun  4 12:17:09 2002
@@ -379,6 +379,20 @@ do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNA
 #define TARGET_VTABLE_USES_DESCRIPTORS 0
 #endif

+/* By default, the vtable entries are void pointers, the alignment is the
same
+   as pointer alignment. The value of this macro says how many bites the
entries
+   should be aligned when special alignment is necessary. */
+#ifndef TARGET_VTABLE_ENTRY_ALIGN
+#define TARGET_VTABLE_ENTRY_ALIGN POINTER_SIZE
+#endif
+
+/* By default, a vtable entry is a void pointer, we can find the next
vtable
+   entry by adding the size of 1 pointer. The value of this macro says how
many
+   pointers we should pass to find the next valid vtable entry. */
+#ifndef TARGET_VTABLE_DATA_ENTRY_DISTANCE
+#define TARGET_VTABLE_DATA_ENTRY_DISTANCE 1
+#endif
+
 /* Select a format to encode pointers in exception handling data.  We
    prefer those that result in fewer dynamic relocations.  Assume no
    special support here and encode direct references.  */


--- class.c.1.449	Tue Jun  4 12:19:46 2002
+++ class.c	Tue Jun  4 14:18:28 2002
@@ -7254,6 +7254,7 @@ build_ctor_vtbl_group (binfo, t)
      constructing the addresses of secondary vtables in the
      construction vtable group.  */
   vtbl = build_vtable (t, id, ptr_type_node);
+  DECL_ALIGN(vtbl) = TARGET_VTABLE_ENTRY_ALIGN;
   list = build_tree_list (vtbl, NULL_TREE);
   accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
 			 binfo, t, list);
@@ -7499,8 +7500,9 @@ build_vtbl_initializer (binfo, orig_binf
   vid.last_init = &vid.inits;
   vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
   vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
-  /* The first vbase or vcall offset is at index -3 in the vtable.  */
-  vid.index = ssize_int (-3);
+  /* The first vbase or vcall offset is at index -3 in the vtable at 64 bit
+     mode and -6 at IA64 32-bit mode because of the padding.  */
+  vid.index = ssize_int (-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);

   /* Add entries to the vtable for RTTI.  */
   build_rtti_vtbl_entries (binfo, &vid);
@@ -7520,6 +7522,30 @@ build_vtbl_initializer (binfo, orig_binf
        vbase = TREE_CHAIN (vbase))
     CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));

+  /* HP Linker requires that vtable info 8-byte aligned on IA64 at both
+     32-bit and 64 bit mode. We put a 4-byte zero after each entry of the
+     vtable to make gcc generate aCC like vtables at 32-bit, thus HP linker
can
+     recognize them properly.
+   */
+  if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
+  {
+    tree current = vid.inits;
+    tree prev ;
+    tree next;
+    prev = current;
+    while (current){
+      tree tt = build_tree_list(NULL_TREE, integer_zero_node);
+      next = TREE_CHAIN(current);
+      if (current != vid.inits)
+        TREE_CHAIN(prev) = tt;
+      else
+        vid.inits=tt;
+      TREE_CHAIN(tt)=current;
+      prev = current;
+      current = next;
+    }
+  }
+
   if (non_fn_entries_p)
     *non_fn_entries_p = list_length (vid.inits);

@@ -7736,8 +7762,9 @@ build_vbase_offset_vtbl_entries (binfo,
 	    abort ();
 	}

-      /* The next vbase will come at a more negative offset.  */
-      vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
+      /* The next vbase will come at a more negative offset. 1 vtable entry
+         at 64-bit mode, 2 vtable entries at IA64 32-bit mode */
+      vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int
(TARGET_VTABLE_DATA_ENTRY_DISTANCE) );

       /* The initializer is the delta from BINFO to this virtual base.
 	 The vbase offsets go in reverse inheritance-graph order, and
@@ -7958,8 +7985,10 @@ add_vcall_offset_vtbl_entries_1 (binfo,
 	BV_VCALL_INDEX (derived_virtuals) = vid->index;

       /* The next vcall offset will be found at a more negative
-	 offset.  */
-      vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
+	 offset.  1 vtable entry at 64-bit mode, 2 vtable entries at IA64 32-bit
+         mode. */
+      vid->index = size_binop (MINUS_EXPR, vid->index,
+                               ssize_int
(TARGET_VTABLE_DATA_ENTRY_DISTANCE));

       /* Keep track of this function.  */
       VARRAY_PUSH_TREE (vid->fns, derived_virtuals);

--- rtti.c.1.133	Tue Jun  4 12:34:14 2002
+++ rtti.c	Tue Jun  4 12:40:47 2002
@@ -101,8 +101,9 @@ build_headof (exp)
   /* We use this a couple of times below, protect it.  */
   exp = save_expr (exp);

-  /* The offset-to-top field is at index -2 from the vptr.  */
-  index = build_int_2 (-2, -1);
+  /* The offset-to-top field is at index -2 from the vptr at 64-bit mode,
+     -4 at IA64 32-bit mode.  */
+  index = build_int_2 (-2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);

   offset = build_vtbl_ref (build_indirect_ref (exp, NULL), index);

@@ -180,8 +181,9 @@ get_tinfo_decl_dynamic (exp)
       tree t;
       tree index;

-      /* The RTTI information is at index -1.  */
-      index = integer_minus_one_node;
+      /* The RTTI information is at index -1 at 64-bit mode, -2 at IA64
32-bit
+         mode.  */
+      index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
       t = build_vtbl_ref (exp, index);
       TREE_TYPE (t) = build_pointer_type (tinfo_decl_type);
       return t;
@@ -1184,7 +1186,7 @@ create_pseudo_type_info VPARAMS((const c
 		       TREE_TYPE (vtable_decl),
 		       vtable_decl,
 		       size_binop (MULT_EXPR,
-				   size_int (2),
+				   size_int (TARGET_VTABLE_DATA_ENTRY_DISTANCE * 2),
 				   TYPE_SIZE_UNIT (vtable_entry_type)));
   TREE_CONSTANT (vtable_decl) = 1;

--- vtable2.C.1.5	Tue Apr  2 12:29:39 2002
+++ vtable2.C	Tue Jun  4 12:42:14 2002
@@ -130,8 +130,12 @@ void _ZN2S42s1Ev ();
 // IA-64 uses function descriptors not function pointers in its vtables.
 #if defined __ia64__
 #define CMP_VPTR(A, B)	(*(void **)(A) == *(void **)(B))
+#ifdef _LP64
 #define INC_VPTR(A)	((A) += 2)
 #else
+#define INC_VPTR(A)	((A) += 4)
+#endif
+#else
 #define CMP_VPTR(A, B)	(*(A) == (ptrdiff_t)(B))
 #define INC_VPTR(A)	((A) += 1)
 #endif
@@ -145,18 +149,37 @@ int main ()
   // Set vtbl to point at the beginning of S4's primary vtable.
   vptr = (ptrdiff_t **) &s4;
   vtbl = *vptr;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl -= 10;
+#else
   vtbl -= 5;
+#endif

   if (*vtbl++ != ((char*) (S0*) &s4) - (char*) &s4)
     return 1;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   if (*vtbl++ != ((char*) (S1*) &s4) - (char*) &s4)
     return 2;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   if (*vtbl++ != ((char*) (S2*) &s4) - (char*) &s4)
     return 3;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   if (*vtbl++ != 0)
     return 4;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   // Skip the RTTI entry.
   vtbl++;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   if (! CMP_VPTR (vtbl, &_ZN2S32s3Ev))
     return 5;
   INC_VPTR (vtbl);
@@ -166,19 +189,37 @@ int main ()
   // The S1 vbase offset.
   if (*vtbl++ != 0)
     return 7;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   // The S4::s1 vcall offset is negative; once you convert to S2, you
   // have to convert to S4 to find the final overrider.
   if (*vtbl++ != ((char*) &s4 - (char*) (S2*) &s4))
     return 8;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   if (*vtbl++ != 0)
     return 9;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   if (*vtbl++ != 0)
     return 10;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   // Now we're at the S2 offset to top entry.
   if (*vtbl++ != ((char*) &s4 - (char*) (S2*) &s4))
     return 11;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   // Skip the RTTI entry.
   vtbl++;
+#if !defined(_LP64) && defined (__ia64__)
+  vtbl++;
+#endif
   // Skip the remaining virtual functions -- they are thunks.
   INC_VPTR (vtbl);
   INC_VPTR (vtbl);
--- tm.texi.1.136	Tue Jun  4 12:55:53 2002
+++ tm.texi	Tue Jun  4 13:00:46 2002
@@ -1694,6 +1694,21 @@ pointer to which the function's data is

 If vtables are used, the value of this macro should be the number
 of words that the function descriptor occupies.
+
+@findex TARGET_VTABLE_ENTRY_ALIGN
+@item TARGET_VTABLE_ENTRY_ALIGN
+Normally, the C++ compiler uses void pionter vtable entries. This macro
+allows the target to use special alignment in vtables.
+
+If the value of this macro is non-zero, it represents the alignment of
+vtable entries in bits.
+
+@findex TARGET_VTABLE_DATA_ENTRY_DISTANCE
+@item TARGET_VTABLE_DATA_ENTRY_DISTANCE
+Normally, the C++ compiler uses 1 void pointer for each vtable entry. This
+macro allows the target to use special padding in vtables. The default
value
+for this macro is 1, if it is greater than 1, it means there are
TARGET_VTABLE_DATA_ENTRY_DISTANCE-1 zero pointers after each entry.
+
 @end table

 @node Escape Sequences


--------------------------------------------------------------------------
Part 2 libstdc++
2002-06-04 Jessica Han <jessica@cup.hp.com>
	* libsupc++/tinfo.cc  Handle the 8 byte vtable entries in IA64 32-bit
        mode.
--- tinfo.cc.1.9	Tue Apr  2 12:38:38 2002
+++ tinfo.cc	Tue Jun  4 13:02:47 2002
@@ -95,7 +95,13 @@ using namespace abi;
 // have to keep alignments consistent manually.
 struct vtable_prefix {
   ptrdiff_t whole_object;           // offset to most derived object
+#if !defined(_LP64) && defined (__ia64__)
+  ptrdiff_t padding1;           // padding to the offset IA64 32-bit only
+#endif
   const __class_type_info *whole_type;  // pointer to most derived
type_info
+#if !defined(_LP64) && defined (__ia64__)
+  ptrdiff_t padding2;           // padding to the pointer IA64 32-bit only
+#endif
   const void *origin;               // what a class's vptr points to
 };




More information about the Libstdc++ mailing list