Commit 8e9eff6b by Geoffrey Keating Committed by Geoffrey Keating

cp-tree.h (enum cp_tree_index): Add CPTI_PFN_VFLAG_IDENTIFIER.

	* cp-tree.h (enum cp_tree_index): Add CPTI_PFN_VFLAG_IDENTIFIER.
	(pfn_vflag_identifier): Define.
	Update comment about layout of pointer functions.
	(build_ptrmemfunc1): Update prototype.
	(expand_ptrmemfunc_cst): Update prototype.
	* decl.c (initialize_predefined_identifiers): Initialize
	pfn_vflag_identifier.
	(build_ptrmemfunc_type): When FUNCTION_BOUNDARY < 16, add
	an extra field to the type.
	* expr.c (cplus_expand_constant): Pass 'flag' between
	expand_ptrmemfunc_cst and build_ptrmemfunc1.
	* typeck.c (get_member_function_from_ptrfunc): When
	FUNCTION_BOUNDARY < 16, look at additional field to determine
	if a pointer-to-member is a real pointer or a vtable offset.
	(build_ptrmemfunc1): Add new parameter to contain extra field.
	(build_ptrmemfunc): Pass the extra field around.
	(expand_ptrmemfunc_cst): Add new parameter to return extra field.
	(pfn_from_ptrmemfunc): Ignore the extra field.

From-SVN: r41824
parent 02d208ff
2001-05-03 Geoffrey Keating <geoffk@redhat.com>
* cp-tree.h (enum cp_tree_index): Add CPTI_PFN_VFLAG_IDENTIFIER.
(pfn_vflag_identifier): Define.
Update comment about layout of pointer functions.
(build_ptrmemfunc1): Update prototype.
(expand_ptrmemfunc_cst): Update prototype.
* decl.c (initialize_predefined_identifiers): Initialize
pfn_vflag_identifier.
(build_ptrmemfunc_type): When FUNCTION_BOUNDARY < 16, add
an extra field to the type.
* expr.c (cplus_expand_constant): Pass 'flag' between
expand_ptrmemfunc_cst and build_ptrmemfunc1.
* typeck.c (get_member_function_from_ptrfunc): When
FUNCTION_BOUNDARY < 16, look at additional field to determine
if a pointer-to-member is a real pointer or a vtable offset.
(build_ptrmemfunc1): Add new parameter to contain extra field.
(build_ptrmemfunc): Pass the extra field around.
(expand_ptrmemfunc_cst): Add new parameter to return extra field.
(pfn_from_ptrmemfunc): Ignore the extra field.
2001-05-03 Mark Mitchell <mark@codesourcery.com> 2001-05-03 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (flag_inline_trees): Update documentation. * cp-tree.h (flag_inline_trees): Update documentation.
......
...@@ -611,6 +611,7 @@ enum cp_tree_index ...@@ -611,6 +611,7 @@ enum cp_tree_index
CPTI_NELTS_IDENTIFIER, CPTI_NELTS_IDENTIFIER,
CPTI_THIS_IDENTIFIER, CPTI_THIS_IDENTIFIER,
CPTI_PFN_IDENTIFIER, CPTI_PFN_IDENTIFIER,
CPTI_PFN_VFLAG_IDENTIFIER,
CPTI_PFN_OR_DELTA2_IDENTIFIER, CPTI_PFN_OR_DELTA2_IDENTIFIER,
CPTI_VPTR_IDENTIFIER, CPTI_VPTR_IDENTIFIER,
CPTI_STD_IDENTIFIER, CPTI_STD_IDENTIFIER,
...@@ -735,6 +736,7 @@ extern tree cp_global_trees[CPTI_MAX]; ...@@ -735,6 +736,7 @@ extern tree cp_global_trees[CPTI_MAX];
#define nelts_identifier cp_global_trees[CPTI_NELTS_IDENTIFIER] #define nelts_identifier cp_global_trees[CPTI_NELTS_IDENTIFIER]
#define this_identifier cp_global_trees[CPTI_THIS_IDENTIFIER] #define this_identifier cp_global_trees[CPTI_THIS_IDENTIFIER]
#define pfn_identifier cp_global_trees[CPTI_PFN_IDENTIFIER] #define pfn_identifier cp_global_trees[CPTI_PFN_IDENTIFIER]
#define pfn_vflag_identifier cp_global_trees[CPTI_PFN_VFLAG_IDENTIFIER]
#define pfn_or_delta2_identifier cp_global_trees[CPTI_PFN_OR_DELTA2_IDENTIFIER] #define pfn_or_delta2_identifier cp_global_trees[CPTI_PFN_OR_DELTA2_IDENTIFIER]
#define vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER] #define vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER]
/* The name of the std namespace. */ /* The name of the std namespace. */
...@@ -2618,29 +2620,27 @@ extern int flag_new_for_scope; ...@@ -2618,29 +2620,27 @@ extern int flag_new_for_scope;
/* A pointer-to-function member type looks like: /* A pointer-to-function member type looks like:
struct { struct {
short __delta; __P __pfn;
short __index; ptrdiff_t __delta;
union {
P __pfn;
short __delta2;
} __pfn_or_delta2;
}; };
where P is a POINTER_TYPE to a METHOD_TYPE appropriate for the where P is either a POINTER_TYPE to a METHOD_TYPE appropriate for
pointer to member. The fields are used as follows: the pointer to member, or one plus twice the index into the vtable;
the two cases are distinguished by looking at the least significant
bit of P. When FUNCTION_BOUNDARY is less than 16 (and so it might
happen that the function pointer might naturally have the low bit
set), the type is instead
If __INDEX is -1, then the function to call is non-virtual, and struct {
is located at the address given by __PFN. __P __pfn;
ptrdiff_t __delta;
If __INDEX is zero, then this a NULL pointer-to-member. char __vflag;
};
Otherwise, the function to call is virtual. Then, __DELTA2 gives and __pfn is a pointer to a method when __vflag is zero.
the offset from an instance of the object to the virtual function
table, and __INDEX - 1 is the index into the vtable to use to
find the function.
The value to use for the THIS parameter is the address of the In all cases, the value to use for the THIS parameter is the
object plus __DELTA. address of the object plus __DELTA / 2 .
For example, given: For example, given:
...@@ -2657,27 +2657,9 @@ extern int flag_new_for_scope; ...@@ -2657,27 +2657,9 @@ extern int flag_new_for_scope;
the pointer-to-member for `&S::f' looks like: the pointer-to-member for `&S::f' looks like:
{ 4, -1, { &f__2B2 } }; { &f__2B2, 4, 0 };
The `4' means that given an `S*' you have to add 4 bytes to get to
the address of the `B2*'. Then, the -1 indicates that this is a
non-virtual function. Of course, `&f__2B2' is the name of that
function.
(Of course, the exact values may differ depending on the mangling
scheme, sizes of types, and such.).
Under the new ABI, we do:
struct {
__P __pfn;
ptrdiff_t __delta;
};
(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. */
/* Get the POINTER_TYPE to the METHOD_TYPE associated with this /* Get the POINTER_TYPE to the METHOD_TYPE associated with this
pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true, pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true,
...@@ -4469,8 +4451,10 @@ extern int cp_type_quals PARAMS ((tree)); ...@@ -4469,8 +4451,10 @@ extern int cp_type_quals PARAMS ((tree));
extern int cp_has_mutable_p PARAMS ((tree)); extern int cp_has_mutable_p PARAMS ((tree));
extern int at_least_as_qualified_p PARAMS ((tree, tree)); extern int at_least_as_qualified_p PARAMS ((tree, tree));
extern int more_qualified_p PARAMS ((tree, tree)); extern int more_qualified_p PARAMS ((tree, tree));
extern tree build_ptrmemfunc1 PARAMS ((tree, tree, tree)); extern tree build_ptrmemfunc1 PARAMS ((tree, tree, tree,
extern void expand_ptrmemfunc_cst PARAMS ((tree, tree *, tree *)); tree));
extern void expand_ptrmemfunc_cst PARAMS ((tree, tree *,
tree *, tree *));
extern tree pfn_from_ptrmemfunc PARAMS ((tree)); extern tree pfn_from_ptrmemfunc PARAMS ((tree));
extern tree type_after_usual_arithmetic_conversions PARAMS ((tree, tree)); extern tree type_after_usual_arithmetic_conversions PARAMS ((tree, tree));
extern tree composite_pointer_type PARAMS ((tree, tree, tree, tree, extern tree composite_pointer_type PARAMS ((tree, tree, tree, tree,
......
...@@ -6303,6 +6303,7 @@ initialize_predefined_identifiers () ...@@ -6303,6 +6303,7 @@ initialize_predefined_identifiers ()
{ "nelts", &nelts_identifier, 0 }, { "nelts", &nelts_identifier, 0 },
{ THIS_NAME, &this_identifier, 0 }, { THIS_NAME, &this_identifier, 0 },
{ VTABLE_PFN_NAME, &pfn_identifier, 0 }, { VTABLE_PFN_NAME, &pfn_identifier, 0 },
{ "__vflag", &pfn_vflag_identifier, 0 },
{ "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 }, { "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 },
{ "_vptr", &vptr_identifier, 0 }, { "_vptr", &vptr_identifier, 0 },
{ "__vtt_parm", &vtt_parm_identifier, 0 }, { "__vtt_parm", &vtt_parm_identifier, 0 },
...@@ -9156,7 +9157,14 @@ build_ptrmemfunc_type (type) ...@@ -9156,7 +9157,14 @@ build_ptrmemfunc_type (type)
fields[0] = build_decl (FIELD_DECL, pfn_identifier, type); fields[0] = build_decl (FIELD_DECL, pfn_identifier, type);
fields[1] = build_decl (FIELD_DECL, delta_identifier, fields[1] = build_decl (FIELD_DECL, delta_identifier,
delta_type_node); delta_type_node);
finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node); if (FUNCTION_BOUNDARY < 16)
{
fields[2] = build_decl (FIELD_DECL, pfn_vflag_identifier,
char_type_node);
finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
} else {
finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node);
}
/* Zap out the name so that the back-end will give us the debugging /* Zap out the name so that the back-end will give us the debugging
information for this anonymous RECORD_TYPE. */ information for this anonymous RECORD_TYPE. */
......
...@@ -62,9 +62,10 @@ cplus_expand_constant (cst) ...@@ -62,9 +62,10 @@ cplus_expand_constant (cst)
{ {
tree delta; tree delta;
tree pfn; tree pfn;
tree flag;
expand_ptrmemfunc_cst (cst, &delta, &pfn); expand_ptrmemfunc_cst (cst, &delta, &pfn, &flag);
cst = build_ptrmemfunc1 (type, delta, pfn); cst = build_ptrmemfunc1 (type, delta, pfn, flag);
} }
} }
break; break;
......
...@@ -2909,9 +2909,22 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) ...@@ -2909,9 +2909,22 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
idx = cp_build_binary_op (TRUNC_DIV_EXPR, idx = cp_build_binary_op (TRUNC_DIV_EXPR,
build1 (NOP_EXPR, vtable_index_type, e3), build1 (NOP_EXPR, vtable_index_type, e3),
TYPE_SIZE_UNIT (vtable_entry_type)); TYPE_SIZE_UNIT (vtable_entry_type));
e1 = cp_build_binary_op (BIT_AND_EXPR, if (FUNCTION_BOUNDARY < 16)
build1 (NOP_EXPR, vtable_index_type, e3), {
integer_one_node); tree delta;
tree pfn;
if (TREE_CODE (function) == PTRMEM_CST)
expand_ptrmemfunc_cst (function, &delta, &pfn, &e1);
else
e1 = build_component_ref (function, pfn_vflag_identifier,
NULL_TREE, 0);
}
else
{
e1 = cp_build_binary_op (BIT_AND_EXPR,
build1 (NOP_EXPR, vtable_index_type, e3),
integer_one_node);
}
vtbl = convert_pointer_to (ptr_type_node, instance); vtbl = convert_pointer_to (ptr_type_node, instance);
delta = cp_convert (ptrdiff_type_node, delta = cp_convert (ptrdiff_type_node,
...@@ -5995,23 +6008,34 @@ get_delta_difference (from, to, force) ...@@ -5995,23 +6008,34 @@ get_delta_difference (from, to, force)
the other components as specified. */ the other components as specified. */
tree tree
build_ptrmemfunc1 (type, delta, pfn) build_ptrmemfunc1 (type, delta, pfn, flag)
tree type, delta, pfn; tree type, delta, pfn, flag;
{ {
tree u = NULL_TREE; tree u = NULL_TREE;
tree delta_field; tree delta_field;
tree pfn_field; tree pfn_field;
tree vflag_field;
/* Pull the FIELD_DECLs out of the type. */ /* Pull the FIELD_DECLs out of the type. */
pfn_field = TYPE_FIELDS (type); pfn_field = TYPE_FIELDS (type);
delta_field = TREE_CHAIN (pfn_field); delta_field = TREE_CHAIN (pfn_field);
vflag_field = TREE_CHAIN (delta_field); /* NULL if no such field. */
/* Make sure DELTA has the type we want. */ /* Make sure DELTA has the type we want. */
delta = convert_and_check (delta_type_node, delta); delta = convert_and_check (delta_type_node, delta);
/* Finish creating the initializer. */ /* Finish creating the initializer. */
u = tree_cons (pfn_field, pfn, if (FUNCTION_BOUNDARY < 16)
build_tree_list (delta_field, delta)); {
u = tree_cons (pfn_field, pfn,
tree_cons (delta_field, delta,
build_tree_list (vflag_field, flag)));
}
else
{
u = tree_cons (pfn_field, pfn,
build_tree_list (delta_field, delta));
}
u = build (CONSTRUCTOR, type, NULL_TREE, u); u = build (CONSTRUCTOR, type, NULL_TREE, u);
TREE_CONSTANT (u) = TREE_CONSTANT (pfn) && TREE_CONSTANT (delta); TREE_CONSTANT (u) = TREE_CONSTANT (pfn) && TREE_CONSTANT (delta);
TREE_STATIC (u) = (TREE_CONSTANT (u) TREE_STATIC (u) = (TREE_CONSTANT (u)
...@@ -6047,6 +6071,7 @@ build_ptrmemfunc (type, pfn, force) ...@@ -6047,6 +6071,7 @@ build_ptrmemfunc (type, pfn, force)
{ {
tree delta = NULL_TREE; tree delta = NULL_TREE;
tree npfn = NULL_TREE; tree npfn = NULL_TREE;
tree flag = NULL_TREE;
tree n; tree n;
if (!force if (!force
...@@ -6075,18 +6100,21 @@ build_ptrmemfunc (type, pfn, force) ...@@ -6075,18 +6100,21 @@ build_ptrmemfunc (type, pfn, force)
/* Obtain the function pointer and the current DELTA. */ /* Obtain the function pointer and the current DELTA. */
if (TREE_CODE (pfn) == PTRMEM_CST) if (TREE_CODE (pfn) == PTRMEM_CST)
expand_ptrmemfunc_cst (pfn, &delta, &npfn); expand_ptrmemfunc_cst (pfn, &delta, &npfn, &flag);
else else
{ {
npfn = build_component_ref (pfn, pfn_identifier, NULL_TREE, 0); npfn = build_component_ref (pfn, pfn_identifier, NULL_TREE, 0);
delta = build_component_ref (pfn, delta_identifier, NULL_TREE, 0); delta = build_component_ref (pfn, delta_identifier, NULL_TREE, 0);
if (FUNCTION_BOUNDARY < 16)
flag = build_component_ref (pfn, pfn_vflag_identifier,
NULL_TREE, 0);
} }
/* Under the new ABI, the conversion is easy. Just adjust /* Under the new ABI, the conversion is easy. Just adjust
the DELTA field. */ the DELTA field. */
delta = cp_convert (ptrdiff_type_node, delta); delta = cp_convert (ptrdiff_type_node, delta);
delta = cp_build_binary_op (PLUS_EXPR, delta, n); delta = cp_build_binary_op (PLUS_EXPR, delta, n);
return build_ptrmemfunc1 (to_type, delta, npfn); return build_ptrmemfunc1 (to_type, delta, npfn, flag);
} }
/* Handle null pointer to member function conversions. */ /* Handle null pointer to member function conversions. */
...@@ -6095,7 +6123,8 @@ build_ptrmemfunc (type, pfn, force) ...@@ -6095,7 +6123,8 @@ build_ptrmemfunc (type, pfn, force)
pfn = build_c_cast (type, integer_zero_node); pfn = build_c_cast (type, integer_zero_node);
return build_ptrmemfunc1 (to_type, return build_ptrmemfunc1 (to_type,
integer_zero_node, integer_zero_node,
pfn); pfn,
integer_zero_node);
} }
if (type_unknown_p (pfn)) if (type_unknown_p (pfn))
...@@ -6106,7 +6135,7 @@ build_ptrmemfunc (type, pfn, force) ...@@ -6106,7 +6135,7 @@ build_ptrmemfunc (type, pfn, force)
return make_ptrmem_cst (to_type, fn); return make_ptrmem_cst (to_type, fn);
} }
/* Return the DELTA, IDX, PFN, and DELTA2 values for the PTRMEM_CST /* Return the DELTA, PFN, and FLAG values for the PTRMEM_CST
given by CST. given by CST.
??? There is no consistency as to the types returned for the above ??? There is no consistency as to the types returned for the above
...@@ -6114,10 +6143,11 @@ build_ptrmemfunc (type, pfn, force) ...@@ -6114,10 +6143,11 @@ build_ptrmemfunc (type, pfn, force)
integer_type_node. */ integer_type_node. */
void void
expand_ptrmemfunc_cst (cst, delta, pfn) expand_ptrmemfunc_cst (cst, delta, pfn, flag)
tree cst; tree cst;
tree *delta; tree *delta;
tree *pfn; tree *pfn;
tree *flag;
{ {
tree type = TREE_TYPE (cst); tree type = TREE_TYPE (cst);
tree fn = PTRMEM_CST_MEMBER (cst); tree fn = PTRMEM_CST_MEMBER (cst);
...@@ -6135,7 +6165,10 @@ expand_ptrmemfunc_cst (cst, delta, pfn) ...@@ -6135,7 +6165,10 @@ expand_ptrmemfunc_cst (cst, delta, pfn)
*delta = get_delta_difference (fn_class, ptr_class, /*force=*/0); *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0);
if (!DECL_VIRTUAL_P (fn)) if (!DECL_VIRTUAL_P (fn))
*pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn)); {
*pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
*flag = integer_zero_node;
}
else else
{ {
/* If we're dealing with a virtual function, we have to adjust 'this' /* If we're dealing with a virtual function, we have to adjust 'this'
...@@ -6155,6 +6188,7 @@ expand_ptrmemfunc_cst (cst, delta, pfn) ...@@ -6155,6 +6188,7 @@ expand_ptrmemfunc_cst (cst, delta, pfn)
integer_one_node)); integer_one_node));
*pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
*pfn)); *pfn));
*flag = integer_one_node;
} }
} }
...@@ -6169,8 +6203,9 @@ pfn_from_ptrmemfunc (t) ...@@ -6169,8 +6203,9 @@ pfn_from_ptrmemfunc (t)
{ {
tree delta; tree delta;
tree pfn; tree pfn;
tree flag;
expand_ptrmemfunc_cst (t, &delta, &pfn); expand_ptrmemfunc_cst (t, &delta, &pfn, &flag);
if (pfn) if (pfn)
return pfn; return pfn;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment