Studying note of GCC-3.4.6 source (156)
来源:互联网 发布:淘宝新店如何找货源 编辑:程序博客网 时间:2024/06/04 12:27
5.13.3. Generate tinfo for fundamental types
After outputting PCH file if required, back in finish_file to continue thestruggle of assemble emitting. Next, the compiler should prepare tinfo for thefundamental types.
finish_file (continue)
2546 /* Otherwise, GDBcan get confused, because in only knows
2547 about source for LINENO-1lines. */
2548 input_line -= 1;
2549
2550 interface_unknown = 1;
2551 interface_only = 0;
2552
2553 /* We now have towrite out all the stuff we put off writing out.
2554 These include:
2555
2556 o Template specializationsthat we have not yet instantiated,
2557 but which are needed.
2558 o Initialization anddestruction for non-local objects with
2559 static storage duration.(Local objects with static storage
2560 duration are initializedwhen their scope is first entered,
2561 and are cleaned up viaatexit.)
2562 o Virtual functiontables.
2563
2564 All of these may cause othersto be needed. For example,
2565 instantiating one function maycause another to be needed, and
2566 generating the initializer foran object may cause templates to be
2567 instantiated, etc., etc. */
2568
2569 timevar_push (TV_VARCONST);
2570
2571 emit_support_tinfos();
All such tinfos would be found within namespace abi_node. In get_tinfo_decl, thesegenerated tinfos will be chained in unemitted_tinfo_decls. Note that the content ofarray fundamentalsis the nodes of fundamental types which are built during setting up thecompiling environment.
1353 void
1354 emit_support_tinfos(void) in rtti.c
1355 {
1356 static tree *const fundamentals[] =
1357 {
1358 &void_type_node,
1359 &boolean_type_node,
1360 &wchar_type_node,
1361 &char_type_node,&signed_char_type_node, &unsigned_char_type_node,
1362 &short_integer_type_node,&short_unsigned_type_node,
1363 &integer_type_node, &unsigned_type_node,
1364 &long_integer_type_node,&long_unsigned_type_node,
1365 &long_long_integer_type_node,&long_long_unsigned_type_node,
1366 &float_type_node,&double_type_node, &long_double_type_node,
1367 0
1368 };
1369 int ix;
1370 tree bltn_type, dtor;
1371
1372 push_nested_namespace(abi_node);
1373 bltn_type = xref_tag(class_type,
1374 get_identifier("__fundamental_type_info"),
1375 true, false);
1376 pop_nested_namespace (abi_node);
1377 if (!COMPLETE_TYPE_P (bltn_type))
1378 return;
1379 dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC(bltn_type), 1);
1380 if (DECL_EXTERNAL (dtor))
1381 return;
1382 doing_runtime = 1;
1383 for (ix = 0;fundamentals[ix]; ix++)
1384 {
1385 tree bltn = *fundamentals[ix];
1386 tree bltn_ptr = build_pointer_type (bltn);
1387 tree bltn_const_ptr = build_pointer_type
1388 (build_qualified_type (bltn, TYPE_QUAL_CONST));
1389 tree tinfo;
1390
1391 tinfo = get_tinfo_decl(bltn);
1392 TREE_USED (tinfo) = 1;
1393 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME(tinfo)) = 1;
1394
1395 tinfo = get_tinfo_decl(bltn_ptr);
1396 TREE_USED (tinfo) = 1;
1397 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME(tinfo)) = 1;
1398
1399 tinfo = get_tinfo_decl(bltn_const_ptr);
1400 TREE_USED (tinfo) = 1;
1401 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME(tinfo)) = 1;
1402 }
1403 }
See that for every fundamental type, three tinfos need generated,one for plain, one for pointer, one for constant pointer.
5.13.4. Stable down immediate tree
Following big DO WHILEloop repeats until nothing related can be changed. At line 2582, instantiate_pending_templatesinstantiates the pending template. Internal, global chain pending_tempaltes is a tree_listholding templates whose instantiations have been deferred, either because theirdefinitions were not yet available, or because we were putting off doing thework. The tree_purose of each node is either a DECL (for a function or staticdata member), or a TYPE (for a class) indicating what we are hoping toinstantiate. The tree_value is not used.
finish_file (continue)
2573 do
2574 {
2575 tree t;
2576 size_t n_old, n_new;
2577
2578 reconsider = false;
2579
2580 /* If there aretemplates that we've put off instantiating, do
2581 them now. */
2582 instantiate_pending_templates ();
2583 ggc_collect ();
2584
2585 /* Write outvirtual tables as required. Note that writing out
2586 the virtual table for a template class maycause the
2587 instantiation of members ofthat class. If we write out
2588 vtables then we remove the class from our listso we don't
2589 have to look at it again. */
2590
2591 while (keyed_classes!= NULL_TREE
2592 && maybe_emit_vtables (TREE_VALUE (keyed_classes)))
2593 {
2594 reconsider = true;
2595 keyed_classes = TREE_CHAIN (keyed_classes);
2596 }
2597
2598 t = keyed_classes;
2599 if (t != NULL_TREE)
2600 {
2601 tree next = TREE_CHAIN (t);
2602
2603 while(next)
2604 {
2605 if (maybe_emit_vtables(TREE_VALUE (next)))
2606 {
2607 reconsider = true;
2608 TREE_CHAIN (t) = TREE_CHAIN (next);
2609 }
2610 else
2611 t = next;
2612
2613 next = TREE_CHAIN (t);
2614 }
2615 }
2616
2617 /* Write outneeded type info variables. We have to be careful
2618 looping through unemitted decls, becauseemit_tinfo_decl may
2619 cause other variables to be needed. We sticknew elements
2620 (and old elements that we may need toreconsider) at the end
2621 of the array, then shift themback to the beginning once we're
2622 done. */
2623
2624 n_old = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls);
2625 for (i = 0;i < n_old; ++i)
2626 {
2627 tree tinfo_decl = VARRAY_TREE (unemitted_tinfo_decls,i);
2628 if (emit_tinfo_decl(tinfo_decl))
2629 reconsider = true;
2630 else
2631 VARRAY_PUSH_TREE (unemitted_tinfo_decls, tinfo_decl);
2632 }
2633
2634 /* The only elements we want to keep are thenew ones. Copy
2635 them to the beginning of thearray, then get rid of the
2636 leftovers. */
2637 n_new = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls)- n_old;
2638 if (n_new)
2639 memmove (&VARRAY_TREE (unemitted_tinfo_decls,0),
2640 &VARRAY_TREE (unemitted_tinfo_decls,n_old),
2641 n_new * sizeof (tree));
2642 memset (&VARRAY_TREE (unemitted_tinfo_decls,n_new),
2643 0, n_old * sizeof(tree));
2644 VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) = n_new;
2645
2646 /* The list ofobjects with static storage duration is built up
2647 in reverse order. We clear STATIC_AGGREGATES so that any new
2648 aggregates added during the initialization ofthese will be
2649 initialized in the correct order when we nextcome around the
2650 loop. */
2651 vars = prune_vars_needing_no_initialization(&static_aggregates);
2652
2653 if (vars)
2654 {
2655 tree v;
2656
2657 /* We need to start a new initializationfunction each time
2658 through the loop. That'sbecause we need to know which
2659 vtables have been referenced, andTREE_SYMBOL_REFERENCED
2660 isn't computed until a function isfinished, and written
2661 out. That's a deficiency in the back-end.When this is
2662 fixed, these initialization functionscould all become
2663 inline, with resulting performanceimprovements. */
2664 tree ssdf_body;
2665
2666 /* Set the line and file, so that it isobviously not from
2667 the source file. */
2668 input_location = locus;
2669 ssdf_body = start_static_storage_duration_function(ssdf_count);
2670
2671 /* Make surethe back end knows about all the variables. */
2672 write_out_vars(vars);
2673
2674 /* Firstgenerate code to do all the initializations. */
2675 for (v =vars; v; v = TREE_CHAIN (v))
2676 do_static_initialization(TREE_VALUE (v),
2677 TREE_PURPOSE (v));
2678
2679 /* Then,generate code to do all the destructions. Do these
2680 in reverse order so that the most recently constructed
2681 variable is the first destroyed. If we'reusing
2682 __cxa_atexit, then we don't need to dothis; functions
2683 were registered at initialization time todestroy the
2684 local statics. */
2685 if (!flag_use_cxa_atexit)
2686 {
2687 vars = nreverse (vars);
2688 for (v= vars; v; v = TREE_CHAIN (v))
2689 do_static_destruction (TREE_VALUE(v));
2690 }
2691 else
2692 vars = NULL_TREE;
2693
2694 /* Finish up the static storage durationfunction for this
2695 round. */
2696 input_location = locus;
2697 finish_static_storage_duration_function(ssdf_body);
2698
2699 /* All thoseinitializations and finalizations might cause
2700 usto need more inline functions, more template
2701 instantiations, etc. */
2702 reconsider = true;
2703 ssdf_count++;
2704 locus.line++;
2705 }
2706
2707 for (i = 0;i < deferred_fns_used;++i)
2708 {
2709 tree decl = VARRAY_TREE (deferred_fns,i);
2710
2711 /* Does it needsynthesizing? */
2712 if (DECL_ARTIFICIAL (decl) && !DECL_INITIAL (decl)
2713 && TREE_USED (decl)
2714 && (! DECL_REALLY_EXTERN(decl) || DECL_INLINE (decl)))
2715 {
2716 /* Eventhough we're already at the top-level, we push
2717 there again. That way, when we pop back a fewlines
2718 hence, all of our state is restored.Otherwise,
2719 finish_function doesn't clean things up, andwe end
2720 up with CURRENT_FUNCTION_DECL set. */
2721 push_to_top_level();
2722 synthesize_method (decl);
2723 pop_from_top_level ();
2724 reconsider = true;
2725 }
2726
2727 /* If thefunction has no body, avoid calling
2728 import_export_decl. On a system withoutweak symbols,
2729 calling import_export_decl will make aninline template
2730 instantiation "static", whichwill result in errors about
2731 the use of undefined functions if there isno body for
2732 the function. */
2733 if (!DECL_SAVED_TREE (decl))
2734 continue;
2735
2736 import_export_decl (decl);
2737
2738 /* We lie tothe back-end, pretending that some functions
2739 are not defined when they really are. Thiskeeps these
2740 functions from being put outunnecessarily. But, we must
2741 stop lying when the functions are referenced,or if they
2742 are not comdat since they need to be putout now. This
2743 is done in a separate for cycle, becauseif some deferred
2744 function is contained in another deferredfunction later
2745 in deferred_fns varray, rest_of_compilation would skip
2746 this function and we really cannot expandthe same
2747 function twice. */
2748 if (DECL_NOT_REALLY_EXTERN (decl)
2749 && DECL_INITIAL (decl)
2750 && DECL_NEEDED_P (decl))
2751 DECL_EXTERNAL (decl) = 0;
2752
2753 /* If we'regoing to need to write this function out, and
2754 there's already a body for it, create RTLfor it now.
2755 (There might be no body if this is amethod we haven't
2756 gotten around to synthesizing yet.) */
2757 if (!DECL_EXTERNAL (decl)
2758 && DECL_NEEDED_P (decl)
2759 && DECL_SAVED_TREE (decl)
2760 && !TREE_ASM_WRITTEN (decl)
2761 && (!flag_unit_at_a_time
2762 || !cgraph_node(decl)->local.finalized))
2763 {
2764 /* We willoutput the function; no longer consider it in this
2765 loop. */
2766 DECL_DEFER_OUTPUT (decl) = 0;
2767 /* GenerateRTL for this function now that we know we
2768 need it. */
2769 expand_or_defer_fn(decl);
2770 /* If we'recompiling -fsyntax-only pretend that this
2771 function has been written out so that we don'ttry to
2772 expand it again. */
2773 if (flag_syntax_only)
2774 TREE_ASM_WRITTEN (decl) = 1;
2775 reconsider = true;
2776 }
2777 }
2778
2779 if (walk_namespaces(wrapup_globals_for_namespace, /*data=*/0))
2780 reconsider = true;
2781
2782 /* Static data members are just likenamespace-scope globals. */
2783 for (i = 0;i < pending_statics_used;++i)
2784 {
2785 tree decl = VARRAY_TREE (pending_statics,i);
2786 if (var_finalized_p(decl))
2787 continue;
2788 import_export_decl (decl);
2789 if (DECL_NOT_REALLY_EXTERN (decl)&& ! DECL_IN_AGGR_P (decl))
2790 DECL_EXTERNAL (decl) = 0;
2791 }
2792 if (pending_statics
2793 && wrapup_global_declarations(&VARRAY_TREE (pending_statics, 0),
2794 pending_statics_used))
2795 reconsider = true;
2796
2797 if (cgraph_assemble_pending_functions ())
2798 reconsider = true;
2799 }
2800 while(reconsider);
5.13.4.1. Iterate - emitting vtable
At first, vtable in used should be marked so as to compiler willemit code for it. In previous section, we have seen that for a class, itsCLASSTYPE_VTABLES maybe contain a list of vtables. It depends on the baseclasses and its definition. And if a class contains vtable, it is also recordedin list of keyed_classes.At line 1565, primary_vtblrefers to the list of vtable of ctype.
1556 static bool
1557 maybe_emit_vtables (tree ctype) in decl2.c
1558 {
1559 tree vtbl;
1560 tree primary_vtbl;
1561 bool needed = false;
1562
1563 /* If the vtablesfor this class have already been emitted there is
1564 nothing more to do. */
1565 primary_vtbl = CLASSTYPE_VTABLES (ctype);
1566 if (var_finalized_p(primary_vtbl))
1567 returnfalse;
1568 /* Ignore dummyvtables made by get_vtable_decl. */
1569 if (TREE_TYPE (primary_vtbl) ==void_type_node)
1570 returnfalse;
1571
1572 import_export_class(ctype);
1573
1574 /* See if any ofthe vtables are needed. */
1575 for (vtbl =CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
1576 {
1577 import_export_vtable(vtbl, ctype, 1);
1578 if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
1579 break;
1580 }
1581 if (!vtbl)
1582 {
1583 /* If thereferences to this class' vtables are optimized away,
1584 still emit the appropriatedebugging information. See
1585 dfs_debug_mark. */
1586 if (DECL_COMDAT(primary_vtbl)
1587 && CLASSTYPE_DEBUG_REQUESTED(ctype))
1588 note_debug_info_needed (ctype);
1589 returnfalse;
1590 }
1591 else if (TREE_PUBLIC (vtbl) &&!DECL_COMDAT (vtbl))
1592 needed = true;
All vtables are declared as public VAR_DECL by compiler, and suchnodes are associated by cgraph_varpool_node,in which if flag finalizedis set means the node has code output.
1544 static bool
1545 var_finalized_p (tree var) in decl2.c
1546 {
1547 if (flag_unit_at_a_time)
1548 return cgraph_varpool_node (var)->finalized;
1549 else
1550 returnTREE_ASM_WRITTEN (var);
1551 }
If flag_unit_at_a_timeis nonzero, a cgraph_varpool_node is created for this VAR_DECL. Below,hashtable cgraph_varpool_hashis the queue of cgraph_varpool_node, which is managed by GC.
441 struct cgraph_varpool_node*
442 cgraph_varpool_node (tree decl) in cgraph.c
443 {
444 structcgraph_varpool_node *node;
445 structcgraph_varpool_node **slot;
446
447 if (!DECL_P (decl) || TREE_CODE (decl) ==FUNCTION_DECL)
448 abort ();
449
450 if (!cgraph_varpool_hash)
451 cgraph_varpool_hash = htab_create_ggc (10,cgraph_varpool_hash_node,
452 eq_cgraph_varpool_node, NULL);
453 slot = (structcgraph_varpool_node **)
454 htab_find_slot_with_hash (cgraph_varpool_hash,DECL_ASSEMBLER_NAME (decl),
455 IDENTIFIER_HASH_VALUE(DECL_ASSEMBLER_NAME (decl)),
456 INSERT);
457 if (*slot)
458 return*slot;
459 node = ggc_alloc_cleared (sizeof (*node));
460 node->decl = decl;
461 cgraph_varpool_n_nodes++;
462 cgraph_varpool_nodes = node;
463 *slot = node;
464 return node;
465 }
Then structure cgraph_varpool_node has following definition.
134 struct cgraph_varpool_nodeGTY(()) in cgraph.h
135 {
136 tree decl;
137 /* Pointer to thenext function in cgraph_varpool_nodes_queue. */
138 structcgraph_varpool_node *next_needed;
139
140 /* Set whenfunction must be output - it is externally visible
141 or it's addressis taken. */
142 bool needed;
143 /* Set once it hasbeen finalized so we consider it to be output. */
144 bool finalized;
145 /* Set whenfunction is scheduled to be assembled. */
146 bool output;
147 };
Above at line 1572, import_export_class determines if it needsoutput the whole set of the class in this translation-unit or just signiture butreferences will be solved at link time.
Remember that option -fno-implicit-templates means never emit codefor non-inline templates which are instantiated implictly. For the case wesuppress the emission by setting import_export to -1.
Next it needs decide whether the specified vtable is external or not(even if the class is external, but if any of its base is defined in thistranslation-unit and output its vtable here, the vtable of the class also needsbe output here).
1442 void
1443 import_export_vtable (tree decl, treetype, int final) in decl2.c
1444 {
1445 if (DECL_INTERFACE_KNOWN (decl))
1446 return;
1447
1448 if (TYPE_FOR_JAVA (type))
1449 {
1450 TREE_PUBLIC (decl) = 1;
1451 DECL_EXTERNAL (decl) = 1;
1452 DECL_INTERFACE_KNOWN (decl) = 1;
1453 }
1454 else if (CLASSTYPE_INTERFACE_KNOWN (type))
1455 {
1456 TREE_PUBLIC (decl) = 1;
1457 DECL_EXTERNAL (decl) =CLASSTYPE_INTERFACE_ONLY (type);
1458 DECL_INTERFACE_KNOWN (decl) = 1;
1459 }
1460 else
1461 {
1462 /* We can onlywait to decide if we have real non-inline virtual
1463 functions in our class, or if we come from atemplate. */
1464
1465 int found =(CLASSTYPE_TEMPLATE_INSTANTIATION (type)
1466 || CLASSTYPE_KEY_METHOD (type) !=NULL_TREE);
1467
1468 if (final || ! found)
1469 {
1470 comdat_linkage (decl);
1471 DECL_EXTERNAL (decl) = 0;
1472 }
1473 else
1474 {
1475 TREE_PUBLIC (decl) = 1;
1476 DECL_EXTERNAL (decl) = 1;
1477 }
1478 }
1479 }
After import_export_vtable sets flags for VAL_DECLof the vtable, DECL_NEEDED_P tells if the vtable needs be emitted. PredicateDECL_COMDAT if holds, indicates that, even if it TREE_PUBLIC, it needs not beput out unless it is needed in this translation unit. Entities like this areshared across translation units (like weak entities), but are guaranteed to begenerated by any translation unit that needs them, and therefore need not beput out anywhere where they are not needed. DECL_COMDAT is just a hint to theback-end; it is up to front-ends which set this flag to ensure that there willnever be any harm, other than bloat, in putting out something which isDECL_COMDAT.
1730 #define DECL_NEEDED_P(DECL) / in cp-tree.h
1731 ((at_eof && TREE_PUBLIC (DECL) &&!DECL_COMDAT (DECL)) /
1732 || (DECL_ASSEMBLER_NAME_SET_P (DECL) /
1733 &&TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL)))/
1734 || (((flag_syntax_only || flag_unit_at_a_time) &&TREE_USED (DECL))))
If any vtable in the vtable chain needs code emitted, the compilerwill emit code for all vtables within. Mark them here.
maybe_emit_vtables (continue)
1595 /* The ABI requiresthat we emit all of the vtables if we emit any
1596 of them. */
1597 for (vtbl =CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
1598 {
1599 /* Write it out. */
1600 import_export_vtable(vtbl, ctype, 1);
1601 mark_vtable_entries(vtbl);
1602
1603 /* If we knowthat DECL is needed, mark it as such for the varpool. */
1604 if (needed)
1605 cgraph_varpool_mark_needed_node(cgraph_varpool_node (vtbl));
1606
1607 if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
1608 {
1609 /* It had better be all done atcompile-time. */
1610 if (store_init_value (vtbl, DECL_INITIAL(vtbl)))
1611 abort ();
1612 }
1613
1614 if (write_symbols == DWARF_DEBUG ||write_symbols == DWARF2_DEBUG)
1615 {
1616 /* Mark theVAR_DECL node representing the vtable itself as a
1617 "gratuitous" one,thereby forcing dwarfout.c to ignore it.
1618 It is rather important thatsuch things be ignored because
1619 any effort to actuallygenerate DWARF for them will run
1620 into trouble when/if weencounter code like:
1621
1622 #pragma interface
1623 struct S { virtual voidmember (); };
1624
1625 because the artificialdeclaration of the vtable itself (as
1626 manufactured by the g++front end) will say that the vtable
1627 is a static member of `S'but only *after* the debug output
1628 for the definition of `S' has already beenoutput. This causes
1629 grief because the DWARFentry for the definition of the vtable
1630 will try to refer back toan earlier *declaration* of the
1631 vtable as a static memberof `S' and there won't be one.
1632 We might be able to arrangeto have the "vtable static member"
1633 attached to the member listfor `S' before the debug info for
1634 `S' get written (whichwould solve the problem) but that would
1635 require more intrusive changes to the g++front end. */
1636
1637 DECL_IGNORED_P (vtbl) = 1;
1638 }
1639
1640 /* Always makevtables weak. */
1641 if (flag_weak)
1642 comdat_linkage (vtbl);
1643
1644 rest_of_decl_compilation(vtbl, NULL, 1, 1);
1645
1646 /* Because we'reonly doing syntax-checking, we'll never end up
1647 actually marking thevariable as written. */
1648 if (flag_syntax_only)
1649 TREE_ASM_WRITTEN (vtbl) = 1;
1650 }
1651
1652 /* Since we'rewriting out the vtable here, also write the debug
1653 info. */
1654 note_debug_info_needed (ctype);
1655
1656 return true;
1657 }
Below function just tags the virtual function as addressable and setsin-used flag to indicate the compiler to emit code later. Remember CONSTRUCTORis always created for initializers of vtable, CONSTRUCTOR_ELTS in debug modecan do extra checking to ensure it’s indeed entity of CONSTRUCTOR and extractthe initializers for the vtables (refers to initialize_array in initialize_vtable or build_vtt. Alsorefers section Finishthe RECORD_TYPE – generate vtable for examples of initialziers).
1323 static void
1324 mark_vtable_entries (tree decl) in decl2.c
1325 {
1326 tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL(decl));
1327
1328 for (;entries; entries = TREE_CHAIN (entries))
1329 {
1330 tree fnaddr = TREE_VALUE (entries);
1331 tree fn;
1332
1333 STRIP_NOPS (fnaddr);
1334
1335 if (TREE_CODE (fnaddr) != ADDR_EXPR
1336 && TREE_CODE (fnaddr) !=FDESC_EXPR)
1337 /* This entryis an offset: a virtual base class offset, a
1338 virtual call offset, anRTTI offset, etc. */
1339 continue;
1340
1341 fn = TREE_OPERAND (fnaddr, 0);
1342 TREE_ADDRESSABLE (fn) = 1;
1343 /* When we don'thave vcall offsets, we output thunks whenever
1344 we output the vtables thatcontain them. With vcall offsets,
1345 we know all the thunks we'llneed when we emit a virtual
1346 function, so we emit thethunks there instead. */
1347 if (DECL_THUNK_P (fn))
1348 use_thunk (fn, /*emit_p=*/0);
1349 mark_used (fn);
1350 }
1351 }
Marks declas in-used can help compiler to remove useless code in later optimization. Theflag is set at line 2982 below. Then for unemitted inline method (generally,except in-charge constructor and destructor, inline method isn’t emitted yet.Considering inline method is defined in header file, which may be included byseveral files within the translation-unit, deferring its handling till the lastmoment is necessary. Though here the caller of mark_used is within the laststep of the process in front-end, however mark_used is called in many places in thefront-end), caches it by deferred_fns. At line 2991, assemble_externalis trivial for Linux on x86 machine. In previous section, we have seen thatcomipler may generate method artificially (for exmaple, cloned ctor and dctorin class), such method shouldn’t run itself but triggered by user definedmethod instead (referred by current_function_decl). If DECL_INITIAL is emptyat line 2998, it means the function has still not been proccessed by call sequence: start_function,begin_function_body,begin_compound_stmt|| finish_compound_stmt,finish_function_body,finish_function– that is not STMT node built for it and linked into STMT list of its triggeryet. Below synthesize_method invokes above mentioned call sequence to generatenecessary STMT nodes for the function, as if it comes from user declaration.Further, skip_evaluationat line 2983 was set by parser. In C++, there is case that no evalutaion of thedeclaration or expression is required, for example, within operator of sizeofor typeof.
2967 void
2968 mark_used (tree decl) in decl2.c
2969 {
2970 /* If DECL is aBASELINK for a single function, then treat it just
2971 like the DECL for thefunction. Otherwise, if the BASELINK is
2972 for an overloaded function, wedon't know which function was
2973 actually used until afteroverload resolution. */
2974 if (TREE_CODE (decl) == BASELINK)
2975 {
2976 decl = BASELINK_FUNCTIONS (decl);
2977 if (really_overloaded_fn (decl))
2978 return;
2979 decl = OVL_CURRENT (decl);
2980 }
2981
2982 TREE_USED (decl) = 1;
2983 if (processing_template_decl || skip_evaluation)
2984 return;
2985
2986 if (TREE_CODE (decl) ==FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
2987 && !TREE_ASM_WRITTEN (decl))
2988 /* Remember it, so we can check it wasdefined. */
2989 defer_fn (decl);
2990
2991 assemble_external (decl);
2992
2993 /* Is it asynthesized method that needs to be synthesized? */
2994 if (TREE_CODE (decl) == FUNCTION_DECL
2995 && DECL_NONSTATIC_MEMBER_FUNCTION_P(decl)
2996 && DECL_ARTIFICIAL (decl)
2997 && !DECL_THUNK_P (decl)
2998 && ! DECL_INITIAL (decl)
2999 /* Kludge:don't synthesize for default args. */
3000 && current_function_decl)
3001 {
3002 synthesize_method (decl);
3003 /* If we'vealready synthesized the method we don't need to
3004 instantiate it, so we can return rightaway. */
3005 return;
3006 }
3007
3008 /* If this is afunction or variable that is an instance of some
3009 template, we now know that wewill need to actually do the
3010 instantiation. We check thatDECL is not an explicit
3011 instantiation because that isnot checked in instantiate_decl. */
3012 if((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
3013 && DECL_LANG_SPECIFIC (decl)&& DECL_TEMPLATE_INFO (decl)
3014 && (!DECL_EXPLICIT_INSTANTIATION(decl)
3015 || (TREE_CODE (decl) == FUNCTION_DECL
3016 && DECL_INLINE(DECL_TEMPLATE_RESULT
3017 (template_for_substitution(decl))))))
3018 {
3019 bool defer;
3020
3021 /* Normally, weput off instantiating functions in order to
3022 improve compile times. Maintaininga stack of active
3023 functions is expensive, and the inliner knowsto
3024 instantiate any functions it might need.
3025
3026 However, if instantiating this function mighthelp us mark
3027 the current function TREE_NOTHROW, we go aheadand
3028 instantiate it now.
3029
3030 This is not needed for unit-at-a-time since wereorder the functions
3031 in topological order anyway.
3032 */
3033 defer = (!flag_exceptions
3034 || flag_unit_at_a_time
3035 || !optimize
3036 || TREE_CODE (decl) !=FUNCTION_DECL
3037 /* If thecalled function can't throw, we don't need to
3038 generate its body to find that out. */
3039 || TREE_NOTHROW (decl)
3040 || !cfun
3041 || !current_function_decl
3042 /* If wealready know the current function can't throw,
3043 then we don't need to work hard to proveit. */
3044 || TREE_NOTHROW (current_function_decl)
3045 /* If wealready know that the current function *can*
3046 throw, there's no point in gathering more
3047 information. */
3048 || cp_function_chain->can_throw);
3049
3050 instantiate_decl (decl, defer);
3051 }
3052 }
We have seen that thunk is a compiler generating function, it shouldalso be done with code emitted. However at this invocation, argument emit_pis false, as result, the function only marks the thunk as in-used and returnswithout really emitting code for it.
336 void
337 use_thunk (tree thunk_fndecl, boolemit_p) in method.c
338 {
339 tree function, alias;
340 tree virtual_offset;
341 HOST_WIDE_INT fixed_offset, virtual_value;
342 bool this_adjusting = DECL_THIS_THUNK_P(thunk_fndecl);
343
344 /* We should havecalled finish_thunk to give it a name. */
345 my_friendly_assert (DECL_NAME (thunk_fndecl),20021127);
346
347 /* We should neverbe using an alias, always refer to the
348 aliasedthunk. */
349 my_friendly_assert (!THUNK_ALIAS (thunk_fndecl),20031023);
350
351 if (TREE_ASM_WRITTEN (thunk_fndecl))
352 return;
353
354 function = THUNK_TARGET (thunk_fndecl);
355 if (DECL_RESULT (thunk_fndecl))
356 /* We alreadyturned this thunk into an ordinary function.
357 There's no need to process this thunkagain. */
358 return;
359
360 if (DECL_THUNK_P (function))
361 /* The target isitself a thunk, process it now. */
362 use_thunk(function, emit_p);
363
364 /* Thunks arealways addressable; they only appear in vtables. */
365 TREE_ADDRESSABLE (thunk_fndecl) = 1;
366
367 /* Figure out whatfunction is being thunked to. It's referenced in
368 this translationunit. */
369 TREE_ADDRESSABLE (function) = 1;
370 mark_used(function);
371 if (!emit_p)
372 return;
…
524 }
If the vtable is public and not shared across translation-units, neededis set at line 1592 in maybe_emit_vtables,then at line 1605, below function is invoked to set the needed flag of associatedcgraph_varpool_node.
568 void
569 cgraph_varpool_mark_needed_node (struct cgraph_varpool_node*node) in cgraph.c
570 {
571 if (!node->needed &&node->finalized)
572 {
573 node->next_needed = cgraph_varpool_nodes_queue;
574 cgraph_varpool_nodes_queue= node;
575 notice_global_symbol(node->decl);
576 }
577 node->needed = 1;
578 }
Next at line 1644 inmaybe_emit_vtables,rest_of_decl_compilationis invoked to try to build the RTL node according to the intermediate node andoutputs any assembler code (label definition, storage allocation andinitialization) if required. Here, argument top_level and at_end are both 1, and asmspec is NULL. Note that at line1957 ASM_FINISH_DECLARE_OBJECT is not defined for x86/Linux.
1910 void
1911 rest_of_decl_compilation (tree decl, in toplev.c
1912 constchar *asmspec,
1913 int top_level,
1914 int at_end)
1915 {
1916 /* We deferredcalling assemble_alias so that we could collect
1917 other attributes such asvisibility. Emit the alias now. */
1918 {
1919 tree alias;
1920 alias = lookup_attribute("alias", DECL_ATTRIBUTES (decl));
1921 if (alias)
1922 {
1923 alias = TREE_VALUE (TREE_VALUE (alias));
1924 alias = get_identifier(TREE_STRING_POINTER (alias));
1925 assemble_alias (decl, alias);
1926 }
1927 }
1928
1929 /* Forwarddeclarations for nested functions are not "external",
1930 but we need to treat them asif they were. */
1931 if (TREE_STATIC (decl) || DECL_EXTERNAL(decl)
1932 || TREE_CODE (decl) == FUNCTION_DECL)
1933 {
1934 timevar_push (TV_VARCONST);
1935
1936 if (asmspec)
1937 make_decl_rtl (decl, asmspec);
1938
1939 /* Don't outputanything when a tentative file-scope definition
1940 is seen. But at end of compilation,do output code for them.
1941
1942 We do output all variableswhen unit-at-a-time is active and rely on
1943 callgraph code to defer themexcept for forward declarations
1944 (seegcc.c-torture/compile/920624-1.c) */
1945 if ((at_end
1946 || !DECL_DEFER_OUTPUT (decl)
1947 || (flag_unit_at_a_time &&DECL_INITIAL (decl)))
1948 && !DECL_EXTERNAL (decl))
1949 {
1950 if (flag_unit_at_a_time && !cgraph_global_info_ready
1951 && TREE_CODE (decl) !=FUNCTION_DECL && top_level)
1952 cgraph_varpool_finalize_decl(decl);
1953 else
1954 assemble_variable (decl, top_level,at_end, 0);
1955 }
1956
1957 #ifdef ASM_FINISH_DECLARE_OBJECT
…
1963 #endif
1964
1965 timevar_pop (TV_VARCONST);
1966 }
1967 else if (DECL_REGISTER (decl) &&asmspec != 0)
1968 {
1969 if (decode_reg_name (asmspec) >= 0)
1970 {
1971 SET_DECL_RTL (decl, NULL_RTX);
1972 make_decl_rtl (decl, asmspec);
1973 }
1974 else
1975 {
1976 error ("invalid register name `%s'for register variable", asmspec);
1977 DECL_REGISTER (decl) = 0;
1978 if (!top_level)
1979 expand_decl (decl);
1980 }
1981 }
…
2011 }
At line 1950 cgraph_global_info_ready is nonzero when wholeunit has been analyzed, so we can access global information (it is still falseunder current situation). Also predicate DECL_DEFER_OUTPUT at line 1946, ifnonzero tells that the linkage status of this decl is not yet known, so it shouldnot be output now.
As vtable is a VAR_DECL, we invoke following function to set finializedflag of associated cgraph_varpool_node to indicate code to be output.
580 void
581 cgraph_varpool_finalize_decl (tree decl) in cgraph.c
582 {
583 structcgraph_varpool_node *node = cgraph_varpool_node(decl);
584
585 /* The firstdeclaration of a variable that comes through this function
586 decides whetherit is global (in C, has external linkage)
587 or local (in C,has internal linkage). So do nothing more
588 if this functionhas already run. */
589 if (node->finalized)
590 return;
591 if (node->needed)
592 {
593 node->next_needed = cgraph_varpool_nodes_queue;
594 cgraph_varpool_nodes_queue= node;
595 notice_global_symbol(decl);
596 }
597 node->finalized = true;
598
599 if (/* Externallyvisible variables must be output. The exception are
600 COMDATfunctions that must be output only when they are needed. */
601 (TREE_PUBLIC (decl) &&!DECL_COMDAT (decl))
602 /* Function whose name is output to theassembler file must be produced.
603 It ispossible to assemble the name later after finalizing the function
604 and the factis noticed in assemble_name then. */
605 || (DECL_ASSEMBLER_NAME_SET_P (decl)
606 && TREE_SYMBOL_REFERENCED(DECL_ASSEMBLER_NAME (decl))))
607 {
608 cgraph_varpool_mark_needed_node(node);
609 }
610 }
As at line 1605 inmaybe_emit_vtables,cgraph_varpool_mark_needed_nodehas been invoked for vtable that needs be output; for such vtable, neededflag of its cgraph node is true, and this node is linked into cgraph_varpool_nodes_queueagain here (see in cgraph_varpool_mark_needed_node at line 571,the condition for linking is “(!node->needed && node->finalized)”,if not added at that time, it is linked here); at line 608 the vtable isprocessed by cgraph_varpool_mark_needed_nodeagain, which is a measure to ensure the cgraph node to be linked into cgraph_varpool_nodes_queue.
Note that if maybe_emit_vtables processes the classsuccessfully, the class would be removed from keyed_classes, and forces nextiteration.
- Studying note of GCC-3.4.6 source (156)
- 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)
- 指针的指针--------二级指针(做一下总结,免得忘了)
- 【每天读一点英文】gnuhpc注释版:The True Nobility
- GCC-3.4.6源代码学习笔记(155)
- Studying note of GCC-3.4.6 source (155)
- GCC-3.4.6源代码学习笔记(156)
- Studying note of GCC-3.4.6 source (156)
- 【每天读一点英文】gnuhpc:The World As I See It(节选)
- 分形艺术网贺岁图集很有新意的新年礼物!
- 做事
- java的几种引用类型
- sql server image type
- 用Java语言编写一个绘图项目的完整过程
- 推荐书目 byr
- 关于java反射机制