Studying note of GCC-3.4.6 source (156)

来源:互联网 发布:淘宝新店如何找货源 编辑:程序博客网 时间:2024/06/04 12:27

5.13.3.      Generate tinfo for fundamental types

After outputting PCH file if required, back in finish_file to continue thestruggle of assemble emitting. Next, the compiler should prepare tinfo for thefundamental types.

 

finish_file (continue)

 

2546     /* Otherwise, GDBcan get confused, because in only knows

2547       about source for LINENO-1lines.  */

2548     input_line -= 1;

2549  

2550     interface_unknown = 1;

2551     interface_only = 0;

2552  

2553    /* We now have towrite out all the stuff we put off writing out.

2554       These include:

2555  

2556      o Template specializationsthat we have not yet instantiated,

2557         but which are needed.

2558       o Initialization anddestruction for non-local objects with

2559         static storage duration.(Local objects with static storage

2560         duration are initializedwhen their scope is first entered,

2561         and are cleaned up viaatexit.)

2562       o Virtual functiontables. 

2563  

2564       All of these may cause othersto be needed. For example,

2565       instantiating one function maycause another to be needed, and

2566       generating the initializer foran object may cause templates to be

2567       instantiated, etc., etc.  */

2568  

2569     timevar_push (TV_VARCONST);

2570  

2571     emit_support_tinfos();

 

All such tinfos would be found within namespace abi_node. In get_tinfo_decl, thesegenerated tinfos will be chained in unemitted_tinfo_decls. Note that the content ofarray fundamentalsis the nodes of fundamental types which are built during setting up thecompiling environment.

 

1353   void

1354   emit_support_tinfos(void)                                                                                     in rtti.c

1355   {

1356     static tree *const fundamentals[] =

1357     {

1358       &void_type_node,

1359       &boolean_type_node,

1360       &wchar_type_node,

1361       &char_type_node,&signed_char_type_node, &unsigned_char_type_node,

1362       &short_integer_type_node,&short_unsigned_type_node,

1363       &integer_type_node, &unsigned_type_node,

1364       &long_integer_type_node,&long_unsigned_type_node,

1365       &long_long_integer_type_node,&long_long_unsigned_type_node,

1366       &float_type_node,&double_type_node, &long_double_type_node,

1367       0

1368     };

1369     int ix;

1370     tree bltn_type, dtor;

1371    

1372     push_nested_namespace(abi_node);

1373     bltn_type = xref_tag(class_type,

1374                       get_identifier("__fundamental_type_info"),

1375                       true, false);

1376     pop_nested_namespace (abi_node);

1377     if (!COMPLETE_TYPE_P (bltn_type))

1378       return;

1379     dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC(bltn_type), 1);

1380     if (DECL_EXTERNAL (dtor))

1381       return;

1382     doing_runtime = 1;

1383     for (ix = 0;fundamentals[ix]; ix++)

1384     {

1385       tree bltn = *fundamentals[ix];

1386       tree bltn_ptr = build_pointer_type (bltn);

1387       tree bltn_const_ptr = build_pointer_type

1388                               (build_qualified_type (bltn, TYPE_QUAL_CONST));

1389       tree tinfo;

1390        

1391       tinfo = get_tinfo_decl(bltn);

1392       TREE_USED (tinfo) = 1;

1393       TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME(tinfo)) = 1;

1394        

1395       tinfo = get_tinfo_decl(bltn_ptr);

1396       TREE_USED (tinfo) = 1;

1397       TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME(tinfo)) = 1;

1398        

1399       tinfo = get_tinfo_decl(bltn_const_ptr);

1400       TREE_USED (tinfo) = 1;

1401       TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME(tinfo)) = 1;

1402     }

1403   }

 

See that for every fundamental type, three tinfos need generated,one for plain, one for pointer, one for constant pointer.

5.13.4.      Stable down immediate tree

Following big DO WHILEloop repeats until nothing related can be changed. At line 2582, instantiate_pending_templatesinstantiates the pending template. Internal, global chain pending_tempaltes is a tree_listholding templates whose instantiations have been deferred, either because theirdefinitions were not yet available, or because we were putting off doing thework. The tree_purose of each node is either a DECL (for a function or staticdata member), or a TYPE (for a class) indicating what we are hoping toinstantiate. The tree_value is not used.

 

finish_file (continue)

 

2573     do

2574     {

2575       tree t;

2576       size_t n_old, n_new;

2577  

2578       reconsider = false;

2579  

2580       /* If there aretemplates that we've put off instantiating, do

2581         them now.  */

2582       instantiate_pending_templates ();

2583       ggc_collect ();

2584  

2585       /* Write outvirtual tables as required. Note that writing out

2586         the virtual table for a template class maycause the

2587         instantiation of members ofthat class. If we write out

2588         vtables then we remove the class from our listso we don't

2589         have to look at it again.  */

2590  

2591       while (keyed_classes!= NULL_TREE

2592              && maybe_emit_vtables (TREE_VALUE (keyed_classes)))

2593       {

2594         reconsider = true;

2595         keyed_classes = TREE_CHAIN (keyed_classes);

2596       }

2597  

2598       t = keyed_classes;

2599       if (t != NULL_TREE)

2600       {

2601         tree next = TREE_CHAIN (t);

2602  

2603         while(next)

2604          {

2605            if (maybe_emit_vtables(TREE_VALUE (next)))

2606            {

2607              reconsider = true;

2608              TREE_CHAIN (t) = TREE_CHAIN (next);

2609            }

2610            else

2611              t = next;

2612  

2613            next = TREE_CHAIN (t);

2614         }

2615       }

2616  

2617      /* Write outneeded type info variables. We have to be careful

2618        looping through unemitted decls, becauseemit_tinfo_decl may

2619        cause other variables to be needed. We sticknew elements

2620        (and old elements that we may need toreconsider) at the end

2621        of the array, then shift themback to the beginning once we're

2622        done. */

2623    

2624       n_old = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls);

2625       for (i = 0;i < n_old; ++i)

2626       {

2627         tree tinfo_decl = VARRAY_TREE (unemitted_tinfo_decls,i);

2628         if (emit_tinfo_decl(tinfo_decl))

2629           reconsider = true;

2630         else

2631           VARRAY_PUSH_TREE (unemitted_tinfo_decls, tinfo_decl);

2632       }

2633    

2634       /* The only elements we want to keep are thenew ones. Copy

2635         them to the beginning of thearray, then get rid of the

2636         leftovers.  */

2637       n_new = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls)- n_old;

2638       if (n_new)

2639         memmove (&VARRAY_TREE (unemitted_tinfo_decls,0),

2640                   &VARRAY_TREE (unemitted_tinfo_decls,n_old),

2641                   n_new * sizeof (tree));

2642       memset (&VARRAY_TREE (unemitted_tinfo_decls,n_new),

2643               0, n_old * sizeof(tree));

2644       VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) = n_new;

2645  

2646       /* The list ofobjects with static storage duration is built up

2647         in reverse order. We clear STATIC_AGGREGATES so that any new

2648         aggregates added during the initialization ofthese will be

2649         initialized in the correct order when we nextcome around the

2650         loop. */

2651       vars = prune_vars_needing_no_initialization(&static_aggregates);

2652  

2653       if (vars)

2654       {

2655         tree v;

2656  

2657         /* We need to start a new initializationfunction each time

2658           through the loop. That'sbecause we need to know which

2659           vtables have been referenced, andTREE_SYMBOL_REFERENCED

2660           isn't computed until a function isfinished, and written

2661           out. That's a deficiency in the back-end.When this is

2662           fixed, these initialization functionscould all become

2663           inline, with resulting performanceimprovements.  */

2664         tree ssdf_body;

2665  

2666         /* Set the line and file, so that it isobviously not from

2667           the source file.  */

2668         input_location = locus;

2669         ssdf_body = start_static_storage_duration_function(ssdf_count);

2670  

2671         /* Make surethe back end knows about all the variables. */

2672         write_out_vars(vars);

2673  

2674         /* Firstgenerate code to do all the initializations. */

2675         for (v =vars; v; v = TREE_CHAIN (v))

2676           do_static_initialization(TREE_VALUE (v),

2677                               TREE_PURPOSE (v));

2678  

2679         /* Then,generate code to do all the destructions. Do these

2680           in reverse order so that the most recently constructed

2681           variable is the first destroyed. If we'reusing

2682           __cxa_atexit, then we don't need to dothis; functions

2683           were registered at initialization time todestroy the

2684           local statics.  */

2685         if (!flag_use_cxa_atexit)

2686         {

2687           vars = nreverse (vars);

2688           for (v= vars; v; v = TREE_CHAIN (v))

2689             do_static_destruction (TREE_VALUE(v));

2690         }

2691         else

2692           vars = NULL_TREE;

2693  

2694         /* Finish up the static storage durationfunction for this

2695           round. */

2696         input_location = locus;

2697         finish_static_storage_duration_function(ssdf_body);

2698  

2699         /* All thoseinitializations and finalizations might cause

2700           usto need more inline functions, more template

2701           instantiations, etc.  */

2702         reconsider = true;

2703         ssdf_count++;

2704         locus.line++;

2705       }

2706        

2707       for (i = 0;i < deferred_fns_used;++i)

2708       {

2709         tree decl = VARRAY_TREE (deferred_fns,i);

2710  

2711         /* Does it needsynthesizing?  */

2712         if (DECL_ARTIFICIAL (decl) && !DECL_INITIAL (decl)

2713            && TREE_USED (decl)

2714            && (! DECL_REALLY_EXTERN(decl) || DECL_INLINE (decl)))

2715         {

2716           /* Eventhough we're already at the top-level, we push

2717             there again. That way, when we pop back a fewlines

2718             hence, all of our state is restored.Otherwise,

2719             finish_function doesn't clean things up, andwe end

2720             up with CURRENT_FUNCTION_DECL set.  */

2721           push_to_top_level();

2722           synthesize_method (decl);

2723           pop_from_top_level ();

2724           reconsider = true;

2725         }

2726  

2727         /* If thefunction has no body, avoid calling

2728           import_export_decl. On a system withoutweak symbols,

2729           calling import_export_decl will make aninline template

2730           instantiation "static", whichwill result in errors about

2731           the use of undefined functions if there isno body for

2732           the function.  */

2733         if (!DECL_SAVED_TREE (decl))

2734           continue;

2735  

2736         import_export_decl (decl);

2737  

2738         /* We lie tothe back-end, pretending that some functions

2739           are not defined when they really are. Thiskeeps these

2740           functions from being put outunnecessarily. But, we must

2741           stop lying when the functions are referenced,or if they

2742           are not comdat since they need to be putout now. This

2743           is done in a separate for cycle, becauseif some deferred

2744           function is contained in another deferredfunction later

2745           in deferred_fns varray, rest_of_compilation would skip

2746           this function and we really cannot expandthe same

2747           function twice.  */

2748         if (DECL_NOT_REALLY_EXTERN (decl)

2749            && DECL_INITIAL (decl)

2750            && DECL_NEEDED_P (decl))

2751           DECL_EXTERNAL (decl) = 0;

2752  

2753         /* If we'regoing to need to write this function out, and

2754           there's already a body for it, create RTLfor it now.

2755           (There might be no body if this is amethod we haven't

2756           gotten around to synthesizing yet.)  */

2757         if (!DECL_EXTERNAL (decl)

2758            && DECL_NEEDED_P (decl)

2759            && DECL_SAVED_TREE (decl)

2760            && !TREE_ASM_WRITTEN (decl)

2761            && (!flag_unit_at_a_time

2762                || !cgraph_node(decl)->local.finalized))

2763         {

2764           /* We willoutput the function; no longer consider it in this

2765             loop. */

2766           DECL_DEFER_OUTPUT (decl) = 0;

2767           /* GenerateRTL for this function now that we know we

2768             need it.  */

2769           expand_or_defer_fn(decl);

2770           /* If we'recompiling -fsyntax-only pretend that this

2771             function has been written out so that we don'ttry to

2772             expand it again.  */

2773           if (flag_syntax_only)

2774             TREE_ASM_WRITTEN (decl) = 1;

2775           reconsider = true;

2776         }

2777       }

2778  

2779       if (walk_namespaces(wrapup_globals_for_namespace, /*data=*/0))

2780         reconsider = true;

2781  

2782       /* Static data members are just likenamespace-scope globals.  */

2783       for (i = 0;i < pending_statics_used;++i)

2784       {

2785         tree decl = VARRAY_TREE (pending_statics,i);

2786         if (var_finalized_p(decl))

2787           continue;

2788         import_export_decl (decl);

2789         if (DECL_NOT_REALLY_EXTERN (decl)&& ! DECL_IN_AGGR_P (decl))

2790           DECL_EXTERNAL (decl) = 0;

2791       }

2792       if (pending_statics

2793          && wrapup_global_declarations(&VARRAY_TREE (pending_statics, 0),

2794                                     pending_statics_used))

2795       reconsider = true;

2796  

2797       if (cgraph_assemble_pending_functions ())

2798         reconsider = true;

2799     }

2800     while(reconsider);

5.13.4.1.             Iterate - emitting vtable

At first, vtable in used should be marked so as to compiler willemit code for it. In previous section, we have seen that for a class, itsCLASSTYPE_VTABLES maybe contain a list of vtables. It depends on the baseclasses and its definition. And if a class contains vtable, it is also recordedin list of keyed_classes.At line 1565, primary_vtblrefers to the list of vtable of ctype.

 

1556   static bool

1557   maybe_emit_vtables (tree ctype)                                                               in decl2.c

1558   {

1559     tree vtbl;

1560     tree primary_vtbl;

1561     bool needed = false;

1562  

1563     /* If the vtablesfor this class have already been emitted there is

1564       nothing more to do.  */

1565     primary_vtbl = CLASSTYPE_VTABLES (ctype);

1566     if (var_finalized_p(primary_vtbl))

1567       returnfalse;

1568    /* Ignore dummyvtables made by get_vtable_decl.  */

1569     if (TREE_TYPE (primary_vtbl) ==void_type_node)

1570       returnfalse;

1571  

1572     import_export_class(ctype);

1573  

1574     /* See if any ofthe vtables are needed.  */

1575     for (vtbl =CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))

1576     {

1577       import_export_vtable(vtbl, ctype, 1);

1578       if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))

1579         break;

1580     }

1581     if (!vtbl)

1582     {

1583       /* If thereferences to this class' vtables are optimized away,

1584         still emit the appropriatedebugging information. See

1585         dfs_debug_mark.  */

1586       if (DECL_COMDAT(primary_vtbl)

1587          && CLASSTYPE_DEBUG_REQUESTED(ctype))

1588         note_debug_info_needed (ctype);

1589       returnfalse;

1590     }

1591     else if (TREE_PUBLIC (vtbl) &&!DECL_COMDAT (vtbl))

1592       needed = true;

 

All vtables are declared as public VAR_DECL by compiler, and suchnodes are associated by cgraph_varpool_node,in which if flag finalizedis set means the node has code output.

 

1544   static bool

1545   var_finalized_p (tree var)                                                                         in decl2.c

1546   {

1547     if (flag_unit_at_a_time)

1548       return cgraph_varpool_node (var)->finalized;

1549     else

1550       returnTREE_ASM_WRITTEN (var);

1551   }

 

If flag_unit_at_a_timeis nonzero, a cgraph_varpool_node is created for this VAR_DECL. Below,hashtable cgraph_varpool_hashis the queue of cgraph_varpool_node, which is managed by GC.

 

441    struct cgraph_varpool_node*

442    cgraph_varpool_node (tree decl)                                                                in cgraph.c

443    {

444      structcgraph_varpool_node *node;

445      structcgraph_varpool_node **slot;

446   

447      if (!DECL_P (decl) || TREE_CODE (decl) ==FUNCTION_DECL)

448        abort ();

449   

450      if (!cgraph_varpool_hash)

451        cgraph_varpool_hash = htab_create_ggc (10,cgraph_varpool_hash_node,

452                                         eq_cgraph_varpool_node, NULL);

453      slot = (structcgraph_varpool_node **)

454        htab_find_slot_with_hash (cgraph_varpool_hash,DECL_ASSEMBLER_NAME (decl),

455                             IDENTIFIER_HASH_VALUE(DECL_ASSEMBLER_NAME (decl)),

456                             INSERT);

457      if (*slot)

458        return*slot;

459      node = ggc_alloc_cleared (sizeof (*node));

460      node->decl = decl;

461      cgraph_varpool_n_nodes++;

462      cgraph_varpool_nodes = node;

463      *slot = node;

464      return node;

465    }

 

Then structure cgraph_varpool_node has following definition.

 

134    struct cgraph_varpool_nodeGTY(())                                                         in cgraph.h

135    {

136      tree decl;

137      /* Pointer to thenext function in cgraph_varpool_nodes_queue. */

138      structcgraph_varpool_node *next_needed;

139   

140      /* Set whenfunction must be output - it is externally visible

141        or it's addressis taken.  */

142      bool needed;

143      /* Set once it hasbeen finalized so we consider it to be output. */

144      bool finalized;

145      /* Set whenfunction is scheduled to be assembled. */

146      bool output;

147    };

 

Above at line 1572, import_export_class determines if it needsoutput the whole set of the class in this translation-unit or just signiture butreferences will be solved at link time.

Remember that option -fno-implicit-templates means never emit codefor non-inline templates which are instantiated implictly. For the case wesuppress the emission by setting import_export to -1.

Next it needs decide whether the specified vtable is external or not(even if the class is external, but if any of its base is defined in thistranslation-unit and output its vtable here, the vtable of the class also needsbe output here).

 

1442   void

1443   import_export_vtable (tree decl, treetype, int final)                                     in decl2.c

1444   {

1445     if (DECL_INTERFACE_KNOWN (decl))

1446       return;

1447  

1448     if (TYPE_FOR_JAVA (type))

1449     {

1450       TREE_PUBLIC (decl) = 1;

1451       DECL_EXTERNAL (decl) = 1;

1452       DECL_INTERFACE_KNOWN (decl) = 1;

1453     }

1454     else if (CLASSTYPE_INTERFACE_KNOWN (type))

1455     {

1456       TREE_PUBLIC (decl) = 1;

1457       DECL_EXTERNAL (decl) =CLASSTYPE_INTERFACE_ONLY (type);

1458       DECL_INTERFACE_KNOWN (decl) = 1;

1459     }

1460     else

1461     {

1462       /* We can onlywait to decide if we have real non-inline virtual

1463         functions in our class, or if we come from atemplate.  */

1464  

1465       int found =(CLASSTYPE_TEMPLATE_INSTANTIATION (type)

1466                 || CLASSTYPE_KEY_METHOD (type) !=NULL_TREE);

1467  

1468       if (final || ! found)

1469       {

1470         comdat_linkage (decl);

1471         DECL_EXTERNAL (decl) = 0;

1472       }

1473       else

1474       {

1475         TREE_PUBLIC (decl) = 1;

1476         DECL_EXTERNAL (decl) = 1;

1477       }

1478     }

1479   }

 

After import_export_vtable sets flags for VAL_DECLof the vtable, DECL_NEEDED_P tells if the vtable needs be emitted. PredicateDECL_COMDAT if holds, indicates that, even if it TREE_PUBLIC, it needs not beput out unless it is needed in this translation unit. Entities like this areshared across translation units (like weak entities), but are guaranteed to begenerated by any translation unit that needs them, and therefore need not beput out anywhere where they are not needed. DECL_COMDAT is just a hint to theback-end; it is up to front-ends which set this flag to ensure that there willnever be any harm, other than bloat, in putting out something which isDECL_COMDAT.

 

1730   #define DECL_NEEDED_P(DECL)                               /                           in cp-tree.h

1731     ((at_eof && TREE_PUBLIC (DECL) &&!DECL_COMDAT (DECL))      /

1732      || (DECL_ASSEMBLER_NAME_SET_P (DECL)                            /

1733        &&TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL)))/

1734      || (((flag_syntax_only || flag_unit_at_a_time) &&TREE_USED (DECL))))

 

If any vtable in the vtable chain needs code emitted, the compilerwill emit code for all vtables within. Mark them here.

 

maybe_emit_vtables (continue)

 

1595    /* The ABI requiresthat we emit all of the vtables if we emit any

1596       of them.  */

1597     for (vtbl =CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))

1598     {

1599       /* Write it out.  */

1600       import_export_vtable(vtbl, ctype, 1);

1601       mark_vtable_entries(vtbl);

1602  

1603       /* If we knowthat DECL is needed, mark it as such for the varpool.  */

1604       if (needed)

1605         cgraph_varpool_mark_needed_node(cgraph_varpool_node (vtbl));

1606  

1607       if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)

1608       {

1609         /* It had better be all done atcompile-time.  */

1610         if (store_init_value (vtbl, DECL_INITIAL(vtbl)))

1611           abort ();

1612       }

1613  

1614       if (write_symbols == DWARF_DEBUG ||write_symbols == DWARF2_DEBUG)

1615       {

1616         /* Mark theVAR_DECL node representing the vtable itself as a

1617          "gratuitous" one,thereby forcing dwarfout.c to ignore it.

1618          It is rather important thatsuch things be ignored because

1619          any effort to actuallygenerate DWARF for them will run

1620          into trouble when/if weencounter code like:

1621  

1622          #pragma interface

1623          struct S { virtual voidmember (); };

1624  

1625          because the artificialdeclaration of the vtable itself (as

1626          manufactured by the g++front end) will say that the vtable

1627          is a static member of `S'but only *after* the debug output

1628          for the definition of `S' has already beenoutput. This causes

1629          grief because the DWARFentry for the definition of the vtable

1630          will try to refer back toan earlier *declaration* of the

1631          vtable as a static memberof `S' and there won't be one.

1632          We might be able to arrangeto have the "vtable static member"

1633          attached to the member listfor `S' before the debug info for

1634          `S' get written (whichwould solve the problem) but that would

1635          require more intrusive changes to the g++front end.  */

1636  

1637         DECL_IGNORED_P (vtbl) = 1;

1638       }

1639  

1640       /* Always makevtables weak.  */

1641       if (flag_weak)

1642         comdat_linkage (vtbl);

1643  

1644       rest_of_decl_compilation(vtbl, NULL, 1, 1);

1645  

1646       /* Because we'reonly doing syntax-checking, we'll never end up

1647         actually marking thevariable as written.  */

1648       if (flag_syntax_only)

1649         TREE_ASM_WRITTEN (vtbl) = 1;

1650     }

1651  

1652     /* Since we'rewriting out the vtable here, also write the debug

1653       info.  */

1654     note_debug_info_needed (ctype);

1655  

1656     return true;

1657   }

 

Below function just tags the virtual function as addressable and setsin-used flag to indicate the compiler to emit code later. Remember CONSTRUCTORis always created for initializers of vtable, CONSTRUCTOR_ELTS in debug modecan do extra checking to ensure it’s indeed entity of CONSTRUCTOR and extractthe initializers for the vtables (refers to initialize_array in initialize_vtable or build_vtt. Alsorefers section Finishthe RECORD_TYPE – generate vtable for examples of initialziers).

 

1323   static void

1324   mark_vtable_entries (tree decl)                                                                 in decl2.c

1325   {

1326     tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL(decl));

1327  

1328     for (;entries; entries = TREE_CHAIN (entries))

1329     {

1330       tree fnaddr = TREE_VALUE (entries);

1331       tree fn;

1332  

1333       STRIP_NOPS (fnaddr);

1334  

1335       if (TREE_CODE (fnaddr) != ADDR_EXPR

1336          && TREE_CODE (fnaddr) !=FDESC_EXPR)

1337         /* This entryis an offset: a virtual base class offset, a

1338           virtual call offset, anRTTI offset, etc.  */

1339         continue;

1340  

1341       fn = TREE_OPERAND (fnaddr, 0);

1342       TREE_ADDRESSABLE (fn) = 1;

1343       /* When we don'thave vcall offsets, we output thunks whenever

1344         we output the vtables thatcontain them. With vcall offsets,

1345         we know all the thunks we'llneed when we emit a virtual

1346         function, so we emit thethunks there instead.  */

1347       if (DECL_THUNK_P (fn))

1348         use_thunk (fn, /*emit_p=*/0);

1349       mark_used (fn);

1350     }

1351   }

 

Marks declas in-used can help compiler to remove useless code in later optimization. Theflag is set at line 2982 below. Then for unemitted inline method (generally,except in-charge constructor and destructor, inline method isn’t emitted yet.Considering inline method is defined in header file, which may be included byseveral files within the translation-unit, deferring its handling till the lastmoment is necessary. Though here the caller of mark_used is within the laststep of the process in front-end, however mark_used is called in many places in thefront-end), caches it by deferred_fns. At line 2991, assemble_externalis trivial for Linux on x86 machine. In previous section, we have seen thatcomipler may generate method artificially (for exmaple, cloned ctor and dctorin class), such method shouldn’t run itself but triggered by user definedmethod instead (referred by current_function_decl). If DECL_INITIAL is emptyat line 2998, it means the function has still not  been proccessed by call sequence: start_function,begin_function_body,begin_compound_stmt|| finish_compound_stmt,finish_function_body,finish_function– that is not STMT node built for it and linked into STMT list of its triggeryet. Below synthesize_method invokes above mentioned call sequence to generatenecessary STMT nodes for the function, as if it comes from user declaration.Further, skip_evaluationat line 2983 was set by parser. In C++, there is case that no evalutaion of thedeclaration or expression is required, for example, within operator of sizeofor typeof.

 

2967   void

2968   mark_used (tree decl)                                                                               in decl2.c

2969   {

2970     /* If DECL is aBASELINK for a single function, then treat it just

2971       like the DECL for thefunction. Otherwise, if the BASELINK is

2972       for an overloaded function, wedon't know which function was

2973       actually used until afteroverload resolution.  */

2974     if (TREE_CODE (decl) == BASELINK)

2975     {

2976       decl = BASELINK_FUNCTIONS (decl);

2977       if (really_overloaded_fn (decl))

2978         return;

2979       decl = OVL_CURRENT (decl);

2980     }

2981  

2982     TREE_USED (decl) = 1;

2983     if (processing_template_decl || skip_evaluation)

2984       return;

2985  

2986     if (TREE_CODE (decl) ==FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)

2987         && !TREE_ASM_WRITTEN (decl))

2988       /* Remember it, so we can check it wasdefined.  */

2989       defer_fn (decl);

2990  

2991     assemble_external (decl);

2992  

2993    /* Is it asynthesized method that needs to be synthesized?  */

2994     if (TREE_CODE (decl) == FUNCTION_DECL

2995         && DECL_NONSTATIC_MEMBER_FUNCTION_P(decl)

2996         && DECL_ARTIFICIAL (decl)

2997         && !DECL_THUNK_P (decl)

2998         && ! DECL_INITIAL (decl)

2999         /* Kludge:don't synthesize for default args.  */

3000         && current_function_decl)

3001     {

3002       synthesize_method (decl);

3003       /* If we'vealready synthesized the method we don't need to

3004         instantiate it, so we can return rightaway.  */

3005       return;

3006     }

3007  

3008     /* If this is afunction or variable that is an instance of some

3009       template, we now know that wewill need to actually do the

3010       instantiation. We check thatDECL is not an explicit

3011       instantiation because that isnot checked in instantiate_decl.  */

3012     if((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)

3013         && DECL_LANG_SPECIFIC (decl)&& DECL_TEMPLATE_INFO (decl)

3014         && (!DECL_EXPLICIT_INSTANTIATION(decl)

3015             || (TREE_CODE (decl) == FUNCTION_DECL

3016                && DECL_INLINE(DECL_TEMPLATE_RESULT

3017                      (template_for_substitution(decl))))))

3018     {

3019       bool defer;

3020  

3021       /* Normally, weput off instantiating functions in order to

3022         improve compile times. Maintaininga stack of active

3023         functions is expensive, and the inliner knowsto

3024         instantiate any functions it might need.

3025  

3026         However, if instantiating this function mighthelp us mark

3027         the current function TREE_NOTHROW, we go aheadand

3028         instantiate it now. 

3029       

3030         This is not needed for unit-at-a-time since wereorder the functions

3031         in topological order anyway.

3032       */

3033       defer = (!flag_exceptions

3034               || flag_unit_at_a_time

3035               || !optimize

3036               || TREE_CODE (decl) !=FUNCTION_DECL

3037               /* If thecalled function can't throw, we don't need to

3038                 generate its body to find that out.  */

3039               || TREE_NOTHROW (decl)

3040               || !cfun

3041               || !current_function_decl

3042               /* If wealready know the current function can't throw,

3043                 then we don't need to work hard to proveit.  */

3044               || TREE_NOTHROW (current_function_decl)

3045               /* If wealready know that the current function *can*

3046                 throw, there's no point in gathering more

3047                 information. */

3048               || cp_function_chain->can_throw);

3049  

3050       instantiate_decl (decl, defer);

3051     }

3052   }

 

We have seen that thunk is a compiler generating function, it shouldalso be done with code emitted. However at this invocation, argument emit_pis false, as result, the function only marks the thunk as in-used and returnswithout really emitting code for it.

 

336    void

337    use_thunk (tree thunk_fndecl, boolemit_p)                                                in method.c

338    {

339      tree function, alias;

340      tree virtual_offset;

341      HOST_WIDE_INT fixed_offset, virtual_value;

342      bool this_adjusting = DECL_THIS_THUNK_P(thunk_fndecl);

343   

344     /* We should havecalled finish_thunk to give it a name. */

345      my_friendly_assert (DECL_NAME (thunk_fndecl),20021127);

346   

347     /* We should neverbe using an alias, always refer to the

348        aliasedthunk.  */

349      my_friendly_assert (!THUNK_ALIAS (thunk_fndecl),20031023);

350   

351      if (TREE_ASM_WRITTEN (thunk_fndecl))

352        return;

353     

354      function = THUNK_TARGET (thunk_fndecl);

355      if (DECL_RESULT (thunk_fndecl))

356        /* We alreadyturned this thunk into an ordinary function.

357          There's no need to process this thunkagain.  */

358        return;

359   

360      if (DECL_THUNK_P (function))

361        /* The target isitself a thunk, process it now.  */

362        use_thunk(function, emit_p);

363     

364      /* Thunks arealways addressable; they only appear in vtables.  */

365      TREE_ADDRESSABLE (thunk_fndecl) = 1;

366   

367      /* Figure out whatfunction is being thunked to. It's referenced in

368        this translationunit.  */

369      TREE_ADDRESSABLE (function) = 1;

370      mark_used(function);

371      if (!emit_p)

372        return;

      

524    }

 

If the vtable is public and not shared across translation-units, neededis set at line 1592 in maybe_emit_vtables,then at line 1605, below function is invoked to set the needed flag of associatedcgraph_varpool_node.

 

568    void

569    cgraph_varpool_mark_needed_node (struct cgraph_varpool_node*node)      in cgraph.c

570    {

571      if (!node->needed &&node->finalized)

572      {

573        node->next_needed = cgraph_varpool_nodes_queue;

574        cgraph_varpool_nodes_queue= node;

575        notice_global_symbol(node->decl);

576      }

577      node->needed = 1;

578    }

 

Next at line 1644 inmaybe_emit_vtables,rest_of_decl_compilationis invoked to try to build the RTL node according to the intermediate node andoutputs any assembler code (label definition, storage allocation andinitialization) if required. Here, argument top_level and at_end are both 1, and asmspec is NULL. Note that at line1957 ASM_FINISH_DECLARE_OBJECT is not defined for x86/Linux.

 

1910   void

1911   rest_of_decl_compilation (tree decl,                                                        in toplev.c

1912                         constchar *asmspec,

1913                         int top_level,

1914                         int at_end)

1915   {

1916    /* We deferredcalling assemble_alias so that we could collect

1917       other attributes such asvisibility. Emit the alias now.  */

1918     {

1919       tree alias;

1920       alias = lookup_attribute("alias", DECL_ATTRIBUTES (decl));

1921       if (alias)

1922       {

1923         alias = TREE_VALUE (TREE_VALUE (alias));

1924         alias = get_identifier(TREE_STRING_POINTER (alias));

1925         assemble_alias (decl, alias);

1926       }

1927     }

1928  

1929     /* Forwarddeclarations for nested functions are not "external",

1930       but we need to treat them asif they were.  */

1931     if (TREE_STATIC (decl) || DECL_EXTERNAL(decl)

1932         || TREE_CODE (decl) == FUNCTION_DECL)

1933     {

1934       timevar_push (TV_VARCONST);

1935  

1936       if (asmspec)

1937         make_decl_rtl (decl, asmspec);

1938  

1939       /* Don't outputanything when a tentative file-scope definition

1940         is seen. But at end of compilation,do output code for them.

1941  

1942         We do output all variableswhen unit-at-a-time is active and rely on

1943         callgraph code to defer themexcept for forward declarations

1944         (seegcc.c-torture/compile/920624-1.c) */

1945       if ((at_end

1946            || !DECL_DEFER_OUTPUT (decl)

1947            || (flag_unit_at_a_time &&DECL_INITIAL (decl)))

1948          && !DECL_EXTERNAL (decl))

1949       {

1950         if (flag_unit_at_a_time && !cgraph_global_info_ready

1951            && TREE_CODE (decl) !=FUNCTION_DECL && top_level)

1952           cgraph_varpool_finalize_decl(decl);

1953         else

1954           assemble_variable (decl, top_level,at_end, 0);

1955       }

1956  

1957   #ifdef ASM_FINISH_DECLARE_OBJECT

      

1963   #endif

1964  

1965      timevar_pop (TV_VARCONST);

1966     }

1967     else if (DECL_REGISTER (decl) &&asmspec != 0)

1968     {

1969       if (decode_reg_name (asmspec) >= 0)

1970       {

1971         SET_DECL_RTL (decl, NULL_RTX);

1972         make_decl_rtl (decl, asmspec);

1973       }

1974       else

1975       {

1976         error ("invalid register name `%s'for register variable", asmspec);

1977         DECL_REGISTER (decl) = 0;

1978         if (!top_level)

1979           expand_decl (decl);

1980       }

1981     }

       

2011   }

 

At line 1950 cgraph_global_info_ready is nonzero when wholeunit has been analyzed, so we can access global information (it is still falseunder current situation). Also predicate DECL_DEFER_OUTPUT at line 1946, ifnonzero tells that the linkage status of this decl is not yet known, so it shouldnot be output now.

As vtable is a VAR_DECL, we invoke following function to set finializedflag of associated cgraph_varpool_node to indicate code to be output.

 

580    void

581    cgraph_varpool_finalize_decl (tree decl)                                                     in cgraph.c

582    {

583      structcgraph_varpool_node *node = cgraph_varpool_node(decl);

584   

585      /* The firstdeclaration of a variable that comes through this function

586        decides whetherit is global (in C, has external linkage)

587        or local (in C,has internal linkage). So do nothing more

588        if this functionhas already run.  */

589      if (node->finalized)

590        return;

591      if (node->needed)

592      {

593        node->next_needed = cgraph_varpool_nodes_queue;

594        cgraph_varpool_nodes_queue= node;

595        notice_global_symbol(decl);

596      }

597      node->finalized = true;

598   

599      if (/* Externallyvisible variables must be output. The exception are

600           COMDATfunctions that must be output only when they are needed.  */

601         (TREE_PUBLIC (decl) &&!DECL_COMDAT (decl))

602          /* Function whose name is output to theassembler file must be produced.

603            It ispossible to assemble the name later after finalizing the function

604            and the factis noticed in assemble_name then.  */

605          || (DECL_ASSEMBLER_NAME_SET_P (decl)

606            && TREE_SYMBOL_REFERENCED(DECL_ASSEMBLER_NAME (decl))))

607     {

608        cgraph_varpool_mark_needed_node(node);

609      }

610    }

 

As at line 1605 inmaybe_emit_vtables,cgraph_varpool_mark_needed_nodehas been invoked for vtable that needs be output; for such vtable, neededflag of its cgraph node is true, and this node is linked into cgraph_varpool_nodes_queueagain here (see in cgraph_varpool_mark_needed_node at line 571,the condition for linking is “(!node->needed && node->finalized)”,if not added at that time, it is linked here); at line 608 the vtable isprocessed by cgraph_varpool_mark_needed_nodeagain, which is a measure to ensure the cgraph node to be linked into cgraph_varpool_nodes_queue.

Note that if maybe_emit_vtables processes the classsuccessfully, the class would be removed from keyed_classes, and forces nextiteration.