Studying note of GCC-3.4.6 source (142 - continue)
2011-01-15 11:06
316 查看
OK. Now let’s see the output
of GCC for our instance 1.
Example 1:
Vtable for C
C::_ZTV1C: 12u entries
0
0u
// vbase offset
4
0u
// vcall offset
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI1C)
16
C
::_ZTcv0_n12_v0_n16_N1C1fEv
// slot for
C::B1::A::f
20
C
::f
// slot for C::f
24
-4u
28
-4u
32
(int (*)(...))-0x000000004
36
(int (*)(...))(& _ZTI1C)
40
C
::_ZTcvn4_n12_v0_n16_N1C1fEv
// slot for C::B2::A::f
44
C
::_ZTchn4_h4_N1C1fEv
// slot for C::B2::f
… // no VTT for A
VTT for B1
B1::_ZTT2B1:
2u entries
0
((& B1::_ZTV2B1) + 16u)
4
((& B1::_ZTV2B1) + 16u)
…
VTT for B2
B2::_ZTT2B2:
2u entries
0
((& B2::_ZTV2B2) + 16u)
4
((& B2::_ZTV2B2) + 16u)
…
Construction
vtable for B1 (0xb7f2d980
instance) in C
C::_ZTC1C0_2B1: 6u
entries
0
0u
4
0u
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI2B1)
16
B1::_ZTcv0_n12_v0_n16_N2B11fEv
// C::B1::f
20
B1::f
Construction
vtable for B2 (0xb7f2da00
instance) in C
C::_ZTC1C4_2B2: 10u
entries
0
-4u
4
0u
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI2B2)
16
B2::_ZTcv0_n12_v0_n16_N2B21fEv
// C::B2::f
20
B2::f
24
4u
28
(int (*)(...))4
32
(int (*)(...))(& _ZTI2B2)
36
B2::_ZTcv0_n12_v0_n16_N2B21fEv
// C::B2::f
VTT for C
C::_ZTT1C: 7u entries
0
((& C::_ZTV1C) + 16u)
// vptr for C
4
((& C::_ZTC1C0_2B1) + 16u)
// construction vtable used for B1
8
((& C::_ZTC1C0_2B1) + 16u)
// construction vtable used for B1::A
12
((& C::_ZTC1C4_2B2) + 16u)
// construction vtable used for B2
16
((& C::_ZTC1C4_2B2) + 36u)
// construction vtable used for B2::A
20
((& C::_ZTV1C) + 16u)
// vptr for
secondary vtable of B2
24
((& C::_ZTV1C) + 40u)
// vptr for secondary vtable of A
Constructing VTT is done
by below function.
6829
static
void
6830
build_vtt
(tree t)
in
class.c
6831
{
6832
tree inits;
6833
tree type;
6834
tree vtt;
6835
tree index;
6836
6837
/* Build up the
initializers for the VTT.
*/
6838
inits = NULL_TREE;
6839
index = size_zero_node;
6840
build_vtt_inits
(TYPE_BINFO (t), t, &inits, &index);
6841
6842
/* If we didn't
need a VTT, we're done.
*/
6843
if (!inits)
6844
return
;
6845
6846
/* Figure out the
type of the VTT.
*/
6847
type = build_index_type
(size_int (list_length (inits) - 1));
6848
type = build_cplus_array_type
(const_ptr_type_node, type);
6849
6850
/* Now, build the
VTT object itself.
*/
6851
vtt = build_vtable
(t, get_vtt_name (t), type);
6852
initialize_array
(vtt, inits);
6853
/* Add the VTT to
the vtables list.
*/
6854
TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));
6855
TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt;
6856
6857
dump_vtt (t, vtt);
6858
}
So for our example, for class B1, B2 and C, VTT is expected, and its
body is constructed by build_vtt_init
bleow, in which argument binfo
is
the binfo of the most derived class, t
is the most derived class, and index
is
the last index the VTT entries occupied.
6892
static
tree *
6893
build_vtt_inits
(tree binfo, tree t,
tree* inits, tree* index)
in
class.c
6894
{
6895
int i;
6896
tree b;
6897
tree init;
6898
tree secondary_vptrs;
6899
int top_level_p = same_type_p (TREE_TYPE
(binfo), t);
6900
6901
/* We only need VTTs
for subobjects with virtual bases.
*/
6902
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE
(binfo)))
6903
return
inits;
6904
6905
/* We need to use a
construction vtable if this is not the primary
6906
VTT.
*/
6907
if (!top_level_p)
6908
{
6909
build_ctor_vtbl_group
(binfo, t);
6910
6911
/* Record the
offset in the VTT where this sub-VTT can be found.
*/
6912
BINFO_SUBVTT_INDEX (binfo) = *index;
6913
}
6914
6915
/* Add the address
of the primary vtable for the complete object.
*/
6916
init = binfo_ctor_vtable
(binfo);
6917
*inits = build_tree_list (NULL_TREE, init);
6918
inits = &TREE_CHAIN (*inits);
6919
if (top_level_p)
6920
{
6921
my_friendly_assert (!BINFO_VPTR_INDEX
(binfo), 20010129);
6922
BINFO_VPTR_INDEX
(binfo) = *index;
6923
}
6924
*index = size_binop (PLUS_EXPR, *index,
TYPE_SIZE_UNIT (ptr_type_node));
6925
6926
/* Recursively add
the secondary VTTs for non-virtual bases.
*/
6927
for
(i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
6928
{
6929
b = BINFO_BASETYPE (binfo, i);
6930
if (!TREE_VIA_VIRTUAL (b))
6931
inits = build_vtt_inits
(BINFO_BASETYPE (binfo, i), t,
6932
inits, index);
6933
}
In previous section, BINFO_VTABLE of the class is set in dfs_accumulate_vtbl_inits
with vtable initializers. It is a PLUS_EXPR specifies the position in the
initializers for the start point of vtable. At line 6916 above, binfo_ctor_vtable
gets this expression from the class.
6865
static
tree
6866
binfo_ctor_vtable
(tree binfo)
in
class.c
6867
{
6868
tree vt;
6869
6870
while
(1)
6871
{
6872
vt = BINFO_VTABLE (binfo);
6873
if (TREE_CODE (vt) == TREE_LIST)
6874
vt = TREE_VALUE (vt);
6875
if (TREE_CODE (vt) == TREE_VEC)
6876
binfo = vt;
6877
else
6878
break
;
6879
}
6880
6881
return
vt;
6882
}
Above at line 6917, init
returned by binfo_ctor_vtable
is built
in a tree_list; and at line 6917, inits
points to the address of chain
field of this tree_list, so in recursion at line 6931, new nodes will be added
into this chain. Above argument index
is the VTT index where the next element
will be replaced (it is also number of bytes), at beginning it is size_zero_node
.
BINFO_VPTR_INDEX holds the index in the VTT where the vptr for the
subobject can be found. For the most derived class C, its vptr is saved at
index 0. And to non-virtual bases, build_ctor_vtbl_group
does below processing.
7098
static
void
7099
build_ctor_vtbl_group
(tree binfo, tree
t)
in
class.c
7100
{
7101
tree list;
7102
tree type;
7103
tree vtbl;
7104
tree inits;
7105
tree id;
7106
tree vbase;
7107
7108
/* See if we've
already created this construction vtable group.
*/
7109
id = mangle_ctor_vtbl_for_type (t, binfo);
7110
if (IDENTIFIER_GLOBAL_VALUE (id))
7111
return
;
7112
7113
my_friendly_assert (!same_type_p (BINFO_TYPE
(binfo), t), 20010124);
7114
/* Build a version
of VTBL (with the wrong type) for use in
7115
constructing the addresses of
secondary vtables in the
7116
construction vtable
group.
*/
7117
vtbl = build_vtable
(t, id, ptr_type_node);
7118
list = build_tree_list (vtbl, NULL_TREE);
7119
accumulate_vtbl_inits
(binfo, TYPE_BINFO (TREE_TYPE (binfo)),
7120
binfo, t, list);
7121
7122
/* Add the vtables
for each of our virtual bases using the vbase in T
7123
binfo.
*/
7124
for
(vbase = TYPE_BINFO (BINFO_TYPE (binfo));
7125
vbase;
7126
vbase = TREE_CHAIN (vbase))
7127
{
7128
tree b;
7129
7130
if (!TREE_VIA_VIRTUAL (vbase))
7131
continue
;
7132
b = copied_binfo
(vbase, binfo);
7133
7134
accumulate_vtbl_inits
(b, vbase, binfo, t, list);
7135
}
7136
inits = TREE_VALUE (list);
7137
7138
/* Figure out the
type of the construction vtable.
*/
7139
type = build_index_type
(size_int (list_length (inits) - 1));
7140
type = build_cplus_array_type
(vtable_entry_type, type);
7141
TREE_TYPE (vtbl) = type;
7142
7143
/* Initialize the
construction vtable.
*/
7144
CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
7145
initialize_array
(vtbl, inits);
7146
dump_vtable (t, binfo, vtbl);
7147
}
Above at line 7109, mangle_ctor_vtbl_for_type
returns the mangled
name for the vtable for linkage purpose. Assertion following makes sure that
only bases will go into this function. Then a new created vtable object is
wrapped into a tree_list node, and at line 7119 passed to the below function as
the last argument. See rtti_binfo
is the binfo of qualified direct base,
the function will prepare the intializers for the base.
Here accumulate_vtbl_inits
handles the base in
interesting and its non-virtual base in pre-order order, and then the virtual
base in order of appearing within inheritance tree later in build_ctor_vblt_group
.
We reshow related functions in below for convenience.
7159
static
void
7160
accumulate_vtbl_inits
(tree binfo,
in
class.c
7161
tree orig_binfo,
7162
tree rtti_binfo,
7163
tree t,
7164
tree inits)
7165
{
7166
int i;
7167
int ctor_vtbl_p = !same_type_p (BINFO_TYPE
(rtti_binfo), t);
7168
7169
my_friendly_assert (same_type_p (BINFO_TYPE
(binfo),
7170
BINFO_TYPE (orig_binfo)),
7171
20000517);
7172
7173
/* If it doesn't
have a vptr, we don't do anything.
*/
7174
if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE
(binfo)))
7175
return
;
7176
7177
/* If we're
building a construction vtable, we're not interested in
7178
subobjects that don't require
construction vtables.
*/
7179
if (ctor_vtbl_p
7180
&& !TYPE_USES_VIRTUAL_BASECLASSES
(BINFO_TYPE (binfo))
7181
&& !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo)))
7182
return
;
7183
7184
/* Build the
initializers for the BINFO-in-T vtable.
*/
7185
TREE_VALUE (inits)
7186
= chainon (TREE_VALUE (inits),
7187
dfs_accumulate_vtbl_inits
(binfo, orig_binfo,
7188
rtti_binfo, t, inits));
7189
7190
/* Walk the BINFO
and its bases. We walk in preorder so that as we
7191
initialize each vtable we can
figure out at what offset the
7192
secondary vtable lies from the
primary vtable. We can't use
7193
dfs_walk here because we need
to iterate through bases of BINFO
7194
and RTTI_BINFO
simultaneously.
*/
7195
for
(i = 0; i
< BINFO_N_BASETYPES (binfo); ++i)
7196
{
7197
tree base_binfo = BINFO_BASETYPE (binfo,
i);
7198
7199
/* Skip virtual bases.
*/
7200
if (TREE_VIA_VIRTUAL (base_binfo))
7201
continue
;
7202
accumulate_vtbl_inits
(base_binfo,
7203
BINFO_BASETYPE (orig_binfo, i),
7204
rtti_binfo, t,
7205
inits);
7206
}
7207
}
This time, ctor_vtbl_p
at line 7167 above is true as
argument t
always refers to the most derived class but rtti_binfo
should never. And condition at line
7179 filters out base that doesn’t derive from virutal base and non-virtual.
7212
static
tree
7213
dfs_accumulate_vtbl_inits
(tree binfo,
in
class.c
7214
tree orig_binfo,
7215
tree rtti_binfo,
7216
tree t,
7217
tree l)
7218
{
7219
tree inits = NULL_TREE;
7220
tree vtbl = NULL_TREE;
7221
int ctor_vtbl_p = !same_type_p (BINFO_TYPE
(rtti_binfo), t);
7222
7223
if (ctor_vtbl_p
7224
&& TREE_VIA_VIRTUAL (orig_binfo)
&& BINFO_PRIMARY_P (orig_binfo))
7225
{
7226
/* In the
hierarchy of BINFO_TYPE (RTTI_BINFO), this is a
7227
primary virtual base. If it is not the same
primary in
7228
the hierarchy of T, we'll need to generate a
ctor vtable
7229
for it, to place at its location in T. If it
is the same
7230
primary, we still need a VTT entry for the
vtable, but it
7231
should point to the ctor vtable for the base
it is a
7232
primary for within the sub-hierarchy of
RTTI_BINFO.
7233
7234
There are three possible cases:
7235
7236
1) We are in the same place.
7237
2) We are a primary base within a lost primary
virtual base of
7238
RTTI_BINFO.
7239
3) We are primary to something not a base of
RTTI_BINFO.
*/
7240
7241
tree b = BINFO_PRIMARY_BASE_OF (binfo);
7242
tree last = NULL_TREE;
7243
7244
/* First, look
through the bases we are primary to for RTTI_BINFO
7245
or a virtual base.
*/
7246
for
(; b; b
= BINFO_PRIMARY_BASE_OF (b))
7247
{
7248
last = b;
7249
if
(TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
7250
break
;
7251
}
7252
/* If we run out
of primary links, keep looking down our
7253
inheritance chain; we might be an indirect
primary.
*/
7254
if (b == NULL_TREE)
7255
for
(b =
last; b; b = BINFO_INHERITANCE_CHAIN (b))
7256
if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
7257
break
;
7258
7259
/* If we found RTTI_BINFO, this is case 1. If
we found a virtual
7260
base B and it is a base of
RTTI_BINFO, this is case 2. In
7261
either case, we share our vtable with LAST,
i.e. the
7262
derived-most base within B of which we are a
primary.
*/
7263
if (b == rtti_binfo
7264
||
(b && purpose_member (BINFO_TYPE (b),
7265
CLASSTYPE_VBASECLASSES (BINFO_TYPE
(rtti_binfo)))))
7266
/* Just set our
BINFO_VTABLE to point to LAST, as we may not have
7267
set LAST's BINFO_VTABLE yet. We'll extract
the actual vptr in
7268
binfo_ctor_vtable after everything's been
set up.
*/
7269
vtbl = last;
7270
7271
/* Otherwise, this is case 3 and we get our
own.
*/
7272
}
7273
else if (!BINFO_NEW_VTABLE_MARKED
(orig_binfo))
7274
return
inits;
7275
7276
if (!vtbl)
7277
{
7278
tree index;
7279
int non_fn_entries;
7280
7281
/* Compute the initializer for this
vtable.
*/
7282
inits = build_vtbl_initializer
(binfo, orig_binfo, t, rtti_binfo,
7283
&non_fn_entries);
7284
7285
/* Figure out the
position to which the VPTR should point.
*/
7286
vtbl = TREE_PURPOSE (l);
7287
vtbl = build1
(ADDR_EXPR,
7288
vtbl_ptr_type_node,
7289
vtbl);
7290
TREE_CONSTANT (vtbl) = 1;
7291
index = size_binop (PLUS_EXPR,
7292
size_int (non_fn_entries),
7293
size_int (list_length (TREE_VALUE (l))));
7294
index = size_binop (MULT_EXPR,
7295
TYPE_SIZE_UNIT (vtable_entry_type),
7296
index);
7297
vtbl = build
(PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
7298
TREE_CONSTANT (vtbl) = 1;
7299
}
7300
7301
if (ctor_vtbl_p)
7302
/* For a
construction vtable, we can't overwrite BINFO_VTABLE.
7303
So, we make a TREE_LIST.
Later, dfs_fixup_binfo_vtbls will
7304
straighten this out.
*/
7305
BINFO_VTABLE (binfo) = tree_cons
(rtti_binfo, vtbl, BINFO_VTABLE (binfo));
7306
else if (BINFO_PRIMARY_P (binfo) &&
TREE_VIA_VIRTUAL (binfo))
7307
inits = NULL_TREE;
7308
else
7309
/* For an
ordinary vtable, set BINFO_VTABLE.
*/
7310
BINFO_VTABLE (binfo) = vtbl;
7311
7312
return
inits;
7313
}
Note that argument orig_binfo
should always refer to the binfo of
the type of base in interesting. And at line 7273 predicate BINFO_NEW_VTABLE_MARKED
returns true if the type has its own vtable. Now rtti_binfo
is the binfo of the
direct base in interesting. In our example, B1, B2 are such bases when handling
C. And t
refers to the binfo of the most derived class, in our example, it is class C. Next
binfo
is the binfo of the base we are processing.
If handles B1 in
accumulate_vtbl_inits
,
in dfs_accumulate_vtbl_inits
,
to orig_binfo
(here it is binfo of B1),
at
line 7224, condition TREE_VIA_VIRTUAL and BINFO_PRIMARY_P are not hold; But at
line 7273, orig_binfo
of course has its own vtable, which breaks the condition. So it will enters IF
block at line 7276, in which the treatment has been seen in previous section
and simliar. As ctor_vtbl_p
is true, code at line 7305 is run, see that binfo
is binfo of B1-in-C, which
has empty BINFO_VTABLE. Because vtable built here is construction vtable, which
can only borrow BINFO_VTABLE temperarily, as result it is built in a tree_list.
Functions cooperative include: binfo_ctor_vtable
, dfs_fixup_binfo_vtbls
.
Exitting from accumulate_vtbl_inits
at line 7119, B1 in C in example 1 should have following
entries in construction vtable (kept in TREE_PURPOSE slot of list
at
line 7118 in
build_ctor_vtbl_group
, and BINFO_VTABLE (binfo of B1-in-C)).
Construction
vtable for B1 (0xb7f2d980
instance) in C
C::_ZTC1C0_2B1: 6u
entries
0
0u
4
0u
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI2B1)
16
B1::_ZTcv0_n12_v0_n16_N2B11fEv
// slot of
B1::A::f
20
B1::f
// slot of B1::f
Then in invoking accumulate_vtbl_inits
at line 7134, binfo
is
binfo of C::B1, and line 7124 fetches the binfo of type B1, so vbase
is
binfo of B1::A, but b
is binfo of C::B1::A, and t
is still type C. They are passed
to dfs_accumulate_vtbl_inits
as the mapping: binfo
(b
),
orig_binfo
(vbase
), rtti_binfo
(binfo
),
and t
(t
).
Next in the function, b
at line 7241 is binfo of C::B1; and last
gets binfo of C::B1 at line 7248. As result, vtbl
is set by the binfo of C::B1
at line 7269. Finally, at line 7305, BINFO_VTABLE(binfo of C::B1::A) is extended
by a tree_list containing binfo of C::B1. And NULL inits
is returned.
However thing is a little different for B2-in-C. Also at exitting
from accumulate_vtbl_inits
at line 7119, B2-in-C in example 1 should have following extra entries in
construction vtable (kept in TREE_PURPOSE slot of list
at line 7118 in build_ctor_vtbl_group
).
Construction
vtable for B2 (0xb7f2da00
instance) in C
C::_ZTC1C4_2B2: 10u
entries
0
-4u
4
0u
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI2B2)
16
B2::_ZTcv0_n12_v0_n16_N2B21fEv
20
B2::f
// slot of B2::f
But in dfs_accumulate_vtbl_inits
for B2::A,
it gets binfo
:
binfo of C::B2 (arg: rtti_binfo
), vbase
: binfo of B2::A (arg: orig_binfo
), b
: binfo of C::B2::A (arg: binfo
),
and t
:
C (arg: t
).
Then b
at line 7241 this time is binfo of C::B2; and last
at line 7248 gets NULL as it
climbs up via path A
à
B1 à
C. So vtbl
keeps NULL in condition at line 7276. Thus the construction vtable generated
for B2::A has below entries:
24
4u
// part of A in B2 - begin
28
(int (*)(...))4
32
(int (*)(...))(& _ZTI2B2)
36
B2::_ZTcv0_n12_v0_n16_N2B21fEv
// part of A
in B2 - end
Line 7140 in build_ctor_vtbl_group
rebuilds the array type for those construction vtables. Next at line 7144, this
construction vtable for base is linked into CLASSTYPE_VTABLES of the most
derived class. And initialize_array
at line 7145 prepares
initializers with exact types for vtable entry.
Return build_vtt_inits
from build_ctor_vtbl_group
, at
line 6916 binfo_ctor_vtable
gets construction vtable from binfo of C::B1 (recorded at index 1).
FOR
block at line 6927 does nothing for B1 or B2, it then arrives below
code.
build_vtt_inits (continue)
6935
/* Add secondary
virtual pointers for all subobjects of BINFO with
6936
either virtual bases or
reachable along a virtual path, except
6937
subobjects that are
non-virtual primary bases.
*/
6938
secondary_vptrs = tree_cons (t, NULL_TREE,
BINFO_TYPE (binfo));
6939
TREE_TYPE (secondary_vptrs) = *index;
6940
VTT_TOP_LEVEL_P (secondary_vptrs) =
top_level_p;
6941
VTT_MARKED_BINFO_P (secondary_vptrs) = 0;
6942
6943
dfs_walk_real
(binfo,
6944
dfs_build_secondary_vptr_vtt_inits
,
6945
NULL,
6946
dfs_ctor_vtable_bases_queue_p,
6947
secondary_vptrs);
6948
VTT_MARKED_BINFO_P (secondary_vptrs) = 1;
6949
dfs_walk (binfo, dfs_unmark,
dfs_ctor_vtable_bases_queue_p,
6950
secondary_vptrs);
6951
6952
*index = TREE_TYPE (secondary_vptrs);
6953
6954
/* The secondary
vptrs come back in reverse order. After we reverse
6955
them, and add the INITS, the
last init will be the first element
6956
of the chain.
*/
6957
secondary_vptrs = TREE_VALUE
(secondary_vptrs);
6958
if (secondary_vptrs)
6959
{
6960
*inits = nreverse (secondary_vptrs);
6961
inits = &TREE_CHAIN (secondary_vptrs);
6962
my_friendly_assert (*inits == NULL_TREE,
20000517);
6963
}
6964
6965
/* Add the
secondary VTTs for virtual bases.
*/
6966
if (top_level_p)
6967
for
(b =
TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
6968
{
6969
if (!TREE_VIA_VIRTUAL (b))
6970
continue
;
6971
6972
inits = build_vtt_inits
(b, t, inits, index);
6973
}
6974
6975
if (!top_level_p)
6976
{
6977
tree data = tree_cons (t, binfo,
NULL_TREE);
6978
VTT_TOP_LEVEL_P (data) = 0;
6979
VTT_MARKED_BINFO_P (data) = 0;
6980
6981
dfs_walk (binfo, dfs_fixup_binfo_vtbls
,
6982
dfs_ctor_vtable_bases_queue_p,
6983
data);
6984
}
6985
6986
return
inits;
6987
}
Above secondary_vptrs
as indicates by its name, is the pointer to secondary vtable in the VTT of the
most derived class (that is C for our example); and index
tells the slot of the VTT
this pointer lies in. The transverse at line 6943, begins at the binfo of base
referred by binfo
(here, i.e., either binfo of C::B1 or binfo of C::B2) and steps into this node.
Routine below then processes the nodes visited in pre-order, see argument data
is secondary_vptrs
.
6996
static
tree
6997
dfs_build_secondary_vptr_vtt_inits
(tree
binfo, void* data)
in
class.c
6998
{
6999
tree l;
7000
tree t;
7001
tree init;
7002
tree index;
7003
int top_level_p;
7004
7005
l = (tree) data;
7006
t = TREE_CHAIN (l);
7007
top_level_p = VTT_TOP_LEVEL_P (l);
7008
7009
BINFO_MARKED (binfo) = 1;
7010
7011
/* We don't care
about bases that don't have vtables.
*/
7012
if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
7013
return
NULL_TREE;
7014
7015
/* We're only
interested in proper subobjects of T.
*/
7016
if (same_type_p (BINFO_TYPE (binfo), t))
7017
return
NULL_TREE;
7018
7019
/* We're not
interested in non-virtual primary bases.
*/
7020
if (!TREE_VIA_VIRTUAL (binfo) &&
BINFO_PRIMARY_P (binfo))
7021
return
NULL_TREE;
7022
7023
/* If BINFO has
virtual bases or is reachable via a virtual path
7024
from T, it'll have a
secondary vptr.
*/
7025
if (!TYPE_USES_VIRTUAL_BASECLASSES
(BINFO_TYPE (binfo))
7026
&& !binfo_via_virtual (binfo, t))
7027
return
NULL_TREE;
7028
7029
/* Record the index
where this secondary vptr can be found.
*/
7030
index = TREE_TYPE (l);
7031
if (top_level_p)
7032
{
7033
my_friendly_assert (!BINFO_VPTR_INDEX
(binfo), 20010129);
7034
BINFO_VPTR_INDEX
(binfo) = index;
7035
}
7036
TREE_TYPE (l) = size_binop (PLUS_EXPR, index,
7037
TYPE_SIZE_UNIT (ptr_type_node));
7038
7039
/* Add the
initializer for the secondary vptr itself.
*/
7040
if (top_level_p && TREE_VIA_VIRTUAL
(binfo))
7041
{
7042
/* It's a primary virtual base, and this is
not the construction
7043
vtable. Find the base this
is primary of in the inheritance graph,
7044
and use that base's vtable
now.
*/
7045
while
(BINFO_PRIMARY_BASE_OF (binfo))
7046
binfo = BINFO_PRIMARY_BASE_OF (binfo);
7047
}
7048
init =
binfo_ctor_vtable
(binfo);
7049
TREE_VALUE (l) = tree_cons (NULL_TREE, init,
TREE_VALUE (l));
7050
7051
return
NULL_TREE;
7052
}
When iterating sub-tree headed by binfo of C::B1, top_level_p
above is false, t
at line 7006 is the type of B1. This node is skipped as condition at line 7016
is hold; At visiting binfo of C::B1::A, as in binfo BINFO_VTABLE of C::B1::A is
the binfo of C::B1, at line 7048 binfo_ctor_vtable
gets construction vtable of
C::B1 again (kept at index 2). Note this function always returns NULL which
forces a full walk within the (sub-)tree. To C::B2, it gets nothing too.
Remember in dfs_accumulate_vtbl_inits
at line 7305,
construction vtable temperarily stays in BINFO_VTABLE. Now construction vtable
has been recorded into VTT, no needs rely upon BINFO_VTABLE any more. Now it is
time to restore BINFO_VTABLE. Pay attention to the constructing of its argument
data. Here, node temperarily appended by C::B1::A is removed (it is C::B2::A
for C::B2).
7075
static
tree
7076
dfs_fixup_binfo_vtbls
(tree binfo, void*
data)
in
class.c
7077
{
7078
BINFO_MARKED (binfo) = 0;
7079
7080
/* We don't care
about bases that don't have vtables.
*/
7081
if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
7082
return
NULL_TREE;
7083
7084
/* If we scribbled
the construction vtable vptr into BINFO, clear it
7085
out now.
*/
7086
if (BINFO_VTABLE (binfo)
7087
&& TREE_CODE (BINFO_VTABLE (binfo))
== TREE_LIST
7088
&& (TREE_PURPOSE (BINFO_VTABLE
(binfo))
7089
== TREE_VALUE ((tree) data)))
7090
BINFO_VTABLE (binfo) = TREE_CHAIN
(BINFO_VTABLE (binfo));
7091
7092
return
NULL_TREE;
7093
}
In treatment of C::B2 mentioned above, when back build_vtt_inits
from build_ctor_vtbl_group
,
its construction vtable is saved in VTT by index 3. Then in dfs_build_secondary_vptr_vtt_inits
for C::B2, binfo_ctor_vtable
at line 7048 gets construction vtable of B2::A (at index 4 in VTT).
After finishes handling B1 and B2, it continues on handling C at
line 6938 in build_vtt_inits
.
It begins to transerve inheritance tree rooted by C at line 6943. So dfs_build_secondary_vptr_vtt_inits
in, top_level_p
is true, and t
is the most derived class C.
During this pre-order walk, C satisfies condtion at line 7016, C::B1 meets
condition at line 7020, and exit the function. For C::B2, index 5 in VTT is set as vptr of C::B2, and its
vtable’s (it’s a secondary vtable) initializer is what we got in previous
section; similarly for C::B1::A, its vptr is in VTT with index 6, also its
vtable’s (secondary vtable too) initialzier is what in BINFO_VTABLE(A-in-C)
prepared in previous section. At last, C::B2::A is skipped, as A has been
visited via C::B1::A.
A is processed in build_vtt_inits
at line 6972 at last, as A
hasn’t virtual base, build_vtt_inits
does nothing.
Returns build_vtt
,
if success, inits
should not be NULL. Following builds appropriate type for VTT and constructs
its static object, then links this object into head of CLASSTYPE_VTABLES of the
most derived class.
of GCC for our instance 1.
Example 1:
Vtable for C
C::_ZTV1C: 12u entries
0
0u
// vbase offset
4
0u
// vcall offset
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI1C)
16
C
::_ZTcv0_n12_v0_n16_N1C1fEv
// slot for
C::B1::A::f
20
C
::f
// slot for C::f
24
-4u
28
-4u
32
(int (*)(...))-0x000000004
36
(int (*)(...))(& _ZTI1C)
40
C
::_ZTcvn4_n12_v0_n16_N1C1fEv
// slot for C::B2::A::f
44
C
::_ZTchn4_h4_N1C1fEv
// slot for C::B2::f
… // no VTT for A
VTT for B1
B1::_ZTT2B1:
2u entries
0
((& B1::_ZTV2B1) + 16u)
4
((& B1::_ZTV2B1) + 16u)
…
VTT for B2
B2::_ZTT2B2:
2u entries
0
((& B2::_ZTV2B2) + 16u)
4
((& B2::_ZTV2B2) + 16u)
…
Construction
vtable for B1 (0xb7f2d980
instance) in C
C::_ZTC1C0_2B1: 6u
entries
0
0u
4
0u
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI2B1)
16
B1::_ZTcv0_n12_v0_n16_N2B11fEv
// C::B1::f
20
B1::f
Construction
vtable for B2 (0xb7f2da00
instance) in C
C::_ZTC1C4_2B2: 10u
entries
0
-4u
4
0u
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI2B2)
16
B2::_ZTcv0_n12_v0_n16_N2B21fEv
// C::B2::f
20
B2::f
24
4u
28
(int (*)(...))4
32
(int (*)(...))(& _ZTI2B2)
36
B2::_ZTcv0_n12_v0_n16_N2B21fEv
// C::B2::f
VTT for C
C::_ZTT1C: 7u entries
0
((& C::_ZTV1C) + 16u)
// vptr for C
4
((& C::_ZTC1C0_2B1) + 16u)
// construction vtable used for B1
8
((& C::_ZTC1C0_2B1) + 16u)
// construction vtable used for B1::A
12
((& C::_ZTC1C4_2B2) + 16u)
// construction vtable used for B2
16
((& C::_ZTC1C4_2B2) + 36u)
// construction vtable used for B2::A
20
((& C::_ZTV1C) + 16u)
// vptr for
secondary vtable of B2
24
((& C::_ZTV1C) + 40u)
// vptr for secondary vtable of A
Constructing VTT is done
by below function.
6829
static
void
6830
build_vtt
(tree t)
in
class.c
6831
{
6832
tree inits;
6833
tree type;
6834
tree vtt;
6835
tree index;
6836
6837
/* Build up the
initializers for the VTT.
*/
6838
inits = NULL_TREE;
6839
index = size_zero_node;
6840
build_vtt_inits
(TYPE_BINFO (t), t, &inits, &index);
6841
6842
/* If we didn't
need a VTT, we're done.
*/
6843
if (!inits)
6844
return
;
6845
6846
/* Figure out the
type of the VTT.
*/
6847
type = build_index_type
(size_int (list_length (inits) - 1));
6848
type = build_cplus_array_type
(const_ptr_type_node, type);
6849
6850
/* Now, build the
VTT object itself.
*/
6851
vtt = build_vtable
(t, get_vtt_name (t), type);
6852
initialize_array
(vtt, inits);
6853
/* Add the VTT to
the vtables list.
*/
6854
TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));
6855
TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt;
6856
6857
dump_vtt (t, vtt);
6858
}
So for our example, for class B1, B2 and C, VTT is expected, and its
body is constructed by build_vtt_init
bleow, in which argument binfo
is
the binfo of the most derived class, t
is the most derived class, and index
is
the last index the VTT entries occupied.
6892
static
tree *
6893
build_vtt_inits
(tree binfo, tree t,
tree* inits, tree* index)
in
class.c
6894
{
6895
int i;
6896
tree b;
6897
tree init;
6898
tree secondary_vptrs;
6899
int top_level_p = same_type_p (TREE_TYPE
(binfo), t);
6900
6901
/* We only need VTTs
for subobjects with virtual bases.
*/
6902
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE
(binfo)))
6903
return
inits;
6904
6905
/* We need to use a
construction vtable if this is not the primary
6906
VTT.
*/
6907
if (!top_level_p)
6908
{
6909
build_ctor_vtbl_group
(binfo, t);
6910
6911
/* Record the
offset in the VTT where this sub-VTT can be found.
*/
6912
BINFO_SUBVTT_INDEX (binfo) = *index;
6913
}
6914
6915
/* Add the address
of the primary vtable for the complete object.
*/
6916
init = binfo_ctor_vtable
(binfo);
6917
*inits = build_tree_list (NULL_TREE, init);
6918
inits = &TREE_CHAIN (*inits);
6919
if (top_level_p)
6920
{
6921
my_friendly_assert (!BINFO_VPTR_INDEX
(binfo), 20010129);
6922
BINFO_VPTR_INDEX
(binfo) = *index;
6923
}
6924
*index = size_binop (PLUS_EXPR, *index,
TYPE_SIZE_UNIT (ptr_type_node));
6925
6926
/* Recursively add
the secondary VTTs for non-virtual bases.
*/
6927
for
(i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
6928
{
6929
b = BINFO_BASETYPE (binfo, i);
6930
if (!TREE_VIA_VIRTUAL (b))
6931
inits = build_vtt_inits
(BINFO_BASETYPE (binfo, i), t,
6932
inits, index);
6933
}
In previous section, BINFO_VTABLE of the class is set in dfs_accumulate_vtbl_inits
with vtable initializers. It is a PLUS_EXPR specifies the position in the
initializers for the start point of vtable. At line 6916 above, binfo_ctor_vtable
gets this expression from the class.
6865
static
tree
6866
binfo_ctor_vtable
(tree binfo)
in
class.c
6867
{
6868
tree vt;
6869
6870
while
(1)
6871
{
6872
vt = BINFO_VTABLE (binfo);
6873
if (TREE_CODE (vt) == TREE_LIST)
6874
vt = TREE_VALUE (vt);
6875
if (TREE_CODE (vt) == TREE_VEC)
6876
binfo = vt;
6877
else
6878
break
;
6879
}
6880
6881
return
vt;
6882
}
Above at line 6917, init
returned by binfo_ctor_vtable
is built
in a tree_list; and at line 6917, inits
points to the address of chain
field of this tree_list, so in recursion at line 6931, new nodes will be added
into this chain. Above argument index
is the VTT index where the next element
will be replaced (it is also number of bytes), at beginning it is size_zero_node
.
BINFO_VPTR_INDEX holds the index in the VTT where the vptr for the
subobject can be found. For the most derived class C, its vptr is saved at
index 0. And to non-virtual bases, build_ctor_vtbl_group
does below processing.
7098
static
void
7099
build_ctor_vtbl_group
(tree binfo, tree
t)
in
class.c
7100
{
7101
tree list;
7102
tree type;
7103
tree vtbl;
7104
tree inits;
7105
tree id;
7106
tree vbase;
7107
7108
/* See if we've
already created this construction vtable group.
*/
7109
id = mangle_ctor_vtbl_for_type (t, binfo);
7110
if (IDENTIFIER_GLOBAL_VALUE (id))
7111
return
;
7112
7113
my_friendly_assert (!same_type_p (BINFO_TYPE
(binfo), t), 20010124);
7114
/* Build a version
of VTBL (with the wrong type) for use in
7115
constructing the addresses of
secondary vtables in the
7116
construction vtable
group.
*/
7117
vtbl = build_vtable
(t, id, ptr_type_node);
7118
list = build_tree_list (vtbl, NULL_TREE);
7119
accumulate_vtbl_inits
(binfo, TYPE_BINFO (TREE_TYPE (binfo)),
7120
binfo, t, list);
7121
7122
/* Add the vtables
for each of our virtual bases using the vbase in T
7123
binfo.
*/
7124
for
(vbase = TYPE_BINFO (BINFO_TYPE (binfo));
7125
vbase;
7126
vbase = TREE_CHAIN (vbase))
7127
{
7128
tree b;
7129
7130
if (!TREE_VIA_VIRTUAL (vbase))
7131
continue
;
7132
b = copied_binfo
(vbase, binfo);
7133
7134
accumulate_vtbl_inits
(b, vbase, binfo, t, list);
7135
}
7136
inits = TREE_VALUE (list);
7137
7138
/* Figure out the
type of the construction vtable.
*/
7139
type = build_index_type
(size_int (list_length (inits) - 1));
7140
type = build_cplus_array_type
(vtable_entry_type, type);
7141
TREE_TYPE (vtbl) = type;
7142
7143
/* Initialize the
construction vtable.
*/
7144
CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
7145
initialize_array
(vtbl, inits);
7146
dump_vtable (t, binfo, vtbl);
7147
}
Above at line 7109, mangle_ctor_vtbl_for_type
returns the mangled
name for the vtable for linkage purpose. Assertion following makes sure that
only bases will go into this function. Then a new created vtable object is
wrapped into a tree_list node, and at line 7119 passed to the below function as
the last argument. See rtti_binfo
is the binfo of qualified direct base,
the function will prepare the intializers for the base.
Here accumulate_vtbl_inits
handles the base in
interesting and its non-virtual base in pre-order order, and then the virtual
base in order of appearing within inheritance tree later in build_ctor_vblt_group
.
We reshow related functions in below for convenience.
7159
static
void
7160
accumulate_vtbl_inits
(tree binfo,
in
class.c
7161
tree orig_binfo,
7162
tree rtti_binfo,
7163
tree t,
7164
tree inits)
7165
{
7166
int i;
7167
int ctor_vtbl_p = !same_type_p (BINFO_TYPE
(rtti_binfo), t);
7168
7169
my_friendly_assert (same_type_p (BINFO_TYPE
(binfo),
7170
BINFO_TYPE (orig_binfo)),
7171
20000517);
7172
7173
/* If it doesn't
have a vptr, we don't do anything.
*/
7174
if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE
(binfo)))
7175
return
;
7176
7177
/* If we're
building a construction vtable, we're not interested in
7178
subobjects that don't require
construction vtables.
*/
7179
if (ctor_vtbl_p
7180
&& !TYPE_USES_VIRTUAL_BASECLASSES
(BINFO_TYPE (binfo))
7181
&& !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo)))
7182
return
;
7183
7184
/* Build the
initializers for the BINFO-in-T vtable.
*/
7185
TREE_VALUE (inits)
7186
= chainon (TREE_VALUE (inits),
7187
dfs_accumulate_vtbl_inits
(binfo, orig_binfo,
7188
rtti_binfo, t, inits));
7189
7190
/* Walk the BINFO
and its bases. We walk in preorder so that as we
7191
initialize each vtable we can
figure out at what offset the
7192
secondary vtable lies from the
primary vtable. We can't use
7193
dfs_walk here because we need
to iterate through bases of BINFO
7194
and RTTI_BINFO
simultaneously.
*/
7195
for
(i = 0; i
< BINFO_N_BASETYPES (binfo); ++i)
7196
{
7197
tree base_binfo = BINFO_BASETYPE (binfo,
i);
7198
7199
/* Skip virtual bases.
*/
7200
if (TREE_VIA_VIRTUAL (base_binfo))
7201
continue
;
7202
accumulate_vtbl_inits
(base_binfo,
7203
BINFO_BASETYPE (orig_binfo, i),
7204
rtti_binfo, t,
7205
inits);
7206
}
7207
}
This time, ctor_vtbl_p
at line 7167 above is true as
argument t
always refers to the most derived class but rtti_binfo
should never. And condition at line
7179 filters out base that doesn’t derive from virutal base and non-virtual.
7212
static
tree
7213
dfs_accumulate_vtbl_inits
(tree binfo,
in
class.c
7214
tree orig_binfo,
7215
tree rtti_binfo,
7216
tree t,
7217
tree l)
7218
{
7219
tree inits = NULL_TREE;
7220
tree vtbl = NULL_TREE;
7221
int ctor_vtbl_p = !same_type_p (BINFO_TYPE
(rtti_binfo), t);
7222
7223
if (ctor_vtbl_p
7224
&& TREE_VIA_VIRTUAL (orig_binfo)
&& BINFO_PRIMARY_P (orig_binfo))
7225
{
7226
/* In the
hierarchy of BINFO_TYPE (RTTI_BINFO), this is a
7227
primary virtual base. If it is not the same
primary in
7228
the hierarchy of T, we'll need to generate a
ctor vtable
7229
for it, to place at its location in T. If it
is the same
7230
primary, we still need a VTT entry for the
vtable, but it
7231
should point to the ctor vtable for the base
it is a
7232
primary for within the sub-hierarchy of
RTTI_BINFO.
7233
7234
There are three possible cases:
7235
7236
1) We are in the same place.
7237
2) We are a primary base within a lost primary
virtual base of
7238
RTTI_BINFO.
7239
3) We are primary to something not a base of
RTTI_BINFO.
*/
7240
7241
tree b = BINFO_PRIMARY_BASE_OF (binfo);
7242
tree last = NULL_TREE;
7243
7244
/* First, look
through the bases we are primary to for RTTI_BINFO
7245
or a virtual base.
*/
7246
for
(; b; b
= BINFO_PRIMARY_BASE_OF (b))
7247
{
7248
last = b;
7249
if
(TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
7250
break
;
7251
}
7252
/* If we run out
of primary links, keep looking down our
7253
inheritance chain; we might be an indirect
primary.
*/
7254
if (b == NULL_TREE)
7255
for
(b =
last; b; b = BINFO_INHERITANCE_CHAIN (b))
7256
if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
7257
break
;
7258
7259
/* If we found RTTI_BINFO, this is case 1. If
we found a virtual
7260
base B and it is a base of
RTTI_BINFO, this is case 2. In
7261
either case, we share our vtable with LAST,
i.e. the
7262
derived-most base within B of which we are a
primary.
*/
7263
if (b == rtti_binfo
7264
||
(b && purpose_member (BINFO_TYPE (b),
7265
CLASSTYPE_VBASECLASSES (BINFO_TYPE
(rtti_binfo)))))
7266
/* Just set our
BINFO_VTABLE to point to LAST, as we may not have
7267
set LAST's BINFO_VTABLE yet. We'll extract
the actual vptr in
7268
binfo_ctor_vtable after everything's been
set up.
*/
7269
vtbl = last;
7270
7271
/* Otherwise, this is case 3 and we get our
own.
*/
7272
}
7273
else if (!BINFO_NEW_VTABLE_MARKED
(orig_binfo))
7274
return
inits;
7275
7276
if (!vtbl)
7277
{
7278
tree index;
7279
int non_fn_entries;
7280
7281
/* Compute the initializer for this
vtable.
*/
7282
inits = build_vtbl_initializer
(binfo, orig_binfo, t, rtti_binfo,
7283
&non_fn_entries);
7284
7285
/* Figure out the
position to which the VPTR should point.
*/
7286
vtbl = TREE_PURPOSE (l);
7287
vtbl = build1
(ADDR_EXPR,
7288
vtbl_ptr_type_node,
7289
vtbl);
7290
TREE_CONSTANT (vtbl) = 1;
7291
index = size_binop (PLUS_EXPR,
7292
size_int (non_fn_entries),
7293
size_int (list_length (TREE_VALUE (l))));
7294
index = size_binop (MULT_EXPR,
7295
TYPE_SIZE_UNIT (vtable_entry_type),
7296
index);
7297
vtbl = build
(PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
7298
TREE_CONSTANT (vtbl) = 1;
7299
}
7300
7301
if (ctor_vtbl_p)
7302
/* For a
construction vtable, we can't overwrite BINFO_VTABLE.
7303
So, we make a TREE_LIST.
Later, dfs_fixup_binfo_vtbls will
7304
straighten this out.
*/
7305
BINFO_VTABLE (binfo) = tree_cons
(rtti_binfo, vtbl, BINFO_VTABLE (binfo));
7306
else if (BINFO_PRIMARY_P (binfo) &&
TREE_VIA_VIRTUAL (binfo))
7307
inits = NULL_TREE;
7308
else
7309
/* For an
ordinary vtable, set BINFO_VTABLE.
*/
7310
BINFO_VTABLE (binfo) = vtbl;
7311
7312
return
inits;
7313
}
Note that argument orig_binfo
should always refer to the binfo of
the type of base in interesting. And at line 7273 predicate BINFO_NEW_VTABLE_MARKED
returns true if the type has its own vtable. Now rtti_binfo
is the binfo of the
direct base in interesting. In our example, B1, B2 are such bases when handling
C. And t
refers to the binfo of the most derived class, in our example, it is class C. Next
binfo
is the binfo of the base we are processing.
If handles B1 in
accumulate_vtbl_inits
,
in dfs_accumulate_vtbl_inits
,
to orig_binfo
(here it is binfo of B1),
at
line 7224, condition TREE_VIA_VIRTUAL and BINFO_PRIMARY_P are not hold; But at
line 7273, orig_binfo
of course has its own vtable, which breaks the condition. So it will enters IF
block at line 7276, in which the treatment has been seen in previous section
and simliar. As ctor_vtbl_p
is true, code at line 7305 is run, see that binfo
is binfo of B1-in-C, which
has empty BINFO_VTABLE. Because vtable built here is construction vtable, which
can only borrow BINFO_VTABLE temperarily, as result it is built in a tree_list.
Functions cooperative include: binfo_ctor_vtable
, dfs_fixup_binfo_vtbls
.
Exitting from accumulate_vtbl_inits
at line 7119, B1 in C in example 1 should have following
entries in construction vtable (kept in TREE_PURPOSE slot of list
at
line 7118 in
build_ctor_vtbl_group
, and BINFO_VTABLE (binfo of B1-in-C)).
Construction
vtable for B1 (0xb7f2d980
instance) in C
C::_ZTC1C0_2B1: 6u
entries
0
0u
4
0u
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI2B1)
16
B1::_ZTcv0_n12_v0_n16_N2B11fEv
// slot of
B1::A::f
20
B1::f
// slot of B1::f
Then in invoking accumulate_vtbl_inits
at line 7134, binfo
is
binfo of C::B1, and line 7124 fetches the binfo of type B1, so vbase
is
binfo of B1::A, but b
is binfo of C::B1::A, and t
is still type C. They are passed
to dfs_accumulate_vtbl_inits
as the mapping: binfo
(b
),
orig_binfo
(vbase
), rtti_binfo
(binfo
),
and t
(t
).
Next in the function, b
at line 7241 is binfo of C::B1; and last
gets binfo of C::B1 at line 7248. As result, vtbl
is set by the binfo of C::B1
at line 7269. Finally, at line 7305, BINFO_VTABLE(binfo of C::B1::A) is extended
by a tree_list containing binfo of C::B1. And NULL inits
is returned.
However thing is a little different for B2-in-C. Also at exitting
from accumulate_vtbl_inits
at line 7119, B2-in-C in example 1 should have following extra entries in
construction vtable (kept in TREE_PURPOSE slot of list
at line 7118 in build_ctor_vtbl_group
).
Construction
vtable for B2 (0xb7f2da00
instance) in C
C::_ZTC1C4_2B2: 10u
entries
0
-4u
4
0u
8
(int (*)(...))0
12
(int (*)(...))(& _ZTI2B2)
16
B2::_ZTcv0_n12_v0_n16_N2B21fEv
20
B2::f
// slot of B2::f
But in dfs_accumulate_vtbl_inits
for B2::A,
it gets binfo
:
binfo of C::B2 (arg: rtti_binfo
), vbase
: binfo of B2::A (arg: orig_binfo
), b
: binfo of C::B2::A (arg: binfo
),
and t
:
C (arg: t
).
Then b
at line 7241 this time is binfo of C::B2; and last
at line 7248 gets NULL as it
climbs up via path A
à
B1 à
C. So vtbl
keeps NULL in condition at line 7276. Thus the construction vtable generated
for B2::A has below entries:
24
4u
// part of A in B2 - begin
28
(int (*)(...))4
32
(int (*)(...))(& _ZTI2B2)
36
B2::_ZTcv0_n12_v0_n16_N2B21fEv
// part of A
in B2 - end
Line 7140 in build_ctor_vtbl_group
rebuilds the array type for those construction vtables. Next at line 7144, this
construction vtable for base is linked into CLASSTYPE_VTABLES of the most
derived class. And initialize_array
at line 7145 prepares
initializers with exact types for vtable entry.
Return build_vtt_inits
from build_ctor_vtbl_group
, at
line 6916 binfo_ctor_vtable
gets construction vtable from binfo of C::B1 (recorded at index 1).
FOR
block at line 6927 does nothing for B1 or B2, it then arrives below
code.
build_vtt_inits (continue)
6935
/* Add secondary
virtual pointers for all subobjects of BINFO with
6936
either virtual bases or
reachable along a virtual path, except
6937
subobjects that are
non-virtual primary bases.
*/
6938
secondary_vptrs = tree_cons (t, NULL_TREE,
BINFO_TYPE (binfo));
6939
TREE_TYPE (secondary_vptrs) = *index;
6940
VTT_TOP_LEVEL_P (secondary_vptrs) =
top_level_p;
6941
VTT_MARKED_BINFO_P (secondary_vptrs) = 0;
6942
6943
dfs_walk_real
(binfo,
6944
dfs_build_secondary_vptr_vtt_inits
,
6945
NULL,
6946
dfs_ctor_vtable_bases_queue_p,
6947
secondary_vptrs);
6948
VTT_MARKED_BINFO_P (secondary_vptrs) = 1;
6949
dfs_walk (binfo, dfs_unmark,
dfs_ctor_vtable_bases_queue_p,
6950
secondary_vptrs);
6951
6952
*index = TREE_TYPE (secondary_vptrs);
6953
6954
/* The secondary
vptrs come back in reverse order. After we reverse
6955
them, and add the INITS, the
last init will be the first element
6956
of the chain.
*/
6957
secondary_vptrs = TREE_VALUE
(secondary_vptrs);
6958
if (secondary_vptrs)
6959
{
6960
*inits = nreverse (secondary_vptrs);
6961
inits = &TREE_CHAIN (secondary_vptrs);
6962
my_friendly_assert (*inits == NULL_TREE,
20000517);
6963
}
6964
6965
/* Add the
secondary VTTs for virtual bases.
*/
6966
if (top_level_p)
6967
for
(b =
TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
6968
{
6969
if (!TREE_VIA_VIRTUAL (b))
6970
continue
;
6971
6972
inits = build_vtt_inits
(b, t, inits, index);
6973
}
6974
6975
if (!top_level_p)
6976
{
6977
tree data = tree_cons (t, binfo,
NULL_TREE);
6978
VTT_TOP_LEVEL_P (data) = 0;
6979
VTT_MARKED_BINFO_P (data) = 0;
6980
6981
dfs_walk (binfo, dfs_fixup_binfo_vtbls
,
6982
dfs_ctor_vtable_bases_queue_p,
6983
data);
6984
}
6985
6986
return
inits;
6987
}
Above secondary_vptrs
as indicates by its name, is the pointer to secondary vtable in the VTT of the
most derived class (that is C for our example); and index
tells the slot of the VTT
this pointer lies in. The transverse at line 6943, begins at the binfo of base
referred by binfo
(here, i.e., either binfo of C::B1 or binfo of C::B2) and steps into this node.
Routine below then processes the nodes visited in pre-order, see argument data
is secondary_vptrs
.
6996
static
tree
6997
dfs_build_secondary_vptr_vtt_inits
(tree
binfo, void* data)
in
class.c
6998
{
6999
tree l;
7000
tree t;
7001
tree init;
7002
tree index;
7003
int top_level_p;
7004
7005
l = (tree) data;
7006
t = TREE_CHAIN (l);
7007
top_level_p = VTT_TOP_LEVEL_P (l);
7008
7009
BINFO_MARKED (binfo) = 1;
7010
7011
/* We don't care
about bases that don't have vtables.
*/
7012
if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
7013
return
NULL_TREE;
7014
7015
/* We're only
interested in proper subobjects of T.
*/
7016
if (same_type_p (BINFO_TYPE (binfo), t))
7017
return
NULL_TREE;
7018
7019
/* We're not
interested in non-virtual primary bases.
*/
7020
if (!TREE_VIA_VIRTUAL (binfo) &&
BINFO_PRIMARY_P (binfo))
7021
return
NULL_TREE;
7022
7023
/* If BINFO has
virtual bases or is reachable via a virtual path
7024
from T, it'll have a
secondary vptr.
*/
7025
if (!TYPE_USES_VIRTUAL_BASECLASSES
(BINFO_TYPE (binfo))
7026
&& !binfo_via_virtual (binfo, t))
7027
return
NULL_TREE;
7028
7029
/* Record the index
where this secondary vptr can be found.
*/
7030
index = TREE_TYPE (l);
7031
if (top_level_p)
7032
{
7033
my_friendly_assert (!BINFO_VPTR_INDEX
(binfo), 20010129);
7034
BINFO_VPTR_INDEX
(binfo) = index;
7035
}
7036
TREE_TYPE (l) = size_binop (PLUS_EXPR, index,
7037
TYPE_SIZE_UNIT (ptr_type_node));
7038
7039
/* Add the
initializer for the secondary vptr itself.
*/
7040
if (top_level_p && TREE_VIA_VIRTUAL
(binfo))
7041
{
7042
/* It's a primary virtual base, and this is
not the construction
7043
vtable. Find the base this
is primary of in the inheritance graph,
7044
and use that base's vtable
now.
*/
7045
while
(BINFO_PRIMARY_BASE_OF (binfo))
7046
binfo = BINFO_PRIMARY_BASE_OF (binfo);
7047
}
7048
init =
binfo_ctor_vtable
(binfo);
7049
TREE_VALUE (l) = tree_cons (NULL_TREE, init,
TREE_VALUE (l));
7050
7051
return
NULL_TREE;
7052
}
When iterating sub-tree headed by binfo of C::B1, top_level_p
above is false, t
at line 7006 is the type of B1. This node is skipped as condition at line 7016
is hold; At visiting binfo of C::B1::A, as in binfo BINFO_VTABLE of C::B1::A is
the binfo of C::B1, at line 7048 binfo_ctor_vtable
gets construction vtable of
C::B1 again (kept at index 2). Note this function always returns NULL which
forces a full walk within the (sub-)tree. To C::B2, it gets nothing too.
Remember in dfs_accumulate_vtbl_inits
at line 7305,
construction vtable temperarily stays in BINFO_VTABLE. Now construction vtable
has been recorded into VTT, no needs rely upon BINFO_VTABLE any more. Now it is
time to restore BINFO_VTABLE. Pay attention to the constructing of its argument
data. Here, node temperarily appended by C::B1::A is removed (it is C::B2::A
for C::B2).
7075
static
tree
7076
dfs_fixup_binfo_vtbls
(tree binfo, void*
data)
in
class.c
7077
{
7078
BINFO_MARKED (binfo) = 0;
7079
7080
/* We don't care
about bases that don't have vtables.
*/
7081
if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
7082
return
NULL_TREE;
7083
7084
/* If we scribbled
the construction vtable vptr into BINFO, clear it
7085
out now.
*/
7086
if (BINFO_VTABLE (binfo)
7087
&& TREE_CODE (BINFO_VTABLE (binfo))
== TREE_LIST
7088
&& (TREE_PURPOSE (BINFO_VTABLE
(binfo))
7089
== TREE_VALUE ((tree) data)))
7090
BINFO_VTABLE (binfo) = TREE_CHAIN
(BINFO_VTABLE (binfo));
7091
7092
return
NULL_TREE;
7093
}
In treatment of C::B2 mentioned above, when back build_vtt_inits
from build_ctor_vtbl_group
,
its construction vtable is saved in VTT by index 3. Then in dfs_build_secondary_vptr_vtt_inits
for C::B2, binfo_ctor_vtable
at line 7048 gets construction vtable of B2::A (at index 4 in VTT).
After finishes handling B1 and B2, it continues on handling C at
line 6938 in build_vtt_inits
.
It begins to transerve inheritance tree rooted by C at line 6943. So dfs_build_secondary_vptr_vtt_inits
in, top_level_p
is true, and t
is the most derived class C.
During this pre-order walk, C satisfies condtion at line 7016, C::B1 meets
condition at line 7020, and exit the function. For C::B2, index 5 in VTT is set as vptr of C::B2, and its
vtable’s (it’s a secondary vtable) initializer is what we got in previous
section; similarly for C::B1::A, its vptr is in VTT with index 6, also its
vtable’s (secondary vtable too) initialzier is what in BINFO_VTABLE(A-in-C)
prepared in previous section. At last, C::B2::A is skipped, as A has been
visited via C::B1::A.
A is processed in build_vtt_inits
at line 6972 at last, as A
hasn’t virtual base, build_vtt_inits
does nothing.
Returns build_vtt
,
if success, inits
should not be NULL. Following builds appropriate type for VTT and constructs
its static object, then links this object into head of CLASSTYPE_VTABLES of the
most derived class.
相关文章推荐
- Studying note of GCC-3.4.6 source (142)
- Studying note of GCC-3.4.6 source (100 continue)
- Studying note of GCC-3.4.6 source (129 continue)
- Studying note of GCC-3.4.6 source (140 - continue)
- Studying note of GCC-3.4.6 source (148 continue)
- Studying note of GCC-3.4.6 source (162 - continue)
- Studying note of GCC-3.4.6 source (64)
- Studying note of GCC-3.4.6 source (73)
- Studying note of GCC-3.4.6 source (79)
- Studying note of GCC-3.4.6 source (94)
- Studying note of GCC-3.4.6 source (99)
- Studying note of GCC-3.4.6 source (109)
- Studying note of GCC-3.4.6 source (114)
- Studying note of GCC-3.4.6 source (119)
- Studying note of GCC-3.4.6 source (131)
- Studying note of GCC-3.4.6 source (136)
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (9)
- Studying note of GCC-3.4.6 source (15)