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