您的位置:首页 > 其它

Studying note of GCC-3.4.6 source (141 - cont 1)

2011-01-09 17:30 423 查看
When finishing handling of B1, build_vcall_and_vbase_vtbl_entries

returns to
the invocation of handling class C. This time build_vbase_offset_vtbl_entries

does nothing, as base A has been processed with BINFO_VTABLE_PATH_MARKED set. And
in build_vcall_offset_vtbl_entries

,
vid->generate_vcall_entries

is set in false for class C, and vid->vbase

is set to binfo of C. Below call
stack would be involved.

build_vcall_and_vbase_vtbl_entries:
for C

build_vcall_offset_vtbl_entries:
for C

add_vcall_offset_vtbl_entries_r:
for C

add_vcall_offset_vtbl_entries_r:

for B1

add_vcall_offset_vtbl_entries_r:
for A

add_vcall_offset_vtbl_entries_1:
for B1

add_vcall_offset:
for B1

add_vcall_offset_vtbl_entries_1:
for C

add_vcall_offset:
for C

add_vcall_offset_vtbl_entries_r:
for B2

add_vcall_offset_vtbl_entries_r:
for A

add_vcall_offset_vtbl_entries_1:
for B2

add_vcall_offset:
for B2

In above call
stack, add_vcall_offset_vtbl_entries_r

first recurses for C’s A, but it does nothing as condition at line 7680
satisified. In following add_vcall_offset

, vid->fns now holds
virtual functions seen above, so same_signature_p

at
line 7805 returns true for B1’s
virtual, and exits the function at line 7810. After returning from add_vcall_offset_vtbl_entries_r

handling B1, invoking add_vcall_offset_vtbl_entries_1

for C.
Similiarly, same_signature_p

returns true for C’s virtual. Then add_vcall_offset_vtbl_entries_r

at line 7698
is recursed for B2 (the non-primary base), it’s original primary base A is
filtered out by conidtion at line 7680, also in add_vcall_offset

, same_signature_p

returns true for B2’s virtual.

When exitting
from build_vcall_and_vbase_vtbl_entries

for C, we will get following vtable initializers and CLASSTYPE_VCALL_INDICES.



In above figure, in the
chain of CLASSTYPE_VCALL_INDICES, value

field of node A::f is -3; it coordinate
with A::f given in chain of last_init.

Back build_vtbl_initializer

, it is still handling
C.

build_vtbl_initializer (continue)

7378

/* If the target
requires padding between data entries, add that now.
*/

7379

if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)

7380

{



7395

}

7396

7397

if (non_fn_entries_p)

7398

*non_fn_entries_p = list_length
(vid.inits);

7399

7400

/* Go through all
the ordinary virtual functions, building up

7401

initializers.
*/

7402

vfun_inits = NULL_TREE;

7403

for
(v =
BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (v))

7404

