123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- /* Utilities for ipa analysis.
- Copyright (C) 2004-2019 Free Software Foundation, Inc.
- Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #ifndef GCC_IPA_UTILS_H
- #define GCC_IPA_UTILS_H
- struct ipa_dfs_info {
- int dfn_number;
- int low_link;
- /* This field will have the samy value for any two nodes in the same strongly
- connected component. */
- int scc_no;
- bool new_node;
- bool on_stack;
- struct cgraph_node* next_cycle;
- PTR aux;
- };
- /* In ipa-utils.c */
- void ipa_print_order (FILE*, const char *, struct cgraph_node**, int);
- int ipa_reduced_postorder (struct cgraph_node **, bool,
- bool (*ignore_edge) (struct cgraph_edge *));
- void ipa_free_postorder_info (void);
- vec<cgraph_node *> ipa_get_nodes_in_cycle (struct cgraph_node *);
- bool ipa_edge_within_scc (struct cgraph_edge *);
- int ipa_reverse_postorder (struct cgraph_node **);
- tree get_base_var (tree);
- void ipa_merge_profiles (struct cgraph_node *dst,
- struct cgraph_node *src, bool preserve_body = false);
- bool recursive_call_p (tree, tree);
- /* In ipa-profile.c */
- bool ipa_propagate_frequency (struct cgraph_node *node);
- /* In ipa-devirt.c */
- struct odr_type_d;
- typedef odr_type_d *odr_type;
- void build_type_inheritance_graph (void);
- void rebuild_type_inheritance_graph (void);
- void update_type_inheritance_graph (void);
- vec <cgraph_node *>
- possible_polymorphic_call_targets (tree, HOST_WIDE_INT,
- ipa_polymorphic_call_context,
- bool *copletep = NULL,
- void **cache_token = NULL,
- bool speuclative = false);
- odr_type get_odr_type (tree, bool insert = false);
- bool odr_type_p (const_tree);
- bool possible_polymorphic_call_target_p (tree ref, gimple *stmt, struct cgraph_node *n);
- void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT,
- const ipa_polymorphic_call_context &,
- bool verbose = true);
- bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT,
- const ipa_polymorphic_call_context &,
- struct cgraph_node *);
- tree polymorphic_ctor_dtor_p (tree, bool);
- tree inlined_polymorphic_ctor_dtor_block_p (tree, bool);
- bool decl_maybe_in_construction_p (tree, tree, gimple *, tree);
- tree vtable_pointer_value_to_binfo (const_tree);
- bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *);
- tree subbinfo_with_vtable_at_offset (tree, unsigned HOST_WIDE_INT, tree);
- void compare_virtual_tables (varpool_node *, varpool_node *);
- bool type_all_derivations_known_p (const_tree);
- bool type_known_to_have_no_derivations_p (tree);
- bool contains_polymorphic_type_p (const_tree);
- void register_odr_type (tree);
- bool types_must_be_same_for_odr (tree, tree);
- bool types_odr_comparable (tree, tree);
- cgraph_node *try_speculative_devirtualization (tree, HOST_WIDE_INT,
- ipa_polymorphic_call_context);
- void warn_types_mismatch (tree t1, tree t2, location_t loc1 = UNKNOWN_LOCATION,
- location_t loc2 = UNKNOWN_LOCATION);
- bool odr_or_derived_type_p (const_tree t);
- bool odr_types_equivalent_p (tree type1, tree type2);
- bool odr_type_violation_reported_p (tree type);
- /* Return vector containing possible targets of polymorphic call E.
- If COMPLETEP is non-NULL, store true if the list is complete.
- CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry
- in the target cache. If user needs to visit every target list
- just once, it can memoize them.
- Returned vector is placed into cache. It is NOT caller's responsibility
- to free it. The vector can be freed on cgraph_remove_node call if
- the particular node is a virtual function present in the cache. */
- inline vec <cgraph_node *>
- possible_polymorphic_call_targets (struct cgraph_edge *e,
- bool *completep = NULL,
- void **cache_token = NULL,
- bool speculative = false)
- {
- ipa_polymorphic_call_context context(e);
- return possible_polymorphic_call_targets (e->indirect_info->otr_type,
- e->indirect_info->otr_token,
- context,
- completep, cache_token,
- speculative);
- }
- /* Same as above but taking OBJ_TYPE_REF as an parameter. */
- inline vec <cgraph_node *>
- possible_polymorphic_call_targets (tree ref,
- gimple *call,
- bool *completep = NULL,
- void **cache_token = NULL)
- {
- ipa_polymorphic_call_context context (current_function_decl, ref, call);
- return possible_polymorphic_call_targets (obj_type_ref_class (ref),
- tree_to_uhwi
- (OBJ_TYPE_REF_TOKEN (ref)),
- context,
- completep, cache_token);
- }
- /* Dump possible targets of a polymorphic call E into F. */
- inline void
- dump_possible_polymorphic_call_targets (FILE *f, struct cgraph_edge *e,
- bool verbose = true)
- {
- ipa_polymorphic_call_context context(e);
- dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type,
- e->indirect_info->otr_token,
- context, verbose);
- }
- /* Return true if N can be possibly target of a polymorphic call of
- E. */
- inline bool
- possible_polymorphic_call_target_p (struct cgraph_edge *e,
- struct cgraph_node *n)
- {
- ipa_polymorphic_call_context context(e);
- return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
- e->indirect_info->otr_token,
- context, n);
- }
- /* Return true if BINFO corresponds to a type with virtual methods.
- Every type has several BINFOs. One is the BINFO associated by the type
- while other represents bases of derived types. The BINFOs representing
- bases do not have BINFO_VTABLE pointer set when this is the single
- inheritance (because vtables are shared). Look up the BINFO of type
- and check presence of its vtable. */
- inline bool
- polymorphic_type_binfo_p (const_tree binfo)
- {
- return (BINFO_TYPE (binfo) && TYPE_BINFO (BINFO_TYPE (binfo))
- && BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (binfo))));
- }
- /* Return true if T is a type with linkage defined. */
- inline bool
- type_with_linkage_p (const_tree t)
- {
- gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
- if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
- return false;
- /* To support -fno-lto-odr-type-merigng recognize types with vtables
- to have linkage. */
- if (RECORD_OR_UNION_TYPE_P (t)
- && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)))
- return true;
- /* After free_lang_data was run and -flto-odr-type-merging we can recongize
- types with linkage by presence of mangled name. */
- if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
- return true;
- if (in_lto_p)
- return false;
- /* We used to check for TYPE_STUB_DECL but that is set to NULL for forward
- declarations. */
- if (!RECORD_OR_UNION_TYPE_P (t) && TREE_CODE (t) != ENUMERAL_TYPE)
- return false;
- /* Builtin types do not define linkage, their TYPE_CONTEXT is NULL. */
- if (!TYPE_CONTEXT (t))
- return false;
- return true;
- }
- /* Return true if T is in anonymous namespace.
- This works only on those C++ types with linkage defined. */
- inline bool
- type_in_anonymous_namespace_p (const_tree t)
- {
- gcc_checking_assert (type_with_linkage_p (t));
- /* free_lang_data clears TYPE_STUB_DECL but sets assembler name to
- "<anon>" */
- if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
- return !strcmp ("<anon>",
- IDENTIFIER_POINTER
- (DECL_ASSEMBLER_NAME (TYPE_NAME (t))));
- else if (!TYPE_STUB_DECL (t))
- return false;
- else
- return !TREE_PUBLIC (TYPE_STUB_DECL (t));
- }
- /* Return true of T is type with One Definition Rule info attached.
- It means that either it is anonymous type or it has assembler name
- set. */
- inline bool
- odr_type_p (const_tree t)
- {
- /* We do not have this information when not in LTO, but we do not need
- to care, since it is used only for type merging. */
- gcc_checking_assert (in_lto_p || flag_lto);
- if (!type_with_linkage_p (t))
- return false;
- /* To support -fno-lto-odr-type-merging consider types with vtables ODR. */
- if (type_in_anonymous_namespace_p (t))
- return true;
- if (TYPE_NAME (t) && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
- {
- /* C++ FE uses magic <anon> as assembler names of anonymous types.
- verify that this match with type_in_anonymous_namespace_p. */
- gcc_checking_assert (strcmp ("<anon>",
- IDENTIFIER_POINTER
- (DECL_ASSEMBLER_NAME (TYPE_NAME (t)))));
- return true;
- }
- return false;
- }
- #endif /* GCC_IPA_UTILS_H */
|