diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 55 | ||||
-rw-r--r-- | gcc/cp/class.c | 400 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 13 | ||||
-rw-r--r-- | gcc/cp/error.c | 2 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 39 | ||||
-rw-r--r-- | gcc/cp/search.c | 45 | ||||
-rw-r--r-- | gcc/cp/tinfo.cc | 5 | ||||
-rw-r--r-- | gcc/cp/tree.c | 3 |
8 files changed, 275 insertions, 287 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f53dd40..a787eb3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,58 @@ +2000-03-28 Mark Mitchell <mark@codesourcery.com> + + Put RTTI entries at negative offsets in new ABI. + * class.c (dfs_build_vbase_offset_vtbl_entries): Put the first + vbase offset at index -3, not -1. + (build_vtabe_offset_vtbl_entries): Use unmarked_vtable_pathp, not + dfs_vtable_path_unmarked_real_bases_queue_p to walk bases. + (dfs_build_vcall_offset_vtbl_entries): Don't use skip_rtti_stuff. + (build_rtti_vtbl_entries): New function. + (set_rtti_entry): Remove. + (build_primary_vtable): Don't use it. + (build_secondary_vtable): Likewise. + (start_vtable): Remove. + (first_vfun_index): New function. + (set_vindex): Likewise. + (add_virtual_function): Don't call start_vtable. Do call + set_vindex. + (set_primary_base): Rename parameter. + (determine_primary_base): Likewise. + (num_vfun_entries): Don't use skip_rtti_stuff. + (num_extra_vtbl_entries): Include RTTI information. + (build_vtbl_initializer): Use build_rtti_vtbl_entries. + (skip_rtti_stuff): Remove. + (dfs_modify_vtables): Don't use it. + (modify_all_vtables): Don't use start_vtable. Do use set_vindex. + (layout_nonempty_base_or_field): Update size handling. + (create_vtable_ptr): Tweak. + (layout_class_type): Adjust parameter names. + (finish_struct_1): Simplify. + * cp-tree.h (CLASSTYPE_VSIZE): Tweak documentation. + (skip_rtti_stuff): Remove. + (first_vfun_index): New function. + (dfs_vtable_path_unmarked_real_bases_queue_p): Remove. + (dfs_vtable_path_marked_real_bases_queue_p): Remove. + (marked_vtable_pathp): Declare. + (unmarked_vtable_pathp): Likewise. + * error.c (dump_expr): Use first_vfun_index to calculate vtable + offsets. + * rtti.c (build_headof): Look for RTTI at negative offsets. + (get_tinfo_decl_dynamic): Likewise. + (tinfo_base_init): Don't take the address of the TINFO_VTABLE_DECL + here. + (create_pseudo_type_info): Do it here instead. Adjust so that + vptr points at first virtual function. + * search.c (marked_vtable_pathp): Make it global. + (unmarked_vtable_pathp): Likewise. + (dfs_vtable_path_unmarked_real_bases_queue_p): Remove. + (dfs_vtable_path_marked_real_bases_queue_p): Likewise. + (dfs_get_pure_virtuals): Don't use skip_rtti_stuff. + (get_pure_virtuals): Likewise. + (expand_upcast_fixups): Likewise. + * tree.c (debug_binfo): Likewise. + * tinfo.cc (__dynamic_cast): Look for vtable_prefix at appropriate + negative offset. + Sun Mar 26 20:15:26 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> * class.c (check_field_decl): Fix typo. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 1e48e89..a0bbf7f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -80,7 +80,6 @@ static tree build_vtable_entry PARAMS ((tree, tree, tree)); static tree get_vtable_name PARAMS ((tree)); static tree get_derived_offset PARAMS ((tree, tree)); static tree get_basefndecls PARAMS ((tree, tree)); -static void set_rtti_entry PARAMS ((tree, tree, tree)); static int build_primary_vtable PARAMS ((tree, tree)); static int build_secondary_vtable PARAMS ((tree, tree)); static tree dfs_finish_vtbls PARAMS ((tree, void *)); @@ -142,7 +141,6 @@ static tree dfs_vcall_offset_queue_p PARAMS ((tree, void *)); static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *)); static tree build_vcall_offset_vtbl_entries PARAMS ((tree, tree)); static tree dfs_count_virtuals PARAMS ((tree, void *)); -static void start_vtable PARAMS ((tree, int *)); static void layout_vtable_decl PARAMS ((tree, int)); static int num_vfun_entries PARAMS ((tree)); static tree dfs_find_final_overrider PARAMS ((tree, void *)); @@ -162,6 +160,8 @@ static int layout_conflict_p PARAMS ((tree, varray_type)); static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int)); static void layout_empty_base PARAMS ((tree, tree, varray_type)); static void accumulate_vtbl_inits PARAMS ((tree, tree)); +static void set_vindex PARAMS ((tree, tree, int *)); +static tree build_rtti_vtbl_entries PARAMS ((tree, tree)); /* Variables shared between class.c and call.c. */ @@ -279,7 +279,7 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data) base. */ vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list)); if (!TREE_VALUE (list)) - BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0); + BINFO_VPTR_FIELD (vbase) = build_int_2 (-3, 0); else { BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list)); @@ -333,11 +333,11 @@ build_vbase_offset_vtbl_entries (binfo, t) TREE_TYPE (list) = binfo; dfs_walk (binfo, dfs_build_vbase_offset_vtbl_entries, - dfs_vtable_path_unmarked_real_bases_queue_p, + unmarked_vtable_pathp, list); dfs_walk (binfo, dfs_vtable_path_unmark, - dfs_vtable_path_marked_real_bases_queue_p, + marked_vtable_pathp, list); inits = nreverse (TREE_VALUE (list)); @@ -405,9 +405,7 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data) /* We chain the offsets on in reverse order. That's correct -- build_vtbl_initializer will straighten them out. */ - for (virtuals = skip_rtti_stuff (binfo, - BINFO_TYPE (binfo), - NULL); + for (virtuals = BINFO_VIRTUALS (binfo); virtuals; virtuals = TREE_CHAIN (virtuals)) { @@ -486,6 +484,82 @@ build_vcall_offset_vtbl_entries (binfo, t) return vod.inits; } +/* Return vtbl initializers for the RTTI entries coresponding to the + BINFO's vtable. BINFO is a part of the hierarchy dominated by + T. */ + +static tree +build_rtti_vtbl_entries (binfo, t) + tree binfo; + tree t; +{ + tree b; + tree basetype; + tree inits; + tree offset; + tree decl; + tree init; + + basetype = BINFO_TYPE (binfo); + inits = NULL_TREE; + + /* For a COM object there is no RTTI entry. */ + if (CLASSTYPE_COM_INTERFACE (basetype)) + return inits; + + /* To find the complete object, we will first convert to our most + primary base, and then add the offset in the vtbl to that value. */ + b = binfo; + while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b))) + b = BINFO_BASETYPE (b, + CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (b))); + offset = size_diffop (size_zero_node, BINFO_OFFSET (b)); + + /* Add the offset-to-top entry. */ + if (flag_vtable_thunks) + { + /* Convert the offset to look like a function pointer, so that + we can put it in the vtable. */ + init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); + TREE_CONSTANT (init) = 1; + inits = tree_cons (NULL_TREE, init, inits); + } + + /* The second entry is, in the case of the new ABI, the address of + the typeinfo object, or, in the case of the old ABI, a function + which returns a typeinfo object. */ + if (new_abi_rtti_p ()) + { + if (flag_rtti) + decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0); + else + decl = integer_zero_node; + + /* Convert the declaration to a type that can be stored in the + vtable. */ + init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl); + TREE_CONSTANT (init) = 1; + } + else + { + if (flag_rtti) + decl = get_tinfo_decl (t); + else + decl = abort_fndecl; + + /* Convert the declaration to a type that can be stored in the + vtable. */ + init = build1 (ADDR_EXPR, vfunc_ptr_type_node, decl); + TREE_CONSTANT (init) = 1; + init = build_vtable_entry (offset, integer_zero_node, init); + } + + /* Hook the RTTI declaration onto the list. */ + inits = tree_cons (NULL_TREE, init, inits); + + return inits; +} + /* Returns a pointer to the virtual base class of EXP that has the indicated TYPE. EXP is of class type, not a pointer type. */ @@ -945,47 +1019,6 @@ get_derived_offset (binfo, type) return size_binop (MINUS_EXPR, offset1, offset2); } -/* Update the rtti info for this class. */ - -static void -set_rtti_entry (virtuals, offset, type) - tree virtuals, offset, type; -{ - tree decl; - - if (CLASSTYPE_COM_INTERFACE (type)) - return; - - if (flag_rtti) - decl = get_tinfo_decl (type); - else if (!new_abi_rtti_p ()) - /* If someone tries to get RTTI information for a type compiled - without RTTI, they're out of luck. By calling __pure_virtual - in this case, we give a small clue as to what went wrong. We - could consider having a __no_typeinfo function as well, for a - more specific hint. */ - decl = abort_fndecl; - else - /* For the new-abi, we just point to the type_info object. */ - decl = NULL_TREE; - - if (flag_vtable_thunks) - { - /* The first slot holds the offset. */ - BV_DELTA (virtuals) = offset; - BV_VCALL_INDEX (virtuals) = integer_zero_node; - - /* The next node holds the decl. */ - virtuals = TREE_CHAIN (virtuals); - offset = ssize_int (0); - } - - /* This slot holds the function to call. */ - BV_DELTA (virtuals) = offset; - BV_VCALL_INDEX (virtuals) = integer_zero_node; - BV_FN (virtuals) = decl; -} - /* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE. Use NAME for the name of the vtable, and VTABLE_TYPE for its type. */ @@ -1067,8 +1100,6 @@ build_primary_vtable (binfo, type) if (binfo) { - tree offset; - if (BINFO_NEW_VTABLE_MARKED (binfo, type)) /* We have already created a vtable for this base, so there's no need to do it again. */ @@ -1079,11 +1110,6 @@ build_primary_vtable (binfo, type) DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo))); DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (BINFO_VTABLE (binfo))); - - /* Now do rtti stuff. */ - offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE); - offset = size_diffop (size_zero_node, offset); - set_rtti_entry (virtuals, offset, type); } else { @@ -1171,10 +1197,6 @@ build_secondary_vtable (binfo, for_type) else offset = BINFO_OFFSET (binfo); - set_rtti_entry (BINFO_VIRTUALS (binfo), - size_diffop (size_zero_node, offset), - for_type); - /* In the new ABI, secondary vtables are laid out as part of the same structure as the primary vtable. */ if (merge_primary_and_secondary_vtables_p ()) @@ -1349,42 +1371,52 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals) } } -/* Call this function whenever its known that a vtable for T is going - to be needed. It's safe to call it more than once. *HAS_VIRTUAL_P - is initialized to the number of slots that are reserved at the - beginning of the vtable for RTTI information. */ +/* Return the index (in the virtual function table) of the first + virtual function. */ + +int +first_vfun_index (t) + tree t; +{ + /* Under the old ABI, the offset-to-top and RTTI entries are at + indices zero and one; under the new ABI, the first virtual + function is at index zero. */ + if (!CLASSTYPE_COM_INTERFACE (t) && !flag_new_abi) + return flag_vtable_thunks ? 2 : 1; + + return 0; +} + +/* Set DECL_VINDEX for DECL. VINDEX_P is the number of virtual + functions present in the vtable so far. */ static void -start_vtable (t, has_virtual_p) +set_vindex (t, decl, vfuns_p) tree t; - int *has_virtual_p; + tree decl; + int *vfuns_p; { - if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (t)) - { - /* If we are using thunks, use two slots at the front, one - for the offset pointer, one for the tdesc pointer. - For ARM-style vtables, use the same slot for both. */ - if (flag_vtable_thunks) - *has_virtual_p = 2; - else - *has_virtual_p = 1; - } + int vindex; + + vindex = (*vfuns_p)++; + vindex += first_vfun_index (t); + DECL_VINDEX (decl) = build_shared_int_cst (vindex); } /* Add a virtual function to all the appropriate vtables for the class T. DECL_VINDEX(X) should be error_mark_node, if we want to allocate a new slot in our table. If it is error_mark_node, we know that no other function from another vtable is overridden by X. - HAS_VIRTUAL keeps track of how many virtuals there are in our main - vtable for the type, and we build upon the NEW_VIRTUALS list + VFUNS_P keeps track of how many virtuals there are in our + main vtable for the type, and we build upon the NEW_VIRTUALS list and return it. */ static void add_virtual_function (new_virtuals_p, overridden_virtuals_p, - has_virtual, fndecl, t) + vfuns_p, fndecl, t) tree *new_virtuals_p; tree *overridden_virtuals_p; - int *has_virtual; + int *vfuns_p; tree fndecl; tree t; /* Structure type. */ { @@ -1409,10 +1441,8 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p, /* We remember that this was the base sub-object for rtti. */ CLASSTYPE_RTTI (t) = t; - start_vtable (t, has_virtual); - /* Now assign virtual dispatch information. */ - DECL_VINDEX (fndecl) = build_shared_int_cst ((*has_virtual)++); + set_vindex (t, fndecl, vfuns_p); DECL_VIRTUAL_CONTEXT (fndecl) = t; /* Save the state we've computed on the NEW_VIRTUALS list. */ @@ -1969,10 +1999,10 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p, /* Make the Ith baseclass of T its primary base. */ static void -set_primary_base (t, i, has_virtual_p) +set_primary_base (t, i, vfuns_p) tree t; int i; - int *has_virtual_p; + int *vfuns_p; { tree basetype; @@ -1982,15 +2012,15 @@ set_primary_base (t, i, has_virtual_p) TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); TYPE_VFIELD (t) = TYPE_VFIELD (basetype); CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype); - *has_virtual_p = CLASSTYPE_VSIZE (basetype); + *vfuns_p = CLASSTYPE_VSIZE (basetype); } /* Determine the primary class for T. */ static void -determine_primary_base (t, has_virtual_p) +determine_primary_base (t, vfuns_p) tree t; - int *has_virtual_p; + int *vfuns_p; { int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); @@ -1998,7 +2028,7 @@ determine_primary_base (t, has_virtual_p) if (n_baseclasses == 0) return; - *has_virtual_p = 0; + *vfuns_p = 0; for (i = 0; i < n_baseclasses; i++) { @@ -2021,7 +2051,7 @@ determine_primary_base (t, has_virtual_p) if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) { - set_primary_base (t, i, has_virtual_p); + set_primary_base (t, i, vfuns_p); CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype)); } else @@ -2039,8 +2069,8 @@ determine_primary_base (t, has_virtual_p) VF_BASETYPE_VALUE (vfields), CLASSTYPE_VFIELDS (t)); - if (*has_virtual_p == 0) - set_primary_base (t, i, has_virtual_p); + if (*vfuns_p == 0) + set_primary_base (t, i, vfuns_p); } } } @@ -2060,7 +2090,7 @@ determine_primary_base (t, has_virtual_p) if (TREE_VIA_VIRTUAL (base_binfo) && CLASSTYPE_NEARLY_EMPTY_P (basetype)) { - set_primary_base (t, i, has_virtual_p); + set_primary_base (t, i, vfuns_p); CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype)); break; } @@ -2557,9 +2587,7 @@ static int num_vfun_entries (binfo) tree binfo; { - return list_length (skip_rtti_stuff (binfo, - BINFO_TYPE (binfo), - NULL)); + return list_length (BINFO_VIRTUALS (binfo)); } /* Called from num_extra_vtbl_entries via dfs_walk. */ @@ -2609,7 +2637,19 @@ num_extra_vtbl_entries (binfo) entries += vod.offsets; } - return entries ? size_int (entries) : size_zero_node; + /* When laying out COM-compatible classes, there are no RTTI + entries. */ + if (CLASSTYPE_COM_INTERFACE (type)) + ; + /* When using vtable thunks, there are two RTTI entries: the "offset + to top" value and the RTTI entry itself. */ + else if (flag_vtable_thunks) + entries += 2; + /* When not using vtable thunks there is only a single entry. */ + else + entries += 1; + + return size_int (entries); } /* Returns the offset (in bytes) from the beginning of BINFO's vtable @@ -2636,7 +2676,6 @@ build_vtbl_initializer (binfo, t) { tree v = BINFO_VIRTUALS (binfo); tree inits = NULL_TREE; - tree type = BINFO_TYPE (binfo); /* Add entries to the vtable that indicate how to adjust the this pointer when calling a virtual function in this class. */ @@ -2646,48 +2685,8 @@ build_vtbl_initializer (binfo, t) inits = chainon (build_vbase_offset_vtbl_entries (binfo, t), inits); - /* Process the RTTI stuff at the head of the list. If we're not - using vtable thunks, then the RTTI entry is just an ordinary - function, and we can process it just like the other virtual - function entries. */ - if (!CLASSTYPE_COM_INTERFACE (type) && flag_vtable_thunks) - { - tree offset; - tree init; - - /* The first entry is an offset. */ - offset = TREE_PURPOSE (v); - my_friendly_assert (TREE_CODE (offset) == INTEGER_CST, - 19990727); - - /* Convert the offset to look like a function pointer, so that - we can put it in the vtable. */ - init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); - TREE_CONSTANT (init) = 1; - inits = tree_cons (NULL_TREE, init, inits); - - v = TREE_CHAIN (v); - - if (new_abi_rtti_p ()) - { - tree decl = TREE_VALUE (v); - - if (decl) - decl = build_unary_op (ADDR_EXPR, decl, 0); - else - decl = integer_zero_node; - decl = build1 (NOP_EXPR, vfunc_ptr_type_node, decl); - TREE_CONSTANT (decl) = 1; - decl = build_vtable_entry (integer_zero_node, integer_zero_node, - decl); - inits = tree_cons (NULL_TREE, decl, inits); - - v = TREE_CHAIN (v); - } - /* In the old abi the second entry (the tdesc pointer) is - just an ordinary function, so it can be dealt with like the - virtual functions. */ - } + /* Add entries to the vtable for RTTI. */ + inits = chainon (build_rtti_vtbl_entries (binfo, t), inits); /* Go through all the ordinary virtual functions, building up initializers. */ @@ -3048,43 +3047,6 @@ find_final_overrider (t, binfo, fn) return build_tree_list (ffod.overriding_fn, ffod.overriding_base); } -/* Return the BINFO_VIRTUALS list for BINFO, without the RTTI stuff at - the front. If non-NULL, N is set to the number of entries - skipped. */ - -tree -skip_rtti_stuff (binfo, t, n) - tree binfo; - tree t; - HOST_WIDE_INT *n; -{ - tree virtuals; - - if (CLASSTYPE_COM_INTERFACE (t)) - return 0; - - if (n) - *n = 0; - virtuals = BINFO_VIRTUALS (binfo); - if (virtuals) - { - /* We always reserve a slot for the offset/tdesc entry. */ - if (n) - ++*n; - virtuals = TREE_CHAIN (virtuals); - } - if (flag_vtable_thunks && virtuals) - { - /* The second slot is reserved for the tdesc pointer when thunks - are used. */ - if (n) - ++*n; - virtuals = TREE_CHAIN (virtuals); - } - - return virtuals; -} - /* Called via dfs_walk. Returns BINFO if BINFO has the same type as DATA (which is really an _TYPE node). */ @@ -3125,10 +3087,8 @@ dfs_modify_vtables (binfo, data) /* Now, go through each of the virtual functions in the virtual function table for BINFO. Find the final overrider, and update the BINFO_VIRTUALS list appropriately. */ - for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL), - old_virtuals = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (binfo)), - BINFO_TYPE (binfo), - NULL); + for (virtuals = BINFO_VIRTUALS (binfo), + old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo))); virtuals; virtuals = TREE_CHAIN (virtuals), old_virtuals = TREE_CHAIN (old_virtuals)) @@ -3138,17 +3098,16 @@ dfs_modify_vtables (binfo, data) tree overrider; tree vindex; tree delta; - HOST_WIDE_INT vindex_val, i; - + HOST_WIDE_INT vindex_val; + HOST_WIDE_INT i; /* Find the function which originally caused this vtable entry to be present. */ fn = BV_FN (old_virtuals); vindex = DECL_VINDEX (fn); b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn)); - fn = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (b)), - BINFO_TYPE (b), - &i); + fn = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (b))); + i = first_vfun_index (BINFO_TYPE (b)); vindex_val = tree_low_cst (vindex, 0); while (i < vindex_val) { @@ -3195,9 +3154,9 @@ dfs_modify_vtables (binfo, data) which should therefore be appended to the end of the vtable for T. */ static tree -modify_all_vtables (t, has_virtual_p, overridden_virtuals) +modify_all_vtables (t, vfuns_p, overridden_virtuals) tree t; - int *has_virtual_p; + int *vfuns_p; tree overridden_virtuals; { tree binfo; @@ -3224,11 +3183,8 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals) if (BINFO_VIRTUALS (binfo) && !value_member (fn, BINFO_VIRTUALS (binfo))) { - /* We know we need a vtable for this class now. */ - start_vtable (t, has_virtual_p); /* Set the vtable index. */ - DECL_VINDEX (fn) - = build_shared_int_cst ((*has_virtual_p)++); + set_vindex (t, fn, vfuns_p); /* We don't need to convert to a base class when calling this function. */ DECL_VIRTUAL_CONTEXT (fn) = t; @@ -4220,9 +4176,10 @@ layout_nonempty_base_or_field (rli, decl, binfo, v) /* Now that we know where it wil be placed, update its BINFO_OFFSET. */ - offset = convert (ssizetype, byte_position (decl)); + offset = byte_position (decl); if (binfo) - propagate_binfo_offsets (binfo, offset); + propagate_binfo_offsets (binfo, + convert (ssizetype, offset)); /* We have to check to see whether or not there is already something of the same type at the offset we're about to use. @@ -4243,7 +4200,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, v) { /* Undo the propogate_binfo_offsets call. */ offset = size_diffop (size_zero_node, offset); - propagate_binfo_offsets (binfo, offset); + propagate_binfo_offsets (binfo, convert (ssizetype, offset)); /* Strip off the size allocated to this field. That puts us at the first place we could have put the field with @@ -4601,11 +4558,11 @@ check_bases_and_members (t, empty_p) responsibility to do that. */ static tree -create_vtable_ptr (t, empty_p, has_virtual_p, +create_vtable_ptr (t, empty_p, vfuns_p, new_virtuals_p, overridden_virtuals_p) tree t; int *empty_p; - int *has_virtual_p; + int *vfuns_p; tree *new_virtuals_p; tree *overridden_virtuals_p; { @@ -4616,17 +4573,15 @@ create_vtable_ptr (t, empty_p, has_virtual_p, for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn)) if (DECL_VINDEX (fn)) add_virtual_function (new_virtuals_p, overridden_virtuals_p, - has_virtual_p, fn, t); + vfuns_p, fn, t); - /* Even if there weren't any new virtual functions, we might need a + /* If we couldn't find an appropriate base class, create a new field + here. Even if there weren't any new virtual functions, we might need a new virtual function table if we're supposed to include vptrs in all classes that need them. */ - if (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()) - start_vtable (t, has_virtual_p); - - /* If we couldn't find an appropriate base class, create a new field - here. */ - if (*has_virtual_p && !TYPE_VFIELD (t)) + if (!TYPE_VFIELD (t) + && (*vfuns_p + || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()))) { /* We build this decl with vtbl_ptr_type_node, which is a `vtable_entry_type*'. It might seem more precise to use @@ -4972,11 +4927,11 @@ end_of_class (t, include_virtuals_p) pointer. */ static void -layout_class_type (t, empty_p, has_virtual_p, +layout_class_type (t, empty_p, vfuns_p, new_virtuals_p, overridden_virtuals_p) tree t; int *empty_p; - int *has_virtual_p; + int *vfuns_p; tree *new_virtuals_p; tree *overridden_virtuals_p; { @@ -4995,10 +4950,10 @@ layout_class_type (t, empty_p, has_virtual_p, /* If possible, we reuse the virtual function table pointer from one of our base classes. */ - determine_primary_base (t, has_virtual_p); + determine_primary_base (t, vfuns_p); /* Create a pointer to our virtual function table. */ - vptr = create_vtable_ptr (t, empty_p, has_virtual_p, + vptr = create_vtable_ptr (t, empty_p, vfuns_p, new_virtuals_p, overridden_virtuals_p); /* Under the new ABI, the vptr is always the first thing in the @@ -5215,7 +5170,7 @@ finish_struct_1 (t) tree t; { tree x; - int has_virtual; + int vfuns; /* The NEW_VIRTUALS is a TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. Each of these functions is a virtual function declared in T that does not override any virtual function from a @@ -5246,7 +5201,7 @@ finish_struct_1 (t) TYPE_SIZE (t) = NULL_TREE; CLASSTYPE_GOT_SEMICOLON (t) = 0; CLASSTYPE_VFIELD_PARENT (t) = -1; - has_virtual = 0; + vfuns = 0; CLASSTYPE_RTTI (t) = NULL_TREE; /* Do end-of-class semantic processing: checking the validity of the @@ -5254,7 +5209,7 @@ finish_struct_1 (t) check_bases_and_members (t, &empty); /* Layout the class itself. */ - layout_class_type (t, &empty, &has_virtual, + layout_class_type (t, &empty, &vfuns, &new_virtuals, &overridden_virtuals); /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we @@ -5278,7 +5233,7 @@ finish_struct_1 (t) } overridden_virtuals - = modify_all_vtables (t, &has_virtual, nreverse (overridden_virtuals)); + = modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals)); /* If necessary, create the primary vtable for this class. */ if (new_virtuals @@ -5288,22 +5243,7 @@ finish_struct_1 (t) new_virtuals = nreverse (new_virtuals); /* We must enter these virtuals into the table. */ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) - { - if (! CLASSTYPE_COM_INTERFACE (t)) - { - /* The second slot is for the tdesc pointer when thunks - are used. */ - if (flag_vtable_thunks) - new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals); - - /* The first slot is for the rtti offset. */ - new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals); - - set_rtti_entry (new_virtuals, - convert (ssizetype, integer_zero_node), t); - } - build_primary_vtable (NULL_TREE, t); - } + build_primary_vtable (NULL_TREE, t); else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t)) /* Here we know enough to change the type of our virtual function table, but we will wait until later this function. */ @@ -5346,7 +5286,7 @@ finish_struct_1 (t) my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE, 20000116); - CLASSTYPE_VSIZE (t) = has_virtual; + CLASSTYPE_VSIZE (t) = vfuns; /* Entries for virtual functions defined in the primary base are followed by entries for new functions unique to this class. */ TYPE_BINFO_VIRTUALS (t) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 57c711f..0433135 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1545,8 +1545,8 @@ struct lang_type CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \ : NULL_TREE) -/* The number of virtual functions defined for this - _CLASSTYPE node. */ +/* The number of virtual functions present in this classes virtual + function table. */ #define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize) /* A chain of BINFOs for the direct and indirect virtual base classes @@ -3685,8 +3685,7 @@ extern void push_lang_context PARAMS ((tree)); extern void pop_lang_context PARAMS ((void)); extern tree instantiate_type PARAMS ((tree, tree, int)); extern void print_class_statistics PARAMS ((void)); -extern tree skip_rtti_stuff PARAMS ((tree, tree, - HOST_WIDE_INT *)); +extern int first_vfun_index PARAMS ((tree)); extern void build_self_reference PARAMS ((void)); extern void warn_hidden PARAMS ((tree)); extern tree get_enclosing_class PARAMS ((tree)); @@ -4212,11 +4211,9 @@ extern tree dfs_skip_nonprimary_vbases_unmarkedp PARAMS ((tree, void *)); extern tree dfs_skip_nonprimary_vbases_markedp PARAMS ((tree, void *)); extern tree dfs_unmarked_real_bases_queue_p PARAMS ((tree, void *)); extern tree dfs_marked_real_bases_queue_p PARAMS ((tree, void *)); -extern tree dfs_vtable_path_unmarked_real_bases_queue_p - PARAMS ((tree, void *)); -extern tree dfs_vtable_path_marked_real_bases_queue_p - PARAMS ((tree, void *)); extern tree dfs_skip_vbases PARAMS ((tree, void *)); +extern tree marked_vtable_pathp PARAMS ((tree, void *)); +extern tree unmarked_vtable_pathp PARAMS ((tree, void *)); extern void mark_primary_bases PARAMS ((tree)); extern tree convert_pointer_to_vbase PARAMS ((tree, tree)); extern tree find_vbase_instance PARAMS ((tree, tree)); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index a0be98f..5600176 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1857,7 +1857,7 @@ dump_expr (t, flags) t = TYPE_METHOD_BASETYPE (t); virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (t)); - n = tree_low_cst (idx, 0); + n = tree_low_cst (idx, 0) - first_vfun_index (t); /* Map vtable index back one, to allow for the null pointer to member. */ diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 30a972c..ea21756 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -132,6 +132,7 @@ build_headof (exp) tree type = TREE_TYPE (exp); tree aref; tree offset; + tree index; my_friendly_assert (TREE_CODE (type) == POINTER_TYPE, 20000112); type = TREE_TYPE (type); @@ -151,7 +152,15 @@ build_headof (exp) /* We use this a couple of times below, protect it. */ exp = save_expr (exp); - aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node); + /* Under the new ABI, the offset-to-top field is at index -2 from + the vptr. */ + if (new_abi_rtti_p ()) + index = build_int_2 (-2, -1); + /* But under the old ABI, it is at offset zero. */ + else + index = integer_zero_node; + + aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), index); if (flag_vtable_thunks) offset = aref; @@ -230,6 +239,7 @@ get_tinfo_decl_dynamic (exp) { /* build reference to type_info from vtable. */ tree t; + tree index; if (! flag_rtti) error ("taking dynamic typeid of object with -fno-rtti"); @@ -247,10 +257,15 @@ get_tinfo_decl_dynamic (exp) exp = build_indirect_ref (exp, NULL_PTR); } - if (flag_vtable_thunks) - t = build_vfn_ref ((tree *) 0, exp, integer_one_node); + /* The RTTI information is always in the vtable, but it's at + different indices depending on the ABI. */ + if (new_abi_rtti_p ()) + index = minus_one_node; + else if (flag_vtable_thunks) + index = integer_one_node; else - t = build_vfn_ref ((tree *) 0, exp, integer_zero_node); + index = integer_zero_node; + t = build_vfn_ref ((tree *) 0, exp, index); TREE_TYPE (t) = build_pointer_type (tinfo_decl_type); return t; } @@ -1284,8 +1299,7 @@ tinfo_base_init (desc, target) if (TINFO_VTABLE_DECL (desc)) { - tree vtbl_ptr = build_unary_op (ADDR_EXPR, TINFO_VTABLE_DECL (desc), 0); - + tree vtbl_ptr = TINFO_VTABLE_DECL (desc); init = tree_cons (NULL_TREE, vtbl_ptr, init); } @@ -1616,7 +1630,18 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...)) /* Get the vtable decl. */ real_type = xref_tag (class_type_node, get_identifier (real_name), 1); vtable_decl = get_vtable_decl (real_type, /*complete=*/1); - + vtable_decl = build_unary_op (ADDR_EXPR, vtable_decl, 0); + + /* Under the new ABI, we need to point into the middle of the + vtable. */ + if (vbase_offsets_in_vtable_p ()) + { + vtable_decl = build (PLUS_EXPR, TREE_TYPE (vtable_decl), + vtable_decl, + size_extra_vtbl_entries (TYPE_BINFO (real_type))); + TREE_CONSTANT (vtable_decl) = 1; + } + /* First field is the pseudo type_info base class. */ fields[0] = build_lang_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index cafdfc2..14ceff2 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -104,8 +104,6 @@ static void expand_upcast_fixups static void fixup_virtual_upcast_offsets PARAMS ((tree, tree, int, int, tree, tree, tree, tree, tree *)); -static tree marked_vtable_pathp PARAMS ((tree, void *)); -static tree unmarked_vtable_pathp PARAMS ((tree, void *)); static tree marked_new_vtablep PARAMS ((tree, void *)); static tree unmarked_new_vtablep PARAMS ((tree, void *)); static tree marked_pushdecls_p PARAMS ((tree, void *)); @@ -2346,30 +2344,6 @@ dfs_marked_real_bases_queue_p (binfo, data) return binfo ? markedp (binfo, NULL) : NULL_TREE; } -/* Like dfs_unmarked_real_bases_queue_p but walks only into things - that are not BINFO_VTABLE_PATH_MARKED. */ - -tree -dfs_vtable_path_unmarked_real_bases_queue_p (binfo, data) - tree binfo; - void *data; -{ - binfo = get_shared_vbase_if_not_primary (binfo, data); - return binfo ? unmarked_vtable_pathp (binfo, NULL): NULL_TREE; -} - -/* Like dfs_unmarked_real_bases_queue_p but walks only into things - that are BINFO_VTABLE_PATH_MARKED. */ - -tree -dfs_vtable_path_marked_real_bases_queue_p (binfo, data) - tree binfo; - void *data; -{ - binfo = get_shared_vbase_if_not_primary (binfo, data); - return binfo ? marked_vtable_pathp (binfo, NULL): NULL_TREE; -} - /* A queue function that skips all virtual bases (and their bases). */ @@ -2400,9 +2374,7 @@ dfs_get_pure_virtuals (binfo, data) { tree virtuals; - for (virtuals = skip_rtti_stuff (binfo, - BINFO_TYPE (binfo), - NULL); + for (virtuals = BINFO_VIRTUALS (binfo); virtuals; virtuals = TREE_CHAIN (virtuals)) if (DECL_PURE_VIRTUAL_P (TREE_VALUE (virtuals))) @@ -2447,7 +2419,7 @@ get_pure_virtuals (type) { tree virtuals; - for (virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL); + for (virtuals = BINFO_VIRTUALS (vbases); virtuals; virtuals = TREE_CHAIN (virtuals)) { @@ -2527,7 +2499,7 @@ unmarkedp (binfo, data) return !BINFO_MARKED (binfo) ? binfo : NULL_TREE; } -static tree +tree marked_vtable_pathp (binfo, data) tree binfo; void *data ATTRIBUTE_UNUSED; @@ -2535,7 +2507,7 @@ marked_vtable_pathp (binfo, data) return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE; } -static tree +tree unmarked_vtable_pathp (binfo, data) tree binfo; void *data ATTRIBUTE_UNUSED; @@ -2863,9 +2835,10 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t, *vbase_offsets = delta; } - virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n); - - while (virtuals) + for (virtuals = BINFO_VIRTUALS (binfo), + n = first_vfun_index (BINFO_TYPE (binfo)); + virtuals; + virtuals = TREE_CHAIN (virtuals), ++n) { tree current_fndecl = TREE_VALUE (virtuals); @@ -2956,8 +2929,6 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t, finish_expr_stmt (build_modify_expr (new_delta, NOP_EXPR, old_delta)); } - ++n; - virtuals = TREE_CHAIN (virtuals); } } diff --git a/gcc/cp/tinfo.cc b/gcc/cp/tinfo.cc index 90c3058..3bf3c90 100644 --- a/gcc/cp/tinfo.cc +++ b/gcc/cp/tinfo.cc @@ -1100,9 +1100,8 @@ __dynamic_cast (const void *src_ptr, // object started from { const void *vtable = *static_cast <const void *const *> (src_ptr); const vtable_prefix *prefix = - adjust_pointer <vtable_prefix> (vtable, 0); - // FIXME: the above offset should be -offsetof (vtable_prefix, origin)); - // but we don't currently layout vtables correctly. + adjust_pointer <vtable_prefix> (vtable, + -offsetof (vtable_prefix, origin)); const void *whole_ptr = adjust_pointer <void> (src_ptr, prefix->whole_object); const __class_type_info *whole_type = prefix->whole_type; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index d1c7d2d..e27ff7b 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -925,7 +925,8 @@ debug_binfo (elem) else fprintf (stderr, "no vtable decl yet\n"); fprintf (stderr, "virtuals:\n"); - virtuals = skip_rtti_stuff (elem, BINFO_TYPE (elem), &n); + virtuals = BINFO_VIRTUALS (elem); + n = first_vfun_index (BINFO_TYPE (elem)); while (virtuals) { |