GCC-3.4.6源代码学习笔记(160)

5.13.4.5.              迭代 处理名字空间中的全局对象

前面我们已经为需要构造函数及析构函数的全局或静态对象准备、注册好了初始化函数及退出函数。这一次的迭代检查是否还有没有处理的全局对象,并处理之。函数 walk_namespaces 从上至下以前序访问名字空间树。

 

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    }

 

namespaces 保存了在 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    }

 

下面的函数是遍历过程中,在每个名字空间节点上执行的实参 f 。实参 data 由调用者传入,表示是否是该函数的最后一次调用。在这里是 0 ,而在 finish_file 2856 行,为 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    }

 

如果这不是最后的调用,那么调用下面的函数来处理名字空间中的全局或静态声明。下面 1572 行的钩子 finish_incomplete_decl ,对于 C++ 前端,指向 lhd_do_nothing_t ,它是一个空函数。

 

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   }

 

注意在此时, 1620 行的 cgraph_global_info_ready 仍然是 false 。看到如果变量真正被使用,在 1636 行,调用 rest_of_decl_compilation ,在其中,对于非外部变量,调用 cgraph_varpool_finalize_decl 来确保生成相关的 cgrap_varpool_node ,并把这个节点标记为已完成( finialized )(对于 FUNCTION_DECL assemble_variable 不做任何事,仅清除 last_assemble_variable_decl )。

另外对于已经被使用,或者在外部可见的内联函数,或者使用编译选项 –fkeep-inline-functions 来发布所有内联函数;其对应的调用表达式应该为函数体所替代,这由下面的函数来完成。

下面的 write_symbols 表示所产生的调试信息的类型。看到真正的工作由 2995 行的 rest_of_compilation 完成,它包含了非常复杂的操作,因此我们暂时不看它。

 

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.              迭代 在类中没有初始值的静态成员

接下来, pending_statics 保存了一个静态类变量列表。这是需要的,因为一个静态类变量可以被声明在该类中,并且不带初始值,然后在该类的外部静态地初始化这个变量。注意到 pending_statics 可能与 static_aggregates 重叠,不过那些变量已经在前面的章节中处理过了,不会在这里再处理。

首先,需要调用 import_export_decl 来确定变量的可见性及链接属性;然后就是 wrapup_global_declarations 。注意没有初始值,不需要为这些对象构建初始化函数,就像章节 迭代 发布全局聚集类的构造函数 /析构函数 中所做的那样。

然后在 DO…WHILE 循环的末尾的 2797 行,如果设置了 flag_unit_at_a_time cgraph_assemble_pending_functions 不做任何事。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值