1 /* Basic IPA utilities for type inheritance graph construction and
3 Copyright (C) 2013 Free Software Foundation, Inc.
4 Contributed by Jan Hubicka
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
23 ODR = One Definition Rule
24 In short, the ODR states that:
25 1 In any translation unit, a template, type, function, or object can
26 have no more than one definition. Some of these can have any number
27 of declarations. A definition provides an instance.
28 2 In the entire program, an object or non-inline function cannot have
29 more than one definition; if an object or function is used, it must
30 have exactly one definition. You can declare an object or function
31 that is never used, in which case you don't have to provide
32 a definition. In no event can there be more than one definition.
33 3 Some things, like types, templates, and extern inline functions, can
34 be defined in more than one translation unit. For a given entity,
35 each definition must be the same. Non-extern objects and functions
36 in different translation units are different entities, even if their
37 names and types are the same.
40 This is Gimple representation of type information of a polymorphic call.
41 It contains two parameters:
42 otr_type is a type of class whose method is called.
43 otr_token is index into virtual table where address is taken.
46 This is the type inheritance information attached to each tree
47 RECORD_TYPE by the C++ frotend. It provides information about base
48 types and virtual tables.
50 BINFO is linked to the RECORD_TYPE by TYPE_BINFO.
51 BINFO also links to its type by BINFO_TYPE and to the virtual table by
54 Base types of a given type are enumerated by BINFO_BASE_BINFO
55 vector. Members of this vectors are not BINFOs associated
56 with a base type. Rather they are new copies of BINFOs
57 (base BINFOs). Their virtual tables may differ from
58 virtual table of the base type. Also BINFO_OFFSET specify
59 offset of the base within the type.
61 In the case of single inheritance, the virtual table is shared
62 and BINFO_VTABLE of base BINFO is NULL. In the case of multiple
63 inheritance the individual virtual tables are pointer to by
64 BINFO_VTABLE of base binfos (that differs of BINFO_VTABLE of
65 binfo associated to the base type).
67 BINFO lookup for a given base type and offset can be done by
68 get_binfo_at_offset. It returns proper BINFO whose virtual table
69 can be used for lookup of virtual methods associated with the
73 This is an index of virtual method in virtual table associated
74 to the type defining it. Token can be looked up from OBJ_TYPE_REF
75 or from DECL_VINDEX of given virtual table.
77 polymorphic (indirect) call
78 This is callgraph represention of virtual method call. Every
79 polymorphic call contains otr_type and otr_token taken from
80 original OBJ_TYPE_REF at callgraph construction time.
84 build_type_inheritance_graph triggers a construction of the type inheritance
87 We reconstruct it based on types of methods we see in the unit.
88 This means that the graph is not complete. Types with no methods are not
89 inserted to the graph. Also types without virtual methods are not
90 represented at all, though it may be easy to add this.
92 The inheritance graph is represented as follows:
94 Vertices are structures odr_type. Every odr_type may correspond
95 to one or more tree type nodes that are equivalent by ODR rule.
96 (the multiple type nodes appear only with linktime optimization)
98 Edges are repsented by odr_type->base and odr_type->derived_types.
99 At the moment we do not track offsets of types for multiple inheritance.
102 possible_polymorphic_call_targets returns, given an parameters found in
103 indirect polymorphic edge all possible polymorphic call targets of the call.
108 #include "coretypes.h"
111 #include "tree-pass.h"
113 #include "pointer-set.h"
115 #include "hash-table.h"
116 #include "tree-pretty-print.h"
117 #include "ipa-utils.h"
120 /* The node of type inheritance graph. For each type unique in
121 One Defintion Rule (ODR) sense, we produce one node linking all
122 main variants of types equivalent to it, bases and derived types. */
124 struct GTY(()) odr_type_d
126 /* Unique ID indexing the type in odr_types array. */
131 vec
<odr_type
> GTY((skip
)) bases
;
132 /* All derrived types with virtual methods seen in unit. */
133 vec
<odr_type
> GTY((skip
)) derived_types
;
134 /* Is it in anonymous namespace? */
135 bool anonymous_namespace
;
139 /* Return true if BINFO corresponds to a type with virtual methods. */
142 polymorphic_type_binfo_p (tree binfo
)
144 /* See if BINFO's type has an virtual table associtated with it. */
145 return BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (binfo
)));
148 /* One Definition Rule hashtable helpers. */
152 typedef odr_type_d value_type
;
153 typedef union tree_node compare_type
;
154 static inline hashval_t
hash (const value_type
*);
155 static inline bool equal (const value_type
*, const compare_type
*);
156 static inline void remove (value_type
*);
159 /* Produce hash based on type name. */
162 hash_type_name (tree t
)
164 gcc_checking_assert (TYPE_MAIN_VARIANT (t
) == t
);
166 /* If not in LTO, all main variants are unique, so we can do
169 return htab_hash_pointer (t
);
171 /* Anonymous types are unique. */
172 if (type_in_anonymous_namespace_p (t
))
173 return htab_hash_pointer (t
);
175 /* Rest is not implemented yet. */
179 /* Return the computed hashcode for ODR_TYPE. */
182 odr_hasher::hash (const value_type
*odr_type
)
184 return hash_type_name (odr_type
->type
);
187 /* Compare types operations T1 and T2 and return true if they are
191 odr_hasher::equal (const value_type
*t1
, const compare_type
*ct2
)
193 tree t2
= const_cast <tree
> (ct2
);
195 gcc_checking_assert (TYPE_MAIN_VARIANT (ct2
) == ct2
);
200 return types_same_for_odr (t1
->type
, t2
);
203 /* Free a phi operation structure VP. */
206 odr_hasher::remove (value_type
*v
)
209 v
->derived_types
.release ();
213 /* ODR type hash used to lookup ODR type based on tree type node. */
215 typedef hash_table
<odr_hasher
> odr_hash_type
;
216 static odr_hash_type odr_hash
;
218 /* ODR types are also stored into ODR_TYPE vector to allow consistent
219 walking. Bases appear before derived types. Vector is garbage collected
220 so we won't end up visiting empty types. */
222 static GTY(()) vec
<odr_type
, va_gc
> *odr_types_ptr
;
223 #define odr_types (*odr_types_ptr)
225 /* Get ODR type hash entry for TYPE. If INSERT is true, create
226 possibly new entry. */
229 get_odr_type (tree type
, bool insert
)
235 type
= TYPE_MAIN_VARIANT (type
);
236 gcc_checking_assert (TYPE_MAIN_VARIANT (type
) == type
);
237 hash
= hash_type_name (type
);
238 slot
= odr_hash
.find_slot_with_hash (type
, hash
, insert
? INSERT
: NO_INSERT
);
242 /* See if we already have entry for type. */
247 /* With LTO we will need to support multiple tree representation of
248 the same ODR type. For now we ignore this. */
249 if (val
->type
== type
)
255 tree binfo
= TYPE_BINFO (type
);
258 val
= ggc_alloc_cleared_odr_type_d ();
261 val
->derived_types
= vNULL
;
263 for (i
= 0; i
< BINFO_N_BASE_BINFOS (binfo
); i
++)
264 /* For now record only polymorphic types. other are
265 pointless for devirtualization and we can not precisely
266 determine ODR equivalency of these during LTO. */
267 if (polymorphic_type_binfo_p (BINFO_BASE_BINFO (binfo
, i
)))
269 odr_type base
= get_odr_type (BINFO_TYPE (BINFO_BASE_BINFO (binfo
,
272 base
->derived_types
.safe_push (val
);
273 val
->bases
.safe_push (base
);
275 /* First record bases, then add into array so ids are increasing. */
277 val
->id
= odr_types
.length();
278 vec_safe_push (odr_types_ptr
, val
);
283 /* Dump ODR type T and all its derrived type. INDENT specify indentation for
284 recusive printing. */
287 dump_odr_type (FILE *f
, odr_type t
, int indent
=0)
290 fprintf (f
, "%*s type %i: ", indent
* 2, "", t
->id
);
291 print_generic_expr (f
, t
->type
, TDF_SLIM
);
293 if (TYPE_NAME (t
->type
))
295 fprintf (f
, "%*s defined at: %s:%i\n", indent
* 2, "",
296 DECL_SOURCE_FILE (TYPE_NAME (t
->type
)),
297 DECL_SOURCE_LINE (TYPE_NAME (t
->type
)));
299 if (t
->bases
.length())
301 fprintf (f
, "%*s base odr type ids: ", indent
* 2, "");
302 for (i
= 0; i
< t
->bases
.length(); i
++)
303 fprintf (f
, " %i", t
->bases
[i
]->id
);
306 if (t
->derived_types
.length())
308 fprintf (f
, "%*s derived types:\n", indent
* 2, "");
309 for (i
= 0; i
< t
->derived_types
.length(); i
++)
310 dump_odr_type (f
, t
->derived_types
[i
], indent
+ 1);
315 /* Dump the type inheritance graph. */
318 dump_type_inheritance_graph (FILE *f
)
321 fprintf (f
, "\n\nType inheritance graph:\n");
322 for (i
= 0; i
< odr_types
.length(); i
++)
324 if (odr_types
[i
]->bases
.length() == 0)
325 dump_odr_type (f
, odr_types
[i
]);
329 /* Given method type T, return type of class it belongs to.
330 Lookup this pointer and get its type. */
333 method_class_type (tree t
)
335 tree first_parm_type
= TREE_VALUE (TYPE_ARG_TYPES (t
));
337 return TREE_TYPE (first_parm_type
);
340 /* Initialize IPA devirt and build inheritance tree graph. */
343 build_type_inheritance_graph (void)
345 struct cgraph_node
*n
;
346 FILE *inheritance_dump_file
;
349 if (odr_hash
.is_created ())
351 timevar_push (TV_IPA_INHERITANCE
);
352 inheritance_dump_file
= dump_begin (TDI_inheritance
, &flags
);
353 odr_hash
.create (23);
355 /* We reconstruct the graph starting of types of all methods seen in the
357 FOR_EACH_FUNCTION (n
)
358 if (DECL_VIRTUAL_P (n
->symbol
.decl
)
359 && symtab_real_symbol_p ((symtab_node
)n
))
360 get_odr_type (method_class_type (TREE_TYPE (n
->symbol
.decl
)), true);
361 if (inheritance_dump_file
)
363 dump_type_inheritance_graph (inheritance_dump_file
);
364 dump_end (TDI_inheritance
, inheritance_dump_file
);
366 timevar_pop (TV_IPA_INHERITANCE
);
369 /* If TARGET has associated node, record it in the NODES array. */
372 maybe_record_node (vec
<cgraph_node
*> &nodes
,
373 tree target
, pointer_set_t
*inserted
)
375 struct cgraph_node
*target_node
;
376 enum built_in_function fcode
;
379 /* Those are used to mark impossible scenarios. */
380 && (fcode
= DECL_FUNCTION_CODE (target
))
381 != BUILT_IN_UNREACHABLE
382 && fcode
!= BUILT_IN_TRAP
383 && !pointer_set_insert (inserted
, target
)
384 && (target_node
= cgraph_get_node (target
)) != NULL
385 && symtab_real_symbol_p ((symtab_node
)target_node
))
386 nodes
.safe_push (target_node
);
389 /* See if BINFO's type match OTR_TYPE. If so, lookup method
390 in vtable of TYPE_BINFO and insert method to NODES array.
391 Otherwise recurse to base BINFOs.
392 This match what get_binfo_at_offset does, but with offset
395 TYPE_BINFO is binfo holding an virtual table matching
396 BINFO's type. In the case of single inheritance, this
397 is binfo of BINFO's type ancestor (vtable is shared),
398 otherwise it is binfo of BINFO's type.
400 MATCHED_VTABLES tracks virtual tables we already did lookup
401 for virtual function in.
405 record_binfo (vec
<cgraph_node
*> &nodes
,
409 HOST_WIDE_INT otr_token
,
410 pointer_set_t
*inserted
,
411 pointer_set_t
*matched_vtables
)
413 tree type
= BINFO_TYPE (binfo
);
417 gcc_checking_assert (BINFO_VTABLE (type_binfo
));
419 if (types_same_for_odr (type
, otr_type
)
420 && !pointer_set_insert (matched_vtables
, BINFO_VTABLE (type_binfo
)))
422 tree target
= gimple_get_virt_method_for_binfo (otr_token
, type_binfo
);
424 maybe_record_node (nodes
, target
, inserted
);
429 for (i
= 0; BINFO_BASE_ITERATE (binfo
, i
, base_binfo
); i
++)
430 /* Walking bases that have no virtual method is pointless excercise. */
431 if (polymorphic_type_binfo_p (base_binfo
))
432 record_binfo (nodes
, base_binfo
, otr_type
,
433 BINFO_VTABLE (base_binfo
) ? base_binfo
: type_binfo
,
438 /* Lookup virtual methods matching OTR_TYPE (with OFFSET and OTR_TOKEN)
439 of TYPE, insert them to NODES, recurse into derived nodes.
440 INSERTED is used to avoid duplicate insertions of methods into NODES.
441 MATCHED_VTABLES are used to avoid duplicate walking vtables. */
444 possible_polymorphic_call_targets_1 (vec
<cgraph_node
*> &nodes
,
445 pointer_set_t
*inserted
,
446 pointer_set_t
*matched_vtables
,
449 HOST_WIDE_INT otr_token
)
451 tree binfo
= TYPE_BINFO (type
->type
);
454 record_binfo (nodes
, binfo
, otr_type
, binfo
, otr_token
, inserted
,
456 for (i
= 0; i
< type
->derived_types
.length(); i
++)
457 possible_polymorphic_call_targets_1 (nodes
, inserted
,
460 type
->derived_types
[i
],
464 /* Cache of queries for polymorphic call targets.
466 Enumerating all call targets may get expensive when there are many
467 polymorphic calls in the program, so we memoize all the previous
468 queries and avoid duplicated work. */
470 struct polymorphic_call_target_d
473 HOST_WIDE_INT otr_token
;
474 vec
<cgraph_node
*> targets
;
477 /* Polymorphic call target cache helpers. */
479 struct polymorphic_call_target_hasher
481 typedef polymorphic_call_target_d value_type
;
482 typedef polymorphic_call_target_d compare_type
;
483 static inline hashval_t
hash (const value_type
*);
484 static inline bool equal (const value_type
*, const compare_type
*);
485 static inline void remove (value_type
*);
488 /* Return the computed hashcode for ODR_QUERY. */
491 polymorphic_call_target_hasher::hash (const value_type
*odr_query
)
493 return iterative_hash_hashval_t (odr_query
->type
->id
,
494 odr_query
->otr_token
);
497 /* Compare cache entries T1 and T2. */
500 polymorphic_call_target_hasher::equal (const value_type
*t1
,
501 const compare_type
*t2
)
503 return t1
->type
== t2
->type
&& t1
->otr_token
== t2
->otr_token
;
506 /* Remove entry in polymorphic call target cache hash. */
509 polymorphic_call_target_hasher::remove (value_type
*v
)
511 v
->targets
.release ();
515 /* Polymorphic call target query cache. */
517 typedef hash_table
<polymorphic_call_target_hasher
>
518 polymorphic_call_target_hash_type
;
519 static polymorphic_call_target_hash_type polymorphic_call_target_hash
;
520 pointer_set_t
*cached_polymorphic_call_targets
;
522 /* Destroy polymorphic call target query cache. */
525 free_polymorphic_call_targets_hash ()
527 polymorphic_call_target_hash
.dispose ();
528 pointer_set_destroy (cached_polymorphic_call_targets
);
529 cached_polymorphic_call_targets
= NULL
;
532 /* When virtual function is removed, we may need to flush the cache. */
535 devirt_node_removal_hook (struct cgraph_node
*n
, void *d ATTRIBUTE_UNUSED
)
537 if (pointer_set_contains (cached_polymorphic_call_targets
, n
))
538 free_polymorphic_call_targets_hash ();
541 /* Return vector containing possible targets of polymorphic call of type
542 OTR_TYPE caling method OTR_TOKEN with OFFSET. If FINALp is non-NULL,
543 store true if the list is complette.
544 CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry
545 in the target cache. If user needs to visit every target list
546 just once, it can memoize them.
548 Returned vector is placed into cache. It is NOT caller's responsibility
549 to free it. The vector can be freed on cgraph_remove_node call if
550 the particular node is a virtual function present in the cache. */
553 possible_polymorphic_call_targets (tree otr_type
,
554 HOST_WIDE_INT otr_token
,
558 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
559 pointer_set_t
*inserted
;
560 pointer_set_t
*matched_vtables
;
561 vec
<cgraph_node
*> nodes
=vNULL
;
563 polymorphic_call_target_d key
;
564 polymorphic_call_target_d
**slot
;
571 type
= get_odr_type (otr_type
, false);
572 /* If we do not have type in our hash it means we never seen any method
577 /* For anonymous namespace types we can attempt to build full type.
578 All derivations must be in this unit. */
579 if (type
->anonymous_namespace
&& finalp
&& !flag_ltrans
)
582 /* Initialize query cache. */
583 if (!cached_polymorphic_call_targets
)
585 cached_polymorphic_call_targets
= pointer_set_create ();
586 polymorphic_call_target_hash
.create (23);
587 if (!node_removal_hook_holder
)
588 node_removal_hook_holder
=
589 cgraph_add_node_removal_hook (&devirt_node_removal_hook
, NULL
);
592 /* Lookup cached answer. */
594 key
.otr_token
= otr_token
;
595 slot
= polymorphic_call_target_hash
.find_slot (&key
, INSERT
);
597 *cache_token
= (void *)*slot
;
599 return (*slot
)->targets
;
601 /* Do actual search. */
602 timevar_push (TV_IPA_VIRTUAL_CALL
);
603 *slot
= XCNEW (polymorphic_call_target_d
);
605 *cache_token
= (void *)*slot
;
606 (*slot
)->type
= type
;
607 (*slot
)->otr_token
= otr_token
;
609 inserted
= pointer_set_create ();
610 matched_vtables
= pointer_set_create ();
612 /* First see virtual method of type itself. */
614 binfo
= TYPE_BINFO (type
->type
);
615 target
= gimple_get_virt_method_for_binfo (otr_token
, binfo
);
617 maybe_record_node (nodes
, target
, inserted
);
618 pointer_set_insert (matched_vtables
, BINFO_VTABLE (binfo
));
620 /* TODO: If method is final, we can stop here and signaize that
621 list is final. We need C++ FE to pass our info about final
622 methods and classes. */
624 /* Walk recursively all derived types. Here we need to lookup proper basetype
625 via their BINFO walk that is done by record_binfo */
626 for (i
= 0; i
< type
->derived_types
.length(); i
++)
627 possible_polymorphic_call_targets_1 (nodes
, inserted
,
629 otr_type
, type
->derived_types
[i
],
631 (*slot
)->targets
= nodes
;
633 pointer_set_destroy (inserted
);
634 pointer_set_destroy (matched_vtables
);
635 timevar_pop (TV_IPA_VIRTUAL_CALL
);
639 /* Dump all possible targets of a polymorphic call. */
642 dump_possible_polymorphic_call_targets (FILE *f
,
644 HOST_WIDE_INT otr_token
)
646 vec
<cgraph_node
*> targets
;
648 odr_type type
= get_odr_type (otr_type
, false);
653 targets
= possible_polymorphic_call_targets (otr_type
, otr_token
,
655 fprintf (f
, "Targets of polymorphic call of type %i ", type
->id
);
656 print_generic_expr (f
, type
->type
, TDF_SLIM
);
657 fprintf (f
, " token %i%s:",
659 final
? " (full list)" : " (partial list, may call to other unit)");
660 for (i
= 0; i
< targets
.length (); i
++)
661 fprintf (f
, " %s/%i", cgraph_node_name (targets
[i
]),
662 targets
[i
]->symbol
.order
);
666 #include "gt-ipa-devirt.h"