{

7405

tree delta;

7406

tree vcall_index;

7407

tree fn, fn_original;

7408

tree init = NULL_TREE;

7409

7410

fn = BV_FN (v);

7411

fn_original = fn;

7412

if (DECL_THUNK_P (fn))

7413

{

7414

if (!DECL_NAME (fn))

7415

finish_thunk
(fn);

7416

if (THUNK_ALIAS (fn))

7417

{

7418

fn = THUNK_ALIAS (fn);

7419

BV_FN (v) = fn;

7420

}

7421

fn_original = THUNK_TARGET (fn);

7422

}

7423

7424

/* If the only
definition of this function signature along our

7425

primary base chain is from a
lost primary, this vtable slot will

7426

never be used, so just zero
it out. This is important to avoid

7427

requiring extra thunks which
cannot be generated with the function.

7428

7429

We first check this in
update_vtable_entry_for_fn, so we handle

7430

restored primary bases
properly; we also need to do it here so we

7431

zero out unused slots in
ctor vtables, rather than filling themff

7432

with erroneous values
(though harmless, apart from relocation

7433

costs).
*/

7434

for
(b = binfo;
; b = get_primary_binfo
(b))

7435

{

7436

/* We found a
defn before a lost primary; go ahead as normal.

*/

7437

if (look_for_overrides_here
(BINFO_TYPE (b), fn_original))

7438

break
;

7439

7440

/* The nearest
definition is from a lost primary; clear the

7441

slot.
*/

7442

if (BINFO_LOST_PRIMARY_P (b))

7443

{

7444

init = size_zero_node;

7445

break
;

7446

}

7447

}

7448

7449

if (! init)

7450

{

7451

/* Pull the
offset for `this', and the function to call, out of

7452

the list.
*/

7453

delta = BV_DELTA (v);

7454

vcall_index
= BV_VCALL_INDEX (v);

7455

7456

my_friendly_assert (TREE_CODE (delta) ==
INTEGER_CST, 19990727);

7457

my_friendly_assert (TREE_CODE (fn) ==
FUNCTION_DECL, 19990727);

7458

7459

/* You can't
call an abstract virtual function; it's abstract.

7460

So, we replace these functions
with __pure_virtual.
*/

7461

if (DECL_PURE_VIRTUAL_P (fn_original))

7462

fn = abort_fndecl;

7463

else if (!integer_zerop
(delta) || vcall_index)

7464

{

7465

fn = make_thunk
(fn, /*this_adjusting=*/
1, delta,
vcall_index);

7466

if (!DECL_NAME (fn))

7467

finish_thunk
(fn);

7468

}

7469

/* Take the
address of the function, considering it to be of an

7470

appropriate generic
type.
*/

7471

init = build1
(ADDR_EXPR, vfunc_ptr_type_node

,
fn);

7472

/* The address
of a function can't change.
*/

7473

TREE_CONSTANT (init) = 1;

7474

}

7475

7476

/* And add it to
the chain of initializers.
*/

7477

if (TARGET_VTABLE_USES_DESCRIPTORS)

7478

{



7493

}

7494

else

7495

vfun_inits = tree_cons (NULL_TREE, init,
vfun_inits);

7496

}

7497

7498

/* The initializers
for virtual functions were built up in reverse

7499

order; straighten them out
now.
*/

7450

vfun_inits = nreverse (vfun_inits);

7451

7452

/* The negative
offset initializers are also in reverse order.

*/

7453

vid.inits = nreverse (vid.inits);

7454

7455

/* Chain the two
together.
*/

7456

return
chainon (vid.inits, vfun_inits);

7457

}

Above orig_binfo

comes from current class, whose BINFO_VIRTUALS has been process by update_vtable_entry_for_fn

(see previous section). Virtuals in BINFO_VIRTUALS can be a thunk, which is
constructed in update_vtable_entry_for_fn

, and only of result-adjustmnet.
Here it is constructing this-adjustment thunk, and information BV_DELTA, BV_VCALL_INDEX
(from CLASSTYPE_VCALL_INDICES of the virtual base. Above can see C also
prepared it for future being virtual base) is also collected by update_vtable_entry_for_fn

.

Now all thunks are still anonymous. In the front-end, that indicates
the thunk is incomplete.

194

void

195

finish_thunk

(tree thunk)

in

method.c

196

{

197

tree function, name;

198

tree fixed_offset = ssize_int
(THUNK_FIXED_OFFSET (thunk));

199

tree virtual_offset = THUNK_VIRTUAL_OFFSET
(thunk);

200

201

my_friendly_assert (!DECL_NAME (thunk)
&& DECL_THUNK_P (thunk), 20021127);

202

if (virtual_offset &&
DECL_RESULT_THUNK_P (thunk))

203

virtual_offset = BINFO_VPTR_FIELD
(virtual_offset);

204

function = THUNK_TARGET (thunk);

205

name = mangle_thunk (function,
DECL_THIS_THUNK_P (thunk),

206

fixed_offset, virtual_offset);

207

208

/* We can end up
with declarations of (logically) different

209

covariant thunks,
that do identical adjustments. The two thunks

210

will be adjusting
between within different hierarchies, which

211

happen to have
the same layout. We must nullify one of them to

212

refer to the
other.
*/

213

if (DECL_RESULT_THUNK_P (thunk))

214

{

215

tree cov_probe;

216

217

for
(cov_probe = DECL_THUNKS (function);

218

cov_probe; cov_probe = TREE_CHAIN
(cov_probe))

219

if (DECL_NAME (cov_probe) == name)

220

{

221

my_friendly_assert (!DECL_THUNKS (thunk),
20031023);

222

THUNK_ALIAS (thunk) = (THUNK_ALIAS
(cov_probe)

223

? THUNK_ALIAS (cov_probe) : cov_probe);

224

break
;

225

}

226

}

227

228

DECL_NAME (thunk) = name;

229

SET_DECL_ASSEMBLER_NAME (thunk, name);

230

}

THUNK_VIRTUAL_OFFSET, for this-adjusting thunk, it is the number of
bytes to be added to the vtable to find the vcall offset; for a result
adjusting thunk, it is the binfo of the relevant virtual base. BINFO_VPTR_FIELD
at line 203 is an INTEGER_CST giving an offset into the vtable where the offset
to the virtual base can be found. So for result adjusting thunk, needs
treatment at line 203 to get the offset of the virtual base. At line 205, mangle_thunk

returns the mangled name for the thunk (at section beginning, we have seen
examples of thunk’s mangled name). After setting the name with the thunk, it
can be regarded as finished. As thunk’s name is constructed by its action, it’s
possible there exists thunk of same name, at which treats the thunk built later
as the alias of the former one, they share the same thunk function.

dfs_accumulate_vtbl_inits
(continue)

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

}

Back to dfs_accumulate_vtbl_inits

, note that we are
still handling class C. above l

is list

in finish_vtbls

, in its TREE_PURPOSE is the TYPE_BINFO_VTABLE
(vtable saved in the binfo of the type, which is VAR_DECL generated by build_primary_vtable

).
And originally, TREE_VALUE of l

is NULL (but at line 7185 in accumulate_vtbl_inits

, it chains l

with
the list returned by dfs_accumulate_vtbl_inits

). See that non_fn_entries

records the number of entries of negative index. So it can know where to begin
the entries visible to programmer.

When returns back to accumulate_vtbl_inits

, after chaining into list

in finish_vtt

,
we get following figure (remember in create_vtable_ptr

, every virtual function has
an extra node generated with 0 delta).



Next, in accumulate_vtbl_inits

,
at line 7195, in FOR
block, binfo B1
within C is not handled as its BINFO_NEW_VTABLE_MARKED unset (see dfs_accumulate_vtbl_inits

line 7273). While for B2 in
C, it has secondary vtable generated, so passes the line successfully. At that
time, ctor_vtbl_p

is false, binfo

from class B2, orig_binfo

from B2 in C, and rtti_binfo

is C’s binfo, it undergoes similar processing as that for C above. Then when
back finish_vtbls

,
A in C is processed by accumulate_vtbl_inits

at
line 6780, in which ctor_vtbl_p

is still false. But this A hasn’t
flag BINFO_NEW_VTABLE_MARKED set, so exits dfs_accumulate_vtbl_inits

immediately.

So before
invoking initialize_vtable

at line 6784, list

is given in below figure.

(Click
here for open
)

Figure 117

: initializer for vtable

Above B1 and A don’t have their part of vtable as they share the
same part with C.

In below function, now argument inits

is the chain referred by value slot of list

in
above figure. This chain holds all initializers for class C’s vtable. Note that
at last vtbl

at line 7297 in dfs_accumulate_vtbl_inits

,
points to the start point of vtable of specified class which is a PLUS_EXPR of
vtbl+4 for C, vtbl+8 for base B2.

6789

static
void

6790

initialize_vtable

(tree binfo, tree
inits)

in
class.c

6791

{

6792

tree decl;

6793

6794

layout_vtable_decl
(binfo, list_length (inits));

6795

decl = get_vtbl_decl_for_binfo
(binfo);

6796

initialize_array
(decl, inits);

6797

dump_vtable (BINFO_TYPE (binfo), binfo, decl);

6798

}

Originally in build_vtable

, vtable is created as type of vtbl_type_node

which is the array of type vtable_entry_type

with empty dimension. Now the
size of the array is settled down, we can create the exact type by layout_vtable_decl

.

1778

static
void

1779

layout_vtable_decl

(tree binfo, int n)

in

class.c

1780

{

1781

tree atype;

1782

tree vtable;

1783

1784

atype = build_cplus_array_type (vtable_entry_type

,

1785

build_index_type
(size_int (n - 1)));

1786

layout_type
(atype);

1787

1788

/* We may have to
grow the vtable.
*/

1789

vtable = get_vtbl_decl_for_binfo
(binfo);

1790

if (!same_type_p (TREE_TYPE (vtable), atype))

1791

{

1792

TREE_TYPE (vtable) = atype;

1793

DECL_SIZE (vtable) = DECL_SIZE_UNIT
(vtable) = NULL_TREE;

1794

layout_decl
(vtable, 0);

1795

}

1796

}

So at line 6795, the vtable VAR_DECL fetched has correct type
defined. And it is passed as argument decl

in below function.

6803

static
void

6804

initialize_array

(tree decl, tree inits)
in

class.c

6805

{

6806

tree context;

6807

6808

context = DECL_CONTEXT (decl);

6809

DECL_CONTEXT (decl) = NULL_TREE;

6810

DECL_INITIAL (decl) = build_constructor
(NULL_TREE, inits);

6811

TREE_HAS_CONSTRUCTOR (DECL_INITIAL (decl)) =
1;

6812

cp_finish_decl
(decl, DECL_INITIAL (decl), NULL_TREE, 0);

6813

DECL_CONTEXT (decl) = context;

6814

}

See node of CONSTRUCTOR is built for initializing this VAR_DECL.
Note that this node has empty type

field (it is treated as unknown).

444

tree

445

build_constructor

(tree type, tree vals)

in
tree.c

446

{

447

tree c = make_node
(CONSTRUCTOR);

448

TREE_TYPE (c) = type;

449

CONSTRUCTOR_ELTS (c) = vals;

450

451

/* ??? May not be
necessary. Mirrors what build does.
*/

452

if (vals)

453

{

454

TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS
(vals);

455

TREE_READONLY (c) = TREE_READONLY (vals);

456

TREE_CONSTANT (c) = TREE_CONSTANT (vals);

457

}

458

else

459

TREE_CONSTANT (c) = 0;
/* safe side */

460

461

return
c;

462

}

Being a VAR_DECL, it is completed by cp_finish_decl

. Note that we
are still within another cp_finish_decl

for the template instantiation
of SmallObject.

4768

void

4769

cp_finish_decl

(tree decl, tree init,
tree asmspec_tree, int flags)

in decl.c

4770

