天天看點

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     

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       

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    

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        

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             ;

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

1625             ;

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    

2979     DECL_DEFER_OUTPUT (fndecl) = 0;

2980  

2981    

2982     if (f->no_debugging_symbols)

2983     {

2984       write_symbols = NO_DEBUG;

2985       debug_hooks = &do_nothing_debug_hooks ;

2986     }

2987  

2988    

2990     input_location = DECL_SOURCE_LOCATION (fndecl);

2991  

2992    

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 不做任何事。

繼續閱讀