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.

t1

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).

t2

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.

原创粉丝点击