aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/ia64/ia64.h18
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/class.c48
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c3
-rw-r--r--gcc/cp/typeck.c6
-rw-r--r--gcc/defaults.h10
-rw-r--r--gcc/doc/tm.texi18
-rw-r--r--gcc/expr.c5
-rw-r--r--gcc/java/ChangeLog6
-rw-r--r--gcc/java/class.c79
-rw-r--r--gcc/java/expr.c11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C18
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable2.C19
-rw-r--r--gcc/tree.def6
-rw-r--r--gcc/varasm.c13
19 files changed, 258 insertions, 31 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c1548ac..8aed647 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h
index 737b1e7..ce8e7f1 100644
--- a/gcc/config/ia64/ia64.h
+++ b/gcc/config/ia64/ia64.h
@@ -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
/* 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)
/* Generating Code for Profiling. */
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f5e7d63..25efd97 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 9caae4b..4273148 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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))
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 0c106c3..ac71fc5 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2662356..525750d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 28236ef..372b8ee 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 8a84565..54dc0ed 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 32dd3e8..f9fef20 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -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. */
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 721e161..cd4ec28 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/expr.c b/gcc/expr.c
index b61fc17..7d23c7a 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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);
}
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index a2ba2a6..fcfb7eb 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -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
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 2e6eadf..260db75 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -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
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index ff0a327..5481289 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 74508a6..ac98003 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
index 6bef481..38f8177 100644
--- a/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
+++ b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
@@ -14,6 +14,16 @@
#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;
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
index 5fe1e14..9847a15 100644
--- a/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
@@ -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) */
diff --git a/gcc/tree.def b/gcc/tree.def
index cd23dd3..4b155b0 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -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)
diff --git a/gcc/varasm.c b/gcc/varasm.c
index f00b596..72ec1a2 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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: