gcc/
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 21 Sep 2001 16:58:22 +0000 (16:58 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 21 Sep 2001 16:58:22 +0000 (16:58 +0000)
        * tree.def (FDESC_EXPR): New.
        * expr.c (expand_expr): Handle it.
        * varasm.c (initializer_constant_valid_p): Likewise.
        (output_constant): Likewise.
        * defaults.h (TARGET_VTABLE_USES_DESCRIPTORS): New.
        * config/ia64/ia64.h (TARGET_VTABLE_USES_DESCRIPTORS): New.
        (ASM_OUTPUT_FDESC): New.
        * doc/tm.texi: Document the new macros.
gcc/cp/
        * class.c (set_vindex): Mind TARGET_VTABLE_USES_DESCRIPTORS.
        (build_vtbl_initializer): Likewise.
        (build_vfn_ref): New.
        * cp-tree.h: Declare it.
        * call.c (build_over_call): Use it.
        * decl2.c (mark_vtable_entries): Mark FDESC_EXPR.
        * typeck.c (get_member_function_from_ptrfunc): Mind descriptors.
gcc/java/
        * class.c (get_dispatch_table): Handle function descriptors.
        (build_dtable_decl): Likewise.
        * expr.c (build_invokevirtual): Likewise.
gcc/testsuite/
        * g++.old-deja/g++.abi/ptrmem.C: Update for ia64 c++ abi.
        * g++.old-deja/g++.abi/vtable2.C: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45733 138bc75d-0d04-0410-961f-82ee72b054a4

19 files changed:
gcc/ChangeLog
gcc/config/ia64/ia64.h
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/typeck.c
gcc/defaults.h
gcc/doc/tm.texi
gcc/expr.c
gcc/java/ChangeLog
gcc/java/class.c
gcc/java/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
gcc/tree.def
gcc/varasm.c

index c1548ac..8aed647 100644 (file)
@@ -1,3 +1,14 @@
+2001-09-21  Richard Henderson  <rth@redhat.com>
+
+       * tree.def (FDESC_EXPR): New.
+       * expr.c (expand_expr): Handle it.
+       * varasm.c (initializer_constant_valid_p): Likewise.
+       (output_constant): Likewise.
+       * defaults.h (TARGET_VTABLE_USES_DESCRIPTORS): New.
+       * config/ia64/ia64.h (TARGET_VTABLE_USES_DESCRIPTORS): New.
+       (ASM_OUTPUT_FDESC): New.
+       * doc/tm.texi: Document the new macros.
+
 21-09-2001  Richard Earnshaw  (reanrsha@arm.com)
 
        * cfgcleanup.c (merge_blocks_move_successor_nojumps): Don't leave 
index 737b1e7..ce8e7f1 100644 (file)
@@ -416,6 +416,13 @@ while (0)
 /* A code distinguishing the floating point format of the target machine.  */
 #define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
 
+/* By default, the C++ compiler will use function addresses in the
+   vtable entries.  Setting this non-zero tells the compiler to use
+   function descriptors instead.  The value of this macro says how
+   many words wide the descriptor is (normally 2).  It is assumed 
+   that the address of a function descriptor may be treated as a
+   pointer to a function.  */
+#define TARGET_VTABLE_USES_DESCRIPTORS 2
 \f
 /* Layout of Source Language Data Types */
 
@@ -1534,6 +1541,17 @@ do {                                                                     \
   fprintf (FILE, "\n");                                                        \
 } while (0)
 
+/* Output part N of a function descriptor for DECL.  For ia64, both
+   words are emitted with a single relocation, so ignore N > 0.  */
+#define ASM_OUTPUT_FDESC(FILE, DECL, PART)                             \
+do {                                                                   \
+  if ((PART) == 0)                                                     \
+    {                                                                  \
+      fputs ("\tdata16.ua @iplt(", FILE);                              \
+      assemble_name (FILE, XSTR (XEXP (DECL_RTL (DECL), 0), 0));       \
+      fputs (")\n", FILE);                                             \
+    }                                                                  \
+} while (0)
 \f
 /* Generating Code for Profiling.  */
 
index f5e7d63..25efd97 100644 (file)
@@ -1,3 +1,13 @@
+2001-09-21  Richard Henderson  <rth@redhat.com>
+
+       * class.c (set_vindex): Mind TARGET_VTABLE_USES_DESCRIPTORS.
+       (build_vtbl_initializer): Likewise.
+       (build_vfn_ref): New.
+       * cp-tree.h: Declare it.
+       * call.c (build_over_call): Use it.
+       * decl2.c (mark_vtable_entries): Mark FDESC_EXPR.
+       * typeck.c (get_member_function_from_ptrfunc): Mind descriptors.
+
 Fri Sep 21 08:16:19 2001  J"orn Rennecke <amylaar@redhat.com>
 
        * decl.c (grokdeclarator): Use C syntax for attr_flags declaration.
index 9caae4b..4273148 100644 (file)
@@ -4321,7 +4321,7 @@ build_over_call (cand, args, flags)
       if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
        fn = build_java_interface_fn_ref (fn, *p);
       else
-       fn = build_vtbl_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn));
+       fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn));
       TREE_TYPE (fn) = t;
     }
   else if (DECL_INLINE (fn))
