110d565efSmrg /* Utilities for ipa analysis.
2*ec02198aSmrg Copyright (C) 2004-2020 Free Software Foundation, Inc.
310d565efSmrg Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
410d565efSmrg
510d565efSmrg This file is part of GCC.
610d565efSmrg
710d565efSmrg GCC is free software; you can redistribute it and/or modify it under
810d565efSmrg the terms of the GNU General Public License as published by the Free
910d565efSmrg Software Foundation; either version 3, or (at your option) any later
1010d565efSmrg version.
1110d565efSmrg
1210d565efSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1310d565efSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1410d565efSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1510d565efSmrg for more details.
1610d565efSmrg
1710d565efSmrg You should have received a copy of the GNU General Public License
1810d565efSmrg along with GCC; see the file COPYING3. If not see
1910d565efSmrg <http://www.gnu.org/licenses/>. */
2010d565efSmrg
2110d565efSmrg #ifndef GCC_IPA_UTILS_H
2210d565efSmrg #define GCC_IPA_UTILS_H
2310d565efSmrg
2410d565efSmrg struct ipa_dfs_info {
2510d565efSmrg int dfn_number;
2610d565efSmrg int low_link;
2710d565efSmrg /* This field will have the samy value for any two nodes in the same strongly
2810d565efSmrg connected component. */
2910d565efSmrg int scc_no;
3010d565efSmrg bool new_node;
3110d565efSmrg bool on_stack;
3210d565efSmrg struct cgraph_node* next_cycle;
3310d565efSmrg PTR aux;
3410d565efSmrg };
3510d565efSmrg
3610d565efSmrg
3710d565efSmrg /* In ipa-utils.c */
3810d565efSmrg void ipa_print_order (FILE*, const char *, struct cgraph_node**, int);
3921ff1670Smrg int ipa_reduced_postorder (struct cgraph_node **, bool,
4010d565efSmrg bool (*ignore_edge) (struct cgraph_edge *));
4110d565efSmrg void ipa_free_postorder_info (void);
4210d565efSmrg vec<cgraph_node *> ipa_get_nodes_in_cycle (struct cgraph_node *);
4310d565efSmrg bool ipa_edge_within_scc (struct cgraph_edge *);
4410d565efSmrg int ipa_reverse_postorder (struct cgraph_node **);
4510d565efSmrg tree get_base_var (tree);
4610d565efSmrg void ipa_merge_profiles (struct cgraph_node *dst,
4710d565efSmrg struct cgraph_node *src, bool preserve_body = false);
4810d565efSmrg bool recursive_call_p (tree, tree);
4910d565efSmrg
5010d565efSmrg /* In ipa-profile.c */
5110d565efSmrg bool ipa_propagate_frequency (struct cgraph_node *node);
5210d565efSmrg
5310d565efSmrg /* In ipa-devirt.c */
5410d565efSmrg
5510d565efSmrg struct odr_type_d;
5610d565efSmrg typedef odr_type_d *odr_type;
57*ec02198aSmrg extern bool thunk_expansion;
5810d565efSmrg void build_type_inheritance_graph (void);
59c7a68eb7Smrg void rebuild_type_inheritance_graph (void);
6010d565efSmrg void update_type_inheritance_graph (void);
6110d565efSmrg vec <cgraph_node *>
6210d565efSmrg possible_polymorphic_call_targets (tree, HOST_WIDE_INT,
6310d565efSmrg ipa_polymorphic_call_context,
6410d565efSmrg bool *copletep = NULL,
6510d565efSmrg void **cache_token = NULL,
6610d565efSmrg bool speuclative = false);
6710d565efSmrg odr_type get_odr_type (tree, bool insert = false);
6810d565efSmrg bool odr_type_p (const_tree);
6910d565efSmrg bool possible_polymorphic_call_target_p (tree ref, gimple *stmt, struct cgraph_node *n);
7010d565efSmrg void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT,
710fc04c29Smrg const ipa_polymorphic_call_context &,
720fc04c29Smrg bool verbose = true);
7310d565efSmrg bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT,
7410d565efSmrg const ipa_polymorphic_call_context &,
7510d565efSmrg struct cgraph_node *);
7610d565efSmrg tree polymorphic_ctor_dtor_p (tree, bool);
7710d565efSmrg tree inlined_polymorphic_ctor_dtor_block_p (tree, bool);
7810d565efSmrg bool decl_maybe_in_construction_p (tree, tree, gimple *, tree);
7910d565efSmrg tree vtable_pointer_value_to_binfo (const_tree);
8010d565efSmrg bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *);
8110d565efSmrg tree subbinfo_with_vtable_at_offset (tree, unsigned HOST_WIDE_INT, tree);
8210d565efSmrg void compare_virtual_tables (varpool_node *, varpool_node *);
8310d565efSmrg bool type_all_derivations_known_p (const_tree);
8410d565efSmrg bool type_known_to_have_no_derivations_p (tree);
8510d565efSmrg bool contains_polymorphic_type_p (const_tree);
8610d565efSmrg void register_odr_type (tree);
8710d565efSmrg bool types_must_be_same_for_odr (tree, tree);
880fc04c29Smrg bool types_odr_comparable (tree, tree);
8910d565efSmrg cgraph_node *try_speculative_devirtualization (tree, HOST_WIDE_INT,
9010d565efSmrg ipa_polymorphic_call_context);
9110d565efSmrg void warn_types_mismatch (tree t1, tree t2, location_t loc1 = UNKNOWN_LOCATION,
9210d565efSmrg location_t loc2 = UNKNOWN_LOCATION);
9310d565efSmrg bool odr_or_derived_type_p (const_tree t);
9410d565efSmrg bool odr_types_equivalent_p (tree type1, tree type2);
950fc04c29Smrg bool odr_type_violation_reported_p (tree type);
96*ec02198aSmrg tree prevailing_odr_type (tree type);
97*ec02198aSmrg void enable_odr_based_tbaa (tree type);
98*ec02198aSmrg bool odr_based_tbaa_p (const_tree type);
99*ec02198aSmrg void set_type_canonical_for_odr_type (tree type, tree canonical);
100*ec02198aSmrg
101*ec02198aSmrg void register_odr_enum (tree type);
10210d565efSmrg
10310d565efSmrg /* Return vector containing possible targets of polymorphic call E.
10410d565efSmrg If COMPLETEP is non-NULL, store true if the list is complete.
10510d565efSmrg CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry
10610d565efSmrg in the target cache. If user needs to visit every target list
10710d565efSmrg just once, it can memoize them.
10810d565efSmrg
10910d565efSmrg Returned vector is placed into cache. It is NOT caller's responsibility
11010d565efSmrg to free it. The vector can be freed on cgraph_remove_node call if
11110d565efSmrg the particular node is a virtual function present in the cache. */
11210d565efSmrg
11310d565efSmrg inline vec <cgraph_node *>
11410d565efSmrg possible_polymorphic_call_targets (struct cgraph_edge *e,
11510d565efSmrg bool *completep = NULL,
11610d565efSmrg void **cache_token = NULL,
11710d565efSmrg bool speculative = false)
11810d565efSmrg {
11910d565efSmrg ipa_polymorphic_call_context context(e);
12010d565efSmrg
12110d565efSmrg return possible_polymorphic_call_targets (e->indirect_info->otr_type,
12210d565efSmrg e->indirect_info->otr_token,
12310d565efSmrg context,
12410d565efSmrg completep, cache_token,
12510d565efSmrg speculative);
12610d565efSmrg }
12710d565efSmrg
12810d565efSmrg /* Same as above but taking OBJ_TYPE_REF as an parameter. */
12910d565efSmrg
13010d565efSmrg inline vec <cgraph_node *>
13110d565efSmrg possible_polymorphic_call_targets (tree ref,
13210d565efSmrg gimple *call,
13310d565efSmrg bool *completep = NULL,
13410d565efSmrg void **cache_token = NULL)
13510d565efSmrg {
13610d565efSmrg ipa_polymorphic_call_context context (current_function_decl, ref, call);
13710d565efSmrg
13810d565efSmrg return possible_polymorphic_call_targets (obj_type_ref_class (ref),
13910d565efSmrg tree_to_uhwi
14010d565efSmrg (OBJ_TYPE_REF_TOKEN (ref)),
14110d565efSmrg context,
14210d565efSmrg completep, cache_token);
14310d565efSmrg }
14410d565efSmrg
14510d565efSmrg /* Dump possible targets of a polymorphic call E into F. */
14610d565efSmrg
14710d565efSmrg inline void
1480fc04c29Smrg dump_possible_polymorphic_call_targets (FILE *f, struct cgraph_edge *e,
1490fc04c29Smrg bool verbose = true)
15010d565efSmrg {
15110d565efSmrg ipa_polymorphic_call_context context(e);
15210d565efSmrg
15310d565efSmrg dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type,
15410d565efSmrg e->indirect_info->otr_token,
1550fc04c29Smrg context, verbose);
15610d565efSmrg }
15710d565efSmrg
15810d565efSmrg /* Return true if N can be possibly target of a polymorphic call of
15910d565efSmrg E. */
16010d565efSmrg
16110d565efSmrg inline bool
possible_polymorphic_call_target_p(struct cgraph_edge * e,struct cgraph_node * n)16210d565efSmrg possible_polymorphic_call_target_p (struct cgraph_edge *e,
16310d565efSmrg struct cgraph_node *n)
16410d565efSmrg {
16510d565efSmrg ipa_polymorphic_call_context context(e);
16610d565efSmrg
16710d565efSmrg return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
16810d565efSmrg e->indirect_info->otr_token,
16910d565efSmrg context, n);
17010d565efSmrg }
17110d565efSmrg
17210d565efSmrg /* Return true if BINFO corresponds to a type with virtual methods.
17310d565efSmrg
17410d565efSmrg Every type has several BINFOs. One is the BINFO associated by the type
17510d565efSmrg while other represents bases of derived types. The BINFOs representing
17610d565efSmrg bases do not have BINFO_VTABLE pointer set when this is the single
17710d565efSmrg inheritance (because vtables are shared). Look up the BINFO of type
17810d565efSmrg and check presence of its vtable. */
17910d565efSmrg
18010d565efSmrg inline bool
polymorphic_type_binfo_p(const_tree binfo)18110d565efSmrg polymorphic_type_binfo_p (const_tree binfo)
18210d565efSmrg {
18310d565efSmrg return (BINFO_TYPE (binfo) && TYPE_BINFO (BINFO_TYPE (binfo))
18410d565efSmrg && BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (binfo))));
18510d565efSmrg }
18610d565efSmrg
18710d565efSmrg /* Return true if T is a type with linkage defined. */
18810d565efSmrg
18910d565efSmrg inline bool
type_with_linkage_p(const_tree t)19010d565efSmrg type_with_linkage_p (const_tree t)
19110d565efSmrg {
1920fc04c29Smrg gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
1930fc04c29Smrg if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
19410d565efSmrg return false;
1950fc04c29Smrg
196*ec02198aSmrg /* After free_lang_data was run we can recongize
1970fc04c29Smrg types with linkage by presence of mangled name. */
1980fc04c29Smrg if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
1990fc04c29Smrg return true;
2000fc04c29Smrg
2010fc04c29Smrg if (in_lto_p)
2020fc04c29Smrg return false;
203*ec02198aSmrg
2040fc04c29Smrg /* We used to check for TYPE_STUB_DECL but that is set to NULL for forward
2050fc04c29Smrg declarations. */
20610d565efSmrg
20710d565efSmrg if (!RECORD_OR_UNION_TYPE_P (t) && TREE_CODE (t) != ENUMERAL_TYPE)
20810d565efSmrg return false;
20910d565efSmrg
21010d565efSmrg /* Builtin types do not define linkage, their TYPE_CONTEXT is NULL. */
21110d565efSmrg if (!TYPE_CONTEXT (t))
21210d565efSmrg return false;
21310d565efSmrg
214*ec02198aSmrg gcc_checking_assert (TREE_CODE (t) == ENUMERAL_TYPE || TYPE_CXX_ODR_P (t));
215*ec02198aSmrg
21610d565efSmrg return true;
21710d565efSmrg }
21810d565efSmrg
21910d565efSmrg /* Return true if T is in anonymous namespace.
22010d565efSmrg This works only on those C++ types with linkage defined. */
22110d565efSmrg
22210d565efSmrg inline bool
type_in_anonymous_namespace_p(const_tree t)22310d565efSmrg type_in_anonymous_namespace_p (const_tree t)
22410d565efSmrg {
22510d565efSmrg gcc_checking_assert (type_with_linkage_p (t));
22610d565efSmrg
2270fc04c29Smrg /* free_lang_data clears TYPE_STUB_DECL but sets assembler name to
2280fc04c29Smrg "<anon>" */
2290fc04c29Smrg if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
2300fc04c29Smrg return !strcmp ("<anon>",
23110d565efSmrg IDENTIFIER_POINTER
2320fc04c29Smrg (DECL_ASSEMBLER_NAME (TYPE_NAME (t))));
2330fc04c29Smrg else if (!TYPE_STUB_DECL (t))
23410d565efSmrg return false;
2350fc04c29Smrg else
2360fc04c29Smrg return !TREE_PUBLIC (TYPE_STUB_DECL (t));
23710d565efSmrg }
23810d565efSmrg
23910d565efSmrg /* Return true of T is type with One Definition Rule info attached.
24010d565efSmrg It means that either it is anonymous type or it has assembler name
24110d565efSmrg set. */
24210d565efSmrg
24310d565efSmrg inline bool
odr_type_p(const_tree t)24410d565efSmrg odr_type_p (const_tree t)
24510d565efSmrg {
24610d565efSmrg /* We do not have this information when not in LTO, but we do not need
24710d565efSmrg to care, since it is used only for type merging. */
248*ec02198aSmrg gcc_checking_assert (in_lto_p || flag_lto || flag_generate_offload);
249*ec02198aSmrg return TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
250*ec02198aSmrg && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t));
25110d565efSmrg }
252*ec02198aSmrg
253*ec02198aSmrg /* If TYPE has mangled ODR name, return it. Otherwise return NULL.
254*ec02198aSmrg The function works only when free_lang_data is run. */
255*ec02198aSmrg
256*ec02198aSmrg inline const char *
get_odr_name_for_type(tree type)257*ec02198aSmrg get_odr_name_for_type (tree type)
258*ec02198aSmrg {
259*ec02198aSmrg tree type_name = TYPE_NAME (type);
260*ec02198aSmrg if (type_name == NULL_TREE
261*ec02198aSmrg || TREE_CODE (type_name) != TYPE_DECL
262*ec02198aSmrg || !DECL_ASSEMBLER_NAME_SET_P (type_name))
263*ec02198aSmrg return NULL;
264*ec02198aSmrg
265*ec02198aSmrg return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (type_name));
26610d565efSmrg }
26710d565efSmrg
26810d565efSmrg #endif /* GCC_IPA_UTILS_H */
269