5.12.3.2.1.2.1.4. Prepare for code generation
The last invocation in cp_parser_function_definition_after_declarator is expand_or_defer_fn . If appropriate, it will generate RTL code for the function; or it does some preparation for RTL generation.
2973 void
2974 expand_or_defer_fn (tree fn) in semantics.c
2975 {
2976 /* When the parser calls us after finishing the body of a template
2977 function, we don't really want to expand the body. */
2978 if (processing_template_decl )
2979 {
2980 /* Normally, collection only occurs in rest_of_compilation. So,
2981 if we don't collect here, we never collect junk generated
2982 during the processing of templates until we hit a
2983 non-template function. */
2984 ggc_collect ();
2985 return ;
2986 }
2987
2988 /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs. */
2989 walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
2990 simplify_aggr_init_exprs_r,
2991 NULL);
2992
2993 /* If this is a constructor or destructor body, we have to clone
2994 it. */
2995 if (maybe_clone_body (fn))
2996 {
2997 /* We don't want to process FN again, so pretend we've written
2998 it out, even though we haven't. */
2999 TREE_ASM_WRITTEN (fn) = 1;
3000 return ;
3001 }
3002
3003 /* There's no reason to do any of the work here if we're only doing
3004 semantic analysis; this code just generates RTL. */
3005 if (flag_syntax_only )
3006 return ;
3007
3008 /* Compute the appropriate object-file linkage for inline functions. */
3009 if (DECL_DECLARED_INLINE_P (fn))
3010 import_export_decl (fn);
3011
3012 /* If this function is marked with the constructor attribute, add it
3013 to the list of functions to be called along with constructors
3014 from static duration objects. */
3015 if (DECL_STATIC_CONSTRUCTOR (fn))
3016 static_ctors = tree_cons (NULL_TREE, fn, static_ctors );
3017
3018 /* If this function is marked with the destructor attribute, add it
3019 to the list of functions to be called along with destructors from
3020 static duration objects. */
3021 if (DECL_STATIC_DESTRUCTOR (fn))
3022 static_dtors = tree_cons (NULL_TREE, fn, static_dtors );
3023
3024 function_depth ++;
3025
3026 /* Expand or defer, at the whim of the compilation unit manager. */
3027 cgraph_finalize_function (fn, function_depth > 1);
3028
3029 function_depth --;
3030 }
The iteration of the tree for the function definition at line 2989, processes the call of function suitable for named return value optimization. We will study it with nrv later.
Above predicate DECL_STATIC_CONSTRUCTOR or DECL_STATIC_DESTRUCTOR holds if the function is declared with __attribute__ ((constructor)) or __attribute__ ((destructor)) . The constructor attribute causes the function to be called automatically before execution enters main (). Similarly, the destructor attribute causes the function to be called automatically after main () has completed or exit () has been called. Functions with these attributes are useful for initializing data that will be used implicitly during the execution of the program.
5.12.3.2.1.2.1.4.1. Update call-graph
Previous section Graph of relation between caller and callee describes cgraph_node and cgraph_edge . Also it studies routine cgraph_node which creates single node of cgraph_node for every function at first invocation and returns this unique node in later invocations. It is the first time to invoke cgraph_finalize_function and cgraph_node for function specified by decl during the compilation.
157 void
158 cgraph_finalize_function (tree decl, bool nested) in cgraphunit.c
159 {
160 struct cgraph_node *node = cgraph_node (decl);
161
162 if (node->local.finalized)
163 {
164 /* As an GCC extension we allow redefinition of the function. The
165 semantics when both copies of bodies differ is not well defined.
166 We replace the old body with new body so in unit at a time mode
167 we always use new body, while in normal mode we may end up with
168 old body inlined into some functions and new body expanded and
169 inlined in others.
170
171 ??? It may make more sense to use one body for inlining and other
172 body for expanding the function but this is difficult to do. */
173
174 /* If node->output is set, then this is a unit-at-a-time compilation
175 and we have already begun whole-unit analysis. This is *not*
176 testing for whether we've already emitted the function. That
177 case can be sort-of legitimately seen with real function
178 redefinition errors. I would argue that the front end should
179 never present us with such a case, but don't enforce that for now. */
180 if (node->output)
181 abort ();
182
183 /* Reset our datastructures so we can analyze the function again. */
184 memset (&node->local, 0, sizeof (node->local));
185 memset (&node->global, 0, sizeof (node->global));
186 memset (&node->rtl, 0, sizeof (node->rtl));
187 node->analyzed = false;
188 node->local.redefined_extern_inline = true;
189 while (node->callees)
190 cgraph_remove_edge (node, node->callees->callee);
191
192 /* We may need to re-queue the node for assembling in case
193 we already proceeded it and ignored as not needed. */
194 if (node->reachable && !flag_unit_at_a_time )
195 {
196 struct cgraph_node *n;
197
198 for (n = cgraph_nodes_queue ; n; n = n->next_needed)
199 if (n == node)
200 break ;
201 if (!n)
202 node->reachable = 0;
203 }
204 }
205
206 notice_global_symbol (decl);
207 node->decl = decl;
208 node->local.finalized = true;
209
210 /* If not unit at a time, then we need to create the call graph
211 now, so that called functions can be queued and emitted now. */
212 if (!flag_unit_at_a_time )
213 {
214 cgraph_analyze_function (node);
215 cgraph_decide_inlining_incrementally (node);
216 }
In the first time invocation, node->local.finalized must be false, but it is updated to true at line 208 immediately. At line 206, notice_global_symbol collects first visible global symbol. As global symbol must be unique across the translation unit, it is useful to generate unique name for the nameless object by the compiler, for example, symbol collected here will be used to generate internal name of annoymous namespace.
1034 void
1035 notice_global_symbol (tree decl) in varasm.c
1036 {
1037 const char **type = &first_global_object_name ;
1038
1039 if (first_global_object_name
1040 || !TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)
1041 || !DECL_NAME (decl)
1042 || (TREE_CODE (decl) != FUNCTION_DECL
1043 && (TREE_CODE (decl) != VAR_DECL
1044 || (DECL_COMMON (decl)
1045 && (DECL_INITIAL (decl) == 0
1046 || DECL_INITIAL (decl) == error_mark_node))))
1047 || GET_CODE (DECL_RTL (decl)) != MEM)
1048 return ;
1049
1050 /* We win when global object is found, but it is usefull to know about weak
1051 symbol as well so we can produce nicer unique names. */
1052 if (DECL_WEAK (decl) || DECL_ONE_ONLY (decl))
1053 type = &weak_global_object_name ;
1054
1055 if (!*type)
1056 {
1057 const char *p;
1058 char *name;
1059 rtx decl_rtl = DECL_RTL (decl);
1060
1061 p = (* targetm .strip_name_encoding) (XSTR (XEXP (decl_rtl, 0), 0));
1062 name = xstrdup (p);
1063
1064 *type = name;
1065 }
1066 }
At line 212 in cgraph_finalize_function , flag_unit_at_a_time is set as 1 if we specify optimization switch higher than –O2 in the compiling command. Usually, we would like to use –O3 option to squeeze out all optimization ability from the compiler. Here assuming flag_unit_at_a_time is 1.
cgraph_finalize_function (continue)
218 if (decide_is_function_needed (node, decl))
219 cgraph_mark_needed_node (node);
220
221 /* If not unit at a time, go ahead and emit everything we've found
222 to be reachable at this time. */
223 if (!nested)
224 {
225 if (!cgraph_assemble_pending_functions ())
226 ggc_collect ();
227 }
228
229 /* If we've not yet emitted decl, tell the debug info about it. */
230 if (!TREE_ASM_WRITTEN (decl))
231 (*debug_hooks ->deferred_inline_function) (decl);
232
233 /* We will never really output the function body, clear the SAVED_INSNS array
234 early then. */
235 if (DECL_EXTERNAL (decl))
236 DECL_SAVED_INSNS (decl) = NULL;
237 }
Routine decide_is_function_needed determines if decl is visible to something either outside this translation unit, something magic in the system configuration, or (if not doing unit-at-a-time) to something we haven't seen yet. At line 93, attribute “used” means that the variable must be emitted even if it appears that the variable is not referenced (compiler will eliminate dead code).
73 static bool
74 decide_is_function_needed (struct cgraph_node *node, tree decl) in cgraphunit.c
75 {
76 /* If we decided it was needed before, but at the time we didn't have
77 the body of the function available, then it's still needed. We have
78 to go back and re-check its dependencies now. */
79 if (node->needed)
80 return true;
81
82 /* Externally visible functions must be output. The exception is
83 COMDAT functions that must be output only when they are needed. */
84 if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
85 return true;
86
87 /* Constructors and destructors are reachable from the runtime by
88 some mechanism. */
89 if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl))
90 return true;
91
92 /* If the user told us it is used, then it must be so. */
93 if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
94 return true;
95
96 /* ??? If the assembler name is set by hand, it is possible to assemble
97 the name later after finalizing the function and the fact is noticed
98 i n assemble_name then. This is arguably a bug. */
99 if (DECL_ASSEMBLER_NAME_SET_P (decl)
100 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
101 return true;
102
103 if (flag_unit_at_a_time )
104 return false;
105
106 /* If not doing unit at a time, then we'll only defer this function
107 if its marked for inlining. Otherwise we want to emit it now. */
108
109 /* "extern inline" functions are never output locally. */
110 if (DECL_EXTERNAL (decl))
111 return false;
112 /* We want to emit COMDAT functions only when absolutely necessary. */
113 if (DECL_COMDAT (decl))
114 return false;
115 if (!DECL_INLINE (decl)
116 || (!node->local.disregard_inline_limits
117 /* When declared inline, defer even the uninlinable functions.
118 This allows them to be eliminated when unused. */
119 && !DECL_DECLARED_INLINE_P (decl)
120 && (!node->local.inlinable || !cgraph_default_inline_p (node))))
121 return true;
122
123 return false;
124 }
If the declaration is visible, cgraph_mark_needed_node needs set the relevant cgraph_node as needed and mark its subnodes as reachable.
286 void
287 cgraph_mark_needed_node (struct cgraph_node *node) in cgraph.c
288 {
289 node->needed = 1;
290 cgraph_mark_reachable_node (node);
291 }
Slot local.finalized is set as true in cgraph_finalize_function already. In routine cgraph_node , line 123 through 128, field origin refers to node of containing function; field nested refers to the node of contained function (i.e, function invoked within); and field next_nested refers to the node of sibling functions contained within the containing function.
260 void
261 cgraph_mark_reachable_node (struct cgraph_node *node) in cgraph.c
262 {
263 if (!node->reachable && node->local.finalized)
264 {
265 notice_global_symbol (node->decl);
266 node->reachable = 1;
267
268 node->next_needed = cgraph_nodes_queue ;
269 cgraph_nodes_queue = node;
270
271 /* At the moment frontend automatically emits all nested functions. */
272 if (node->nested)
273 {
274 struct cgraph_node *node2;
275
276 for (node2 = node->nested; node2; node2 = node2->next_nested)
277 if (!node2->reachable)
278 cgraph_mark_reachable_node (node2);
279 }
280 }
281 }
All nodes of external visible functions should be chained tegother, which is pointed by cgraph_nodes_queue .
Back cgraph_finalize_function , if it is not a nested function (inline function defined within another function or class context), cgraph_assemble_pending_functions just returns false, if flag_unit_at_a_time is true, to trigger garbage collection.