Studying note of GCC-3.4.6 source (173)
来源:互联网 发布:中控门禁系统数据库 编辑:程序博客网 时间:2024/05/21 09:45
5.13.5.3. Analysis translation-unit
After cgraph_varpool_assemble_pending_declsemits assemble for all pending variables (note that they are visible out of thetranslation-unit), returns cgraph_finalize_compilation_unit and beginsanalyzing the translation-unit.
cgraph_finalize_compilation_unit(continue)
383 timevar_push (TV_CGRAPH);
384 if (cgraph_dump_file)
385 {
386 fprintf (cgraph_dump_file,"Initial entry points:");
387 for (node = cgraph_nodes; node; node =node->next)
388 if (node->needed && DECL_SAVED_TREE (node->decl))
389 fprintf (cgraph_dump_file," %s", cgraph_node_name (node));
390 fprintf (cgraph_dump_file,"/n");
391 }
392
393 /* Propagate reachability flag and lowerrepresentation of all reachable
394 functions. In the future, lowering willintroduce new functions and
395 new entry points on the way (by templateinstantiation and virtual
396 method table generation for instance). */
397 while (cgraph_nodes_queue)
398 {
399 struct cgraph_edge *edge;
400 tree decl = cgraph_nodes_queue->decl;
401
402 node = cgraph_nodes_queue;
403 cgraph_nodes_queue = cgraph_nodes_queue->next_needed;
404
405 /* ??? It is possible to create extern inlinefunction and later using
406 weak alas attribute to kill it's body.See
407 gcc.c-torture/compile/20011119-1.c */
408 if (!DECL_SAVED_TREE (decl))
409 continue;
410
411 if (node->analyzed || !node->reachable || !DECL_SAVED_TREE (decl))
412 abort ();
413
414 cgraph_analyze_function (node);
415
416 for (edge = node->callees; edge; edge= edge->next_callee)
417 if (!edge->callee->reachable)
418 cgraph_mark_reachable_node(edge->callee);
419
420 cgraph_varpool_assemble_pending_decls();
421 }
Queue cgraph_nodes_queuerecords cgraph_node associating with the function.
5.13.5.3.1. Analyzing functions
5.13.5.3.1.1. Build cgraph for caller-callee
DECL_SAVED_TREE is the intermediate tree representing thefunction-body. In some circumstance, it may be empty, for example in functiontemplate, so above condition at line 408 to filter out all functions withfunction-body unknown. Line 411 is a sainty check, if it is satisfied, means thecompiler has something wrong.
319 static void
320 cgraph_analyze_function (struct cgraph_node *node) in cgraphunit.c
321 {
322 tree decl = node->decl;
323 struct cgraph_edge *e;
324
325 current_function_decl= decl;
326
327 /* First kill forward declaration so reverseinlining works properly. */
328 cgraph_create_edges (decl,DECL_SAVED_TREE (decl));
Note, in below procedure, it may append to cgraph_nodes_queue, thus allfunctions visited would get handled.
Below, cgraph_create_edges iterates thefunction-body, creates cgraph_* nodes for those candidates without them, andappends them to corresponding queues.
306 void
307 cgraph_create_edges (tree decl, tree body) in cgraphunit.c
308 {
309 /* The nodes we're interested in are nevershared, so walk
310 the tree ignoring duplicates. */
311 visited_nodes= htab_create (37, htab_hash_pointer,
312 htab_eq_pointer, NULL);
313 walk_tree (&body, record_call_1,decl, visited_nodes);
314 htab_delete (visited_nodes);
315 visited_nodes= NULL;
316 }
We have seen before, in walk_tree, once the function passed as itsargument returns non-null value, the iteration will be terminated. Here, record_call_1always returns NULL, and forces walk_tree to do the full iteration aspossible.
240 static tree
241 record_call_1 (tree *tp, int *walk_subtrees, void *data) in cgraphunit.c
242 {
243 tree t = *tp;
244
245 switch (TREE_CODE (t))
246 {
247 case VAR_DECL:
248 /* ??? Really, we should mark this decl as*potentially* referenced
249 by this function and re-examine whether thedecl is actually used
250 after rtl has been generated. */
251 if (TREE_STATIC (t))
252 cgraph_varpool_mark_needed_node (cgraph_varpool_node (t));
253 break;
254
255 case ADDR_EXPR:
256 if (flag_unit_at_a_time)
257 {
258 /*Record dereferences to the functions. This makes the
259 functions reachable unconditionally. */
260 tree decl = TREE_OPERAND (*tp, 0);
261 if (TREE_CODE (decl) == FUNCTION_DECL)
262 cgraph_mark_needed_node(cgraph_node (decl));
263 }
264 break;
As global variable is visible outside of the translation-unit (TREE_PUBLICholds), output it anyhow (eliminating unused global variables can be done bylinker, which is a feature GCC will implement). And the visibility of staticvariable is only confined in the file declaring it, or files including thedefining file, once it is unused, the compiler can eliminate it from assemblercode.
(Keep in mind that cgraph_* nodes are only used for analyzingfunctions, global or static variables; local variables as only locates in thedefining function, needn’t such “heavy weapons”). At line 252, sets thevariable as “needed”, and if its associated front-end node is completed, addsthe cgraph_varpool_node into cgraph_varpool_nodes_queue queue. Note thatfunction called at line 252 can guarantee every variable would only be addedonce (neededand finalizedfields of cgraph_varpool_node of every added variable are 1, prevents it fromadding again).
For ADD_EXPR atline 255, if it is the reference of variable address, it needs not handle here,when record_call_1enters its operands, the associated VAR_DECL node will be found and processed.What needs treatment is function, see that it just stands for referring thefunction address, not invoke, and if its associated front-end node iscompleted, and adds it into queue cgraph_nodes_queue. Similarly, the insertionguarantees once addition too.
record_call_1 (continue)
266 case CALL_EXPR:
267 {
268 tree decl = get_callee_fndecl (*tp);
269 if (decl && TREE_CODE (decl) == FUNCTION_DECL)
270 {
271 cgraph_record_call(data, decl);
272
273 /* When wesee a function call, we don't want to look at the
274 function reference in the ADDR_EXPR thatis hanging from
275 the CALL_EXPR we're examining here,because we would
276 conclude incorrectly that the function'saddress could be
277 taken by something that is not afunction call. So only
278 walk the function parameter list, skipthe other subtrees. */
279
280 walk_tree(&TREE_OPERAND (*tp, 1), record_call_1, data,
281 visited_nodes);
282 *walk_subtrees = 0;
283 }
284 break;
285 }
Next is the handling of function invocation. It gets the noderepresenting function invocation at line 268, as in analysis using cgraph, itneeds generate map of call-relation among functions (see section Graph ofrelation between caller and callee).
295 struct cgraph_edge *
296 cgraph_record_call (tree caller, tree callee) in cgraph.c
297 {
298 return create_edge(cgraph_node (caller), cgraph_node (callee));
299 }
Here note that, at line 271, argument data (that is parameter caller)is the FUNCTION_DECL node of the function under analyzing (it is parameter declof cgraph_create_edges).
154 static struct cgraph_edge *
155 create_edge (struct cgraph_node*caller, struct cgraph_node *callee) in cgraph.c
156 {
157 struct cgraph_edge*edge = ggc_alloc (sizeof (struct cgraph_edge));
158 struct cgraph_edge *edge2;
159
160 if (!DECL_SAVED_TREE (callee->decl))
161 edge->inline_failed = N_("function body not available");
162 else if (callee->local.redefined_extern_inline)
163 edge->inline_failed = N_("redefined extern inline functions arenot "
164 "considered forinlining");
165 else if (callee->local.inlinable)
166 edge->inline_failed = N_("function not considered forinlining");
167 else
168 edge->inline_failed = N_("function not inlinable");
169
170 /* At the moment we don't associate calls withspecific CALL_EXPRs
171 as we probably ought to, so we mustpreserve inline_call flags to
172 be the same in all copies of the sameedge. */
173 if (cgraph_global_info_ready)
174 for (edge2 = caller->callees; edge2;edge2 = edge2->next_callee)
175 if (edge2->callee == callee)
176 {
177 edge->inline_failed= edge2->inline_failed;
178 break;
179 }
180
181 edge->caller = caller;
182 edge->callee = callee;
183 edge->next_caller = callee->callers;
184 edge->next_callee = caller->callees;
185 caller->callees = edge;
186 callee->callers = edge;
187 return edge;
188 }
See in previous (section Graphof relation between caller and callee), cgraph_edge is used to bindcgraph_node of the caller and callee. The callee may have been analyzedalready, then set the cgraph_edge accordingly. Further, once analyzing thetranslation-unit, cgraph_global_info_ready will be set as 1, at which time needtraverse all callees of the function (next_callee chains all callees), andcheck if existing the cgraph_edge (line 175 condition).
At line 280, the second operand of CALL_EXPR is its arguments list, walk_treenext visits it. And at line 281, walk_subtrees is set as 0, which indicates thatsubtree under this CALL_EXPR is irrelevant.
record_call_1 (continue)
287 default:
288 /* Save some cycles by not walking types anddeclaration as we
289 won't find anything useful there anyway. */
290 if (DECL_P (*tp) || TYPE_P (*tp))
291 {
292 *walk_subtrees = 0;
293 break;
294 }
295
296 if ((unsigned int) TREE_CODE (t) >= LAST_AND_UNUSED_TREE_CODE)
297 return (*lang_hooks.callgraph.analyze_expr) (tp, walk_subtrees, data);
298 break;
299 }
300
301 return NULL;
302 }
Similarly, in function analyzing, we don’t care about type anddeclaration, which are skipped at line 292. The common used code in front-endis ended at LAST_AND_UNUSED_TREE_CODE (not include), which is followed by thoseused by the language. Obvious, such nodes should be processed via languagehooks.
2497 tree
2498 cxx_callgraph_analyze_expr (tree *tp,int *walk_subtrees ATTRIBUTE_UNUSED, in decl2.c
2499 tree from ATTRIBUTE_UNUSED)
2500 {
2501 tree t = *tp;
2502
2503 if (flag_unit_at_a_time)
2504 switch(TREE_CODE (t))
2505 {
2506 casePTRMEM_CST:
2507 if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
2508 cgraph_mark_needed_node(cgraph_node (PTRMEM_CST_MEMBER (t)));
2509 break;
2510 caseBASELINK:
2511 if (TREE_CODE (BASELINK_FUNCTIONS (t))== FUNCTION_DECL)
2512 cgraph_mark_needed_node (cgraph_node(BASELINK_FUNCTIONS (t)));
2513 break;
2514
2515 default:
2516 break;
2517 }
2518
2519 return NULL;
2520 }
For C++, what needs handle is the reference of address of method,and the access of member of the base from the derived class.
- Studying note of GCC-3.4.6 source (173)
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (1)
- Studying note of GCC-3.4.6 source (2)
- Studying note of GCC-3.4.6 source (3)
- Studying note of GCC-3.4.6 source (4)
- Studying note of GCC-3.4.6 source (5)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (8)
- Studying note of GCC-3.4.6 source (9)
- Studying note of GCC-3.4.6 source (10)
- Studying note of GCC-3.4.6 source (10 cont1)
- Studying note of GCC-3.4.6 source (10 cont2)
- Studying note of GCC-3.4.6 source (10 cont3)
- Studying note of GCC-3.4.6 source (10 cont4)
- Studying note of GCC-3.4.6 source (11)
- Studying note of GCC-3.4.6 source (12)
- Studying note of GCC-3.4.6 source (13)
- 《人生六部书——处世经典 之方圆处世》
- android之字符串自动关联相应程序,主要有email/phone/web
- GCC-3.4.6源代码学习笔记(173)
- word 文字 阴影 背景
- c中的续行符为"/"
- Studying note of GCC-3.4.6 source (173)
- 无线通信技术
- 1200
- DSP240x_Sci.h
- Python、VPython、NumPy、MatPlotLib简介
- #pragma用法(1)#pragma startup和#pragma exit
- GCC-3.4.6源代码学习笔记(174)
- MM_jumpMenu函数 跳转菜单
- HQL有关查询详解