aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2001-05-12 10:41:31 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2001-05-12 10:41:31 +0000
commitcb7fdde2d7c297ba9a736e8dfc9de4a4560a7634 (patch)
treeefe6294b4f0878077cd2207e8ab373069a36bb66 /gcc
parentf3c55c97be3655882c12b1f76548694575a301f2 (diff)
downloadgcc-cb7fdde2d7c297ba9a736e8dfc9de4a4560a7634.zip
gcc-cb7fdde2d7c297ba9a736e8dfc9de4a4560a7634.tar.gz
gcc-cb7fdde2d7c297ba9a736e8dfc9de4a4560a7634.tar.bz2
cp-tree.h (ptrmemfunc_vbit_where_t): Declare type.
* cp-tree.h (ptrmemfunc_vbit_where_t): Declare type. * typeck.c (get_member_function_from_ptrfunc, build_ptrmemfunc, expand_ptrmemfunc_cst): Take TARGET_PTRMEMFUNC_VBIT_LOCATION into account. From-SVN: r41990
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/cp-tree.h14
-rw-r--r--gcc/cp/typeck.c71
3 files changed, 76 insertions, 16 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d15bad55..4dffdff 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,4 +1,9 @@
-2001-05-11 Alexandre Oliva <aoliva@redhat.com>
+2001-05-12 Alexandre Oliva <aoliva@redhat.com>
+
+ * cp-tree.h (ptrmemfunc_vbit_where_t): Declare type.
+ * typeck.c (get_member_function_from_ptrfunc,
+ build_ptrmemfunc, expand_ptrmemfunc_cst): Take
+ TARGET_PTRMEMFUNC_VBIT_LOCATION into account.
Reverted Geoff Keating's 2001-05-03's patch.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7e22edc..d313fcd 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2673,7 +2673,19 @@ extern int flag_new_for_scope;
(We don't need DELTA2, because the vtable is always the first thing
in the object.) If the function is virtual, then PFN is one plus
twice the index into the vtable; otherwise, it is just a pointer to
- the function. */
+ the function.
+
+ Unfortunately, using the lowest bit of PFN doesn't work in
+ architectures that don't impose alignment requirements on function
+ addresses, or that use the lowest bit to tell one ISA from another,
+ for example. For such architectures, we use the lowest bit of
+ DELTA instead of the lowest bit of the PFN, and DELTA will be
+ multiplied by 2. */
+enum ptrmemfunc_vbit_where_t
+{
+ ptrmemfunc_vbit_in_pfn,
+ ptrmemfunc_vbit_in_delta
+};
/* Get the POINTER_TYPE to the METHOD_TYPE associated with this
pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true,
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 440955d..209b682 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2894,6 +2894,11 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
e3 = PFN_FROM_PTRMEMFUNC (function);
+ vtbl = convert_pointer_to (ptr_type_node, instance);
+ delta = cp_convert (ptrdiff_type_node,
+ build_component_ref (function, delta_identifier,
+ NULL_TREE, 0));
+
/* This used to avoid checking for virtual functions if basetype
has no virtual functions, according to an earlier ANSI draft.
With the final ISO C++ rules, such an optimization is
@@ -2906,14 +2911,31 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
load-with-sign-extend, while the second used normal load then
shift to sign-extend. An optimizer flaw, perhaps, but it's
easier to make this change. */
- idx = cp_build_binary_op (TRUNC_DIV_EXPR,
- build1 (NOP_EXPR, vtable_index_type, e3),
- TYPE_SIZE_UNIT (vtable_entry_type));
- e1 = cp_build_binary_op (BIT_AND_EXPR,
- build1 (NOP_EXPR, vtable_index_type, e3),
- integer_one_node);
+ switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
+ {
+ case ptrmemfunc_vbit_in_pfn:
+ idx = cp_build_binary_op (TRUNC_DIV_EXPR,
+ build1 (NOP_EXPR, vtable_index_type, e3),
+ TYPE_SIZE_UNIT (vtable_entry_type));
+ e1 = cp_build_binary_op (BIT_AND_EXPR,
+ build1 (NOP_EXPR, vtable_index_type, e3),
+ integer_one_node);
+ break;
+
+ case ptrmemfunc_vbit_in_delta:
+ idx = build1 (NOP_EXPR, vtable_index_type, e3);
+ e1 = cp_build_binary_op (BIT_AND_EXPR,
+ delta, integer_one_node);
+ delta = cp_build_binary_op (RSHIFT_EXPR,
+ build1 (NOP_EXPR, vtable_index_type,
+ delta),
+ integer_one_node);
+ break;
+
+ default:
+ abort ();
+ }
- vtbl = convert_pointer_to (ptr_type_node, instance);
delta = cp_convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier,
NULL_TREE, 0));
@@ -6085,6 +6107,8 @@ build_ptrmemfunc (type, pfn, force)
/* Under the new ABI, the conversion is easy. Just adjust
the DELTA field. */
delta = cp_convert (ptrdiff_type_node, delta);
+ if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
+ n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node);
delta = cp_build_binary_op (PLUS_EXPR, delta, n);
return build_ptrmemfunc1 (to_type, delta, npfn);
}
@@ -6146,13 +6170,32 @@ expand_ptrmemfunc_cst (cst, delta, pfn)
*delta = fold (build (PLUS_EXPR, TREE_TYPE (*delta),
*delta, BINFO_OFFSET (binfo)));
- /* Under the new ABI, we set PFN to the vtable offset, plus
- one, at which the function can be found. */
- *pfn = fold (build (MULT_EXPR, integer_type_node,
- DECL_VINDEX (fn),
- TYPE_SIZE_UNIT (vtable_entry_type)));
- *pfn = fold (build (PLUS_EXPR, integer_type_node, *pfn,
- integer_one_node));
+ /* Under the new ABI, we set PFN to the vtable offset at
+ which the function can be found, plus one (unless
+ ptrmemfunc_vbit_in_delta, in which case delta is shifted
+ left, and then incremented). */
+ *pfn = DECL_VINDEX (fn);
+
+ switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
+ {
+ case ptrmemfunc_vbit_in_pfn:
+ *pfn = fold (build (MULT_EXPR, integer_type_node, *pfn,
+ TYPE_SIZE_UNIT (vtable_entry_type)));
+ *pfn = fold (build (PLUS_EXPR, integer_type_node, *pfn,
+ integer_one_node));
+ break;
+
+ case ptrmemfunc_vbit_in_delta:
+ *delta = fold (build (LSHIFT_EXPR, TREE_TYPE (*delta),
+ *delta, integer_one_node));
+ *delta = fold (build (PLUS_EXPR, TREE_TYPE (*delta),
+ *delta, integer_one_node));
+ break;
+
+ default:
+ abort ();
+ }
+
*pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
*pfn));
}