index 0c106c3..ac71fc5 100644 (file)
@@ -459,9 +459,9 @@ build_vtable_entry_ref (basetype, idx)
 }
 
 /* Given an object INSTANCE, return an expression which yields the
-   virtual function vtable element corresponding to INDEX.  There are
-   many special cases for INSTANCE which we take care of here, mainly
-   to avoid creating extra tree nodes when we don't have to.  */
+   vtable element corresponding to INDEX.  There are many special
+   cases for INSTANCE which we take care of here, mainly to avoid
+   creating extra tree nodes when we don't have to.  */
 
 tree
 build_vtbl_ref (instance, idx)
@@ -543,6 +543,24 @@ build_vtbl_ref (instance, idx)
   return aref;
 }
 
+/* Given an object INSTANCE, return an expression which yields a
+   function pointer corresponding to vtable element INDEX.  */
+
+tree
+build_vfn_ref (instance, idx)
+     tree instance, idx;
+{
+  tree aref = build_vtbl_ref (instance, idx);
+
+  /* When using function descriptors, the address of the
+     vtable entry is treated as a function pointer.  */
+  if (TARGET_VTABLE_USES_DESCRIPTORS)
+    return build1 (NOP_EXPR, TREE_TYPE (aref),
+                  build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
+
+  return aref;
+}
+
 /* Return the name of the virtual function table (as an IDENTIFIER_NODE)
    for the given TYPE.  */
 
@@ -823,7 +841,9 @@ set_vindex (decl, vfuns_p)
 {
   int vindex;
 
-  vindex = (*vfuns_p)++;
+  vindex = *vfuns_p;
+  *vfuns_p += (TARGET_VTABLE_USES_DESCRIPTORS
+              ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
   DECL_VINDEX (decl) = build_shared_int_cst (vindex);
 }
 
@@ -7587,7 +7607,25 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
          }
 
       /* And add it to the chain of initializers.  */
-      vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
+      if (TARGET_VTABLE_USES_DESCRIPTORS)
+       {
+         int i;
+         if (init == size_zero_node)
+           for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
+             vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
+         else
+           for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
+             {
+               tree fdesc = build (FDESC_EXPR, vfunc_ptr_type_node,
+                                   TREE_OPERAND (init, 0),
+                                   build_int_2 (i, 0));
+               TREE_CONSTANT (fdesc) = 1;
+
+               vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits);
+             }
+       }
+      else
+        vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
     }
 
   /* The initializers for virtual functions were built up in reverse
index 2662356..525750d 100644 (file)
@@ -3527,6 +3527,7 @@ extern tree perform_implicit_conversion         PARAMS ((tree, tree));
 /* in class.c */
 extern tree build_vbase_path                   PARAMS ((enum tree_code, tree, tree, tree, int));
 extern tree build_vtbl_ref                     PARAMS ((tree, tree));
+extern tree build_vfn_ref                      PARAMS ((tree, tree));
 extern tree get_vtable_decl                     PARAMS ((tree, int));
 extern void add_method                         PARAMS ((tree, tree, int));
 extern int currently_open_class                        PARAMS ((tree));
