Studying note of GCC-3.4.6 source (160)

5.13.4.5.              Iterate – handling globals in namespaces

Before, we have prepared and registered initialize and exitting function for global or static objects having constructor or destructor. In this iteration, it checks if there is any global not finialized, and makes it. Function walk_namespaces visits the tree of namespaces from top down in pre-order.

 

848    int

849    walk_namespaces (walk_namespaces_fn f, void* data)                                      in decl.c

850    {

851      return walk_namespaces_r (global_namespace , f, data);

852    }

 

Slot namespaces holds a chain of namespace declared within namespace .

 

831    static int

832    walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data)           in decl.c

833    {

834      int result = 0;

835      tree current = NAMESPACE_LEVEL (namespace)->namespaces;    

836   

837      result |= (*f) (namespace, data);

838   

839      for (; current; current = TREE_CHAIN (current))

840        result |= walk_namespaces_r (current, f, data);

841   

842      return result;

843    }

 

Below function is the argument f executed upon every node of namespace during the traversal. Argument data is passed from caller to indicate whether it is the last time invocation of the function. Here it is 0, and later at line 2856 in finish_file , it is 1.

 

905    int

906    wrapup_globals_for_namespace (tree namespace, void* data)                                    in decl.c

907    {

908      struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);

909      varray_type statics = level->static_decls;

910      tree *vec = &VARRAY_TREE (statics, 0);

911       int len = VARRAY_ACTIVE_SIZE (statics);

912      int last_time = (data != 0);

913   

914      if (last_time)

915      {

916        check_global_declarations (vec, len);

917        return 0;

918      }

919   

920      /* Write out any globals that need to be output.  */

921      return wrapup_global_declarations (vec, len);

922    }

 

If it is not the last invocation, then following function is invoked to process global or static declarations within the namespace. Below hook finish_incomplete_decl at line 1572 hooks lhd_do_nothing_t for C++ front-end, which is an empty function.

 

1554   int

1555   wrapup_global_declarations (tree *vec, int len)                                           in toplev.c

1556   {

1557     tree decl;

1558     int i;

1559     int reconsider;

1560     int output_something = 0;

1561  

1562     for (i = 0; i < len; i++)

1563     {

1564       decl = vec[i];

1565  

1566        /* We're not deferring this any longer. Assignment is

1567         conditional to avoid needlessly dirtying PCH pages.  */

1568       if (DECL_DEFER_OUTPUT (decl) != 0)

1569         DECL_DEFER_OUTPUT (decl) = 0;

1570  

1571       if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0)

1572         (*lang_hooks .finish_incomplete_decl) (decl);

1573     }

1574  

1575     /* Now emit any global variables or functions that we have been

1576       putting off. We need to loop in case one of the things emitted

1577       here references another one which comes earlier in the list.  */

1578     do

1579     {

1580       reconsider = 0;

1581       for (i = 0; i < len; i++)

1582       {

1583         decl = vec[i];

1584  

1585         if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))

1586           continue ;

1587  

1588         /* Don't write out static consts, unless we still need them.

1589  

1590           We also keep static consts if not optimizing (for debugging),

1591           unless the user specified -fno-keep-static-consts.

1592           ??? They might be better written into the debug information.

1593           This is possible when using DWARF.

1594  

1595           A language processor that wants static constants to be always

1596           written out (even if it is not used) is responsible for

1597           calling rest_of_decl_compilation itself. E.g. the C front-end

1598           calls rest_of_decl_compilation from finish_decl.

1599           One motivation for this is that is conventional in some

1600           environments to write things like:

1601           static const char rcsid[] = "... version string ...";

1602           intending to force the string to be in the executable.

1603  

1604           A language processor that would prefer to have unneeded

1605           static constants "optimized away" would just defer writing

1606           them out until here. E.g. C++ does this, because static

1607           constants are often defined in header files.

1608  

1609           ??? A tempting alternative (for both C and C++) would be

1610           to force a constant to be written if and only if it is

1611           defined in a main file, as opposed to an include file.  */

1612  

1613         if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))

1614         {

1615           bool needed = 1;

1616  

1617           if (flag_unit_at_a_time

1618              && cgraph_varpool_node (decl)->finalized)

1619             needed = 0;

1620             else if ((flag_unit_at_a_time && !cgraph_global_info_ready )

1621                   && (TREE_USED (decl)

1622                       || TREE_USED (DECL_ASSEMBLER_NAME (decl))))

1623             /* needed */ ;

1624           else if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))

1625             /* needed */ ;

1626           else if (DECL_COMDAT (decl))

1627             needed = 0;

1628           else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)

1629                 && (optimize || !flag_keep_static_consts

1630                      || DECL_ARTIFICIAL (decl)))

1631             needed = 0;

1632  

1633           if (needed)

1634           {

1635             reconsider = 1;

1636             rest_of_decl_compilation (decl, NULL, 1, 1);

1637           }

1638         }

1639  

1640         if (TREE_CODE (decl) == FUNCTION_DECL

1641            && DECL_INITIAL (decl) != 0

1642            && DECL_SAVED_INSNS (decl) != 0

1643            && DECL_SAVED_INSNS (decl)->saved_for_inline

1644            && (flag_keep_inline_functions

1645                || (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))

1646                || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))

1647         {

1648           reconsider = 1;

1649           output_inline_function (decl);

1650         }

1651       }

1652  

1653       if (reconsider)

1654         output_something = 1;

1655     }

1656     while (reconsider);

1657  

1658     return output_something;

1659   }

 

Note at this point, cgraph_global_info_ready at line 1620 is still false. See if the variable is really used, at line 1636 rest_of_decl_compilation is invoked, which in turn, for non-external variable, invokes cgraph_varpool_finalize_decl to ensure associated cgrap_varpool_node is generated and marks the node as finialized (for FUNCTION_DECL, assemble_variable does nothing meaningful but cleans last_assemble_variable_decl ).

Further for inline function which is in-used, or visible external; or using compilation option –fkeep-inline-functions to emit any and all inline functions; the corresponding call expression should be replaced by the function body, which is done by below function.

Below write_symbols indicates the type of debugging information produced. See the real work is done by rest_of_compilation at line 2995, which embodies a complex operation, so we leave it for later section.

 

2965   void

2966   output_inline_function (tree fndecl)                                                            in integrate.c

2967   {

2968     enum debug_info_type old_write_symbols = write_symbols ;

2969     const struct gcc_debug_hooks *const old_debug_hooks = debug_hooks ;

2970     struct function *f = DECL_SAVED_INSNS (fndecl);

2971  

2972     old_cfun = cfun ;

2973     cfun = f;

2974     current_function_decl = fndecl;

2975  

2976     set_new_last_label_num (f->inl_max_label_num);

2977  

2978     /* We're not deferring this any longer.  */

2979     DECL_DEFER_OUTPUT (fndecl) = 0;

2980  

2981     /* If requested, suppress debugging information.  */

2982     if (f->no_debugging_symbols)

2983     {

2984       write_symbols = NO_DEBUG;

2985       debug_hooks = &do_nothing_debug_hooks ;

2986     }

2987  

2988     /* Make sure warnings emitted by the optimizers (e.g. control reaches

2989       end of non-void function) is not wildly incorrect.  */

2990     input_location = DECL_SOURCE_LOCATION (fndecl);

2991  

2992     /* Compile this function all the way down to assembly code. As a

2993       side effect this destroys the saved RTL representation, but

2994       that's okay, because we don't need to inline this anymore.  */

2995     rest_of_compilation (fndecl);

2996     DECL_INLINE (fndecl) = 0;

2997  

2998     cfun = old_cfun;

2999     current_function_decl = old_cfun ? old_cfun->decl : 0;

3000     write_symbols = old_write_symbols;

3001     debug_hooks = old_debug_hooks;

3002   }

5.13.4.6.              Iterate – handling static member without initializers in classes

Next, pending_statics holds a list of static class variables. This is needed, because a static class variable can be declared inside the class without an initializer, and then initialized, statically, outside the class. Note that pending_statics may overlap with static_aggregates , but those variables already handled in previous section, and will not be processed here.

First, import_export_decl needs be invoked to determine visibility and linkage property of the variables; then comes wrapup_global_declarations . Note that without initializers, there is no need to build initialization functions for these objects like section Iterate – emitting code for ctor/dtor of global aggregate .

Then at line 2797 at the end of the DO…WHILE loop, cgraph_assemble_pending_functions does nothing if flag_unit_at_a_time is set.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值