From 0d1edf04e982ae14b042e5079feda4ffd334b527 Mon Sep 17 00:00:00 2001 From: geoffk Date: Fri, 4 May 2001 06:28:54 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41824 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 21 +++++++++++++++++++ gcc/cp/cp-tree.h | 64 +++++++++++++++++++++----------------------------------- gcc/cp/decl.c | 10 ++++++++- gcc/cp/expr.c | 5 +++-- gcc/cp/typeck.c | 63 ++++++++++++++++++++++++++++++++++++++++++------------- 5 files changed, 106 insertions(+), 57 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0acfdb9..9030ae6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,24 @@ +2001-05-03 Geoffrey Keating + + * 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 * cp-tree.h (flag_inline_trees): Update documentation. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 05a0d0f..e1b9361 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -611,6 +611,7 @@ enum cp_tree_index CPTI_NELTS_IDENTIFIER, CPTI_THIS_IDENTIFIER, CPTI_PFN_IDENTIFIER, + CPTI_PFN_VFLAG_IDENTIFIER, CPTI_PFN_OR_DELTA2_IDENTIFIER, CPTI_VPTR_IDENTIFIER, CPTI_STD_IDENTIFIER, @@ -735,6 +736,7 @@ extern tree cp_global_trees[CPTI_MAX]; #define nelts_identifier cp_global_trees[CPTI_NELTS_IDENTIFIER] #define this_identifier cp_global_trees[CPTI_THIS_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 vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER] /* The name of the std namespace. */ @@ -2618,29 +2620,27 @@ extern int flag_new_for_scope; /* A pointer-to-function member type looks like: struct { - short __delta; - short __index; - union { - P __pfn; - short __delta2; - } __pfn_or_delta2; + __P __pfn; + ptrdiff_t __delta; }; - where P is a POINTER_TYPE to a METHOD_TYPE appropriate for the - pointer to member. The fields are used as follows: + where P is either a POINTER_TYPE to a METHOD_TYPE appropriate for + 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 - is located at the address given by __PFN. - - If __INDEX is zero, then this a NULL pointer-to-member. + struct { + __P __pfn; + ptrdiff_t __delta; + char __vflag; + }; - Otherwise, the function to call is virtual. Then, __DELTA2 gives - 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. + and __pfn is a pointer to a method when __vflag is zero. - The value to use for the THIS parameter is the address of the - object plus __DELTA. + In all cases, the value to use for the THIS parameter is the + address of the object plus __DELTA / 2 . For example, given: @@ -2657,27 +2657,9 @@ extern int flag_new_for_scope; the pointer-to-member for `&S::f' looks like: - { 4, -1, { &f__2B2 } }; - - 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; - }; + { &f__2B2, 4, 0 }; - (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 pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true, @@ -4469,8 +4451,10 @@ extern int cp_type_quals PARAMS ((tree)); extern int cp_has_mutable_p PARAMS ((tree)); extern int at_least_as_qualified_p PARAMS ((tree, tree)); extern int more_qualified_p PARAMS ((tree, tree)); -extern tree build_ptrmemfunc1 PARAMS ((tree, tree, tree)); -extern void expand_ptrmemfunc_cst PARAMS ((tree, tree *, tree *)); +extern tree build_ptrmemfunc1 PARAMS ((tree, tree, tree, + tree)); +extern void expand_ptrmemfunc_cst PARAMS ((tree, tree *, + tree *, tree *)); extern tree pfn_from_ptrmemfunc PARAMS ((tree)); extern tree type_after_usual_arithmetic_conversions PARAMS ((tree, tree)); extern tree composite_pointer_type PARAMS ((tree, tree, tree, tree, diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 54d84f4..b04206d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6303,6 +6303,7 @@ initialize_predefined_identifiers () { "nelts", &nelts_identifier, 0 }, { THIS_NAME, &this_identifier, 0 }, { VTABLE_PFN_NAME, &pfn_identifier, 0 }, + { "__vflag", &pfn_vflag_identifier, 0 }, { "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 }, { "_vptr", &vptr_identifier, 0 }, { "__vtt_parm", &vtt_parm_identifier, 0 }, @@ -9156,7 +9157,14 @@ build_ptrmemfunc_type (type) fields[0] = build_decl (FIELD_DECL, pfn_identifier, type); fields[1] = build_decl (FIELD_DECL, delta_identifier, 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 information for this anonymous RECORD_TYPE. */ diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 6855160..7163a5b 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -62,9 +62,10 @@ cplus_expand_constant (cst) { tree delta; tree pfn; + tree flag; - expand_ptrmemfunc_cst (cst, &delta, &pfn); - cst = build_ptrmemfunc1 (type, delta, pfn); + expand_ptrmemfunc_cst (cst, &delta, &pfn, &flag); + cst = build_ptrmemfunc1 (type, delta, pfn, flag); } } break; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 440955d..6d010d8 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2909,9 +2909,22 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) 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); + if (FUNCTION_BOUNDARY < 16) + { + 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); delta = cp_convert (ptrdiff_type_node, @@ -5995,23 +6008,34 @@ get_delta_difference (from, to, force) the other components as specified. */ tree -build_ptrmemfunc1 (type, delta, pfn) - tree type, delta, pfn; +build_ptrmemfunc1 (type, delta, pfn, flag) + tree type, delta, pfn, flag; { tree u = NULL_TREE; tree delta_field; tree pfn_field; + tree vflag_field; /* Pull the FIELD_DECLs out of the type. */ pfn_field = TYPE_FIELDS (type); 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. */ delta = convert_and_check (delta_type_node, delta); /* Finish creating the initializer. */ - u = tree_cons (pfn_field, pfn, - build_tree_list (delta_field, delta)); + if (FUNCTION_BOUNDARY < 16) + { + 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); TREE_CONSTANT (u) = TREE_CONSTANT (pfn) && TREE_CONSTANT (delta); TREE_STATIC (u) = (TREE_CONSTANT (u) @@ -6047,6 +6071,7 @@ build_ptrmemfunc (type, pfn, force) { tree delta = NULL_TREE; tree npfn = NULL_TREE; + tree flag = NULL_TREE; tree n; if (!force @@ -6075,18 +6100,21 @@ build_ptrmemfunc (type, pfn, force) /* Obtain the function pointer and the current DELTA. */ if (TREE_CODE (pfn) == PTRMEM_CST) - expand_ptrmemfunc_cst (pfn, &delta, &npfn); + expand_ptrmemfunc_cst (pfn, &delta, &npfn, &flag); else { npfn = build_component_ref (pfn, pfn_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 the DELTA field. */ delta = cp_convert (ptrdiff_type_node, delta); 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. */ @@ -6095,7 +6123,8 @@ build_ptrmemfunc (type, pfn, force) pfn = build_c_cast (type, integer_zero_node); return build_ptrmemfunc1 (to_type, integer_zero_node, - pfn); + pfn, + integer_zero_node); } if (type_unknown_p (pfn)) @@ -6106,7 +6135,7 @@ build_ptrmemfunc (type, pfn, force) 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. ??? There is no consistency as to the types returned for the above @@ -6114,10 +6143,11 @@ build_ptrmemfunc (type, pfn, force) integer_type_node. */ void -expand_ptrmemfunc_cst (cst, delta, pfn) +expand_ptrmemfunc_cst (cst, delta, pfn, flag) tree cst; tree *delta; tree *pfn; + tree *flag; { tree type = TREE_TYPE (cst); tree fn = PTRMEM_CST_MEMBER (cst); @@ -6135,7 +6165,10 @@ expand_ptrmemfunc_cst (cst, delta, pfn) *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0); 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 { /* If we're dealing with a virtual function, we have to adjust 'this' @@ -6155,6 +6188,7 @@ expand_ptrmemfunc_cst (cst, delta, pfn) integer_one_node)); *pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn)); + *flag = integer_one_node; } } @@ -6169,8 +6203,9 @@ pfn_from_ptrmemfunc (t) { tree delta; tree pfn; + tree flag; - expand_ptrmemfunc_cst (t, &delta, &pfn); + expand_ptrmemfunc_cst (t, &delta, &pfn, &flag); if (pfn) return pfn; } -- 2.7.4