diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1995-06-22 22:42:04 -0400 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1995-06-22 22:42:04 -0400 |
commit | b532e7f1dc84b4045b5f2d7cfe4a571bb575b22e (patch) | |
tree | 65a4c9d4828dffec9c1e4ace0d8b06f8f613b564 /gcc | |
parent | e1b7b0cb2e688fac7793af38a4d805a13e36056b (diff) | |
download | gcc-b532e7f1dc84b4045b5f2d7cfe4a571bb575b22e.zip gcc-b532e7f1dc84b4045b5f2d7cfe4a571bb575b22e.tar.gz gcc-b532e7f1dc84b4045b5f2d7cfe4a571bb575b22e.tar.bz2 |
(build_signature_table_constructor): Use DECL_CONTEXT instead of...
(build_signature_table_constructor): Use DECL_CONTEXT instead of
DECL_CLASS_CONTEXT for calculating the vfield offset so abstract
virtual functions are handled correctly.
(build_signature_table_constructor): Store the correct delta in signature table
entries. It does not yet work for classes with virtual base classes as
implementations of signatures.
(build_signature_method_call): Add the delta to the object_ptr before
generating the function call.
(build_signature_method_call): Dereference the optr for the direct and virtual
calls.
(build_signature_table_constructor): Make the tag for default
implementations -1 instead of 2.
(build_signature_method_call): Change the generated conditional expression
correspondingly.
(build_signature_pointer_constructor): Deleted the sorry message that said we
can't handle multiple inheritance for implementations of signatures
(build_signature_method_call): Use the offset from the sigtable entry instead
of the vptr field from the signature pointer for building a virtual function
call.
(build_vptr_ref): Deleted.
(build_signature_pointer_or_reference_type): Deleted construction of the vptr
field.
(build_signature_pointer_constructor): Deleted initialization of/assignment to
the vptr field.
(build_signature_table_constructor): Convert the signature table entry fields
to their correct types.
(build_signature_table_constructor): Don't call digest_init for the fields of
a sigtable entry, it's wasted time.
(build_signature_table_constructor): Correctly set the offset and index fields
of a sigtable entry. Build the constructor the way digest_init does,
digest_init can't handle initializing an anonymous union inside a struct.
(build_signature_method_call): Use the index field instead of the delta field
to get the vtable index.
(build_signature_table_constructor): Rename code and offset to tag and delta,
respectively.
(build_signature_method_call): Ditto. Use above variables.
From-SVN: r10046
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/sig.c | 194 |
1 files changed, 102 insertions, 92 deletions
diff --git a/gcc/cp/sig.c b/gcc/cp/sig.c index 2a12cd3..9f4802c 100644 --- a/gcc/cp/sig.c +++ b/gcc/cp/sig.c @@ -1,5 +1,5 @@ /* Functions dealing with signatures and signature pointers/references. - Copyright (C) 1992, 1995 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Contributed by Gerald Baumgartner (gb@cs.purdue.edu) This file is part of GNU CC. @@ -144,7 +144,6 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp) struct { void * optr; const s * sptr; - vtbl_type_node * vptr; }; A `const' signature pointer/reference is a @@ -152,7 +151,6 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp) struct { const void * optr; const s * sptr; - vtbl_type_node * vptr; }; Similarly, for `volatile' and `const volatile'. @@ -162,7 +160,7 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp) { tree obj_type = build_type_variant (void_type_node, constp, volatilep); tree optr_type = build_pointer_type (obj_type); - tree optr, sptr, vptr; + tree optr, sptr; optr = build_lang_field_decl (FIELD_DECL, get_identifier (SIGNATURE_OPTR_NAME), @@ -171,11 +169,8 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp) DECL_CLASS_CONTEXT (optr) = t; if (m) - { - /* We can share `sptr' and `vptr' among type variants. */ - sptr = TREE_CHAIN (TYPE_FIELDS (m)); - vptr = TREE_CHAIN (sptr); - } + /* We can share the `sptr' field among type variants. */ + sptr = TREE_CHAIN (TYPE_FIELDS (m)); else { tree sig_tbl_type = cp_build_type_variant (to_type, 1, 0); @@ -183,25 +178,16 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp) sptr = build_lang_field_decl (FIELD_DECL, get_identifier (SIGNATURE_SPTR_NAME), build_pointer_type (sig_tbl_type)); - vptr = build_lang_field_decl (FIELD_DECL, - get_identifier (SIGNATURE_VPTR_NAME), - build_pointer_type (vtbl_type_node)); DECL_FIELD_CONTEXT (sptr) = t; DECL_CLASS_CONTEXT (sptr) = t; - DECL_FIELD_CONTEXT (vptr) = t; - DECL_CLASS_CONTEXT (vptr) = t; - TREE_CHAIN (sptr) = vptr; - TREE_CHAIN (vptr) = NULL_TREE; + TREE_CHAIN (sptr) = NULL_TREE; } TREE_CHAIN (optr) = sptr; TYPE_FIELDS (t) = optr; - /* To make `build_vfn_ref' work when building a signature method call. */ - CLASSTYPE_VFIELD (t) = vptr; - DECL_FCONTEXT (CLASSTYPE_VFIELD (t)) = t; TYPE_ALIGN (t) = TYPE_ALIGN (optr_type); - /* A signature pointer/reference isn't a `real' class. */ + /* A signature pointer/reference type isn't a `real' class type. */ IS_AGGR_TYPE (t) = 0; } @@ -573,36 +559,68 @@ build_signature_table_constructor (sig_ty, rhs) } else { - tree code, offset, pfn; + tree tag, delta, pfn, offset, index; + tree tag_decl, delta_decl, pfn_decl, offset_decl, index_decl; if (rhs_method == sig_method) { - code = integer_two_node; - offset = integer_zero_node; + tag = build_unary_op (NEGATE_EXPR, integer_one_node, 0); + delta = integer_zero_node; pfn = build_unary_op (ADDR_EXPR, rhs_method, 0); TREE_TYPE (pfn) = ptr_type_node; offset_p = 0; /* we can't offset the rhs sig table */ } else if (DECL_VINDEX (rhs_method)) { - code = integer_one_node; - offset = DECL_VINDEX (rhs_method); + tag = integer_one_node; + delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method), + rhstype, 1)); pfn = null_pointer_node; + offset = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method), + rhstype, 0)); + index = DECL_VINDEX (rhs_method); } else { - code = integer_zero_node; - offset = integer_zero_node; + tag = integer_zero_node; + delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method), + rhstype, 1)); pfn = build_unary_op (ADDR_EXPR, rhs_method, 0); TREE_TYPE (pfn) = ptr_type_node; TREE_ADDRESSABLE (rhs_method) = 1; } - tbl_entry = tree_cons (NULL_TREE, code, - tree_cons (NULL_TREE, offset, - build_tree_list (NULL_TREE, pfn))); - tbl_entry = build_nt (CONSTRUCTOR, NULL_TREE, tbl_entry); - TREE_HAS_CONSTRUCTOR (tbl_entry) = 1; + /* Since digest_init doesn't handle initializing selected fields + of a struct (i.e., anonymous union), we build the constructor + by hand, without calling digest_init. */ + tag_decl = TYPE_FIELDS (sigtable_entry_type); + delta_decl = TREE_CHAIN (tag_decl); + pfn_decl = TREE_CHAIN (delta_decl); + offset_decl = TREE_CHAIN (pfn_decl); + index_decl = TREE_CHAIN (offset_decl); + + tag = convert (TREE_TYPE (tag_decl), tag); + delta = convert (TREE_TYPE (delta_decl), delta); + + if (DECL_VINDEX (rhs_method)) + { + offset = convert (TREE_TYPE (offset_decl), offset); + index = convert (TREE_TYPE (index_decl), index); + + tbl_entry = tree_cons (offset_decl, offset, + build_tree_list (index_decl, index)); + } + else + { + pfn = convert (TREE_TYPE (pfn_decl), pfn); + + tbl_entry = build_tree_list (pfn_decl, pfn); + } + tbl_entry = tree_cons (tag_decl, tag, + tree_cons (delta_decl, delta, tbl_entry)); + tbl_entry = build (CONSTRUCTOR, sigtable_entry_type, + NULL_TREE, tbl_entry); + TREE_CONSTANT (tbl_entry) = 1; } @@ -744,7 +762,7 @@ build_signature_pointer_constructor (lhs, rhs) tree lhstype = initp ? lhs : TREE_TYPE (lhs); tree rhstype = TREE_TYPE (rhs); tree sig_ty = SIGNATURE_TYPE (lhstype); - tree sig_tbl, sptr_expr, optr_expr, vptr_expr; + tree sig_tbl, sptr_expr, optr_expr; tree result; if (! ((TREE_CODE (rhstype) == POINTER_TYPE @@ -781,7 +799,6 @@ build_signature_pointer_constructor (lhs, rhs) /* LHS and RHS are signature pointers/refs of the same signature. */ optr_expr = build_optr_ref (rhs); sptr_expr = build_sptr_ref (rhs); - vptr_expr = build_vptr_ref (rhs); } else { @@ -805,19 +822,10 @@ build_signature_pointer_constructor (lhs, rhs) else sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0); TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty); - vptr_expr = build_vptr_ref (rhs); } } else { - tree rhs_vptr; - - if (TYPE_USES_COMPLEX_INHERITANCE (TREE_TYPE (rhstype))) - { - sorry ("class with multiple inheritance as implementation of signature"); - return error_mark_node; - } - sig_tbl = build_sigtable (sig_ty, TREE_TYPE (rhstype), rhs); if (sig_tbl == error_mark_node) return error_mark_node; @@ -832,22 +840,12 @@ build_signature_pointer_constructor (lhs, rhs) } else sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0); - if (CLASSTYPE_VFIELD (TREE_TYPE (rhstype))) - { - rhs_vptr = DECL_NAME (CLASSTYPE_VFIELD (TREE_TYPE (rhstype))); - vptr_expr = build_component_ref (build_indirect_ref (rhs, 0), - rhs_vptr, NULL_TREE, 0); - } - else - vptr_expr = copy_node (null_pointer_node); - TREE_TYPE (vptr_expr) = build_pointer_type (vtbl_type_node); } if (initp) { result = tree_cons (NULL_TREE, optr_expr, - tree_cons (NULL_TREE, sptr_expr, - build_tree_list (NULL_TREE, vptr_expr))); + build_tree_list (NULL_TREE, sptr_expr)); result = build_nt (CONSTRUCTOR, NULL_TREE, result); TREE_HAS_CONSTRUCTOR (result) = 1; result = digest_init (lhstype, result, 0); @@ -861,14 +859,10 @@ build_signature_pointer_constructor (lhs, rhs) optr_expr); sptr_expr = build_modify_expr (build_sptr_ref (lhs), NOP_EXPR, sptr_expr); - vptr_expr = build_modify_expr (build_vptr_ref (lhs), NOP_EXPR, - vptr_expr); result = tree_cons (NULL_TREE, optr_expr, tree_cons (NULL_TREE, sptr_expr, - tree_cons (NULL_TREE, vptr_expr, - build_tree_list (NULL_TREE, - lhs)))); + build_tree_list (NULL_TREE, lhs))); result = build_compound_expr (result); } @@ -911,32 +905,40 @@ build_signature_method_call (basetype, instance, function, parms) tree basetype, instance, function, parms; { tree saved_instance = save_this (instance); /* Create temp for `this'. */ + tree object_ptr = build_optr_ref (saved_instance); + tree new_object_ptr, new_parms; tree signature_tbl_ptr = build_sptr_ref (saved_instance); tree sig_field_name = DECL_NAME (DECL_MEMFUNC_POINTER_TO (function)); tree basetype_path = TYPE_BINFO (basetype); tree tbl_entry = build_component_ref (build1 (INDIRECT_REF, basetype, signature_tbl_ptr), sig_field_name, basetype_path, 1); - tree code, offset, pfn, vfn; + tree tag, delta, pfn, offset, index, vfn; tree deflt_call = NULL_TREE, direct_call, virtual_call, result; - code = build_component_ref (tbl_entry, get_identifier (SIGTABLE_CODE_NAME), - NULL_TREE, 1); - offset = build_component_ref (tbl_entry, - get_identifier (SIGTABLE_OFFSET_NAME), - NULL_TREE, 1); - pfn = build_component_ref (tbl_entry, get_identifier (SIGTABLE_PFN_NAME), - NULL_TREE, 1); + tbl_entry = save_expr (tbl_entry); + tag = build_component_ref (tbl_entry, tag_identifier, NULL_TREE, 1); + delta = build_component_ref (tbl_entry, delta_identifier, NULL_TREE, 1); + pfn = build_component_ref (tbl_entry, pfn_identifier, NULL_TREE, 1); + offset = build_component_ref (tbl_entry, offset_identifier, NULL_TREE, 1); + index = build_component_ref (tbl_entry, index_identifier, NULL_TREE, 1); TREE_TYPE (pfn) = build_pointer_type (TREE_TYPE (function)); if (IS_DEFAULT_IMPLEMENTATION (function)) { pfn = save_expr (pfn); - deflt_call = build_function_call (pfn, - tree_cons (NULL_TREE, saved_instance, - TREE_CHAIN (parms))); + deflt_call = build_function_call (pfn, parms); } + new_object_ptr = build (PLUS_EXPR, TYPE_POINTER_TO (basetype), + convert (ptrdiff_type_node, object_ptr), + convert (ptrdiff_type_node, delta)); + + parms = tree_cons (NULL_TREE, + convert (TYPE_POINTER_TO (basetype), object_ptr), + TREE_CHAIN (parms)); + new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms)); + { /* Cast the signature method to have `this' of a normal pointer type. */ tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))); @@ -946,11 +948,31 @@ build_signature_method_call (basetype, instance, function, parms) TYPE_READONLY (old_this), TYPE_VOLATILE (old_this)); - direct_call = build_function_call (pfn, parms); + direct_call = build_function_call (pfn, new_parms); + + { + tree vfld, vtbl, aref; + + vfld = build (PLUS_EXPR, + build_pointer_type (build_pointer_type (vtbl_type_node)), + convert (ptrdiff_type_node, object_ptr), + convert (ptrdiff_type_node, offset)); + vtbl = build_indirect_ref (build_indirect_ref (vfld, NULL_PTR), + NULL_PTR); + aref = build_array_ref (vtbl, index); + + if (flag_vtable_thunks) + vfn = aref; + else + vfn = build_component_ref (aref, pfn_identifier, 0, 0); + + TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function)); - vfn = build_vfn_ref (&TREE_VALUE (parms), saved_instance, offset); - TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function)); - virtual_call = build_function_call (vfn, parms); + if (flag_vtable_thunks) + virtual_call = build_function_call (vfn, parms); + else + virtual_call = build_function_call (vfn, new_parms); + } /* Undo the cast, make `this' a signature pointer again. */ TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = old_this; @@ -970,16 +992,16 @@ build_signature_method_call (basetype, instance, function, parms) if (IS_DEFAULT_IMPLEMENTATION (function)) { - tree test = build_binary_op_nodefault (EQ_EXPR, code, integer_one_node, - EQ_EXPR); - result = build_conditional_expr (code, + tree test = build_binary_op_nodefault (LT_EXPR, tag, integer_zero_node, + LT_EXPR); + result = build_conditional_expr (tag, build_conditional_expr (test, - virtual_call, - deflt_call), + deflt_call, + virtual_call), direct_call); } else - result = build_conditional_expr (code, virtual_call, direct_call); + result = build_conditional_expr (tag, virtual_call, direct_call); /* If we created a temporary variable for `this', initialize it first. */ if (instance != saved_instance) @@ -1013,15 +1035,3 @@ build_sptr_ref (instance) return build_component_ref (instance, field, NULL_TREE, 1); } - -/* Create a COMPONENT_REF expression for referencing the VPTR field - of a signature pointer or reference. */ - -tree -build_vptr_ref (instance) - tree instance; -{ - tree field = get_identifier (SIGNATURE_VPTR_NAME); - - return build_component_ref (instance, field, NULL_TREE, 1); -} |