Studying note of GCC-3.4.6 source (139)
2011-01-02 12:58
330 查看
5.12.5.2.2.2.1.3.9.
Finish the
derived RECORD_TYPE – layout the class
Go back finish_struct_1
, below keyed_classes
is a tree_list of the
classes whose vtables may have to be emitted in this translation unit. The
candidate in the list is the class that contains no non-inline, non-pure
virtaul method. In other words, the class only contains pure virtual method
or/and inline virtual method. For such class, vtable should be emitted in every
translation unit where the class definitions appears (i.e, via #include); while
for other class contains other virtual method, vtable should be emitted in the
translation unit in which virtual method defined.
finish_struct_1 (continue)
5033
/* Find the key
method.
*/
5034
if (TYPE_CONTAINS_VPTR_P (t))
5035
{
5036
CLASSTYPE_KEY_METHOD (t) = key_method
(t);
5037
5038
/* If a
polymorphic class has no key method, we may emit the vtable
5039
i
n every translation unit where the class
definition appears.
*/
5040
if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)
5041
keyed_classes
= tree_cons (NULL_TREE, t, keyed_classes
);
5042
}
5043
5044
/* Layout the class
itself.
*/
5045
layout_class_type
(t, &virtuals);
5046
if (CLASSTYPE_AS_BASE (t) != t)
5047
/* We use the base type for trivial
assignments, and hence it
5048
needs a mode.
*/
5049
compute_record_mode
(CLASSTYPE_AS_BASE (t));
CLASSTYPE_KEY_METHOD hold the first non-inline and non-pure virtual
method in the class, this field is used during vtable generation.
4973
static
tree
4974
key_method
(tree type)
in class.c
4975
{
4976
tree method;
4977
4978
if (TYPE_FOR_JAVA (type)
4979
||
processing_template_decl
4980
||
CLASSTYPE_TEMPLATE_INSTANTIATION (type)
4981
||
CLASSTYPE_INTERFACE_KNOWN (type))
4982
return
NULL_TREE;
4983
4984
for
(method =
TYPE_METHODS (type); method != NULL_TREE;
4985
method = TREE_CHAIN (method))
4986
if (DECL_VINDEX (method) != NULL_TREE
4987
&& ! DECL_DECLARED_INLINE_P
(method)
4988
&& ! DECL_PURE_VIRTUAL_P
(method))
4989
return
method;
4990
4991
return
NULL_TREE;
4992
}
Keep in mind that no virtual method is allowed within class template.
If we have already determined whether or not vtables, VTTs,
typeinfo, and other similar per-class data should be emitted in this
translation unit; CLASSTYPE_INTERFACE_KNOWN is true, such class should not be
kept in
keyed_classes
even it meets the qualification.
Then we can layout the class to determine the real size of the type,
the offset of every data member from the start byte of every instance, their
sizes, pack bytes, and even the book-keeping data generated by the compiler.
Obviously, it is a quite complex procedure.
Before going deep into the code, let’s see real layout generated by
GCC with following examples:
Example 1:
class
A { virtual
A* f (); };
class
B1 : virtual
public
A { virtual
B1* f (); };
class
B2 : virtual
public
A { virtual
B2* f (); };
class
C: public
B1, public
B2 { virtual
C* f (); };
int main() { return
0; }
With command g++ -fdump-class-hierarchy –o test test.cc, gcc will
dump information about class hierarchy into a dump file (i.e., test.01.class),
and we can see following output (we omit information other than layout
temperarily):
…
Class A
size=4 align=4
base size=4 base align=4
A (0xb7f2d680) 0 nearly-empty
vptr=((& A::_ZTV1A) + 8u)
…
Class B1
size=4 align=4
base size=4 base align=4
B1 (0xb7f2d700) 0 nearly-empty
vptridx=0u vptr=((& B1::_ZTV2B1) + 16u)
A (0xb7f2d740) 0 nearly-empty virtual
primary-for B1 (0xb7f2d700)
vptridx=4u vbaseoffset=-0x000000010
…
Class B2
size=4 align=4
base size=4 base align=4
B2 (0xb7f2d840) 0 nearly-empty
vptridx=0u vptr=((& B2::_ZTV2B2) + 16u)
A (0xb7f2d880) 0 nearly-empty virtual
primary-for B2 (0xb7f2d840)
vptridx=4u vbaseoffset=-0x000000010
…
Class C
size=8 align=4
base size=8 base align=4
C (0xb7f2d940) 0
vptridx=0u vptr=((& C::_ZTV1C) + 16u)
B1 (0xb7f2d980) 0 nearly-empty
primary-for C (0xb7f2d940)
subvttidx=4u
A (0xb7f2d9c0)
0 nearly-empty virtual
primary-for B1 (0xb7f2d980)
vptridx=20u vbaseoffset=-0x000000010
B2 (0xb7f2da00) 4 nearly-empty
lost-primary
subvttidx=12u vptridx=24u vptr=((& C::_ZTV1C) + 40u)
A (0xb7f2d9c0)
alternative-path
In the output “A (0xb7f2d680) 0 nearly-empty”, “A” is the class
the binfo comes from, “(0xb7f2d680)”
is the address of the binfo, “0”
is the offset of binfo in the class layout, “nearly-empty” tells that the class
is a nearly-empty class.
And the output “size=8 align=4” is the size and alignment of the class, while “base
size=8 base align=4” is the
size and alignment of CLASSTYPE_AS_BASE of the class (with vritual bases
stripped).
Example 2 (add field “int
a” into class A):
class
A { int a; virtual
A* f (); };
class
B1 : virtual
public
A { virtual
B1* f (); };
class
B2 : virtual
public
A { virtual
B2* f (); };
class
C: public
B1, public
B2 { virtual
C* f (); };
int main() { return
0; }
The output is then:
…
Class A
size=8 align=4
base size=8 base align=4
A (0xb7fae680)
0
vptr=((& A::_ZTV1A) + 8u)
…
Class B1
size=12 align=4
base size=4 base align=4
B1
(0xb7fae700) 0 nearly-empty
vptridx=0u vptr=((& B1::_ZTV2B1) + 12u)
A (0xb7fae740) 4 virtual
vptridx=4u vbaseoffset=-0x00000000c vptr=((& B1::_ZTV2B1) + 28u)
…
Class B2
size=12 align=4
base size=4 base align=4
B2
(0xb7fae800) 0 nearly-empty
vptridx=0u vptr=((& B2::_ZTV2B2) + 12u)
A (0xb7fae840) 4 virtual
vptridx=4u vbaseoffset=-0x00000000c vptr=((& B2::_ZTV2B2) + 28u)
…
Class C
size=16 align=4
base size=8 base align=4
C (0xb7fae8c0) 0
vptridx=0u vptr=((& C::_ZTV1C) + 12u)
B1
(0xb7fae900) 0 nearly-empty
primary-for C (0xb7fae8c0)
subvttidx=4u
A (0xb7fae940) 8 virtual
vptridx=20u vbaseoffset=-0x00000000c vptr=((& C::_ZTV1C) + 44u)
B2 (0xb7fae980) 4 nearly-empty
subvttidx=12u vptridx=24u vptr=((&
C::_ZTV1C) + 28u)
A (0xb7fae940) alternative-path
By introducing field “int
a”, class A is not a nearly-empty class any more, but still are B1 and B2. This
fact affects the layout deeply. And we can find the reason from the code below.
4637
static
void
4638
layout_class_type
(tree t, tree
*virtuals_p)
in class.c
4639
{
4640
tree non_static_data_members;
4641
tree field;
4642
tree vptr;
4643
record_layout_info
rli;
4644
/* Maps offsets
(represented as INTEGER_CSTs) to a TREE_LIST of
4645
types that appear at that
offset.
*/
4646
splay_tree empty_base_offsets;
4647
/* True if the last
field layed out was a bit-field.
*/
4648
bool last_field_was_bitfield = false;
4649
/* The location at
which the next field should be inserted.
*/
4650
tree *next_field;
4651
/* T, as a base
class.
*/
4652
tree base_t;
4653
4654
/* Keep track of
the first non-static data member.
*/
4655
non_static_data_members = TYPE_FIELDS (t);
4656
4657
/* Start laying out
the record.
*/
4658
rli = start_record_layout
(t);
4659
4660
/* If possible, we
reuse the virtual function table pointer from one
4661
of our base classes.
*/
4662
determine_primary_base
(t);
In case of mulitply heritage, base classes will be layed out one
after one in the derived class. The first base class with offset of 0, no doubt
can be directly accessed from the head of the derived class, while in other
base classes followed, the nonzero offset from the head of the derived class
should be added to the offset of its field from its head to access the field
which entails one extra indirect addressing. Plus the case of deep inheritage,
which base to be placed first must be selected carefully. Here notice that determine_primary_base
is invoked for every class definition. If we call it for a complex class, its
base classes should have been handled by this function already.
1267
static
void
1268
determine_primary_base
(tree t)
in
class.c
1269
{
1270
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
1271
tree vbases;
1272
tree type_binfo;
1273
1274
/* If there are no
baseclasses, there is certainly no primary base.
*/
1275
if (n_baseclasses == 0)
1276
return
;
1277
1278
type_binfo = TYPE_BINFO (t);
1279
1280
for
(i = 0; i
< n_baseclasses; i++)
1281
{
1282
tree base_binfo = BINFO_BASETYPE
(type_binfo, i);
1283
tree basetype = BINFO_TYPE (base_binfo);
1284
1285
if (TYPE_CONTAINS_VPTR_P (basetype))
1286
{
1287
/* We prefer a
non-virtual base, although a virtual one will
1288
do.
*/
1289
if (TREE_VIA_VIRTUAL (base_binfo))
1290
continue
;
1291
1292
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
1293
{
1294
set_primary_base
(t, base_binfo);
1295
CLASSTYPE_VFIELDS (t) = copy_list
(CLASSTYPE_VFIELDS (basetype));
1296
}
1297
else
1298
{
1299
tree vfields;
1300
1301
/* Only add unique vfields, and flatten them out as we
go.
*/
1302
for
(vfields = CLASSTYPE_VFIELDS (basetype);
1303
vfields;
1304
vfields = TREE_CHAIN (vfields))
1305
if (VF_BINFO_VALUE (vfields) ==
NULL_TREE
1306
|| ! TREE_VIA_VIRTUAL
(VF_BINFO_VALUE (vfields)))
1307
CLASSTYPE_VFIELDS (t)
1308
= tree_cons (base_binfo,
1309
VF_BASETYPE_VALUE
(vfields),
1310
CLASSTYPE_VFIELDS
(t));
1311
}
1312
}
1313
}
Non-vritual base class containing vtable is the most preferred. The
first such base encountered is bound with the class by following set_primary_base
.
Note that TYPE_VFIELD is the compiler-generated field used to point to virtual
function tables.
1253
static
void
1254
set_primary_base
(tree t, tree binfo)
in
class.c
1255
{
1256
tree basetype;
1257
1258
CLASSTYPE_PRIMARY_BINFO (t) = binfo;
1259
basetype = BINFO_TYPE (binfo);
1260
TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE
(basetype);
1261
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS
(basetype);
1262
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
1263
}
Above field CLASSTYPE_VFIELDS is a list of vtables that this type
contains (both the primary and secondaries). The TREE_VALUE is the class type
where the vtable was introduced. For a vtable inherited from the primary base,
or introduced by this class, the TREE_PURPOSE is NULL. For other vtables (those
from non-primary bases), the TREE_PURPOSE is the BINFO of the base from which
the vtable was inherited.
Note that CLASSTYPE_VFIELDS of the derived class originial is empty;
and virtual base, unless it’s nearly empty (at that time, it can’t have
vtable), can be the primary base (even it’s the only base having vtable). So
above copying vtable can ensure only be done on non-virtual bases. And see that
if it’s the primary base, the derived will copy its CLASSTYPE_VFIELDS directlt
(PURPOSE field of node for the primary base’s vtable is NULL). It is because
primary base always stays at head of the derived, if it has vtable, its address
will be that of the derived’s vtable, thus the derived will just take the
vtable for its using.
determine_primary_base (continue)
1315
if (!TYPE_VFIELD (t))
1316
CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
1317
1318
/* Find the
indirect primary bases - those virtual bases which are primary
1319
bases of something else in
this hierarchy.
*/
1320
for
(vbases = CLASSTYPE_VBASECLASSES (t);
1321
vbases;
1322
vbases = TREE_CHAIN (vbases))
1323
{
1324
tree vbase_binfo = TREE_VALUE (vbases);
1325
1326
/* See if this
virtual base is an indirect primary base. To be so,
1327
it must be a primary base
within the hierarchy of one of our
1328
direct bases.
*/
1329
for
(i = 0;
i < n_baseclasses; ++i)
1330
{
1331
tree basetype = TYPE_BINFO_BASETYPE (t,
i);
1332
tree v;
1333
1334
for
(v =
CLASSTYPE_VBASECLASSES (basetype);
1335
v;
1336
v = TREE_CHAIN (v))
1337
{
1338
tree base_vbase = TREE_VALUE (v);
1339
1340
if (BINFO_PRIMARY_P (base_vbase)
1341
&& same_type_p (BINFO_TYPE
(base_vbase),
1342
BINFO_TYPE
(vbase_binfo)))
1343
{
1344
BINFO_INDIRECT_PRIMARY_P
(vbase_binfo) = 1;
1345
break
;
1346
}
1347
}
1348
1349
/* If we've
discovered that this virtual base is an indirect
1350
primary base, then we can move on to the
next virtual
1351
base.
*/
1352
if (BINFO_INDIRECT_PRIMARY_P
(vbase_binfo))
1353
break
;
1354
}
1355
}
1356
1357
/* A
"nearly-empty" virtual base class can be the primary base
1358
class, if no non-virtual
polymorphic base can be found.
*/
1359
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
1360
{
1361
/* If not NULL,
this is the best primary base candidate we have
1362
found so far.
*/
1363
tree candidate = NULL_TREE;
1364
tree base_binfo;
1365
1366
/* Loop over the
baseclasses.
*/
1367
for
(base_binfo = TYPE_BINFO (t);
1368
base_binfo;
1369
base_binfo = TREE_CHAIN (base_binfo))
1370
{
1371
tree basetype = BINFO_TYPE (base_binfo);
1372
1373
if (TREE_VIA_VIRTUAL (base_binfo)
1374
&& CLASSTYPE_NEARLY_EMPTY_P
(basetype))
1375
{
1376
/* If this is not an indirect primary base,
then it's
1377
definitely our primary
base.
*/
1378
if (!BINFO_INDIRECT_PRIMARY_P
(base_binfo))
1379
{
1380
candidate = base_binfo;
1381
break
;
1382
}
1383
1384
/* If this is
an indirect primary base, it still could be
1385
our primary base --
unless we later find there's another
1386
nearly-empty virtual
base that isn't an indirect
1387
primary base.
*/
1388
if (!candidate)
1389
candidate = base_binfo;
1390
}
1391
}
1392
1393
/* If we've got a
primary base, use it.
*/
1394
if (candidate)
1395
{
1396
set_primary_base
(t, candidate);
1397
CLASSTYPE_VFIELDS (t)
1398
= copy_list (CLASSTYPE_VFIELDS
(BINFO_TYPE (candidate)));
1399
}
1400
}
1401
1402
/* Mark the primary
base classes at this point.
*/
1403
mark_primary_bases
(t);
1404
}
If can’t find out non-virtual base containing vtable, TYPE_VFIELD of
the derived keeps NULL (in set_primary base
, it would be set as TYPE_VFIELD
of the primary base), by which no matter what’s CLASSTYPE_PRIMARY_BINFO now,
set it by NULL. Next see if any virtual base can be the primary base. The
qualified ones, besides must be nearly empty, that never be a primary base is
preferred. Otherwise, as the last measure, using the last virtual base in the
derived’s declaration (it can reduce the chance of conflicting).
Strictly speaking, in a derived there must be only one primary base.
For example:
class
A {…}; class
B: public
A {…}; class
C: public
B {…};
The primary base of class B is class A, but in class C, the primary
base is class B, not class A. However, in class C, the binfo of B is copied
from class B, information of primary base is left out. But virtual base is
different, so below function also needs restore thing to order for virtual base.
1218
static
void
1219
mark_primary_bases
(tree type)
in
class.c
1220
{
1221
tree binfo;
1222
1223
/* Walk the bases
in inheritance graph order.
*/
1224
for
(binfo =
TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))
1225
{
1226
tree base_binfo = get_primary_binfo
(binfo);
1227
1228
if (!base_binfo)
1229
/* Not a
dynamic base.
*/
;
1230
else if (BINFO_PRIMARY_P (base_binfo))
1231
BINFO_LOST_PRIMARY_P (binfo) = 1;
1232
else
1233
{
1234
BINFO_PRIMARY_BASE_OF (base_binfo) =
binfo;
1235
/* A virtual
binfo might have been copied from within
1236
another hierarchy. As we're about to use
it as a primary
1237
base, make sure
the offsets match.
*/
1238
if (TREE_VIA_VIRTUAL (base_binfo))
1239
{
1240
tree delta = size_diffop (convert
(ssizetype,
1241
BINFO_OFFSET
(binfo)),
1242
convert (ssizetype,
1243
BINFO_OFFSET
(base_binfo)));
1244
1245
propagate_binfo_offsets
(base_binfo, delta);
1246
}
1247
}
1248
}
1249
}
At line 1226 get_primary_binfo
returns the copied binfo of
primary base of the type corresponding to parameter binfo
if it is set, otherwise null.
6470
tree
6471
get_primary_binfo
(tree binfo)
in
class.c
6472
{
6473
tree primary_base;
6474
tree result;
6475
6476
primary_base = CLASSTYPE_PRIMARY_BINFO
(BINFO_TYPE (binfo));
6477
if (!primary_base)
6478
return
NULL_TREE;
6479
6480
result = copied_binfo
(primary_base, binfo);
6481
return
result;
6482
}
Given primary_base
,
copied_binfo
gets its counterpart from binfo
. Consider the example:
class
A { virtual
… };
class
B: public
A { virtual
… };
class
C: public
A { virtual
… };
class
D: public
B, C { … };
First, at line 1224 in
mark_primary_bases
,
in chain of TYPE_BINFO(D), there is D
à
B
à
A
à
C
à
A in order. Obviously, CLASSTYPE_PRIMARY_BINFO(D) returns the
copied info of B (it is set by set_primary_base
); then below at line 2578, copied_binfo
is recursed and gets
binfo
of D, then in FOR loop at line 2581, searching
among D’s bases: B, C; and find that B is the target. As the copied binfo of B
is gotten from class B, BINFO_PRIMARY_P (base_binfo) at line 1230 returns NULL,
which means B isn’t a primary base (but it is now). So we set it as D’s primary
base at line 1234 (distiguish it from CLASSTYPE_PRIMARY_BINFO).
Then for binfo of B, A is its primary base. Searching the copied
binfo of A in D, is similar with that of the copied binfo of B, except that A
appears both in B and C within D. But the searching procedure will ensure B
à
A be found. As A is the primary base of B, but in the A’s copied
binfo hasn’t BINFO_PRIMARY_P set, it satifies condition at line 1232 and set as
the primray base of B’s copied binfo.
And similarly we get copied binfo of A in C within D, and it also
hasn’t BINFO_PRIMARY_P set.
2556
tree
2557
copied_binfo
(tree binfo, tree here)
in
search.c
2558
{
2559
tree result = NULL_TREE;
2560
2561
if (TREE_VIA_VIRTUAL (binfo))
2562
{
2563
tree t;
2564
2565
for
(t = here; BINFO_INHERITANCE_CHAIN (t);
2566
t = BINFO_INHERITANCE_CHAIN (t))
2567
continue
;
2568
2569
result = purpose_member (BINFO_TYPE
(binfo),
2570
CLASSTYPE_VBASECLASSES (BINFO_TYPE (t)));
2571
result = TREE_VALUE (result);
2572
}
2573
else if (BINFO_INHERITANCE_CHAIN (binfo))
2574
{
2575
tree base_binfos;
2576
int ix, n;
2577
2578
base_binfos = copied_binfo
(BINFO_INHERITANCE_CHAIN (binfo), here);
2579
base_binfos = BINFO_BASETYPES
(base_binfos);
2580
n = TREE_VEC_LENGTH (base_binfos);
2581
for
(ix =
0; ix != n; ix++)
2582
{
2583
tree base = TREE_VEC_ELT (base_binfos,
ix);
2584
2585
if (BINFO_TYPE (base) == BINFO_TYPE
(binfo))
2586
{
2587
result = base;
2588
break
;
2589
}
2590
}
2591
}
2592
else
2593
{
2594
my_friendly_assert (BINFO_TYPE (here) ==
BINFO_TYPE (binfo), 20030202);
2595
result = here;
2596
}
2597
2598
my_friendly_assert (result, 20030202);
2599
return
result;
2600
}
Further conside following example:
class
A { virtual
… };
class
B: virtual
public
A { … };
class
C: virtual
public
A { … };
class
D: public
B, C { … };
In TYPE_BINFO(D) chain, there is D
à
B
à
A
à
C in order, as A being virtual base can only have single instance
within D. The procedure almost the same, except searching the counterpart of
virtual base is down from the top of the inherient tree instead of climbing up
from the base. And as virtual base A never
uses copied binfo, it satifies condtion at line 1230 in mark_primary_bases
.
In copy_base_binfos
,
it copies the offset information with the binfos. But the offset is related to
the binfos copied. And being the primary base, the virtual base (include
non-virtual base) must be placed at beginning of the layout (in fact after
vtable). This adjustmemt is done by propagate_binfo_offsets
(for non-virtual base
binfo, its offset is always 0, and its non-virtual bases maintain the relative
unchanged offset when laying out this base within current type).
4355
static
void
4356
propagate_binfo_offsets
(tree binfo,
tree offset)
in
class.c
4357
{
4358
int i;
4359
tree primary_binfo;
4360
4361
/* Update BINFO's offset.
*/
4362
BINFO_OFFSET (binfo)
4363
= convert (sizetype,
4364
size_binop (PLUS_EXPR,
4365
convert (ssizetype,
BINFO_OFFSET (binfo)),
4366
offset));
4367
4368
/* Find the primary
base class.
*/
4369
primary_binfo = get_primary_binfo
(binfo);
4370
4371
/* Scan all of the
bases, pushing the BINFO_OFFSET adjust
4372
downwards.
*/
4373
for
(i = -1; i < BINFO_N_BASETYPES (binfo); ++i)
4374
{
4375
tree base_binfo;
4376
4377
/* On the first
time through the loop, do the primary base.
4378
Because the primary base
need not be an immediate base, we
4379
must handle the primary base
specially.
*/
4380
if (i == -1)
4381
{
4382
if (!primary_binfo)
4383
continue
;
4384
4385
base_binfo = primary_binfo;
4386
}
4387
else
4388
{
4389
base_binfo = BINFO_BASETYPE (binfo, i);
4390
/* Don't do the
primary base twice.
*/
4391
if (base_binfo == primary_binfo)
4392
continue
;
4393
}
4394
4395
/* Skip virtual
bases that aren't our canonical primary base.
*/
4396
if (TREE_VIA_VIRTUAL (base_binfo)
4397
&& BINFO_PRIMARY_BASE_OF
(base_binfo) != binfo)
4398
continue
;
4399
4400
propagate_binfo_offsets
(base_binfo, offset);
4401
}
4402
}
Function propagate_binfo_offsets
adjusts the whole
base with the offset adjustment. Remember BINFO_OFFSET indicates the offset where
this basetype appears in its derived class. In previous, see that primary base
may not be the immediate base, so FOR loop at line 4373 includes an extra
counter to recover primrary base not of immediate base.
Finish the
derived RECORD_TYPE – layout the class
Go back finish_struct_1
, below keyed_classes
is a tree_list of the
classes whose vtables may have to be emitted in this translation unit. The
candidate in the list is the class that contains no non-inline, non-pure
virtaul method. In other words, the class only contains pure virtual method
or/and inline virtual method. For such class, vtable should be emitted in every
translation unit where the class definitions appears (i.e, via #include); while
for other class contains other virtual method, vtable should be emitted in the
translation unit in which virtual method defined.
finish_struct_1 (continue)
5033
/* Find the key
method.
*/
5034
if (TYPE_CONTAINS_VPTR_P (t))
5035
{
5036
CLASSTYPE_KEY_METHOD (t) = key_method
(t);
5037
5038
/* If a
polymorphic class has no key method, we may emit the vtable
5039
i
n every translation unit where the class
definition appears.
*/
5040
if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)
5041
keyed_classes
= tree_cons (NULL_TREE, t, keyed_classes
);
5042
}
5043
5044
/* Layout the class
itself.
*/
5045
layout_class_type
(t, &virtuals);
5046
if (CLASSTYPE_AS_BASE (t) != t)
5047
/* We use the base type for trivial
assignments, and hence it
5048
needs a mode.
*/
5049
compute_record_mode
(CLASSTYPE_AS_BASE (t));
CLASSTYPE_KEY_METHOD hold the first non-inline and non-pure virtual
method in the class, this field is used during vtable generation.
4973
static
tree
4974
key_method
(tree type)
in class.c
4975
{
4976
tree method;
4977
4978
if (TYPE_FOR_JAVA (type)
4979
||
processing_template_decl
4980
||
CLASSTYPE_TEMPLATE_INSTANTIATION (type)
4981
||
CLASSTYPE_INTERFACE_KNOWN (type))
4982
return
NULL_TREE;
4983
4984
for
(method =
TYPE_METHODS (type); method != NULL_TREE;
4985
method = TREE_CHAIN (method))
4986
if (DECL_VINDEX (method) != NULL_TREE
4987
&& ! DECL_DECLARED_INLINE_P
(method)
4988
&& ! DECL_PURE_VIRTUAL_P
(method))
4989
return
method;
4990
4991
return
NULL_TREE;
4992
}
Keep in mind that no virtual method is allowed within class template.
If we have already determined whether or not vtables, VTTs,
typeinfo, and other similar per-class data should be emitted in this
translation unit; CLASSTYPE_INTERFACE_KNOWN is true, such class should not be
kept in
keyed_classes
even it meets the qualification.
Then we can layout the class to determine the real size of the type,
the offset of every data member from the start byte of every instance, their
sizes, pack bytes, and even the book-keeping data generated by the compiler.
Obviously, it is a quite complex procedure.
Before going deep into the code, let’s see real layout generated by
GCC with following examples:
Example 1:
class
A { virtual
A* f (); };
class
B1 : virtual
public
A { virtual
B1* f (); };
class
B2 : virtual
public
A { virtual
B2* f (); };
class
C: public
B1, public
B2 { virtual
C* f (); };
int main() { return
0; }
With command g++ -fdump-class-hierarchy –o test test.cc, gcc will
dump information about class hierarchy into a dump file (i.e., test.01.class),
and we can see following output (we omit information other than layout
temperarily):
…
Class A
size=4 align=4
base size=4 base align=4
A (0xb7f2d680) 0 nearly-empty
vptr=((& A::_ZTV1A) + 8u)
…
Class B1
size=4 align=4
base size=4 base align=4
B1 (0xb7f2d700) 0 nearly-empty
vptridx=0u vptr=((& B1::_ZTV2B1) + 16u)
A (0xb7f2d740) 0 nearly-empty virtual
primary-for B1 (0xb7f2d700)
vptridx=4u vbaseoffset=-0x000000010
…
Class B2
size=4 align=4
base size=4 base align=4
B2 (0xb7f2d840) 0 nearly-empty
vptridx=0u vptr=((& B2::_ZTV2B2) + 16u)
A (0xb7f2d880) 0 nearly-empty virtual
primary-for B2 (0xb7f2d840)
vptridx=4u vbaseoffset=-0x000000010
…
Class C
size=8 align=4
base size=8 base align=4
C (0xb7f2d940) 0
vptridx=0u vptr=((& C::_ZTV1C) + 16u)
B1 (0xb7f2d980) 0 nearly-empty
primary-for C (0xb7f2d940)
subvttidx=4u
A (0xb7f2d9c0)
0 nearly-empty virtual
primary-for B1 (0xb7f2d980)
vptridx=20u vbaseoffset=-0x000000010
B2 (0xb7f2da00) 4 nearly-empty
lost-primary
subvttidx=12u vptridx=24u vptr=((& C::_ZTV1C) + 40u)
A (0xb7f2d9c0)
alternative-path
In the output “A (0xb7f2d680) 0 nearly-empty”, “A” is the class
the binfo comes from, “(0xb7f2d680)”
is the address of the binfo, “0”
is the offset of binfo in the class layout, “nearly-empty” tells that the class
is a nearly-empty class.
And the output “size=8 align=4” is the size and alignment of the class, while “base
size=8 base align=4” is the
size and alignment of CLASSTYPE_AS_BASE of the class (with vritual bases
stripped).
Example 2 (add field “int
a” into class A):
class
A { int a; virtual
A* f (); };
class
B1 : virtual
public
A { virtual
B1* f (); };
class
B2 : virtual
public
A { virtual
B2* f (); };
class
C: public
B1, public
B2 { virtual
C* f (); };
int main() { return
0; }
The output is then:
…
Class A
size=8 align=4
base size=8 base align=4
A (0xb7fae680)
0
vptr=((& A::_ZTV1A) + 8u)
…
Class B1
size=12 align=4
base size=4 base align=4
B1
(0xb7fae700) 0 nearly-empty
vptridx=0u vptr=((& B1::_ZTV2B1) + 12u)
A (0xb7fae740) 4 virtual
vptridx=4u vbaseoffset=-0x00000000c vptr=((& B1::_ZTV2B1) + 28u)
…
Class B2
size=12 align=4
base size=4 base align=4
B2
(0xb7fae800) 0 nearly-empty
vptridx=0u vptr=((& B2::_ZTV2B2) + 12u)
A (0xb7fae840) 4 virtual
vptridx=4u vbaseoffset=-0x00000000c vptr=((& B2::_ZTV2B2) + 28u)
…
Class C
size=16 align=4
base size=8 base align=4
C (0xb7fae8c0) 0
vptridx=0u vptr=((& C::_ZTV1C) + 12u)
B1
(0xb7fae900) 0 nearly-empty
primary-for C (0xb7fae8c0)
subvttidx=4u
A (0xb7fae940) 8 virtual
vptridx=20u vbaseoffset=-0x00000000c vptr=((& C::_ZTV1C) + 44u)
B2 (0xb7fae980) 4 nearly-empty
subvttidx=12u vptridx=24u vptr=((&
C::_ZTV1C) + 28u)
A (0xb7fae940) alternative-path
By introducing field “int
a”, class A is not a nearly-empty class any more, but still are B1 and B2. This
fact affects the layout deeply. And we can find the reason from the code below.
4637
static
void
4638
layout_class_type
(tree t, tree
*virtuals_p)
in class.c
4639
{
4640
tree non_static_data_members;
4641
tree field;
4642
tree vptr;
4643
record_layout_info
rli;
4644
/* Maps offsets
(represented as INTEGER_CSTs) to a TREE_LIST of
4645
types that appear at that
offset.
*/
4646
splay_tree empty_base_offsets;
4647
/* True if the last
field layed out was a bit-field.
*/
4648
bool last_field_was_bitfield = false;
4649
/* The location at
which the next field should be inserted.
*/
4650
tree *next_field;
4651
/* T, as a base
class.
*/
4652
tree base_t;
4653
4654
/* Keep track of
the first non-static data member.
*/
4655
non_static_data_members = TYPE_FIELDS (t);
4656
4657
/* Start laying out
the record.
*/
4658
rli = start_record_layout
(t);
4659
4660
/* If possible, we
reuse the virtual function table pointer from one
4661
of our base classes.
*/
4662
determine_primary_base
(t);
In case of mulitply heritage, base classes will be layed out one
after one in the derived class. The first base class with offset of 0, no doubt
can be directly accessed from the head of the derived class, while in other
base classes followed, the nonzero offset from the head of the derived class
should be added to the offset of its field from its head to access the field
which entails one extra indirect addressing. Plus the case of deep inheritage,
which base to be placed first must be selected carefully. Here notice that determine_primary_base
is invoked for every class definition. If we call it for a complex class, its
base classes should have been handled by this function already.
1267
static
void
1268
determine_primary_base
(tree t)
in
class.c
1269
{
1270
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
1271
tree vbases;
1272
tree type_binfo;
1273
1274
/* If there are no
baseclasses, there is certainly no primary base.
*/
1275
if (n_baseclasses == 0)
1276
return
;
1277
1278
type_binfo = TYPE_BINFO (t);
1279
1280
for
(i = 0; i
< n_baseclasses; i++)
1281
{
1282
tree base_binfo = BINFO_BASETYPE
(type_binfo, i);
1283
tree basetype = BINFO_TYPE (base_binfo);
1284
1285
if (TYPE_CONTAINS_VPTR_P (basetype))
1286
{
1287
/* We prefer a
non-virtual base, although a virtual one will
1288
do.
*/
1289
if (TREE_VIA_VIRTUAL (base_binfo))
1290
continue
;
1291
1292
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
1293
{
1294
set_primary_base
(t, base_binfo);
1295
CLASSTYPE_VFIELDS (t) = copy_list
(CLASSTYPE_VFIELDS (basetype));
1296
}
1297
else
1298
{
1299
tree vfields;
1300
1301
/* Only add unique vfields, and flatten them out as we
go.
*/
1302
for
(vfields = CLASSTYPE_VFIELDS (basetype);
1303
vfields;
1304
vfields = TREE_CHAIN (vfields))
1305
if (VF_BINFO_VALUE (vfields) ==
NULL_TREE
1306
|| ! TREE_VIA_VIRTUAL
(VF_BINFO_VALUE (vfields)))
1307
CLASSTYPE_VFIELDS (t)
1308
= tree_cons (base_binfo,
1309
VF_BASETYPE_VALUE
(vfields),
1310
CLASSTYPE_VFIELDS
(t));
1311
}
1312
}
1313
}
Non-vritual base class containing vtable is the most preferred. The
first such base encountered is bound with the class by following set_primary_base
.
Note that TYPE_VFIELD is the compiler-generated field used to point to virtual
function tables.
1253
static
void
1254
set_primary_base
(tree t, tree binfo)
in
class.c
1255
{
1256
tree basetype;
1257
1258
CLASSTYPE_PRIMARY_BINFO (t) = binfo;
1259
basetype = BINFO_TYPE (binfo);
1260
TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE
(basetype);
1261
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS
(basetype);
1262
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
1263
}
Above field CLASSTYPE_VFIELDS is a list of vtables that this type
contains (both the primary and secondaries). The TREE_VALUE is the class type
where the vtable was introduced. For a vtable inherited from the primary base,
or introduced by this class, the TREE_PURPOSE is NULL. For other vtables (those
from non-primary bases), the TREE_PURPOSE is the BINFO of the base from which
the vtable was inherited.
Note that CLASSTYPE_VFIELDS of the derived class originial is empty;
and virtual base, unless it’s nearly empty (at that time, it can’t have
vtable), can be the primary base (even it’s the only base having vtable). So
above copying vtable can ensure only be done on non-virtual bases. And see that
if it’s the primary base, the derived will copy its CLASSTYPE_VFIELDS directlt
(PURPOSE field of node for the primary base’s vtable is NULL). It is because
primary base always stays at head of the derived, if it has vtable, its address
will be that of the derived’s vtable, thus the derived will just take the
vtable for its using.
determine_primary_base (continue)
1315
if (!TYPE_VFIELD (t))
1316
CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
1317
1318
/* Find the
indirect primary bases - those virtual bases which are primary
1319
bases of something else in
this hierarchy.
*/
1320
for
(vbases = CLASSTYPE_VBASECLASSES (t);
1321
vbases;
1322
vbases = TREE_CHAIN (vbases))
1323
{
1324
tree vbase_binfo = TREE_VALUE (vbases);
1325
1326
/* See if this
virtual base is an indirect primary base. To be so,
1327
it must be a primary base
within the hierarchy of one of our
1328
direct bases.
*/
1329
for
(i = 0;
i < n_baseclasses; ++i)
1330
{
1331
tree basetype = TYPE_BINFO_BASETYPE (t,
i);
1332
tree v;
1333
1334
for
(v =
CLASSTYPE_VBASECLASSES (basetype);
1335
v;
1336
v = TREE_CHAIN (v))
1337
{
1338
tree base_vbase = TREE_VALUE (v);
1339
1340
if (BINFO_PRIMARY_P (base_vbase)
1341
&& same_type_p (BINFO_TYPE
(base_vbase),
1342
BINFO_TYPE
(vbase_binfo)))
1343
{
1344
BINFO_INDIRECT_PRIMARY_P
(vbase_binfo) = 1;
1345
break
;
1346
}
1347
}
1348
1349
/* If we've
discovered that this virtual base is an indirect
1350
primary base, then we can move on to the
next virtual
1351
base.
*/
1352
if (BINFO_INDIRECT_PRIMARY_P
(vbase_binfo))
1353
break
;
1354
}
1355
}
1356
1357
/* A
"nearly-empty" virtual base class can be the primary base
1358
class, if no non-virtual
polymorphic base can be found.
*/
1359
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
1360
{
1361
/* If not NULL,
this is the best primary base candidate we have
1362
found so far.
*/
1363
tree candidate = NULL_TREE;
1364
tree base_binfo;
1365
1366
/* Loop over the
baseclasses.
*/
1367
for
(base_binfo = TYPE_BINFO (t);
1368
base_binfo;
1369
base_binfo = TREE_CHAIN (base_binfo))
1370
{
1371
tree basetype = BINFO_TYPE (base_binfo);
1372
1373
if (TREE_VIA_VIRTUAL (base_binfo)
1374
&& CLASSTYPE_NEARLY_EMPTY_P
(basetype))
1375
{
1376
/* If this is not an indirect primary base,
then it's
1377
definitely our primary
base.
*/
1378
if (!BINFO_INDIRECT_PRIMARY_P
(base_binfo))
1379
{
1380
candidate = base_binfo;
1381
break
;
1382
}
1383
1384
/* If this is
an indirect primary base, it still could be
1385
our primary base --
unless we later find there's another
1386
nearly-empty virtual
base that isn't an indirect
1387
primary base.
*/
1388
if (!candidate)
1389
candidate = base_binfo;
1390
}
1391
}
1392
1393
/* If we've got a
primary base, use it.
*/
1394
if (candidate)
1395
{
1396
set_primary_base
(t, candidate);
1397
CLASSTYPE_VFIELDS (t)
1398
= copy_list (CLASSTYPE_VFIELDS
(BINFO_TYPE (candidate)));
1399
}
1400
}
1401
1402
/* Mark the primary
base classes at this point.
*/
1403
mark_primary_bases
(t);
1404
}
If can’t find out non-virtual base containing vtable, TYPE_VFIELD of
the derived keeps NULL (in set_primary base
, it would be set as TYPE_VFIELD
of the primary base), by which no matter what’s CLASSTYPE_PRIMARY_BINFO now,
set it by NULL. Next see if any virtual base can be the primary base. The
qualified ones, besides must be nearly empty, that never be a primary base is
preferred. Otherwise, as the last measure, using the last virtual base in the
derived’s declaration (it can reduce the chance of conflicting).
Strictly speaking, in a derived there must be only one primary base.
For example:
class
A {…}; class
B: public
A {…}; class
C: public
B {…};
The primary base of class B is class A, but in class C, the primary
base is class B, not class A. However, in class C, the binfo of B is copied
from class B, information of primary base is left out. But virtual base is
different, so below function also needs restore thing to order for virtual base.
1218
static
void
1219
mark_primary_bases
(tree type)
in
class.c
1220
{
1221
tree binfo;
1222
1223
/* Walk the bases
in inheritance graph order.
*/
1224
for
(binfo =
TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))
1225
{
1226
tree base_binfo = get_primary_binfo
(binfo);
1227
1228
if (!base_binfo)
1229
/* Not a
dynamic base.
*/
;
1230
else if (BINFO_PRIMARY_P (base_binfo))
1231
BINFO_LOST_PRIMARY_P (binfo) = 1;
1232
else
1233
{
1234
BINFO_PRIMARY_BASE_OF (base_binfo) =
binfo;
1235
/* A virtual
binfo might have been copied from within
1236
another hierarchy. As we're about to use
it as a primary
1237
base, make sure
the offsets match.
*/
1238
if (TREE_VIA_VIRTUAL (base_binfo))
1239
{
1240
tree delta = size_diffop (convert
(ssizetype,
1241
BINFO_OFFSET
(binfo)),
1242
convert (ssizetype,
1243
BINFO_OFFSET
(base_binfo)));
1244
1245
propagate_binfo_offsets
(base_binfo, delta);
1246
}
1247
}
1248
}
1249
}
At line 1226 get_primary_binfo
returns the copied binfo of
primary base of the type corresponding to parameter binfo
if it is set, otherwise null.
6470
tree
6471
get_primary_binfo
(tree binfo)
in
class.c
6472
{
6473
tree primary_base;
6474
tree result;
6475
6476
primary_base = CLASSTYPE_PRIMARY_BINFO
(BINFO_TYPE (binfo));
6477
if (!primary_base)
6478
return
NULL_TREE;
6479
6480
result = copied_binfo
(primary_base, binfo);
6481
return
result;
6482
}
Given primary_base
,
copied_binfo
gets its counterpart from binfo
. Consider the example:
class
A { virtual
… };
class
B: public
A { virtual
… };
class
C: public
A { virtual
… };
class
D: public
B, C { … };
First, at line 1224 in
mark_primary_bases
,
in chain of TYPE_BINFO(D), there is D
à
B
à
A
à
C
à
A in order. Obviously, CLASSTYPE_PRIMARY_BINFO(D) returns the
copied info of B (it is set by set_primary_base
); then below at line 2578, copied_binfo
is recursed and gets
binfo
of D, then in FOR loop at line 2581, searching
among D’s bases: B, C; and find that B is the target. As the copied binfo of B
is gotten from class B, BINFO_PRIMARY_P (base_binfo) at line 1230 returns NULL,
which means B isn’t a primary base (but it is now). So we set it as D’s primary
base at line 1234 (distiguish it from CLASSTYPE_PRIMARY_BINFO).
Then for binfo of B, A is its primary base. Searching the copied
binfo of A in D, is similar with that of the copied binfo of B, except that A
appears both in B and C within D. But the searching procedure will ensure B
à
A be found. As A is the primary base of B, but in the A’s copied
binfo hasn’t BINFO_PRIMARY_P set, it satifies condition at line 1232 and set as
the primray base of B’s copied binfo.
And similarly we get copied binfo of A in C within D, and it also
hasn’t BINFO_PRIMARY_P set.
2556
tree
2557
copied_binfo
(tree binfo, tree here)
in
search.c
2558
{
2559
tree result = NULL_TREE;
2560
2561
if (TREE_VIA_VIRTUAL (binfo))
2562
{
2563
tree t;
2564
2565
for
(t = here; BINFO_INHERITANCE_CHAIN (t);
2566
t = BINFO_INHERITANCE_CHAIN (t))
2567
continue
;
2568
2569
result = purpose_member (BINFO_TYPE
(binfo),
2570
CLASSTYPE_VBASECLASSES (BINFO_TYPE (t)));
2571
result = TREE_VALUE (result);
2572
}
2573
else if (BINFO_INHERITANCE_CHAIN (binfo))
2574
{
2575
tree base_binfos;
2576
int ix, n;
2577
2578
base_binfos = copied_binfo
(BINFO_INHERITANCE_CHAIN (binfo), here);
2579
base_binfos = BINFO_BASETYPES
(base_binfos);
2580
n = TREE_VEC_LENGTH (base_binfos);
2581
for
(ix =
0; ix != n; ix++)
2582
{
2583
tree base = TREE_VEC_ELT (base_binfos,
ix);
2584
2585
if (BINFO_TYPE (base) == BINFO_TYPE
(binfo))
2586
{
2587
result = base;
2588
break
;
2589
}
2590
}
2591
}
2592
else
2593
{
2594
my_friendly_assert (BINFO_TYPE (here) ==
BINFO_TYPE (binfo), 20030202);
2595
result = here;
2596
}
2597
2598
my_friendly_assert (result, 20030202);
2599
return
result;
2600
}
Further conside following example:
class
A { virtual
… };
class
B: virtual
public
A { … };
class
C: virtual
public
A { … };
class
D: public
B, C { … };
In TYPE_BINFO(D) chain, there is D
à
B
à
A
à
C in order, as A being virtual base can only have single instance
within D. The procedure almost the same, except searching the counterpart of
virtual base is down from the top of the inherient tree instead of climbing up
from the base. And as virtual base A never
uses copied binfo, it satifies condtion at line 1230 in mark_primary_bases
.
In copy_base_binfos
,
it copies the offset information with the binfos. But the offset is related to
the binfos copied. And being the primary base, the virtual base (include
non-virtual base) must be placed at beginning of the layout (in fact after
vtable). This adjustmemt is done by propagate_binfo_offsets
(for non-virtual base
binfo, its offset is always 0, and its non-virtual bases maintain the relative
unchanged offset when laying out this base within current type).
4355
static
void
4356
propagate_binfo_offsets
(tree binfo,
tree offset)
in
class.c
4357
{
4358
int i;
4359
tree primary_binfo;
4360
4361
/* Update BINFO's offset.
*/
4362
BINFO_OFFSET (binfo)
4363
= convert (sizetype,
4364
size_binop (PLUS_EXPR,
4365
convert (ssizetype,
BINFO_OFFSET (binfo)),
4366
offset));
4367
4368
/* Find the primary
base class.
*/
4369
primary_binfo = get_primary_binfo
(binfo);
4370
4371
/* Scan all of the
bases, pushing the BINFO_OFFSET adjust
4372
downwards.
*/
4373
for
(i = -1; i < BINFO_N_BASETYPES (binfo); ++i)
4374
{
4375
tree base_binfo;
4376
4377
/* On the first
time through the loop, do the primary base.
4378
Because the primary base
need not be an immediate base, we
4379
must handle the primary base
specially.
*/
4380
if (i == -1)
4381
{
4382
if (!primary_binfo)
4383
continue
;
4384
4385
base_binfo = primary_binfo;
4386
}
4387
else
4388
{
4389
base_binfo = BINFO_BASETYPE (binfo, i);
4390
/* Don't do the
primary base twice.
*/
4391
if (base_binfo == primary_binfo)
4392
continue
;
4393
}
4394
4395
/* Skip virtual
bases that aren't our canonical primary base.
*/
4396
if (TREE_VIA_VIRTUAL (base_binfo)
4397
&& BINFO_PRIMARY_BASE_OF
(base_binfo) != binfo)
4398
continue
;
4399
4400
propagate_binfo_offsets
(base_binfo, offset);
4401
}
4402
}
Function propagate_binfo_offsets
adjusts the whole
base with the offset adjustment. Remember BINFO_OFFSET indicates the offset where
this basetype appears in its derived class. In previous, see that primary base
may not be the immediate base, so FOR loop at line 4373 includes an extra
counter to recover primrary base not of immediate base.
相关文章推荐
- Studying note of GCC-3.4.6 source (139 - cont 1)
- Studying note of GCC-3.4.6 source (139 - cont 2)
- Studying note of GCC-3.4.6 source (151)
- Studying note of GCC-3.4.6 source (25 cont1)
- Studying note of GCC-3.4.6 source (26)
- Studying note of GCC-3.4.6 source (33)
- Studying note of GCC-3.4.6 source (38)
- Studying note of GCC-3.4.6 source (39)
- Studying note of GCC-3.4.6 source (175)
- Studying note of GCC-3.4.6 source (181)
- Studying note of GCC-3.4.6 source (55)
- Studying note of GCC-3.4.6 source (66)
- Studying note of GCC-3.4.6 source (86)
- Studying note of GCC-3.4.6 source (103)
- Studying note of GCC-3.4.6 source (104)
- Studying note of GCC-3.4.6 source (107)
- Studying note of GCC-3.4.6 source (120)
- Studying note of GCC-3.4.6 source (5)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (140 - continue)