Studying note of GCC-3.4.6 source (141 - cont 1)
来源:互联网 发布:云栈菜鸟淘宝打印组件 编辑:程序博客网 时间:2024/05/21 05:18
When finishing handling of B1, build_vcall_and_vbase_vtbl_entries returns tothe invocation of handling class C. This time build_vbase_offset_vtbl_entriesdoes nothing, as base A has been processed with BINFO_VTABLE_PATH_MARKED set. Andin build_vcall_offset_vtbl_entries,vid->generate_vcall_entriesis set in false for class C, and vid->vbase is set to binfo of C. Below callstack 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 callstack, add_vcall_offset_vtbl_entries_rfirst recurses for C’s A, but it does nothing as condition at line 7680satisified. In following add_vcall_offset, vid->fns now holdsvirtual functions seen above, so same_signature_p atline 7805 returns true for B1’svirtual, and exits the function at line 7810. After returning from add_vcall_offset_vtbl_entries_rhandling B1, invoking add_vcall_offset_vtbl_entries_1 for C.Similiarly, same_signature_preturns true for C’s virtual. Then add_vcall_offset_vtbl_entries_r at line 7698is recursed for B2 (the non-primary base), it’s original primary base A isfiltered out by conidtion at line 7680, also in add_vcall_offset, same_signature_preturns true for B2’s virtual.
When exittingfrom build_vcall_and_vbase_vtbl_entriesfor C, we will get following vtable initializers and CLASSTYPE_VCALL_INDICES.
In above figure, in thechain of CLASSTYPE_VCALL_INDICES, value field of node A::f is -3; it coordinatewith A::f given in chain of last_init.
Back build_vtbl_initializer, it is still handlingC.
build_vtbl_initializer (continue)
7378 /* If the targetrequires 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 allthe 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 onlydefinition of this function signature along our
7425 primary base chain is from alost primary, this vtable slot will
7426 never be used, so just zeroit out. This is important to avoid
7427 requiring extra thunks whichcannot be generated with the function.
7428
7429 We first check this inupdate_vtable_entry_for_fn, so we handle
7430 restored primary basesproperly; we also need to do it here so we
7431 zero out unused slots inctor 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 adefn before a lost primary; go ahead as normal. */
7437 if (look_for_overrides_here(BINFO_TYPE (b), fn_original))
7438 break;
7439
7440 /* The nearestdefinition 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 theoffset 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'tcall an abstract virtual function; it's abstract.
7460 So, we replace these functionswith __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 theaddress of the function, considering it to be of an
7470 appropriate generictype. */
7471 init = build1(ADDR_EXPR, vfunc_ptr_type_node,fn);
7472 /* The addressof a function can't change. */
7473 TREE_CONSTANT (init) = 1;
7474 }
7475
7476 /* And add it tothe 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 initializersfor virtual functions were built up in reverse
7499 order; straighten them outnow. */
7450 vfun_inits = nreverse (vfun_inits);
7451
7452 /* The negativeoffset initializers are also in reverse order. */
7453 vid.inits = nreverse (vid.inits);
7454
7455 /* Chain the twotogether. */
7456 returnchainon (vid.inits, vfun_inits);
7457 }
Above orig_binfocomes 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 isconstructed 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 alsoprepared 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 indicatesthe thunk is incomplete.
194 void
195 finish_thunk (tree thunk) inmethod.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 upwith declarations of (logically) different
209 covariant thunks,that do identical adjustments. The two thunks
210 will be adjustingbetween within different hierarchies, which
211 happen to havethe same layout. We must nullify one of them to
212 refer to theother. */
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 ofbytes to be added to the vtable to find the vcall offset; for a resultadjusting thunk, it is the binfo of the relevant virtual base. BINFO_VPTR_FIELDat line 203 is an INTEGER_CST giving an offset into the vtable where the offsetto the virtual base can be found. So for result adjusting thunk, needstreatment at line 203 to get the offset of the virtual base. At line 205, mangle_thunkreturns the mangled name for the thunk (at section beginning, we have seenexamples of thunk’s mangled name). After setting the name with the thunk, itcan be regarded as finished. As thunk’s name is constructed by its action, it’spossible there exists thunk of same name, at which treats the thunk built lateras the alias of the former one, they share the same thunk function.
dfs_accumulate_vtbl_inits(continue)
7285 /* Figure out theposition 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 overwriteBINFO_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, setBINFO_VTABLE. */
7310 BINFO_VTABLE (binfo) = vtbl;
7311
7312 return inits;
7313 }
Back to dfs_accumulate_vtbl_inits, note that we arestill 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 withthe list returned by dfs_accumulate_vtbl_inits). See that non_fn_entriesrecords the number of entries of negative index. So it can know where to beginthe 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 hasan extra node generated with 0 delta).
Next, in accumulate_vtbl_inits,at line 7195, in FOR block, binfo B1within C is not handled as its BINFO_NEW_VTABLE_MARKED unset (see dfs_accumulate_vtbl_initsline 7273). While for B2 inC, it has secondary vtable generated, so passes the line successfully. At thattime, ctor_vtbl_pis false, binfofrom class B2, orig_binfofrom B2 in C, and rtti_binfois C’s binfo, it undergoes similar processing as that for C above. Then whenback finish_vtbls,A in C is processed by accumulate_vtbl_inits atline 6780, in which ctor_vtbl_p is still false. But this A hasn’tflag BINFO_NEW_VTABLE_MARKED set, so exits dfs_accumulate_vtbl_inits immediately.
So beforeinvoking initialize_vtableat line 6784, listis given in below figure.
(Clickhere for open)
Figure 117: initializer for vtable
Above B1 and A don’t have their part of vtable as they share thesame part with C.
In below function, now argument inits is the chain referred by value slot of list inabove figure. This chain holds all initializers for class C’s vtable. Note thatat last vtblat line 7297 in dfs_accumulate_vtbl_inits,points to the start point of vtable of specified class which is a PLUS_EXPR ofvtbl+4 for C, vtbl+8 for base B2.
6789 static void
6790 initialize_vtable (tree binfo, treeinits) 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_nodewhich is the array of type vtable_entry_type with empty dimension. Now thesize 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) inclass.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 togrow 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 typedefined. And it is passed as argument decl in below function.
6803 static void
6804 initialize_array (tree decl, tree inits) inclass.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 benecessary. 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 weare still within another cp_finish_decl for the template instantiationof 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 (notinitialization) in declaration");
4784 return;
4785 }
4786
4787 my_friendly_assert (TREE_CODE (decl) !=RESULT_DECL, 20030619);
4788
4789 /* Assume nocleanup is required. */
4790 cleanup = NULL_TREE;
4791
4792 /* If a name wasspecified, 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' tonamespace `%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 gotofinish_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 arehandled by store_parm_decls, not cp_finish_decl. */
4845 my_friendly_assert (TREE_CODE (decl) !=PARM_DECL, 19990828);
4846
4847 /* Take care ofTYPE_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, GNUC++ puts constants in text space, making them
4875 impossible to initialize. Inthe future, one would hope for
4876 an operating system whichunderstood the difference between
4877 initialization and the runningof 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 canhave thread-local storage. Other types may require
4889 various kinds of non-trivialinitialization. */
4890 if (DECL_THREAD_LOCAL (decl) &&!pod_type_p (TREE_TYPE (decl)))
4891 error ("`%D' cannot be thread-localbecause it has non-POD type `%T'",
4892 decl, TREE_TYPE (decl));
4893 /* Convert theinitializer 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 initializedinside the
4898 class-specifier, there can be an initializereven if DECL
4899 is *not* defined. */
4900 && (!DECL_EXTERNAL (decl) || init))
4901 {
4902 init = check_initializer(decl, init, flags, &cleanup);
4903 /* Thread-localstorage cannot be dynamically initialized. */
4904 if(DECL_THREAD_LOCAL (decl) && init)
4905 {
4906 error ("`%D' is thread-local and socannot 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 initializedby 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 staticstorage
4925 duration is zero-initialized at programstartup before
4926 any other initialization takes place.
4927
4928 We cannot create an appropriateinitializer until after
4929 the type of DECL is finalized. IfDECL_INITIAL is set,
4930 then the DECL is statically initialized,and any
4931 necessary zero-initialization has alreadybeen 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 theinitialization 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 datamember 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. Atline 4794, maybe_apply_renaming_pragmais only useful for Solaris and Tru64 UNIX system for compatibility with thesystem headers.
- Studying note of GCC-3.4.6 source (141 - cont 1)
- Studying note of GCC-3.4.6 source (141 - cont 2)
- Studying note of GCC-3.4.6 source (139 - cont 1)
- Studying note of GCC-3.4.6 source (147 - cont 1)
- Studying note of GCC-3.4.6 source (19 cont)
- Studying note of GCC-3.4.6 source (24 cont)
- Studying note of GCC-3.4.6 source (139 - cont 2)
- Studying note of GCC-3.4.6 source (147 - cont 2)
- Studying note of GCC-3.4.6 source (141)
- Studying note of GCC-3.4.6 source (1)
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (2)
- Studying note of GCC-3.4.6 source (3)
- Studying note of GCC-3.4.6 source (4)
- 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 (8)
- Studying note of GCC-3.4.6 source (9)
- cegui的looknfeel配置
- X下隐藏鼠标光标
- Python导入性能-import载入测试
- jdbc中从properties文件中读取数据库连接字符串
- TDD Tips
- Studying note of GCC-3.4.6 source (141 - cont 1)
- Linux 下 stdin stdout stderr 的由来
- 晕,IBM网站竟然被黑
- 学习批处理命令
- 实例学习SQL的Select命令
- 基类与派生类对象的关系
- DLL自定义窗口类
- GCC-3.4.6源代码学习笔记(141-续2)
- MFC坐标转换