Studying note of GCC-3.4.6 source (156)

5.13.3.      Generate tinfo for fundamental types

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

 

finish_file (continue)

 

2546     /* Otherwise, GDB can get confused, because in only knows

2547       about source for LINENO-1 lines.  */

2548     input_line -= 1;

2549  

2550     interface_unknown = 1;

2551     interface_only = 0;

2552  

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

2554       These include:

2555  

2556       o Template specializations that we have not yet instantiated,

2557         but which are needed.

2558       o Initialization and destruction for non-local objects with

2559         static storage duration. (Local objects with static storage

2560         duration are initialized when their scope is first entered,

2561         and are cleaned up via atexit.)

2562       o Virtual function tables. 

2563  

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

2565       instantiating one function may cause another to be needed, and

2566       generating the initializer for an 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 , these generated tinfos will be chained in unemitted_tinfo_decls . Note that the content of array fundamentals is the nodes of fundamental types which are built during setting up the compiling 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 WHILE loop repeats until nothing related can be changed. At line 2582, instantiate_pending_templates instantiates the pending template. Internal, global chain pending_tempaltes is a tree_list holding templates whose instantiations have been deferred, either because their definitions were not yet available, or because we were putting off doing the work. The tree_purose of each node is either a DECL (for a function or static data member), or a TYPE (for a class) indicating what we are hoping to instantiate. 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 are templates that we've put off instantiating, do

2581         them now.  */

2582       instantiate_pending_templates ();

2583       ggc_collect ();

2584  

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

2586          the virtual table for a template class may cause the

2587         instantiation of members of that class. If we write out

2588          vtables then we remove the class from our list so 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 out needed type info variables. We have to be careful

2618         looping through unemitted decls, because emit_tinfo_decl may

2619         cause other variables to be needed. We stick new elements

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

2621        of the array, then shift them back 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 the new ones. Copy

2635         them to the beginning of the array, 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 of objects with static storage duration is built up

2647          i n reverse order. We clear STATIC_AGGREGATES so that any new

2648          aggregates added during the initialization of these will be

2649          initialized in the correct order when we next come 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 initialization function each time

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

2659            vtables have been referenced, and TREE_SYMBOL_REFERENCED

2660            isn't computed until a function is finished, and written

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

2662            fixed, these initialization functions could all become

2663            inline, with resulting performance improvements.  */

2664         tree ssdf_body;

2665  

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

2667            the source file.  */

2668         input_location = locus;

2669         ssdf_body = start_static_storage_duration_function (ssdf_count);

2670  

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

2672         write_out_vars (vars);

2673  

2674         /* First generate 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            i n reverse order so that the most recently constructed

2681            variable is the first destroyed. If we're using

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

2683            were registered at initialization time to destroy 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 duration function for this

2695            round.  */

2696         input_location = locus;

2697         finish_static_storage_duration_function (ssdf_body);

2698  

2699         /* All those initializations and finalizations might cause

2700             us to 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 need synthesizing?  */

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

2713            && TREE_USED (decl)

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

2715         {

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

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

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

2719              finish_function doesn't clean things up, and we 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 the function has no body, avoid calling

2728            import_export_decl. On a system without weak symbols,

2729            calling import_export_decl will make an inline template

2730            instantiation "static", which will result in errors about

2731            the use of undefined functions if there is no body for

2732            the function.  */

2733         if (!DECL_SAVED_TREE (decl))

2734           continue ;

2735  

2736         import_export_decl (decl);

2737  

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

2739            are not defined when they really are. This keeps these

2740            functions from being put out unnecessarily. But, we must

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

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

2743            is done in a separate for cycle, because if some deferred

2744            function is contained in another deferred function later

2745            i n deferred_fns varray, rest_of_compilation would skip

2746            this function and we really cannot expand the 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're going to need to write this function out, and

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

2755            (There might be no body if this is a method 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 will output the function; no longer consider it in this

2765              loop.  */

2766           DECL_DEFER_OUTPUT (decl) = 0;

2767           /* Generate RTL for this function now that we know we

2768             need it.  */

2769           expand_or_defer_fn (decl);

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

2771              function has been written out so that we don't try 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 like namespace-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 will emit code for it. In previous section, we have seen that for a class, its CLASSTYPE_VTABLES maybe contain a list of vtables. It depends on the base classes and its definition. And if a class contains vtable, it is also recorded in list of keyed_classes . At line 1565, primary_vtbl refers 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 vtables for 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       return false;

1568     /* Ignore dummy vtables made by get_vtable_decl.  */

1569     if (TREE_TYPE (primary_vtbl) == void_type_node)

1570       return false;

1571  

1572     import_export_class (ctype);

1573  

1574     /* See if any of the 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 the references to this class' vtables are optimized away,

1584         still emit the appropriate debugging information. See

1585         dfs_debug_mark.  */

1586       if (DECL_COMDAT (primary_vtbl)

1587          && CLASSTYPE_DEBUG_REQUESTED (ctype))

1588         note_debug_info_needed (ctype);

1589       return false;

1590     }

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

1592       needed = true;

 

All vtables are declared as public VAR_DECL by compiler, and such nodes are associated by cgraph_varpool_node , in which if flag finalized is 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       return TREE_ASM_WRITTEN (var);

1551   }

 

If flag_unit_at_a_time is nonzero, a cgraph_varpool_node is created for this VAR_DECL. Below, hashtable cgraph_varpool_hash is 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      struct cgraph_varpool_node *node;

445      struct cgraph_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 = (struct cgraph_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_node GTY(())                                                         in cgraph.h

135    {

136      tree decl;

137      /* Pointer to the next function in cgraph_varpool_nodes_queue.  */

138      struct cgraph_varpool_node *next_needed;

139   

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

141        or it's address is taken.  */

142      bool needed;

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

144      bool finalized;

145      /* Set when function is scheduled to be assembled.  */

146      bool output;

147    };

 

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

Remember that option -fno-implicit-templates means never emit code for non-inline templates which are instantiated implictly. For the case we suppress 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 this translation-unit and output its vtable here, the vtable of the class also needs be output here).

 

1442   void

1443   import_export_vtable (tree decl, tree type, 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 only wait to decide if we have real non-inline virtual

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

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_DECL of the vtable, DECL_NEEDED_P tells if the vtable needs be emitted. Predicate DECL_COMDAT if holds, indicates that, even if it TREE_PUBLIC, it needs not be put out unless it is needed in this translation unit. Entities like this are shared across translation units (like weak entities), but are guaranteed to be generated by any translation unit that needs them, and therefore need not be put out anywhere where they are not needed. DECL_COMDAT is just a hint to the back-end; it is up to front-ends which set this flag to ensure that there will never be any harm, other than bloat, in putting out something which is DECL_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 compiler will emit code for all vtables within. Mark them here.

 

maybe_emit_vtables (continue)

 

1595     /* The ABI requires that 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 know that 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 at compile-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 the VAR_DECL node representing the vtable itself as a

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

1618          It is rather important that such things be ignored because

1619          any effort to actually generate DWARF for them will run

1620          into trouble when/if we encounter code like:

1621  

1622          #pragma interface

1623          struct S { virtual void member (); };

1624  

1625          because the artificial declaration 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 been output. This causes

1629          grief because the DWARF entry for the definition of the vtable

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

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

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

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

1634          `S' get written (which would 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 make vtables weak.  */

1641       if (flag_weak )

1642         comdat_linkage (vtbl);

1643  

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

1645  

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

1647         actually marking the variable as written.  */

1648       if (flag_syntax_only )

1649         TREE_ASM_WRITTEN (vtbl) = 1;

1650     }

1651  

1652     /* Since we're writing 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 sets in-used flag to indicate the compiler to emit code later. Remember CONSTRUCTOR is always created for initializers of vtable, CONSTRUCTOR_ELTS in debug mode can do extra checking to ensure it’s indeed entity of CONSTRUCTOR and extract the initializers for the vtables (refers to initialize_array in initialize_vtable or build_vtt . Also refers section Finish the 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 entry is an offset: a virtual base class offset, a

1338           virtual call offset, an RTTI offset, etc.  */

1339         continue ;

1340  

1341       fn = TREE_OPERAND (fnaddr, 0);

1342       TREE_ADDRESSABLE (fn) = 1;

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

1344         we output the vtables that contain them. With vcall offsets,

1345         we know all the thunks we'll need when we emit a virtual

1346         function, so we emit the thunks there instead.  */

1347       if (DECL_THUNK_P (fn))

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

1349       mark_used (fn);

1350     }

1351   }

 

Marks decl as in-used can help compiler to remove useless code in later optimization. The flag 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 by several files within the translation-unit, deferring its handling till the last moment is necessary. Though here the caller of mark_used is within the last step of the process in front-end, however mark_used is called in many places in the front-end), caches it by deferred_fns . At line 2991, assemble_external is trivial for Linux on x86 machine. In previous section, we have seen that comipler may generate method artificially (for exmaple, cloned ctor and dctor in class), such method shouldn’t run itself but triggered by user defined method instead (referred by current_function_decl ). If DECL_INITIAL is empty at 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 trigger yet. Below synthesize_method invokes above mentioned call sequence to generate necessary STMT nodes for the function, as if it comes from user declaration. Further, skip_evaluation at line 2983 was set by parser. In C++, there is case that no evalutaion of the declaration or expression is required, for example, within operator of sizeof or typeof .

 

2967   void

2968   mark_used (tree decl)                                                                               in decl2.c

2969   {

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

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

2972       for an overloaded function, we don't know which function was

2973       actually used until after overload 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 was defined.  */

2989       defer_fn (decl);

2990  

2991     assemble_external (decl);

2992  

2993     /* Is it a synthesized 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've already synthesized the method we don't need to

3004          instantiate it, so we can return right away.  */

3005       return ;

3006     }

3007  

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

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

3010       instantiation. We check that DECL is not an explicit

3011       instantiation because that is not 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, we put off instantiating functions in order to

3022         improve compile times. Maintaining a stack of active

3023          functions is expensive, and the inliner knows to

3024          instantiate any functions it might need.

3025  

3026          However, if instantiating this function might help us mark

3027          the current function TREE_NOTHROW, we go ahead and

3028          instantiate it now. 

3029       

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

3031          i n topological order anyway.

3032        */

3033       defer = (!flag_exceptions

3034               || flag_unit_at_a_time

3035               || !optimize

3036               || TREE_CODE (decl) != FUNCTION_DECL

3037               /* If the called 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 we already know the current function can't throw,

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

3044               || TREE_NOTHROW (current_function_decl )

3045               /* If we already 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 should also be done with code emitted. However at this invocation, argument emit_p is false, as result, the function only marks the thunk as in-used and returns without really emitting code for it.

 

336    void

337    use_thunk (tree thunk_fndecl, bool emit_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 have called finish_thunk to give it a name.  */

345      my_friendly_assert (DECL_NAME (thunk_fndecl), 20021127);

346   

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

348        aliased thunk.  */

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 already turned this thunk into an ordinary function.

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

358        return ;

359   

360      if (DECL_THUNK_P (function))

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

362        use_thunk (function, emit_p);

363     

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

365      TREE_ADDRESSABLE (thunk_fndecl) = 1;

366   

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

368        this translation unit.  */

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, needed is set at line 1592 in maybe_emit_vtables , then at line 1605, below function is invoked to set the needed flag of associated cgraph_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 in maybe_emit_vtables , rest_of_decl_compilation is invoked to try to build the RTL node according to the intermediate node and outputs any assembler code (label definition, storage allocation and initialization) if required. Here, argument top_level and at_end are both 1, and asmspec is NULL. Note that at line 1957 ASM_FINISH_DECLARE_OBJECT is not defined for x86/Linux.

 

1910   void

1911   rest_of_decl_compilation (tree decl,                                                         in toplev.c

1912                         const char *asmspec,

1913                          int top_level,

1914                         int at_end)

1915   {

1916     /* We deferred calling assemble_alias so that we could collect

1917       other attributes such as visibility. 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     /* Forward declarations for nested functions are not "external",

1930       but we need to treat them as if 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 output anything 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 variables when unit-at-a-time is active and rely on

1943         callgraph code to defer them except for forward declarations

1944         (see gcc.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 whole unit has been analyzed, so we can access global information (it is still false under current situation). Also predicate DECL_DEFER_OUTPUT at line 1946, if nonzero tells that the linkage status of this decl is not yet known, so it should not be output now.

As vtable is a VAR_DECL, we invoke following function to set finialized flag 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      struct cgraph_varpool_node *node = cgraph_varpool_node (decl);

584   

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

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

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

588        if this function has 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 (/* Externally visible variables must be output. The exception are

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

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

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

603            It is possible to assemble the name later after finalizing the function

604            and the fact is 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 in maybe_emit_vtables , cgraph_varpool_mark_needed_node has been invoked for vtable that needs be output; for such vtable, needed flag of its cgraph node is true, and this node is linked into cgraph_varpool_nodes_queue again 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 is processed by cgraph_varpool_mark_needed_node again, 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 class successfully, the class would be removed from keyed_classes , and forces next iteration.

 

你可能感兴趣的:(Studying note of GCC-3.4.6 source (156))