/* Utilities for ipa analysis.
- Copyright (C) 2004-2014 Free Software Foundation, Inc.
+ Copyright (C) 2004-2015 Free Software Foundation, Inc.
Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
This file is part of GCC.
#ifndef GCC_IPA_UTILS_H
#define GCC_IPA_UTILS_H
-#include "cgraph.h"
struct ipa_dfs_info {
int dfn_number;
PTR aux;
};
-/* Context of polymorphic call. This is used by ipa-devirt walkers of the
- type inheritance graph. */
-
-class ipa_polymorphic_call_context {
-public:
- /* The called object appears in an object of type OUTER_TYPE
- at offset OFFSET. When information is not 100% reliable, we
- use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */
- HOST_WIDE_INT offset;
- HOST_WIDE_INT speculative_offset;
- tree outer_type;
- tree speculative_outer_type;
- /* True if outer object may be in construction or destruction. */
- bool maybe_in_construction;
- /* True if outer object may be of derived type. */
- bool maybe_derived_type;
- /* True if speculative outer object may be of derived type. We always
- speculate that construction does not happen. */
- bool speculative_maybe_derived_type;
-
- /* Build empty "I know nothing" context. */
- ipa_polymorphic_call_context ();
-
- /* Build polymorphic call context for indirect call E. */
- ipa_polymorphic_call_context (cgraph_edge *e);
-
- /* Make context non-speculative. */
- void clear_speculation ();
-
- /* Walk container types and modify context to point to actual class
- containing EXPECTED_TYPE as base class. */
- bool restrict_to_inner_class (tree expected_type);
-
- /* Look for vtable stores or constructor calls to work out dynamic type
- of memory location. */
- bool get_dynamic_type (tree, tree, tree, gimple);
-};
-
-/* Build polymorphic call context for indirect call E. */
-
-inline
-ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e)
-{
- offset = e->indirect_info->offset;
- speculative_offset = e->indirect_info->speculative_offset;
- outer_type = e->indirect_info->outer_type;
- speculative_outer_type = e->indirect_info->speculative_outer_type;
- maybe_in_construction = e->indirect_info->maybe_in_construction;
- maybe_derived_type = e->indirect_info->maybe_derived_type;
- speculative_maybe_derived_type = e->indirect_info->speculative_maybe_derived_type;
-}
-
-/* Build empty "I know nothing" context. */
-
-inline
-ipa_polymorphic_call_context::ipa_polymorphic_call_context ()
- : offset(0), speculative_offset(0), outer_type(NULL),
- speculative_outer_type(NULL), maybe_in_construction(false),
- maybe_derived_type(false), speculative_maybe_derived_type(false)
-{
-}
-
-/* Make context non-speculative. */
-
-inline void
-ipa_polymorphic_call_context::clear_speculation ()
-{
- speculative_outer_type = NULL;
- speculative_offset = 0;
- speculative_maybe_derived_type = false;
-}
/* In ipa-utils.c */
void ipa_print_order (FILE*, const char *, struct cgraph_node**, int);
int ipa_reverse_postorder (struct cgraph_node **);
tree get_base_var (tree);
void ipa_merge_profiles (struct cgraph_node *dst,
- struct cgraph_node *src);
+ struct cgraph_node *src, bool preserve_body = false);
bool recursive_call_p (tree, tree);
/* In ipa-profile.c */
vec <cgraph_node *>
possible_polymorphic_call_targets (tree, HOST_WIDE_INT,
ipa_polymorphic_call_context,
- bool *final = NULL,
+ bool *copletep = NULL,
void **cache_token = NULL,
- int *nonconstruction_targets = NULL);
+ bool speuclative = false);
odr_type get_odr_type (tree, bool insert = false);
+bool type_in_anonymous_namespace_p (const_tree);
+bool type_with_linkage_p (const_tree);
+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 possible_polymorphic_call_target_p (tree, HOST_WIDE_INT,
const ipa_polymorphic_call_context &,
struct cgraph_node *);
-tree method_class_type (const_tree);
-tree get_polymorphic_call_info (tree, tree, tree *,
- HOST_WIDE_INT *,
- ipa_polymorphic_call_context *,
- gimple call = NULL);
-bool get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *,
- tree, tree, HOST_WIDE_INT);
+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, bool strict = false);
+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);
/* Return vector containing possible targets of polymorphic call E.
- If FINALP is non-NULL, store true if the list is complette.
+ 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.
inline vec <cgraph_node *>
possible_polymorphic_call_targets (struct cgraph_edge *e,
- bool *final = NULL,
+ bool *completep = NULL,
void **cache_token = NULL,
- int *nonconstruction_targets = NULL)
+ bool speculative = false)
{
- gcc_checking_assert (e->indirect_info->polymorphic);
ipa_polymorphic_call_context context(e);
+
return possible_polymorphic_call_targets (e->indirect_info->otr_type,
e->indirect_info->otr_token,
context,
- final, cache_token,
- nonconstruction_targets);
+ 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 *final = NULL,
+ bool *completep = NULL,
void **cache_token = NULL)
{
- tree otr_type;
- HOST_WIDE_INT otr_token;
- ipa_polymorphic_call_context context;
+ ipa_polymorphic_call_context context (current_function_decl, ref, call);
- get_polymorphic_call_info (current_function_decl,
- ref,
- &otr_type, &otr_token, &context, call);
return possible_polymorphic_call_targets (obj_type_ref_class (ref),
tree_to_uhwi
(OBJ_TYPE_REF_TOKEN (ref)),
context,
- final, cache_token);
+ 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)
{
- gcc_checking_assert (e->indirect_info->polymorphic);
ipa_polymorphic_call_context context(e);
+
dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type,
e->indirect_info->otr_token,
context);
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 N can be possibly target of a polymorphic call of
- OBJ_TYPE_REF expression CALL. */
+/* Return true if BINFO corresponds to a type with virtual methods.
-inline bool
-possible_polymorphic_call_target_p (tree call,
- struct cgraph_node *n)
-{
- ipa_polymorphic_call_context context;
- return possible_polymorphic_call_target_p (obj_type_ref_class (call),
- tree_to_uhwi
- (OBJ_TYPE_REF_TOKEN (call)),
- context,
- n);
-}
+ 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. */
-/* 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. */
-
-static inline bool
-odr_type_p (const_tree t)
+inline bool
+polymorphic_type_binfo_p (const_tree binfo)
{
- if (type_in_anonymous_namespace_p (t))
- return true;
- /* 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_assert (in_lto_p || flag_lto);
-
- return (TYPE_NAME (t)
- && (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t))));
+ /* See if BINFO's type has an virtual table associtated with it.
+ Check is defensive because of Java FE produces BINFOs
+ without BINFO_TYPE set. */
+ return (BINFO_TYPE (binfo) && TYPE_BINFO (BINFO_TYPE (binfo))
+ && BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (binfo))));
}
#endif /* GCC_IPA_UTILS_H */