{

4771

tree type;

4772

tree ttype = NULL_TREE;

4773

tree cleanup;

4774

const
char
*asmspec = NULL;

4775

int was_readonly = 0;

4776

bool var_definition_p = false;

4777

4778

if (decl == error_mark_node)

4779

return
;

4780

else if (! decl)

4781

{

4782

if (init)

4783

error ("assignment (not
initialization) in declaration");

4784

return
;

4785

}

4786

4787

my_friendly_assert (TREE_CODE (decl) !=
RESULT_DECL, 20030619);

4788

4789

/* Assume no
cleanup is required.
*/

4790

cleanup = NULL_TREE;

4791

4792

/* If a name was
specified, get the string.
*/

4793

if (global_scope_p (current_binding_level

))

4794

asmspec_tree = maybe_apply_renaming_pragma
(decl, asmspec_tree);

4795

if (asmspec_tree)

4796

asmspec = TREE_STRING_POINTER
(asmspec_tree);

4797

4798

if (init && TREE_CODE (init) ==
NAMESPACE_DECL)

4799

{

4800

error ("cannot initialize `%D' to
namespace `%D'",

4802

decl, init);

4803

init = NULL_TREE;

4804

}

4805

4806

if (current_class_type

4807

&& CP_DECL_CONTEXT (decl) == current_class_type

4808

&& TYPE_BEING_DEFINED (current_class_type

)

4809

&& (DECL_INITIAL (decl) || init))

4810

DECL_INITIALIZED_IN_CLASS_P (decl) = 1;

4811

4812

if (TREE_CODE (decl) == VAR_DECL

4813

&& DECL_CONTEXT (decl)

4814

&& TREE_CODE (DECL_CONTEXT (decl))
== NAMESPACE_DECL

4815

&& DECL_CONTEXT (decl) != current_namespace

4816

&& init)

4817

{

4818

/* Leave the namespace of the object.
*/

4819

pop_decl_namespace ();

4820

}

4821

4822

type = TREE_TYPE (decl);

4823

4824

if (type == error_mark_node)

4825

goto
finish_end0;

4826

4827

if (TYPE_HAS_MUTABLE_P (type))

4828

TREE_READONLY (decl) = 0;

4829

4830

if (processing_template_decl

)

4831

{



4842

}

4843

4844

/* Parameters are
handled by store_parm_decls, not cp_finish_decl.
*/

4845

my_friendly_assert (TREE_CODE (decl) !=
PARM_DECL, 19990828);

4846

4847

/* Take care of
TYPE_DECLs up front.
*/

4848

if (TREE_CODE (decl) == TYPE_DECL)

4849

{



4868

}

4869

4870

if (TREE_CODE (decl) != FUNCTION_DECL)

4871

ttype = target_type (type);

4872

4873

4874

/* Currently, GNU
C++ puts constants in text space, making them

4875

impossible to initialize. In
the future, one would hope for

4876

an operating system which
understood the difference between

4877

initialization and the running
of a program.
*/

4878

if (! DECL_EXTERNAL (decl) &&
TREE_READONLY (decl))

4879

{

4880

was_readonly = 1;

4881

if (TYPE_NEEDS_CONSTRUCTING (type)

4882

||
TREE_CODE (type) == REFERENCE_TYPE)

4883

TREE_READONLY (decl) = 0;

4884

}

4885

4886

if (TREE_CODE (decl) == VAR_DECL)

4887

{

4888

/* Only PODs can
have thread-local storage. Other types may require

4889

various kinds of non-trivial
initialization.
*/

4890

if (DECL_THREAD_LOCAL (decl) &&
!pod_type_p (TREE_TYPE (decl)))

4891

error ("`%D' cannot be thread-local
because it has non-POD type `%T'",

4892

decl, TREE_TYPE (decl));

4893

/* Convert the
initializer to the type of DECL, if we have not

4894

already initialized DECL.
*/

4895

if (!DECL_INITIALIZED_P (decl)

4896

/* If !DECL_EXTERNAL then DECL is being defined. In the

4897

case of a static data member initialized
inside the

4898

class-specifier, there can be an initializer
even if DECL

4899

is *not* defined.
*/

4900

&& (!DECL_EXTERNAL (decl) || init))

4901

{

4902

init = check_initializer
(decl, init, flags, &cleanup);

4903

/* Thread-local
storage cannot be dynamically initialized.

*/

4904

if
(DECL_THREAD_LOCAL (decl) && init)

4905

{

4906

error ("`%D' is thread-local and so
cannot be dynamically "

4907

"initialized", decl);

4908

init = NULL_TREE;

4909

}

4910

if
(DECL_EXTERNAL (decl) && init)

4911

{

4912

/* The static data member cannot be initialized by a

4913

non-constant when being declared.
*/

4914

error ("`%D' cannot be initialized
by a non-constant expression"

4915

" when being declared", decl);

4916

DECL_INITIALIZED_IN_CLASS_P (decl) = 0;

4917

init = NULL_TREE;

4918

}

4919

4920

/* Handle:

4921

4922

[dcl.init]

4923

4924

The memory occupied by any object of static
storage

4925

duration is zero-initialized at program
startup before

4926

any other initialization takes place.

4927

4928

We cannot create an appropriate
initializer until after

4929

the type of DECL is finalized. If
DECL_INITIAL is set,

4930

then the DECL is statically initialized,
and any

4931

necessary zero-initialization has already
been performed.
*/

4932

if
(TREE_STATIC (decl) && !DECL_INITIAL (decl))

4933

DECL_INITIAL (decl) = build_zero_init
(TREE_TYPE (decl),

4934

/*nelts=*/
NULL_TREE,

4935

/*static_storage_p=*/
true);

4936

/* Remember that the
initialization for this variable has

4937

taken place.

*/

4938

DECL_INITIALIZED_P (decl) = 1;

4939

/* This declaration is the definition of this variable,

4940

unless we are initializing a static data
member within

4941

the class specifier.
*/

4942

if
(!DECL_EXTERNAL (decl))

4943

var_definition_p = true;

4944

}



4951

}

Before entering the function, we clean DELC_CONTEXT of decl

. At
line 4794, maybe_apply_renaming_pragma

is only useful for Solaris and Tru64 UNIX system for compatibility with the
system headers.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: