/* Utilities for ipa analysis.
   Copyright (C) 2004-2015 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,
			  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 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 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 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_deriavations_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);

/* 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)
{
  ipa_polymorphic_call_context context(e);

  dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type,
					  e->indirect_info->otr_token,
					  context);
}

/* 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 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)
{
  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))));
}

/* 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)
{
  /* 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  */