index 28236ef..372b8ee 100644 (file)
@@ -2168,7 +2168,8 @@ mark_vtable_entries (decl)
       tree fnaddr = TREE_VALUE (entries);
       tree fn;
       
-      if (TREE_CODE (fnaddr) != ADDR_EXPR)
+      if (TREE_CODE (fnaddr) != ADDR_EXPR
+         && TREE_CODE (fnaddr) != FDESC_EXPR)
        /* This entry is an offset: a virtual base class offset, a
           virtual call offset, an RTTI offset, etc.  */
        continue;
index 8a84565..54dc0ed 100644 (file)
@@ -2910,6 +2910,12 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
       vtbl = build_indirect_ref (vtbl, NULL);
       e2 = build_array_ref (vtbl, idx);
 
+      /* When using function descriptors, the address of the
+        vtable entry is treated as a function pointer.  */
+      if (TARGET_VTABLE_USES_DESCRIPTORS)
+       e2 = build1 (NOP_EXPR, TREE_TYPE (e2),
+                    build_unary_op (ADDR_EXPR, e2, /*noconvert=*/1));
+
       TREE_TYPE (e2) = TREE_TYPE (e3);
       e1 = build_conditional_expr (e1, e2, e3);
       
index 32dd3e8..f9fef20 100644 (file)
@@ -358,6 +358,16 @@ do {                                                               \
 #define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
 #endif
 
+/* By default, the C++ compiler will use function addresses in the
+   vtable entries.  Setting this non-zero tells the compiler to use
+   function descriptors instead.  The value of this macro says how
+   many words wide the descriptor is (normally 2).  It is assumed 
+   that the address of a function descriptor may be treated as a
+   pointer to a function.  */
+#ifndef TARGET_VTABLE_USES_DESCRIPTORS
+#define TARGET_VTABLE_USES_DESCRIPTORS 0
+#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.  */
index 721e161..cd4ec28 100644 (file)
@@ -1597,6 +1597,18 @@ In general, you should not have to define this macro.  On architectures
 in which function addresses are always even, according to
 @code{FUNCTION_BOUNDARY}, GCC will automatically define this macro to
 @code{ptrmemfunc_vbit_in_pfn}.
+
+@findex TARGET_VTABLE_USES_DESCRIPTORS
+@item TARGET_VTABLE_USES_DESCRIPTORS
+Normally, the C++ compiler uses function pointers in vtables.  This
+macro allows the target to change to use ``function descriptors'' 
+instead.  Function descriptors are found on targets for whom a
+function pointer is actually a small data structure.  Normally the
+data structure consists of the actual code address plus a data 
+pointer to which the function's data is relative.
+
+If vtables are used, the value of this macro should be the number
+of words that the function descriptor occupies.
 @end table
 
 @node Escape Sequences
@@ -6012,6 +6024,12 @@ If the assembler has a @code{.ascii} pseudo-op as found in the
 Berkeley Unix assembler, do not define the macro
 @code{ASM_OUTPUT_ASCII}.
 
+@findex ASM_OUTPUT_FDESC
+@item ASM_OUTPUT_FDESC (@var{stream}, @var{decl}, @var{n})
+A C statement to output word @var{n} of a function descriptor for
+@var{decl}.  This must be defined if @code{TARGET_VTABLE_USES_DESCRIPTORS}
+is defined, and is otherwise unused.
+
 @findex CONSTANT_POOL_BEFORE_FUNCTION
 @item CONSTANT_POOL_BEFORE_FUNCTION
 You may define this macro as a C expression.  You should define the
index b61fc17..7d23c7a 100644 (file)
@@ -8757,6 +8757,11 @@ expand_expr (exp, target, tmode, modifier)
     case EXC_PTR_EXPR:
       return get_exception_pointer (cfun);
 
+    case FDESC_EXPR:
+      /* Function descriptors are not valid except for as
+        initialization constants, and should not be expanded.  */
+      abort ();
+
     default:
       return (*lang_expand_expr) (exp, original_target, tmode, modifier);
     }
