您的位置:首页 > 其它

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: