tree.def (FDESC_EXPR): New.
gcc/ * 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. From-SVN: r45733
This commit is contained in:
parent
2e3b2d2c07
commit
6723181663
19 changed files with 258 additions and 31 deletions
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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)
|
||||
|
|
13
gcc/varasm.c
13
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:
|
||||
|
|
Loading…
Add table
Reference in a new issue