index a2ba2a6..fcfb7eb 100644 (file)
@@ -1,3 +1,9 @@
+2001-09-21  Richard Henderson  <rth@redhat.com>
+
+       * class.c (get_dispatch_table): Handle function descriptors.
+       (build_dtable_decl): Likewise.
+       * expr.c (build_invokevirtual): Likewise.
+
 2001-09-19  Alexandre Petit-Bianco  <apbianco@redhat.com>
 
        * parse.h: (WFL_STRIP_BRACKET): Re-written using
index 2e6eadf..260db75 100644 (file)
@@ -1372,9 +1372,11 @@ get_dispatch_table (type, this_class_addr)
 {
   int abstract_p = CLASS_ABSTRACT (TYPE_NAME (type));
   tree vtable = get_dispatch_vector (type);
-  int i;
+  int i, j;
   tree list = NULL_TREE;
   int nvirtuals = TREE_VEC_LENGTH (vtable);
+  int arraysize;
+
   for (i = nvirtuals;  --i >= 0; )
     {
       tree method = TREE_VEC_ELT (vtable, i);
@@ -1383,27 +1385,52 @@ get_dispatch_table (type, this_class_addr)
          if (! abstract_p)
            warning_with_decl (method,
                               "abstract method in non-abstract class");
-         method = null_pointer_node;
+
+         if (TARGET_VTABLE_USES_DESCRIPTORS)
+           for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j)
+             list = tree_cons (NULL_TREE, null_pointer_node, list);
+         else
+           list = tree_cons (NULL_TREE, null_pointer_node, list);
        }
       else
        {
          if (!DECL_RTL_SET_P (method))
            make_decl_rtl (method, NULL);
-         method = build1 (ADDR_EXPR, nativecode_ptr_type_node, method);
+
+         if (TARGET_VTABLE_USES_DESCRIPTORS)
+           for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j)
+             {
+               tree fdesc = build (FDESC_EXPR, nativecode_ptr_type_node, 
+                                   method, build_int_2 (j, 0));
+               TREE_CONSTANT (fdesc) = 1;
+               list = tree_cons (NULL_TREE, fdesc, list);
+             }
+         else
+           list = tree_cons (NULL_TREE,
+                             build1 (ADDR_EXPR, nativecode_ptr_type_node,
+                                     method),
+                             list);
        }
-      list = tree_cons (NULL_TREE /*DECL_VINDEX (method) + 2*/,
-                       method, list);
     }
+
   /* Dummy entry for compatibility with G++ -fvtable-thunks.  When
      using the Boehm GC we sometimes stash a GC type descriptor
      there. We set the PURPOSE to NULL_TREE not to interfere (reset)
      the emitted byte count during the output to the assembly file. */
-  list = tree_cons (NULL_TREE, get_boehm_type_descriptor (type),
-                   list);
+  for (j = 1; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j)
+    list = tree_cons (NULL_TREE, null_pointer_node, list);
+  list = tree_cons (NULL_TREE, get_boehm_type_descriptor (type), list);
+
+  for (j = 1; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j)
+    list = tree_cons (NULL_TREE, null_pointer_node, list);
   list = tree_cons (integer_zero_node, this_class_addr, list);
-  return build (CONSTRUCTOR, build_prim_array_type (nativecode_ptr_type_node,
-                                                   nvirtuals + 2),
-                NULL_TREE, list);
+
+  arraysize = nvirtuals + 2;
+  if (TARGET_VTABLE_USES_DESCRIPTORS)
+    arraysize *= TARGET_VTABLE_USES_DESCRIPTORS;
+  return build (CONSTRUCTOR,
+               build_prim_array_type (nativecode_ptr_type_node, arraysize),
+               NULL_TREE, list);
 }
 
 void
@@ -1733,13 +1760,37 @@ build_dtable_decl (type)
      TYPE. */
   if (current_class == type)
     {
-      tree dummy = NULL_TREE, aomt, n;
+      tree dummy = NULL_TREE;
+      int n;
 
       dtype = make_node (RECORD_TYPE);
+
       PUSH_FIELD (dtype, dummy, "class", class_ptr_type);
-      n = build_int_2 (TREE_VEC_LENGTH (get_dispatch_vector (type)), 0);
-      aomt = build_array_type (ptr_type_node, build_index_type (n));
-      PUSH_FIELD (dtype, dummy, "methods", aomt);
+      for (n = 1; n < TARGET_VTABLE_USES_DESCRIPTORS; ++n)
+       {
+         tree tmp_field = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node);
+         TREE_CHAIN (dummy) = tmp_field;
+         DECL_CONTEXT (tmp_field) = dtype;
+         DECL_ARTIFICIAL (tmp_field) = 1;
+         dummy = tmp_field;
+       }
+
+      PUSH_FIELD (dtype, dummy, "gc_descr", ptr_type_node);
+      for (n = 1; n < TARGET_VTABLE_USES_DESCRIPTORS; ++n)
+       {
+         tree tmp_field = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node);
+         TREE_CHAIN (dummy) = tmp_field;
+         DECL_CONTEXT (tmp_field) = dtype;
+         DECL_ARTIFICIAL (tmp_field) = 1;
+         dummy = tmp_field;
+       }
+
+      n = TREE_VEC_LENGTH (get_dispatch_vector (type));
+      if (TARGET_VTABLE_USES_DESCRIPTORS)
+       n *= TARGET_VTABLE_USES_DESCRIPTORS;
+
+      PUSH_FIELD (dtype, dummy, "methods",
+                 build_prim_array_type (nativecode_ptr_type_node, n));
       layout_type (dtype);
     }
   else
index ff0a327..5481289 100644 (file)
@@ -1845,9 +1845,18 @@ build_invokevirtual (dtable, method)
   method_index = size_binop (PLUS_EXPR, method_index, size_int (2));
   method_index = size_binop (MULT_EXPR, method_index,
                             TYPE_SIZE_UNIT (nativecode_ptr_ptr_type_node));
+
+  if (TARGET_VTABLE_USES_DESCRIPTORS)
+    method_index = size_binop (MULT_EXPR, method_index,
+                              size_int (TARGET_VTABLE_USES_DESCRIPTORS));
+
   func = fold (build (PLUS_EXPR, nativecode_ptr_ptr_type_node, dtable,
                      convert (nativecode_ptr_ptr_type_node, method_index)));
-  func = build1 (INDIRECT_REF, nativecode_ptr_type_node, func);
+
+  if (TARGET_VTABLE_USES_DESCRIPTORS)
+    func = build1 (NOP_EXPR, nativecode_ptr_type_node, func);
+  else
+    func = build1 (INDIRECT_REF, nativecode_ptr_type_node, func);
 
   return func;
 }
index 74508a6..ac98003 100644 (file)
@@ -1,3 +1,8 @@
+2001-09-21  Richard Henderson  <rth@redhat.com>
+
+       * g++.old-deja/g++.abi/ptrmem.C: Update for ia64 c++ abi.
+       * g++.old-deja/g++.abi/vtable2.C: Likewise.
+
 2001-09-21  Joseph S. Myers  <jsm28@cam.ac.uk>
 
        Table-driven attributes.
index 6bef481..38f8177 100644 (file)
 #define ADJUST_DELTA(delta, virt) (delta)
 #endif
 
+/* IA64 uses function descriptors instead of function pointers in its
+   vtables, which means that we can't meaningfully compare them directly.  */
+#if defined __ia64__
+#define CMP_PTRFN(A, B)        (*(void **)(A) == *(void **)(B))
+#define VPTE_SIZE      (16)
+#else
+#define CMP_PTRFN(A, B) ((A) == (B))
+#define VPTE_SIZE      sizeof(void *)
+#endif
+
 #if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
 
 // Check that pointers-to-member functions are represented correctly.
@@ -85,12 +95,12 @@ main ()
   // There should be no adjustment for the `T' version, and an
   // appropriate adjustment for the `S' version.
   y = &T::f;
-  if (yp->ptr != ADJUST_PTRFN (&_ZN1T1fEv, 0))
+  if (! CMP_PTRFN (yp->ptr, ADJUST_PTRFN (&_ZN1T1fEv, 0)))
     return 5;
   if (yp->adj != ADJUST_DELTA (0, 0))
     return 6;
   x = (sp) y;
-  if (xp->ptr != ADJUST_PTRFN (&_ZN1T1fEv, 0))
+  if (! CMP_PTRFN (xp->ptr, ADJUST_PTRFN (&_ZN1T1fEv, 0)))
     return 7;
   if (xp->adj != ADJUST_DELTA (delta, 0))
     return 8;
@@ -99,12 +109,12 @@ main ()
   // one.  `T::h' is in the second slot: the vtable pointer points to
   // the first virtual function.
   y = &T::h;
-  if (yp->ptr != ADJUST_PTRFN (sizeof (void *), 1))
+  if (yp->ptr != ADJUST_PTRFN (VPTE_SIZE, 1))
     return 9;
   if (yp->adj != ADJUST_DELTA (0, 1))
     return 10;
   x = (sp) y;
-  if (xp->ptr != ADJUST_PTRFN (sizeof (void *), 1))
+  if (xp->ptr != ADJUST_PTRFN (VPTE_SIZE, 1))
     return 11;
   if (xp->adj != ADJUST_DELTA (delta, 1))
     return 12;
index 5fe1e14..9847a15 100644 (file)
@@ -127,6 +127,15 @@ void _ZN2S32s3Ev ();
 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))
+#define INC_VPTR(A)    ((A) += 2)
+#else
+#define CMP_VPTR(A, B) (*(A) == (ptrdiff_t)(B))
+#define INC_VPTR(A)    ((A) += 1)
+#endif
+
 int main ()
 {
   S4 s4;
@@ -148,10 +157,12 @@ int main ()
     return 4;
   // Skip the RTTI entry.
   vtbl++;
-  if (*vtbl++ != (ptrdiff_t) &_ZN2S32s3Ev)
+  if (! CMP_VPTR (vtbl, &_ZN2S32s3Ev))
     return 5;
-  if (*vtbl++ != (ptrdiff_t) &_ZN2S42s1Ev)
+  INC_VPTR (vtbl);
+  if (! CMP_VPTR (vtbl, &_ZN2S42s1Ev))
     return 6;
+  INC_VPTR (vtbl);
   // The S1 vbase offset.
   if (*vtbl++ != 0)
     return 7;
@@ -169,8 +180,8 @@ int main ()
   // Skip the RTTI entry.
   vtbl++;
   // Skip the remaining virtual functions -- they are thunks.
-  vtbl++;
-  vtbl++;
+  INC_VPTR (vtbl);
+  INC_VPTR (vtbl);
 }
 
 #else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
index cd23dd3..4b155b0 100644 (file)
@@ -716,9 +716,13 @@ DEFTREECODE (ADDR_EXPR, "addr_expr", 'e', 1)
 DEFTREECODE (REFERENCE_EXPR, "reference_expr", 'e', 1)
 
 /* Operand is a function constant; result is a function variable value
-   of typeEPmode.  Used only for languages that need static chains.  */
+   of type EPmode.  Used only for languages that need static chains.  */
 DEFTREECODE (ENTRY_VALUE_EXPR, "entry_value_expr", 'e', 1)
 
+/* Operand0 is a function constant; result is part N of a function 
+   descriptor of type ptr_mode.  */
+DEFTREECODE (FDESC_EXPR, "fdesc_expr", 'e', 2)
+
 /* Given two real or integer operands of the same type,
    returns a complex value of the corresponding complex type.  */
 DEFTREECODE (COMPLEX_EXPR, "complex_expr", '2', 2)
index f00b596..72ec1a2 100644 (file)
@@ -4277,6 +4277,7 @@ initializer_constant_valid_p (value, endtype)
       return null_pointer_node;
 
     case ADDR_EXPR:
+    case FDESC_EXPR:
       return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0;
 
     case NON_LVALUE_EXPR:
@@ -4469,6 +4470,18 @@ output_constant (exp, size, align)
       return;
     }
 
+  if (TREE_CODE (exp) == FDESC_EXPR)
+    {
+      HOST_WIDE_INT part = tree_low_cst (TREE_OPERAND (exp, 1), 0);
+      tree decl = TREE_OPERAND (exp, 0);
+#ifdef ASM_OUTPUT_FDESC
+      ASM_OUTPUT_FDESC (asm_out_file, decl, part);
+#else
+      abort ();
+#endif
+      return;
+    }
+
   switch (code)
     {
     case CHAR_TYPE: