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.