xref: /dragonfly/contrib/gcc-8.0/gcc/cgraph.h (revision e215fc28)
138fd1498Szrj /* Callgraph handling code.
238fd1498Szrj    Copyright (C) 2003-2018 Free Software Foundation, Inc.
338fd1498Szrj    Contributed by Jan Hubicka
438fd1498Szrj 
538fd1498Szrj This file is part of GCC.
638fd1498Szrj 
738fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
838fd1498Szrj the terms of the GNU General Public License as published by the Free
938fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1038fd1498Szrj version.
1138fd1498Szrj 
1238fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1338fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1438fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1538fd1498Szrj for more details.
1638fd1498Szrj 
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3.  If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>.  */
2038fd1498Szrj 
2138fd1498Szrj #ifndef GCC_CGRAPH_H
2238fd1498Szrj #define GCC_CGRAPH_H
2338fd1498Szrj 
2438fd1498Szrj #include "profile-count.h"
2538fd1498Szrj #include "ipa-ref.h"
2638fd1498Szrj #include "plugin-api.h"
2738fd1498Szrj 
2838fd1498Szrj class ipa_opt_pass_d;
2938fd1498Szrj typedef ipa_opt_pass_d *ipa_opt_pass;
3038fd1498Szrj 
3138fd1498Szrj /* Symbol table consists of functions and variables.
3238fd1498Szrj    TODO: add labels and CONST_DECLs.  */
3338fd1498Szrj enum symtab_type
3438fd1498Szrj {
3538fd1498Szrj   SYMTAB_SYMBOL,
3638fd1498Szrj   SYMTAB_FUNCTION,
3738fd1498Szrj   SYMTAB_VARIABLE
3838fd1498Szrj };
3938fd1498Szrj 
4038fd1498Szrj /* Section names are stored as reference counted strings in GGC safe hashtable
4138fd1498Szrj    (to make them survive through PCH).  */
4238fd1498Szrj 
4338fd1498Szrj struct GTY((for_user)) section_hash_entry
4438fd1498Szrj {
4538fd1498Szrj   int ref_count;
4638fd1498Szrj   char *name;  /* As long as this datastructure stays in GGC, we can not put
4738fd1498Szrj 		  string at the tail of structure of GGC dies in horrible
4838fd1498Szrj 		  way  */
4938fd1498Szrj };
5038fd1498Szrj 
5138fd1498Szrj struct section_name_hasher : ggc_ptr_hash<section_hash_entry>
5238fd1498Szrj {
5338fd1498Szrj   typedef const char *compare_type;
5438fd1498Szrj 
5538fd1498Szrj   static hashval_t hash (section_hash_entry *);
5638fd1498Szrj   static bool equal (section_hash_entry *, const char *);
5738fd1498Szrj };
5838fd1498Szrj 
5938fd1498Szrj enum availability
6038fd1498Szrj {
6138fd1498Szrj   /* Not yet set by cgraph_function_body_availability.  */
6238fd1498Szrj   AVAIL_UNSET,
6338fd1498Szrj   /* Function body/variable initializer is unknown.  */
6438fd1498Szrj   AVAIL_NOT_AVAILABLE,
6538fd1498Szrj   /* Function body/variable initializer is known but might be replaced
6638fd1498Szrj      by a different one from other compilation unit and thus needs to
6738fd1498Szrj      be dealt with a care.  Like AVAIL_NOT_AVAILABLE it can have
6838fd1498Szrj      arbitrary side effects on escaping variables and functions, while
6938fd1498Szrj      like AVAILABLE it might access static variables.  */
7038fd1498Szrj   AVAIL_INTERPOSABLE,
7138fd1498Szrj   /* Function body/variable initializer is known and will be used in final
7238fd1498Szrj      program.  */
7338fd1498Szrj   AVAIL_AVAILABLE,
7438fd1498Szrj   /* Function body/variable initializer is known and all it's uses are
7538fd1498Szrj      explicitly visible within current unit (ie it's address is never taken and
7638fd1498Szrj      it is not exported to other units). Currently used only for functions.  */
7738fd1498Szrj   AVAIL_LOCAL
7838fd1498Szrj };
7938fd1498Szrj 
8038fd1498Szrj /* Classification of symbols WRT partitioning.  */
8138fd1498Szrj enum symbol_partitioning_class
8238fd1498Szrj {
8338fd1498Szrj    /* External declarations are ignored by partitioning algorithms and they are
8438fd1498Szrj       added into the boundary later via compute_ltrans_boundary.  */
8538fd1498Szrj    SYMBOL_EXTERNAL,
8638fd1498Szrj    /* Partitioned symbols are pur into one of partitions.  */
8738fd1498Szrj    SYMBOL_PARTITION,
8838fd1498Szrj    /* Duplicated symbols (such as comdat or constant pool references) are
8938fd1498Szrj       copied into every node needing them via add_symbol_to_partition.  */
9038fd1498Szrj    SYMBOL_DUPLICATE
9138fd1498Szrj };
9238fd1498Szrj 
9338fd1498Szrj /* Base of all entries in the symbol table.
9438fd1498Szrj    The symtab_node is inherited by cgraph and varpol nodes.  */
9538fd1498Szrj class GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"),
9638fd1498Szrj 	   chain_next ("%h.next"), chain_prev ("%h.previous")))
9738fd1498Szrj   symtab_node
9838fd1498Szrj {
9938fd1498Szrj public:
10038fd1498Szrj   /* Return name.  */
10138fd1498Szrj   const char *name () const;
10238fd1498Szrj 
10338fd1498Szrj   /* Return dump name.  */
10438fd1498Szrj   const char *dump_name () const;
10538fd1498Szrj 
10638fd1498Szrj   /* Return asm name.  */
10738fd1498Szrj   const char *asm_name () const;
10838fd1498Szrj 
10938fd1498Szrj   /* Return dump name with assembler name.  */
11038fd1498Szrj   const char *dump_asm_name () const;
11138fd1498Szrj 
11238fd1498Szrj   /* Add node into symbol table.  This function is not used directly, but via
11338fd1498Szrj      cgraph/varpool node creation routines.  */
11438fd1498Szrj   void register_symbol (void);
11538fd1498Szrj 
11638fd1498Szrj   /* Remove symbol from symbol table.  */
11738fd1498Szrj   void remove (void);
11838fd1498Szrj 
11938fd1498Szrj   /* Dump symtab node to F.  */
12038fd1498Szrj   void dump (FILE *f);
12138fd1498Szrj 
12238fd1498Szrj   /* Dump symtab node to stderr.  */
12338fd1498Szrj   void DEBUG_FUNCTION debug (void);
12438fd1498Szrj 
12538fd1498Szrj   /* Verify consistency of node.  */
12638fd1498Szrj   void DEBUG_FUNCTION verify (void);
12738fd1498Szrj 
12838fd1498Szrj   /* Return ipa reference from this symtab_node to
12938fd1498Szrj      REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type
13038fd1498Szrj      of the use and STMT the statement (if it exists).  */
13138fd1498Szrj   ipa_ref *create_reference (symtab_node *referred_node,
13238fd1498Szrj 			     enum ipa_ref_use use_type);
13338fd1498Szrj 
13438fd1498Szrj   /* Return ipa reference from this symtab_node to
13538fd1498Szrj      REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type
13638fd1498Szrj      of the use and STMT the statement (if it exists).  */
13738fd1498Szrj   ipa_ref *create_reference (symtab_node *referred_node,
13838fd1498Szrj 			     enum ipa_ref_use use_type, gimple *stmt);
13938fd1498Szrj 
14038fd1498Szrj   /* If VAL is a reference to a function or a variable, add a reference from
14138fd1498Szrj      this symtab_node to the corresponding symbol table node.  Return the new
14238fd1498Szrj      reference or NULL if none was created.  */
14338fd1498Szrj   ipa_ref *maybe_create_reference (tree val, gimple *stmt);
14438fd1498Szrj 
14538fd1498Szrj   /* Clone all references from symtab NODE to this symtab_node.  */
14638fd1498Szrj   void clone_references (symtab_node *node);
14738fd1498Szrj 
14838fd1498Szrj   /* Remove all stmt references in non-speculative references.
14938fd1498Szrj      Those are not maintained during inlining & clonning.
15038fd1498Szrj      The exception are speculative references that are updated along
15138fd1498Szrj      with callgraph edges associated with them.  */
15238fd1498Szrj   void clone_referring (symtab_node *node);
15338fd1498Szrj 
15438fd1498Szrj   /* Clone reference REF to this symtab_node and set its stmt to STMT.  */
15538fd1498Szrj   ipa_ref *clone_reference (ipa_ref *ref, gimple *stmt);
15638fd1498Szrj 
15738fd1498Szrj   /* Find the structure describing a reference to REFERRED_NODE
15838fd1498Szrj      and associated with statement STMT.  */
15938fd1498Szrj   ipa_ref *find_reference (symtab_node *referred_node, gimple *stmt,
16038fd1498Szrj 			   unsigned int lto_stmt_uid);
16138fd1498Szrj 
16238fd1498Szrj   /* Remove all references that are associated with statement STMT.  */
16338fd1498Szrj   void remove_stmt_references (gimple *stmt);
16438fd1498Szrj 
16538fd1498Szrj   /* Remove all stmt references in non-speculative references.
16638fd1498Szrj      Those are not maintained during inlining & clonning.
16738fd1498Szrj      The exception are speculative references that are updated along
16838fd1498Szrj      with callgraph edges associated with them.  */
16938fd1498Szrj   void clear_stmts_in_references (void);
17038fd1498Szrj 
17138fd1498Szrj   /* Remove all references in ref list.  */
17238fd1498Szrj   void remove_all_references (void);
17338fd1498Szrj 
17438fd1498Szrj   /* Remove all referring items in ref list.  */
17538fd1498Szrj   void remove_all_referring (void);
17638fd1498Szrj 
17738fd1498Szrj   /* Dump references in ref list to FILE.  */
17838fd1498Szrj   void dump_references (FILE *file);
17938fd1498Szrj 
18038fd1498Szrj   /* Dump referring in list to FILE.  */
18138fd1498Szrj   void dump_referring (FILE *);
18238fd1498Szrj 
18338fd1498Szrj   /* Get number of references for this node.  */
num_references(void)18438fd1498Szrj   inline unsigned num_references (void)
18538fd1498Szrj   {
18638fd1498Szrj     return ref_list.references ? ref_list.references->length () : 0;
18738fd1498Szrj   }
18838fd1498Szrj 
18938fd1498Szrj   /* Iterates I-th reference in the list, REF is also set.  */
19038fd1498Szrj   ipa_ref *iterate_reference (unsigned i, ipa_ref *&ref);
19138fd1498Szrj 
19238fd1498Szrj   /* Iterates I-th referring item in the list, REF is also set.  */
19338fd1498Szrj   ipa_ref *iterate_referring (unsigned i, ipa_ref *&ref);
19438fd1498Szrj 
19538fd1498Szrj   /* Iterates I-th referring alias item in the list, REF is also set.  */
19638fd1498Szrj   ipa_ref *iterate_direct_aliases (unsigned i, ipa_ref *&ref);
19738fd1498Szrj 
19838fd1498Szrj   /* Return true if symtab node and TARGET represents
19938fd1498Szrj      semantically equivalent symbols.  */
20038fd1498Szrj   bool semantically_equivalent_p (symtab_node *target);
20138fd1498Szrj 
20238fd1498Szrj   /* Classify symbol symtab node for partitioning.  */
20338fd1498Szrj   enum symbol_partitioning_class get_partitioning_class (void);
20438fd1498Szrj 
20538fd1498Szrj   /* Return comdat group.  */
get_comdat_group()20638fd1498Szrj   tree get_comdat_group ()
20738fd1498Szrj     {
20838fd1498Szrj       return x_comdat_group;
20938fd1498Szrj     }
21038fd1498Szrj 
21138fd1498Szrj   /* Return comdat group as identifier_node.  */
get_comdat_group_id()21238fd1498Szrj   tree get_comdat_group_id ()
21338fd1498Szrj     {
21438fd1498Szrj       if (x_comdat_group && TREE_CODE (x_comdat_group) != IDENTIFIER_NODE)
21538fd1498Szrj 	x_comdat_group = DECL_ASSEMBLER_NAME (x_comdat_group);
21638fd1498Szrj       return x_comdat_group;
21738fd1498Szrj     }
21838fd1498Szrj 
21938fd1498Szrj   /* Set comdat group.  */
set_comdat_group(tree group)22038fd1498Szrj   void set_comdat_group (tree group)
22138fd1498Szrj     {
22238fd1498Szrj       gcc_checking_assert (!group || TREE_CODE (group) == IDENTIFIER_NODE
22338fd1498Szrj 			   || DECL_P (group));
22438fd1498Szrj       x_comdat_group = group;
22538fd1498Szrj     }
22638fd1498Szrj 
22738fd1498Szrj   /* Return section as string.  */
get_section()22838fd1498Szrj   const char * get_section ()
22938fd1498Szrj     {
23038fd1498Szrj       if (!x_section)
23138fd1498Szrj 	return NULL;
23238fd1498Szrj       return x_section->name;
23338fd1498Szrj     }
23438fd1498Szrj 
23538fd1498Szrj   /* Remove node from same comdat group.   */
23638fd1498Szrj   void remove_from_same_comdat_group (void);
23738fd1498Szrj 
23838fd1498Szrj   /* Add this symtab_node to the same comdat group that OLD is in.  */
23938fd1498Szrj   void add_to_same_comdat_group (symtab_node *old_node);
24038fd1498Szrj 
24138fd1498Szrj   /* Dissolve the same_comdat_group list in which NODE resides.  */
24238fd1498Szrj   void dissolve_same_comdat_group_list (void);
24338fd1498Szrj 
24438fd1498Szrj   /* Return true when symtab_node is known to be used from other (non-LTO)
24538fd1498Szrj      object file. Known only when doing LTO via linker plugin.  */
24638fd1498Szrj   bool used_from_object_file_p (void);
24738fd1498Szrj 
24838fd1498Szrj   /* Walk the alias chain to return the symbol NODE is alias of.
24938fd1498Szrj      If NODE is not an alias, return NODE.
25038fd1498Szrj      When AVAILABILITY is non-NULL, get minimal availability in the chain.
25138fd1498Szrj      When REF is non-NULL, assume that reference happens in symbol REF
25238fd1498Szrj      when determining the availability.  */
25338fd1498Szrj   symtab_node *ultimate_alias_target (enum availability *avail = NULL,
25438fd1498Szrj 				      struct symtab_node *ref = NULL);
25538fd1498Szrj 
25638fd1498Szrj   /* Return next reachable static symbol with initializer after NODE.  */
25738fd1498Szrj   inline symtab_node *next_defined_symbol (void);
25838fd1498Szrj 
25938fd1498Szrj   /* Add reference recording that symtab node is alias of TARGET.
26038fd1498Szrj      If TRANSPARENT is true make the alias to be transparent alias.
26138fd1498Szrj      The function can fail in the case of aliasing cycles; in this case
26238fd1498Szrj      it returns false.  */
26338fd1498Szrj   bool resolve_alias (symtab_node *target, bool transparent = false);
26438fd1498Szrj 
26538fd1498Szrj   /* C++ FE sometimes change linkage flags after producing same
26638fd1498Szrj      body aliases.  */
26738fd1498Szrj   void fixup_same_cpp_alias_visibility (symtab_node *target);
26838fd1498Szrj 
26938fd1498Szrj   /* Call callback on symtab node and aliases associated to this node.
27038fd1498Szrj      When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
27138fd1498Szrj      skipped.  */
27238fd1498Szrj   bool call_for_symbol_and_aliases (bool (*callback) (symtab_node *, void *),
27338fd1498Szrj 				    void *data,
27438fd1498Szrj 				    bool include_overwrite);
27538fd1498Szrj 
27638fd1498Szrj   /* If node can not be interposable by static or dynamic linker to point to
27738fd1498Szrj      different definition, return this symbol. Otherwise look for alias with
27838fd1498Szrj      such property and if none exists, introduce new one.  */
27938fd1498Szrj   symtab_node *noninterposable_alias (void);
28038fd1498Szrj 
28138fd1498Szrj   /* Return node that alias is aliasing.  */
28238fd1498Szrj   inline symtab_node *get_alias_target (void);
28338fd1498Szrj 
28438fd1498Szrj   /* Set section for symbol and its aliases.  */
28538fd1498Szrj   void set_section (const char *section);
28638fd1498Szrj 
28738fd1498Szrj   /* Set section, do not recurse into aliases.
28838fd1498Szrj      When one wants to change section of symbol and its aliases,
28938fd1498Szrj      use set_section.  */
29038fd1498Szrj   void set_section_for_node (const char *section);
29138fd1498Szrj 
29238fd1498Szrj   /* Set initialization priority to PRIORITY.  */
29338fd1498Szrj   void set_init_priority (priority_type priority);
29438fd1498Szrj 
29538fd1498Szrj   /* Return the initialization priority.  */
29638fd1498Szrj   priority_type get_init_priority ();
29738fd1498Szrj 
29838fd1498Szrj   /* Return availability of NODE when referenced from REF.  */
29938fd1498Szrj   enum availability get_availability (symtab_node *ref = NULL);
30038fd1498Szrj 
30138fd1498Szrj   /* Return true if NODE binds to current definition in final executable
30238fd1498Szrj      when referenced from REF.  If REF is NULL return conservative value
30338fd1498Szrj      for any reference.  */
30438fd1498Szrj   bool binds_to_current_def_p (symtab_node *ref = NULL);
30538fd1498Szrj 
30638fd1498Szrj   /* Make DECL local.  */
30738fd1498Szrj   void make_decl_local (void);
30838fd1498Szrj 
30938fd1498Szrj   /* Copy visibility from N.  */
31038fd1498Szrj   void copy_visibility_from (symtab_node *n);
31138fd1498Szrj 
31238fd1498Szrj   /* Return desired alignment of the definition.  This is NOT alignment useful
31338fd1498Szrj      to access THIS, because THIS may be interposable and DECL_ALIGN should
31438fd1498Szrj      be used instead.  It however must be guaranteed when output definition
31538fd1498Szrj      of THIS.  */
31638fd1498Szrj   unsigned int definition_alignment ();
31738fd1498Szrj 
31838fd1498Szrj   /* Return true if alignment can be increased.  */
31938fd1498Szrj   bool can_increase_alignment_p ();
32038fd1498Szrj 
32138fd1498Szrj   /* Increase alignment of symbol to ALIGN.  */
32238fd1498Szrj   void increase_alignment (unsigned int align);
32338fd1498Szrj 
32438fd1498Szrj   /* Return true if list contains an alias.  */
32538fd1498Szrj   bool has_aliases_p (void);
32638fd1498Szrj 
32738fd1498Szrj   /* Return true when the symbol is real symbol, i.e. it is not inline clone
32838fd1498Szrj      or abstract function kept for debug info purposes only.  */
32938fd1498Szrj   bool real_symbol_p (void);
33038fd1498Szrj 
33138fd1498Szrj   /* Return true when the symbol needs to be output to the LTO symbol table.  */
33238fd1498Szrj   bool output_to_lto_symbol_table_p (void);
33338fd1498Szrj 
33438fd1498Szrj   /* Determine if symbol declaration is needed.  That is, visible to something
33538fd1498Szrj      either outside this translation unit, something magic in the system
33638fd1498Szrj      configury. This function is used just during symbol creation.  */
33738fd1498Szrj   bool needed_p (void);
33838fd1498Szrj 
33938fd1498Szrj   /* Return true if this symbol is a function from the C frontend specified
34038fd1498Szrj      directly in RTL form (with "__RTL").  */
34138fd1498Szrj   bool native_rtl_p () const;
34238fd1498Szrj 
34338fd1498Szrj   /* Return true when there are references to the node.  */
34438fd1498Szrj   bool referred_to_p (bool include_self = true);
34538fd1498Szrj 
34638fd1498Szrj   /* Return true if symbol can be discarded by linker from the binary.
34738fd1498Szrj      Assume that symbol is used (so there is no need to take into account
34838fd1498Szrj      garbage collecting linkers)
34938fd1498Szrj 
35038fd1498Szrj      This can happen for comdats, commons and weaks when they are previaled
35138fd1498Szrj      by other definition at static linking time.  */
35238fd1498Szrj   inline bool
can_be_discarded_p(void)35338fd1498Szrj   can_be_discarded_p (void)
35438fd1498Szrj   {
35538fd1498Szrj     return (DECL_EXTERNAL (decl)
35638fd1498Szrj 	    || ((get_comdat_group ()
35738fd1498Szrj 		 || DECL_COMMON (decl)
35838fd1498Szrj 		 || (DECL_SECTION_NAME (decl) && DECL_WEAK (decl)))
35938fd1498Szrj 		&& ((resolution != LDPR_PREVAILING_DEF
36038fd1498Szrj 		     && resolution != LDPR_PREVAILING_DEF_IRONLY_EXP)
36138fd1498Szrj 		    || flag_incremental_link)
36238fd1498Szrj 		&& resolution != LDPR_PREVAILING_DEF_IRONLY));
36338fd1498Szrj   }
36438fd1498Szrj 
36538fd1498Szrj   /* Return true if NODE is local to a particular COMDAT group, and must not
36638fd1498Szrj      be named from outside the COMDAT.  This is used for C++ decloned
36738fd1498Szrj      constructors.  */
comdat_local_p(void)36838fd1498Szrj   inline bool comdat_local_p (void)
36938fd1498Szrj   {
37038fd1498Szrj     return (same_comdat_group && !TREE_PUBLIC (decl));
37138fd1498Szrj   }
37238fd1498Szrj 
37338fd1498Szrj   /* Return true if ONE and TWO are part of the same COMDAT group.  */
37438fd1498Szrj   inline bool in_same_comdat_group_p (symtab_node *target);
37538fd1498Szrj 
37638fd1498Szrj   /* Return true if symbol is known to be nonzero.  */
37738fd1498Szrj   bool nonzero_address ();
37838fd1498Szrj 
37938fd1498Szrj   /* Return 0 if symbol is known to have different address than S2,
38038fd1498Szrj      Return 1 if symbol is known to have same address as S2,
38138fd1498Szrj      return 2 otherwise.
38238fd1498Szrj 
38338fd1498Szrj      If MEMORY_ACCESSED is true, assume that both memory pointer to THIS
38438fd1498Szrj      and S2 is going to be accessed.  This eliminates the situations when
38538fd1498Szrj      either THIS or S2 is NULL and is seful for comparing bases when deciding
38638fd1498Szrj      about memory aliasing.  */
38738fd1498Szrj   int equal_address_to (symtab_node *s2, bool memory_accessed = false);
38838fd1498Szrj 
38938fd1498Szrj   /* Return true if symbol's address may possibly be compared to other
39038fd1498Szrj      symbol's address.  */
39138fd1498Szrj   bool address_matters_p ();
39238fd1498Szrj 
39338fd1498Szrj   /* Return true if NODE's address can be compared.  This use properties
39438fd1498Szrj      of NODE only and does not look if the address is actually taken in
39538fd1498Szrj      interesting way.  For that use ADDRESS_MATTERS_P instead.  */
39638fd1498Szrj   bool address_can_be_compared_p (void);
39738fd1498Szrj 
39838fd1498Szrj   /* Return symbol table node associated with DECL, if any,
39938fd1498Szrj      and NULL otherwise.  */
get(const_tree decl)40038fd1498Szrj   static inline symtab_node *get (const_tree decl)
40138fd1498Szrj   {
40238fd1498Szrj     /* Check that we are called for sane type of object - functions
40338fd1498Szrj        and static or external variables.  */
40438fd1498Szrj     gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
40538fd1498Szrj 			 || (TREE_CODE (decl) == VAR_DECL
40638fd1498Szrj 			     && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
40738fd1498Szrj 				 || in_lto_p)));
40838fd1498Szrj     /* Check that the mapping is sane - perhaps this check can go away,
40938fd1498Szrj        but at the moment frontends tends to corrupt the mapping by calling
41038fd1498Szrj        memcpy/memset on the tree nodes.  */
41138fd1498Szrj     gcc_checking_assert (!decl->decl_with_vis.symtab_node
41238fd1498Szrj 			 || decl->decl_with_vis.symtab_node->decl == decl);
41338fd1498Szrj     return decl->decl_with_vis.symtab_node;
41438fd1498Szrj   }
41538fd1498Szrj 
41638fd1498Szrj   /* Try to find a symtab node for declaration DECL and if it does not
41738fd1498Szrj      exist or if it corresponds to an inline clone, create a new one.  */
41838fd1498Szrj   static inline symtab_node * get_create (tree node);
41938fd1498Szrj 
42038fd1498Szrj   /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
42138fd1498Szrj      Return NULL if there's no such node.  */
42238fd1498Szrj   static symtab_node *get_for_asmname (const_tree asmname);
42338fd1498Szrj 
42438fd1498Szrj   /* Verify symbol table for internal consistency.  */
42538fd1498Szrj   static DEBUG_FUNCTION void verify_symtab_nodes (void);
42638fd1498Szrj 
42738fd1498Szrj   /* Perform internal consistency checks, if they are enabled.  */
42838fd1498Szrj   static inline void checking_verify_symtab_nodes (void);
42938fd1498Szrj 
43038fd1498Szrj   /* Type of the symbol.  */
43138fd1498Szrj   ENUM_BITFIELD (symtab_type) type : 8;
43238fd1498Szrj 
43338fd1498Szrj   /* The symbols resolution.  */
43438fd1498Szrj   ENUM_BITFIELD (ld_plugin_symbol_resolution) resolution : 8;
43538fd1498Szrj 
43638fd1498Szrj   /*** Flags representing the symbol type.  ***/
43738fd1498Szrj 
43838fd1498Szrj   /* True when symbol corresponds to a definition in current unit.
43938fd1498Szrj      set via finalize_function or finalize_decl  */
44038fd1498Szrj   unsigned definition : 1;
44138fd1498Szrj   /* True when symbol is an alias.
44238fd1498Szrj      Set by ssemble_alias.  */
44338fd1498Szrj   unsigned alias : 1;
44438fd1498Szrj   /* When true the alias is translated into its target symbol either by GCC
44538fd1498Szrj      or assembler (it also may just be a duplicate declaration of the same
44638fd1498Szrj      linker name).
44738fd1498Szrj 
44838fd1498Szrj      Currently transparent aliases come in three different flavors
44938fd1498Szrj        - aliases having the same assembler name as their target (aka duplicated
45038fd1498Szrj 	 declarations). In this case the assembler names compare via
45138fd1498Szrj 	 assembler_names_equal_p and weakref is false
45238fd1498Szrj        - aliases that are renamed at a time being output to final file
45338fd1498Szrj 	 by varasm.c. For those DECL_ASSEMBLER_NAME have
45438fd1498Szrj 	 IDENTIFIER_TRANSPARENT_ALIAS set and thus also their assembler
45538fd1498Szrj 	 name must be unique.
45638fd1498Szrj 	 Weakrefs belong to this cateogry when we target assembler without
45738fd1498Szrj 	 .weakref directive.
45838fd1498Szrj        - weakrefs that are renamed by assembler via .weakref directive.
45938fd1498Szrj 	 In this case the alias may or may not be definition (depending if
46038fd1498Szrj 	 target declaration was seen by the compiler), weakref is set.
46138fd1498Szrj 	 Unless we are before renaming statics, assembler names are different.
46238fd1498Szrj 
46338fd1498Szrj      Given that we now support duplicate declarations, the second option is
46438fd1498Szrj      redundant and will be removed.  */
46538fd1498Szrj   unsigned transparent_alias : 1;
46638fd1498Szrj   /* True when alias is a weakref.  */
46738fd1498Szrj   unsigned weakref : 1;
46838fd1498Szrj   /* C++ frontend produce same body aliases and extra name aliases for
46938fd1498Szrj      virtual functions and vtables that are obviously equivalent.
47038fd1498Szrj      Those aliases are bit special, especially because C++ frontend
47138fd1498Szrj      visibility code is so ugly it can not get them right at first time
47238fd1498Szrj      and their visibility needs to be copied from their "masters" at
47338fd1498Szrj      the end of parsing.  */
47438fd1498Szrj   unsigned cpp_implicit_alias : 1;
47538fd1498Szrj   /* Set once the definition was analyzed.  The list of references and
47638fd1498Szrj      other properties are built during analysis.  */
47738fd1498Szrj   unsigned analyzed : 1;
47838fd1498Szrj   /* Set for write-only variables.  */
47938fd1498Szrj   unsigned writeonly : 1;
48038fd1498Szrj   /* Visibility of symbol was used for further optimization; do not
48138fd1498Szrj      permit further changes.  */
48238fd1498Szrj   unsigned refuse_visibility_changes : 1;
48338fd1498Szrj 
48438fd1498Szrj   /*** Visibility and linkage flags.  ***/
48538fd1498Szrj 
48638fd1498Szrj   /* Set when function is visible by other units.  */
48738fd1498Szrj   unsigned externally_visible : 1;
48838fd1498Szrj   /* Don't reorder to other symbols having this set.  */
48938fd1498Szrj   unsigned no_reorder : 1;
49038fd1498Szrj   /* The symbol will be assumed to be used in an invisible way (like
49138fd1498Szrj      by an toplevel asm statement).  */
49238fd1498Szrj   unsigned force_output : 1;
49338fd1498Szrj   /* Like FORCE_OUTPUT, but in the case it is ABI requiring the symbol to be
49438fd1498Szrj      exported.  Unlike FORCE_OUTPUT this flag gets cleared to symbols promoted
49538fd1498Szrj      to static and it does not inhibit optimization.  */
49638fd1498Szrj   unsigned forced_by_abi : 1;
49738fd1498Szrj   /* True when the name is known to be unique and thus it does not need mangling.  */
49838fd1498Szrj   unsigned unique_name : 1;
49938fd1498Szrj   /* Specify whether the section was set by user or by
50038fd1498Szrj      compiler via -ffunction-sections.  */
50138fd1498Szrj   unsigned implicit_section : 1;
50238fd1498Szrj   /* True when body and other characteristics have been removed by
50338fd1498Szrj      symtab_remove_unreachable_nodes. */
50438fd1498Szrj   unsigned body_removed : 1;
50538fd1498Szrj 
50638fd1498Szrj   /*** WHOPR Partitioning flags.
50738fd1498Szrj        These flags are used at ltrans stage when only part of the callgraph is
50838fd1498Szrj        available. ***/
50938fd1498Szrj 
51038fd1498Szrj   /* Set when variable is used from other LTRANS partition.  */
51138fd1498Szrj   unsigned used_from_other_partition : 1;
51238fd1498Szrj   /* Set when function is available in the other LTRANS partition.
51338fd1498Szrj      During WPA output it is used to mark nodes that are present in
51438fd1498Szrj      multiple partitions.  */
51538fd1498Szrj   unsigned in_other_partition : 1;
51638fd1498Szrj 
51738fd1498Szrj 
51838fd1498Szrj 
51938fd1498Szrj   /*** other flags.  ***/
52038fd1498Szrj 
52138fd1498Szrj   /* Set when symbol has address taken. */
52238fd1498Szrj   unsigned address_taken : 1;
52338fd1498Szrj   /* Set when init priority is set.  */
52438fd1498Szrj   unsigned in_init_priority_hash : 1;
52538fd1498Szrj 
52638fd1498Szrj   /* Set when symbol needs to be streamed into LTO bytecode for LTO, or in case
52738fd1498Szrj      of offloading, for separate compilation for a different target.  */
52838fd1498Szrj   unsigned need_lto_streaming : 1;
52938fd1498Szrj 
53038fd1498Szrj   /* Set when symbol can be streamed into bytecode for offloading.  */
53138fd1498Szrj   unsigned offloadable : 1;
53238fd1498Szrj 
53358e805e6Szrj   /* Set when symbol is an IFUNC resolver.  */
53458e805e6Szrj   unsigned ifunc_resolver : 1;
53558e805e6Szrj 
53638fd1498Szrj 
53738fd1498Szrj   /* Ordering of all symtab entries.  */
53838fd1498Szrj   int order;
53938fd1498Szrj 
54038fd1498Szrj   /* Declaration representing the symbol.  */
54138fd1498Szrj   tree decl;
54238fd1498Szrj 
54338fd1498Szrj   /* Linked list of symbol table entries starting with symtab_nodes.  */
54438fd1498Szrj   symtab_node *next;
54538fd1498Szrj   symtab_node *previous;
54638fd1498Szrj 
54738fd1498Szrj   /* Linked list of symbols with the same asm name.  There may be multiple
54838fd1498Szrj      entries for single symbol name during LTO, because symbols are renamed
54938fd1498Szrj      only after partitioning.
55038fd1498Szrj 
55138fd1498Szrj      Because inline clones are kept in the assembler name has, they also produce
55238fd1498Szrj      duplicate entries.
55338fd1498Szrj 
55438fd1498Szrj      There are also several long standing bugs where frontends and builtin
55538fd1498Szrj      code produce duplicated decls.  */
55638fd1498Szrj   symtab_node *next_sharing_asm_name;
55738fd1498Szrj   symtab_node *previous_sharing_asm_name;
55838fd1498Szrj 
55938fd1498Szrj   /* Circular list of nodes in the same comdat group if non-NULL.  */
56038fd1498Szrj   symtab_node *same_comdat_group;
56138fd1498Szrj 
56238fd1498Szrj   /* Vectors of referring and referenced entities.  */
56338fd1498Szrj   ipa_ref_list ref_list;
56438fd1498Szrj 
56538fd1498Szrj   /* Alias target. May be either DECL pointer or ASSEMBLER_NAME pointer
56638fd1498Szrj      depending to what was known to frontend on the creation time.
56738fd1498Szrj      Once alias is resolved, this pointer become NULL.  */
56838fd1498Szrj   tree alias_target;
56938fd1498Szrj 
57038fd1498Szrj   /* File stream where this node is being written to.  */
57138fd1498Szrj   struct lto_file_decl_data * lto_file_data;
57238fd1498Szrj 
57338fd1498Szrj   PTR GTY ((skip)) aux;
57438fd1498Szrj 
57538fd1498Szrj   /* Comdat group the symbol is in.  Can be private if GGC allowed that.  */
57638fd1498Szrj   tree x_comdat_group;
57738fd1498Szrj 
57838fd1498Szrj   /* Section name. Again can be private, if allowed.  */
57938fd1498Szrj   section_hash_entry *x_section;
58038fd1498Szrj 
58138fd1498Szrj protected:
58238fd1498Szrj   /* Dump base fields of symtab nodes to F.  Not to be used directly.  */
58338fd1498Szrj   void dump_base (FILE *);
58438fd1498Szrj 
58538fd1498Szrj   /* Verify common part of symtab node.  */
58638fd1498Szrj   bool DEBUG_FUNCTION verify_base (void);
58738fd1498Szrj 
58838fd1498Szrj   /* Remove node from symbol table.  This function is not used directly, but via
58938fd1498Szrj      cgraph/varpool node removal routines.  */
59038fd1498Szrj   void unregister (void);
59138fd1498Szrj 
59238fd1498Szrj   /* Return the initialization and finalization priority information for
59338fd1498Szrj      DECL.  If there is no previous priority information, a freshly
59438fd1498Szrj      allocated structure is returned.  */
59538fd1498Szrj   struct symbol_priority_map *priority_info (void);
59638fd1498Szrj 
59738fd1498Szrj   /* Worker for call_for_symbol_and_aliases_1.  */
59838fd1498Szrj   bool call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *, void *),
59938fd1498Szrj 				      void *data,
60038fd1498Szrj 				      bool include_overwrite);
60138fd1498Szrj private:
60238fd1498Szrj   /* Worker for set_section.  */
60338fd1498Szrj   static bool set_section (symtab_node *n, void *s);
60438fd1498Szrj 
60538fd1498Szrj   /* Worker for symtab_resolve_alias.  */
60638fd1498Szrj   static bool set_implicit_section (symtab_node *n, void *);
60738fd1498Szrj 
60838fd1498Szrj   /* Worker searching noninterposable alias.  */
60938fd1498Szrj   static bool noninterposable_alias (symtab_node *node, void *data);
61038fd1498Szrj 
61138fd1498Szrj   /* Worker for ultimate_alias_target.  */
61238fd1498Szrj   symtab_node *ultimate_alias_target_1 (enum availability *avail = NULL,
61338fd1498Szrj 					symtab_node *ref = NULL);
61438fd1498Szrj 
61538fd1498Szrj   /* Get dump name with normal or assembly name.  */
61638fd1498Szrj   const char *get_dump_name (bool asm_name_p) const;
61738fd1498Szrj };
61838fd1498Szrj 
61938fd1498Szrj inline void
checking_verify_symtab_nodes(void)62038fd1498Szrj symtab_node::checking_verify_symtab_nodes (void)
62138fd1498Szrj {
62238fd1498Szrj   if (flag_checking)
62338fd1498Szrj     symtab_node::verify_symtab_nodes ();
62438fd1498Szrj }
62538fd1498Szrj 
62638fd1498Szrj /* Walk all aliases for NODE.  */
62738fd1498Szrj #define FOR_EACH_ALIAS(node, alias) \
62838fd1498Szrj   for (unsigned x_i = 0; node->iterate_direct_aliases (x_i, alias); x_i++)
62938fd1498Szrj 
63038fd1498Szrj /* This is the information that is put into the cgraph local structure
63138fd1498Szrj    to recover a function.  */
63238fd1498Szrj struct lto_file_decl_data;
63338fd1498Szrj 
63438fd1498Szrj extern const char * const cgraph_availability_names[];
63538fd1498Szrj extern const char * const ld_plugin_symbol_resolution_names[];
63638fd1498Szrj extern const char * const tls_model_names[];
63738fd1498Szrj 
63838fd1498Szrj /* Sub-structure of cgraph_node.  Holds information about thunk, used only for
63938fd1498Szrj    same body aliases.
64038fd1498Szrj 
64138fd1498Szrj    Thunks are basically wrappers around methods which are introduced in case
64238fd1498Szrj    of multiple inheritance in order to adjust the value of the "this" pointer
64338fd1498Szrj    or of the returned value.
64438fd1498Szrj 
64538fd1498Szrj    In the case of this-adjusting thunks, each back-end can override the
64638fd1498Szrj    can_output_mi_thunk/output_mi_thunk target hooks to generate a minimal thunk
64738fd1498Szrj    (with a tail call for instance) directly as assembly.  For the default hook
64838fd1498Szrj    or for the case where the can_output_mi_thunk hooks return false, the thunk
64938fd1498Szrj    is gimplified and lowered using the regular machinery.  */
65038fd1498Szrj 
65138fd1498Szrj struct GTY(()) cgraph_thunk_info {
65238fd1498Szrj   /* Offset used to adjust "this".  */
65338fd1498Szrj   HOST_WIDE_INT fixed_offset;
65438fd1498Szrj 
65538fd1498Szrj   /* Offset in the virtual table to get the offset to adjust "this".  Valid iff
65638fd1498Szrj      VIRTUAL_OFFSET_P is true.  */
65738fd1498Szrj   HOST_WIDE_INT virtual_value;
65838fd1498Szrj 
65938fd1498Szrj   /* Thunk target, i.e. the method that this thunk wraps.  Depending on the
66038fd1498Szrj      TARGET_USE_LOCAL_THUNK_ALIAS_P macro, this may have to be a new alias.  */
66138fd1498Szrj   tree alias;
66238fd1498Szrj 
66338fd1498Szrj   /* Nonzero for a "this" adjusting thunk and zero for a result adjusting
66438fd1498Szrj      thunk.  */
66538fd1498Szrj   bool this_adjusting;
66638fd1498Szrj 
66738fd1498Szrj   /* If true, this thunk is what we call a virtual thunk.  In this case:
66838fd1498Szrj      * for this-adjusting thunks, after the FIXED_OFFSET based adjustment is
66938fd1498Szrj        done, add to the result the offset found in the vtable at:
67038fd1498Szrj 	 vptr + VIRTUAL_VALUE
67138fd1498Szrj      * for result-adjusting thunks, the FIXED_OFFSET adjustment is done after
67238fd1498Szrj        the virtual one.  */
67338fd1498Szrj   bool virtual_offset_p;
67438fd1498Szrj 
67538fd1498Szrj   /* ??? True for special kind of thunks, seems related to instrumentation.  */
67638fd1498Szrj   bool add_pointer_bounds_args;
67738fd1498Szrj 
67838fd1498Szrj   /* Set to true when alias node (the cgraph_node to which this struct belong)
67938fd1498Szrj      is a thunk.  Access to any other fields is invalid if this is false.  */
68038fd1498Szrj   bool thunk_p;
68138fd1498Szrj };
68238fd1498Szrj 
68338fd1498Szrj /* Information about the function collected locally.
68438fd1498Szrj    Available after function is analyzed.  */
68538fd1498Szrj 
68638fd1498Szrj struct GTY(()) cgraph_local_info {
68738fd1498Szrj   /* Set when function is visible in current compilation unit only and
68838fd1498Szrj      its address is never taken.  */
68938fd1498Szrj   unsigned local : 1;
69038fd1498Szrj 
69138fd1498Szrj   /* False when there is something makes versioning impossible.  */
69238fd1498Szrj   unsigned versionable : 1;
69338fd1498Szrj 
69438fd1498Szrj   /* False when function calling convention and signature can not be changed.
69538fd1498Szrj      This is the case when __builtin_apply_args is used.  */
69638fd1498Szrj   unsigned can_change_signature : 1;
69738fd1498Szrj 
69838fd1498Szrj   /* True when the function has been originally extern inline, but it is
69938fd1498Szrj      redefined now.  */
70038fd1498Szrj   unsigned redefined_extern_inline : 1;
70138fd1498Szrj 
70238fd1498Szrj   /* True if the function may enter serial irrevocable mode.  */
70338fd1498Szrj   unsigned tm_may_enter_irr : 1;
70438fd1498Szrj };
70538fd1498Szrj 
70638fd1498Szrj /* Information about the function that needs to be computed globally
70738fd1498Szrj    once compilation is finished.  Available only with -funit-at-a-time.  */
70838fd1498Szrj 
70938fd1498Szrj struct GTY(()) cgraph_global_info {
71038fd1498Szrj   /* For inline clones this points to the function they will be
71138fd1498Szrj      inlined into.  */
71238fd1498Szrj   cgraph_node *inlined_to;
71338fd1498Szrj };
71438fd1498Szrj 
71538fd1498Szrj /* Represent which DECL tree (or reference to such tree)
71638fd1498Szrj    will be replaced by another tree while versioning.  */
71738fd1498Szrj struct GTY(()) ipa_replace_map
71838fd1498Szrj {
71938fd1498Szrj   /* The tree that will be replaced.  */
72038fd1498Szrj   tree old_tree;
72138fd1498Szrj   /* The new (replacing) tree.  */
72238fd1498Szrj   tree new_tree;
72338fd1498Szrj   /* Parameter number to replace, when old_tree is NULL.  */
72438fd1498Szrj   int parm_num;
72538fd1498Szrj   /* True when a substitution should be done, false otherwise.  */
72638fd1498Szrj   bool replace_p;
72738fd1498Szrj   /* True when we replace a reference to old_tree.  */
72838fd1498Szrj   bool ref_p;
72938fd1498Szrj };
73038fd1498Szrj 
73138fd1498Szrj struct GTY(()) cgraph_clone_info
73238fd1498Szrj {
73338fd1498Szrj   vec<ipa_replace_map *, va_gc> *tree_map;
73438fd1498Szrj   bitmap args_to_skip;
73538fd1498Szrj   bitmap combined_args_to_skip;
73638fd1498Szrj };
73738fd1498Szrj 
73838fd1498Szrj enum cgraph_simd_clone_arg_type
73938fd1498Szrj {
74038fd1498Szrj   SIMD_CLONE_ARG_TYPE_VECTOR,
74138fd1498Szrj   SIMD_CLONE_ARG_TYPE_UNIFORM,
74238fd1498Szrj   /* These are only for integer/pointer arguments passed by value.  */
74338fd1498Szrj   SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP,
74438fd1498Szrj   SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP,
74538fd1498Szrj   /* These 6 are only for reference type arguments or arguments passed
74638fd1498Szrj      by reference.  */
74738fd1498Szrj   SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP,
74838fd1498Szrj   SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP,
74938fd1498Szrj   SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP,
75038fd1498Szrj   SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP,
75138fd1498Szrj   SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP,
75238fd1498Szrj   SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP,
75338fd1498Szrj   SIMD_CLONE_ARG_TYPE_MASK
75438fd1498Szrj };
75538fd1498Szrj 
75638fd1498Szrj /* Function arguments in the original function of a SIMD clone.
75738fd1498Szrj    Supplementary data for `struct simd_clone'.  */
75838fd1498Szrj 
75938fd1498Szrj struct GTY(()) cgraph_simd_clone_arg {
76038fd1498Szrj   /* Original function argument as it originally existed in
76138fd1498Szrj      DECL_ARGUMENTS.  */
76238fd1498Szrj   tree orig_arg;
76338fd1498Szrj 
76438fd1498Szrj   /* orig_arg's function (or for extern functions type from
76538fd1498Szrj      TYPE_ARG_TYPES).  */
76638fd1498Szrj   tree orig_type;
76738fd1498Szrj 
76838fd1498Szrj   /* If argument is a vector, this holds the vector version of
76938fd1498Szrj      orig_arg that after adjusting the argument types will live in
77038fd1498Szrj      DECL_ARGUMENTS.  Otherwise, this is NULL.
77138fd1498Szrj 
77238fd1498Szrj      This basically holds:
77338fd1498Szrj        vector(simdlen) __typeof__(orig_arg) new_arg.  */
77438fd1498Szrj   tree vector_arg;
77538fd1498Szrj 
77638fd1498Szrj   /* vector_arg's type (or for extern functions new vector type.  */
77738fd1498Szrj   tree vector_type;
77838fd1498Szrj 
77938fd1498Szrj   /* If argument is a vector, this holds the array where the simd
78038fd1498Szrj      argument is held while executing the simd clone function.  This
78138fd1498Szrj      is a local variable in the cloned function.  Its content is
78238fd1498Szrj      copied from vector_arg upon entry to the clone.
78338fd1498Szrj 
78438fd1498Szrj      This basically holds:
78538fd1498Szrj        __typeof__(orig_arg) simd_array[simdlen].  */
78638fd1498Szrj   tree simd_array;
78738fd1498Szrj 
78838fd1498Szrj   /* A SIMD clone's argument can be either linear (constant or
78938fd1498Szrj      variable), uniform, or vector.  */
79038fd1498Szrj   enum cgraph_simd_clone_arg_type arg_type;
79138fd1498Szrj 
79238fd1498Szrj   /* For arg_type SIMD_CLONE_ARG_TYPE_LINEAR_*CONSTANT_STEP this is
79338fd1498Szrj      the constant linear step, if arg_type is
79438fd1498Szrj      SIMD_CLONE_ARG_TYPE_LINEAR_*VARIABLE_STEP, this is index of
79538fd1498Szrj      the uniform argument holding the step, otherwise 0.  */
79638fd1498Szrj   HOST_WIDE_INT linear_step;
79738fd1498Szrj 
79838fd1498Szrj   /* Variable alignment if available, otherwise 0.  */
79938fd1498Szrj   unsigned int alignment;
80038fd1498Szrj };
80138fd1498Szrj 
80238fd1498Szrj /* Specific data for a SIMD function clone.  */
80338fd1498Szrj 
80438fd1498Szrj struct GTY(()) cgraph_simd_clone {
80538fd1498Szrj   /* Number of words in the SIMD lane associated with this clone.  */
80638fd1498Szrj   unsigned int simdlen;
80738fd1498Szrj 
80838fd1498Szrj   /* Number of annotated function arguments in `args'.  This is
80938fd1498Szrj      usually the number of named arguments in FNDECL.  */
81038fd1498Szrj   unsigned int nargs;
81138fd1498Szrj 
81238fd1498Szrj   /* Max hardware vector size in bits for integral vectors.  */
81338fd1498Szrj   unsigned int vecsize_int;
81438fd1498Szrj 
81538fd1498Szrj   /* Max hardware vector size in bits for floating point vectors.  */
81638fd1498Szrj   unsigned int vecsize_float;
81738fd1498Szrj 
81838fd1498Szrj   /* Machine mode of the mask argument(s), if they are to be passed
81938fd1498Szrj      as bitmasks in integer argument(s).  VOIDmode if masks are passed
82038fd1498Szrj      as vectors of characteristic type.  */
82138fd1498Szrj   machine_mode mask_mode;
82238fd1498Szrj 
82338fd1498Szrj   /* The mangling character for a given vector size.  This is used
82438fd1498Szrj      to determine the ISA mangling bit as specified in the Intel
82538fd1498Szrj      Vector ABI.  */
82638fd1498Szrj   unsigned char vecsize_mangle;
82738fd1498Szrj 
82838fd1498Szrj   /* True if this is the masked, in-branch version of the clone,
82938fd1498Szrj      otherwise false.  */
83038fd1498Szrj   unsigned int inbranch : 1;
83138fd1498Szrj 
83238fd1498Szrj   /* Doubly linked list of SIMD clones.  */
83338fd1498Szrj   cgraph_node *prev_clone, *next_clone;
83438fd1498Szrj 
83538fd1498Szrj   /* Original cgraph node the SIMD clones were created for.  */
83638fd1498Szrj   cgraph_node *origin;
83738fd1498Szrj 
83838fd1498Szrj   /* Annotated function arguments for the original function.  */
83938fd1498Szrj   cgraph_simd_clone_arg GTY((length ("%h.nargs"))) args[1];
84038fd1498Szrj };
84138fd1498Szrj 
84238fd1498Szrj /* Function Multiversioning info.  */
84338fd1498Szrj struct GTY((for_user)) cgraph_function_version_info {
84438fd1498Szrj   /* The cgraph_node for which the function version info is stored.  */
84538fd1498Szrj   cgraph_node *this_node;
84638fd1498Szrj   /* Chains all the semantically identical function versions.  The
84738fd1498Szrj      first function in this chain is the version_info node of the
84838fd1498Szrj      default function.  */
84938fd1498Szrj   cgraph_function_version_info *prev;
85038fd1498Szrj   /* If this version node corresponds to a dispatcher for function
85138fd1498Szrj      versions, this points to the version info node of the default
85238fd1498Szrj      function, the first node in the chain.  */
85338fd1498Szrj   cgraph_function_version_info *next;
85438fd1498Szrj   /* If this node corresponds to a function version, this points
85538fd1498Szrj      to the dispatcher function decl, which is the function that must
85638fd1498Szrj      be called to execute the right function version at run-time.
85738fd1498Szrj 
85838fd1498Szrj      If this cgraph node is a dispatcher (if dispatcher_function is
85938fd1498Szrj      true, in the cgraph_node struct) for function versions, this
86038fd1498Szrj      points to resolver function, which holds the function body of the
86138fd1498Szrj      dispatcher. The dispatcher decl is an alias to the resolver
86238fd1498Szrj      function decl.  */
86338fd1498Szrj   tree dispatcher_resolver;
86438fd1498Szrj };
86538fd1498Szrj 
86638fd1498Szrj #define DEFCIFCODE(code, type, string)	CIF_ ## code,
86738fd1498Szrj /* Reasons for inlining failures.  */
86838fd1498Szrj 
86938fd1498Szrj enum cgraph_inline_failed_t {
87038fd1498Szrj #include "cif-code.def"
87138fd1498Szrj   CIF_N_REASONS
87238fd1498Szrj };
87338fd1498Szrj 
87438fd1498Szrj enum cgraph_inline_failed_type_t
87538fd1498Szrj {
87638fd1498Szrj   CIF_FINAL_NORMAL = 0,
87738fd1498Szrj   CIF_FINAL_ERROR
87838fd1498Szrj };
87938fd1498Szrj 
88038fd1498Szrj struct cgraph_edge;
88138fd1498Szrj 
88238fd1498Szrj struct cgraph_edge_hasher : ggc_ptr_hash<cgraph_edge>
88338fd1498Szrj {
88438fd1498Szrj   typedef gimple *compare_type;
88538fd1498Szrj 
88638fd1498Szrj   static hashval_t hash (cgraph_edge *);
88738fd1498Szrj   static hashval_t hash (gimple *);
88838fd1498Szrj   static bool equal (cgraph_edge *, gimple *);
88938fd1498Szrj };
89038fd1498Szrj 
89138fd1498Szrj /* The cgraph data structure.
89238fd1498Szrj    Each function decl has assigned cgraph_node listing callees and callers.  */
89338fd1498Szrj 
89438fd1498Szrj struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node {
89538fd1498Szrj public:
89638fd1498Szrj   /* Remove the node from cgraph and all inline clones inlined into it.
89738fd1498Szrj      Skip however removal of FORBIDDEN_NODE and return true if it needs to be
89838fd1498Szrj      removed.  This allows to call the function from outer loop walking clone
89938fd1498Szrj      tree.  */
90038fd1498Szrj   bool remove_symbol_and_inline_clones (cgraph_node *forbidden_node = NULL);
90138fd1498Szrj 
90238fd1498Szrj   /* Record all references from cgraph_node that are taken
90338fd1498Szrj      in statement STMT.  */
90438fd1498Szrj   void record_stmt_references (gimple *stmt);
90538fd1498Szrj 
90638fd1498Szrj   /* Like cgraph_set_call_stmt but walk the clone tree and update all
90738fd1498Szrj      clones sharing the same function body.
90838fd1498Szrj      When WHOLE_SPECULATIVE_EDGES is true, all three components of
90938fd1498Szrj      speculative edge gets updated.  Otherwise we update only direct
91038fd1498Szrj      call.  */
91138fd1498Szrj   void set_call_stmt_including_clones (gimple *old_stmt, gcall *new_stmt,
91238fd1498Szrj 				       bool update_speculative = true);
91338fd1498Szrj 
91438fd1498Szrj   /* Walk the alias chain to return the function cgraph_node is alias of.
91538fd1498Szrj      Walk through thunk, too.
91638fd1498Szrj      When AVAILABILITY is non-NULL, get minimal availability in the chain.
91738fd1498Szrj      When REF is non-NULL, assume that reference happens in symbol REF
91838fd1498Szrj      when determining the availability.  */
91938fd1498Szrj   cgraph_node *function_symbol (enum availability *avail = NULL,
92038fd1498Szrj 				struct symtab_node *ref = NULL);
92138fd1498Szrj 
92238fd1498Szrj   /* Walk the alias chain to return the function cgraph_node is alias of.
92338fd1498Szrj      Walk through non virtual thunks, too.  Thus we return either a function
92438fd1498Szrj      or a virtual thunk node.
92538fd1498Szrj      When AVAILABILITY is non-NULL, get minimal availability in the chain.
92638fd1498Szrj      When REF is non-NULL, assume that reference happens in symbol REF
92738fd1498Szrj      when determining the availability.  */
92838fd1498Szrj   cgraph_node *function_or_virtual_thunk_symbol
92938fd1498Szrj 				(enum availability *avail = NULL,
93038fd1498Szrj 				 struct symtab_node *ref = NULL);
93138fd1498Szrj 
93238fd1498Szrj   /* Create node representing clone of N executed COUNT times.  Decrease
93338fd1498Szrj      the execution counts from original node too.
93438fd1498Szrj      The new clone will have decl set to DECL that may or may not be the same
93538fd1498Szrj      as decl of N.
93638fd1498Szrj 
93738fd1498Szrj      When UPDATE_ORIGINAL is true, the counts are subtracted from the original
93838fd1498Szrj      function's profile to reflect the fact that part of execution is handled
93938fd1498Szrj      by node.
94038fd1498Szrj      When CALL_DUPLICATOIN_HOOK is true, the ipa passes are acknowledged about
94138fd1498Szrj      the new clone. Otherwise the caller is responsible for doing so later.
94238fd1498Szrj 
94338fd1498Szrj      If the new node is being inlined into another one, NEW_INLINED_TO should be
94438fd1498Szrj      the outline function the new one is (even indirectly) inlined to.
94538fd1498Szrj      All hooks will see this in node's global.inlined_to, when invoked.
94638fd1498Szrj      Can be NULL if the node is not inlined.  SUFFIX is string that is appended
94738fd1498Szrj      to the original name.  */
94838fd1498Szrj   cgraph_node *create_clone (tree decl, profile_count count,
94938fd1498Szrj 			     bool update_original,
95038fd1498Szrj 			     vec<cgraph_edge *> redirect_callers,
95138fd1498Szrj 			     bool call_duplication_hook,
95238fd1498Szrj 			     cgraph_node *new_inlined_to,
95338fd1498Szrj 			     bitmap args_to_skip, const char *suffix = NULL);
95438fd1498Szrj 
95538fd1498Szrj   /* Create callgraph node clone with new declaration.  The actual body will
95638fd1498Szrj      be copied later at compilation stage.  */
95738fd1498Szrj   cgraph_node *create_virtual_clone (vec<cgraph_edge *> redirect_callers,
95838fd1498Szrj 				     vec<ipa_replace_map *, va_gc> *tree_map,
95938fd1498Szrj 				     bitmap args_to_skip, const char * suffix);
96038fd1498Szrj 
96138fd1498Szrj   /* cgraph node being removed from symbol table; see if its entry can be
96238fd1498Szrj    replaced by other inline clone.  */
96338fd1498Szrj   cgraph_node *find_replacement (void);
96438fd1498Szrj 
96538fd1498Szrj   /* Create a new cgraph node which is the new version of
96638fd1498Szrj      callgraph node.  REDIRECT_CALLERS holds the callers
96738fd1498Szrj      edges which should be redirected to point to
96838fd1498Szrj      NEW_VERSION.  ALL the callees edges of the node
96938fd1498Szrj      are cloned to the new version node.  Return the new
97038fd1498Szrj      version node.
97138fd1498Szrj 
97238fd1498Szrj      If non-NULL BLOCK_TO_COPY determine what basic blocks
97338fd1498Szrj      was copied to prevent duplications of calls that are dead
97438fd1498Szrj      in the clone.
97538fd1498Szrj 
97638fd1498Szrj      SUFFIX is string that is appended to the original name.  */
97738fd1498Szrj 
97838fd1498Szrj   cgraph_node *create_version_clone (tree new_decl,
97938fd1498Szrj 				    vec<cgraph_edge *> redirect_callers,
98038fd1498Szrj 				    bitmap bbs_to_copy,
98138fd1498Szrj 				    const char *suffix = NULL);
98238fd1498Szrj 
98338fd1498Szrj   /* Perform function versioning.
98438fd1498Szrj      Function versioning includes copying of the tree and
98538fd1498Szrj      a callgraph update (creating a new cgraph node and updating
98638fd1498Szrj      its callees and callers).
98738fd1498Szrj 
98838fd1498Szrj      REDIRECT_CALLERS varray includes the edges to be redirected
98938fd1498Szrj      to the new version.
99038fd1498Szrj 
99138fd1498Szrj      TREE_MAP is a mapping of tree nodes we want to replace with
99238fd1498Szrj      new ones (according to results of prior analysis).
99338fd1498Szrj 
99438fd1498Szrj      If non-NULL ARGS_TO_SKIP determine function parameters to remove
99538fd1498Szrj      from new version.
99638fd1498Szrj      If SKIP_RETURN is true, the new version will return void.
99738fd1498Szrj      If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
99838fd1498Szrj      If non_NULL NEW_ENTRY determine new entry BB of the clone.
99938fd1498Szrj 
1000*e215fc28Szrj      If TARGET_ATTRIBUTES is non-null, when creating a new declaration,
1001*e215fc28Szrj      add the attributes to DECL_ATTRIBUTES.  And call valid_attribute_p
1002*e215fc28Szrj      that will promote value of the attribute DECL_FUNCTION_SPECIFIC_TARGET
1003*e215fc28Szrj      of the declaration.
1004*e215fc28Szrj 
100538fd1498Szrj      Return the new version's cgraph node.  */
100638fd1498Szrj   cgraph_node *create_version_clone_with_body
100738fd1498Szrj     (vec<cgraph_edge *> redirect_callers,
100838fd1498Szrj      vec<ipa_replace_map *, va_gc> *tree_map, bitmap args_to_skip,
100938fd1498Szrj      bool skip_return, bitmap bbs_to_copy, basic_block new_entry_block,
1010*e215fc28Szrj      const char *clone_name, tree target_attributes = NULL_TREE);
101138fd1498Szrj 
101238fd1498Szrj   /* Insert a new cgraph_function_version_info node into cgraph_fnver_htab
101338fd1498Szrj      corresponding to cgraph_node.  */
101438fd1498Szrj   cgraph_function_version_info *insert_new_function_version (void);
101538fd1498Szrj 
101638fd1498Szrj   /* Get the cgraph_function_version_info node corresponding to node.  */
101738fd1498Szrj   cgraph_function_version_info *function_version (void);
101838fd1498Szrj 
101938fd1498Szrj   /* Discover all functions and variables that are trivially needed, analyze
102038fd1498Szrj      them as well as all functions and variables referred by them  */
102138fd1498Szrj   void analyze (void);
102238fd1498Szrj 
102338fd1498Szrj   /* Add thunk alias into callgraph.  The alias declaration is ALIAS and it
102438fd1498Szrj      aliases DECL with an adjustments made into the first parameter.
102538fd1498Szrj      See comments in struct cgraph_thunk_info for detail on the parameters.  */
102638fd1498Szrj   cgraph_node * create_thunk (tree alias, tree, bool this_adjusting,
102738fd1498Szrj 			      HOST_WIDE_INT fixed_offset,
102838fd1498Szrj 			      HOST_WIDE_INT virtual_value,
102938fd1498Szrj 			      tree virtual_offset,
103038fd1498Szrj 			      tree real_alias);
103138fd1498Szrj 
103238fd1498Szrj 
103338fd1498Szrj   /* Return node that alias is aliasing.  */
103438fd1498Szrj   inline cgraph_node *get_alias_target (void);
103538fd1498Szrj 
103638fd1498Szrj   /* Given function symbol, walk the alias chain to return the function node
103738fd1498Szrj      is alias of. Do not walk through thunks.
103838fd1498Szrj      When AVAILABILITY is non-NULL, get minimal availability in the chain.
103938fd1498Szrj      When REF is non-NULL, assume that reference happens in symbol REF
104038fd1498Szrj      when determining the availability.  */
104138fd1498Szrj 
104238fd1498Szrj   cgraph_node *ultimate_alias_target (availability *availability = NULL,
104338fd1498Szrj 				      symtab_node *ref = NULL);
104438fd1498Szrj 
104538fd1498Szrj   /* Expand thunk NODE to gimple if possible.
104638fd1498Szrj      When FORCE_GIMPLE_THUNK is true, gimple thunk is created and
104738fd1498Szrj      no assembler is produced.
104838fd1498Szrj      When OUTPUT_ASM_THUNK is true, also produce assembler for
104938fd1498Szrj      thunks that are not lowered.  */
105038fd1498Szrj   bool expand_thunk (bool output_asm_thunks, bool force_gimple_thunk);
105138fd1498Szrj 
105238fd1498Szrj   /*  Call expand_thunk on all callers that are thunks and analyze those
105338fd1498Szrj       nodes that were expanded.  */
105438fd1498Szrj   void expand_all_artificial_thunks ();
105538fd1498Szrj 
105638fd1498Szrj   /* Assemble thunks and aliases associated to node.  */
105738fd1498Szrj   void assemble_thunks_and_aliases (void);
105838fd1498Szrj 
105938fd1498Szrj   /* Expand function specified by node.  */
106038fd1498Szrj   void expand (void);
106138fd1498Szrj 
106238fd1498Szrj   /* As an GCC extension we allow redefinition of the function.  The
106338fd1498Szrj      semantics when both copies of bodies differ is not well defined.
106438fd1498Szrj      We replace the old body with new body so in unit at a time mode
106538fd1498Szrj      we always use new body, while in normal mode we may end up with
106638fd1498Szrj      old body inlined into some functions and new body expanded and
106738fd1498Szrj      inlined in others.  */
106838fd1498Szrj   void reset (void);
106938fd1498Szrj 
107038fd1498Szrj   /* Creates a wrapper from cgraph_node to TARGET node. Thunk is used for this
107138fd1498Szrj      kind of wrapper method.  */
107238fd1498Szrj   void create_wrapper (cgraph_node *target);
107338fd1498Szrj 
107438fd1498Szrj   /* Verify cgraph nodes of the cgraph node.  */
107538fd1498Szrj   void DEBUG_FUNCTION verify_node (void);
107638fd1498Szrj 
107738fd1498Szrj   /* Remove function from symbol table.  */
107838fd1498Szrj   void remove (void);
107938fd1498Szrj 
108038fd1498Szrj   /* Dump call graph node to file F.  */
108138fd1498Szrj   void dump (FILE *f);
108238fd1498Szrj 
108338fd1498Szrj   /* Dump call graph node to stderr.  */
108438fd1498Szrj   void DEBUG_FUNCTION debug (void);
108538fd1498Szrj 
108638fd1498Szrj   /* When doing LTO, read cgraph_node's body from disk if it is not already
108738fd1498Szrj      present.  */
108838fd1498Szrj   bool get_untransformed_body (void);
108938fd1498Szrj 
109038fd1498Szrj   /* Prepare function body.  When doing LTO, read cgraph_node's body from disk
109138fd1498Szrj      if it is not already present.  When some IPA transformations are scheduled,
109238fd1498Szrj      apply them.  */
109338fd1498Szrj   bool get_body (void);
109438fd1498Szrj 
109538fd1498Szrj   /* Release memory used to represent body of function.
109638fd1498Szrj      Use this only for functions that are released before being translated to
109738fd1498Szrj      target code (i.e. RTL).  Functions that are compiled to RTL and beyond
109838fd1498Szrj      are free'd in final.c via free_after_compilation().  */
109938fd1498Szrj   void release_body (bool keep_arguments = false);
110038fd1498Szrj 
110138fd1498Szrj   /* Return the DECL_STRUCT_FUNCTION of the function.  */
110238fd1498Szrj   struct function *get_fun (void);
110338fd1498Szrj 
110438fd1498Szrj   /* cgraph_node is no longer nested function; update cgraph accordingly.  */
110538fd1498Szrj   void unnest (void);
110638fd1498Szrj 
110738fd1498Szrj   /* Bring cgraph node local.  */
110838fd1498Szrj   void make_local (void);
110938fd1498Szrj 
111038fd1498Szrj   /* Likewise indicate that a node is having address taken.  */
111138fd1498Szrj   void mark_address_taken (void);
111238fd1498Szrj 
111338fd1498Szrj   /* Set fialization priority to PRIORITY.  */
111438fd1498Szrj   void set_fini_priority (priority_type priority);
111538fd1498Szrj 
111638fd1498Szrj   /* Return the finalization priority.  */
111738fd1498Szrj   priority_type get_fini_priority (void);
111838fd1498Szrj 
111938fd1498Szrj   /* Create edge from a given function to CALLEE in the cgraph.  */
112038fd1498Szrj   cgraph_edge *create_edge (cgraph_node *callee,
112138fd1498Szrj 			    gcall *call_stmt, profile_count count);
112238fd1498Szrj 
112338fd1498Szrj   /* Create an indirect edge with a yet-undetermined callee where the call
112438fd1498Szrj      statement destination is a formal parameter of the caller with index
112538fd1498Szrj      PARAM_INDEX. */
112638fd1498Szrj   cgraph_edge *create_indirect_edge (gcall *call_stmt, int ecf_flags,
112738fd1498Szrj 				     profile_count count,
112838fd1498Szrj 				     bool compute_indirect_info = true);
112938fd1498Szrj 
113038fd1498Szrj   /* Like cgraph_create_edge walk the clone tree and update all clones sharing
113138fd1498Szrj    same function body.  If clones already have edge for OLD_STMT; only
113238fd1498Szrj    update the edge same way as cgraph_set_call_stmt_including_clones does.  */
113338fd1498Szrj   void create_edge_including_clones (cgraph_node *callee,
113438fd1498Szrj 				     gimple *old_stmt, gcall *stmt,
113538fd1498Szrj 				     profile_count count,
113638fd1498Szrj 				     cgraph_inline_failed_t reason);
113738fd1498Szrj 
113838fd1498Szrj   /* Return the callgraph edge representing the GIMPLE_CALL statement
113938fd1498Szrj      CALL_STMT.  */
114038fd1498Szrj   cgraph_edge *get_edge (gimple *call_stmt);
114138fd1498Szrj 
114238fd1498Szrj   /* Collect all callers of cgraph_node and its aliases that are known to lead
114338fd1498Szrj      to NODE (i.e. are not overwritable) and that are not thunks.  */
114438fd1498Szrj   vec<cgraph_edge *> collect_callers (void);
114538fd1498Szrj 
114638fd1498Szrj   /* Remove all callers from the node.  */
114738fd1498Szrj   void remove_callers (void);
114838fd1498Szrj 
114938fd1498Szrj   /* Remove all callees from the node.  */
115038fd1498Szrj   void remove_callees (void);
115138fd1498Szrj 
115238fd1498Szrj   /* Return function availability.  See cgraph.h for description of individual
115338fd1498Szrj      return values.  */
115438fd1498Szrj   enum availability get_availability (symtab_node *ref = NULL);
115538fd1498Szrj 
115638fd1498Szrj   /* Set TREE_NOTHROW on cgraph_node's decl and on aliases of the node
115738fd1498Szrj      if any to NOTHROW.  */
115838fd1498Szrj   bool set_nothrow_flag (bool nothrow);
115938fd1498Szrj 
116038fd1498Szrj   /* SET DECL_IS_MALLOC on cgraph_node's decl and on aliases of the node
116138fd1498Szrj      if any.  */
116238fd1498Szrj   bool set_malloc_flag (bool malloc_p);
116338fd1498Szrj 
116438fd1498Szrj   /* If SET_CONST is true, mark function, aliases and thunks to be ECF_CONST.
116538fd1498Szrj     If SET_CONST if false, clear the flag.
116638fd1498Szrj 
116738fd1498Szrj     When setting the flag be careful about possible interposition and
116838fd1498Szrj     do not set the flag for functions that can be interposet and set pure
116938fd1498Szrj     flag for functions that can bind to other definition.
117038fd1498Szrj 
117138fd1498Szrj     Return true if any change was done. */
117238fd1498Szrj 
117338fd1498Szrj   bool set_const_flag (bool set_const, bool looping);
117438fd1498Szrj 
117538fd1498Szrj   /* Set DECL_PURE_P on cgraph_node's decl and on aliases of the node
117638fd1498Szrj      if any to PURE.
117738fd1498Szrj 
117838fd1498Szrj      When setting the flag, be careful about possible interposition.
117938fd1498Szrj      Return true if any change was done. */
118038fd1498Szrj 
118138fd1498Szrj   bool set_pure_flag (bool pure, bool looping);
118238fd1498Szrj 
118338fd1498Szrj   /* Call callback on function and aliases associated to the function.
118438fd1498Szrj      When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
118538fd1498Szrj      skipped. */
118638fd1498Szrj 
118738fd1498Szrj   bool call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
118838fd1498Szrj 						      void *),
118938fd1498Szrj 				    void *data, bool include_overwritable);
119038fd1498Szrj 
119138fd1498Szrj   /* Call callback on cgraph_node, thunks and aliases associated to NODE.
119238fd1498Szrj      When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
119338fd1498Szrj      skipped.  When EXCLUDE_VIRTUAL_THUNKS is true, virtual thunks are
119438fd1498Szrj      skipped.  */
119538fd1498Szrj   bool call_for_symbol_thunks_and_aliases (bool (*callback) (cgraph_node *node,
119638fd1498Szrj 							     void *data),
119738fd1498Szrj 					   void *data,
119838fd1498Szrj 					   bool include_overwritable,
119938fd1498Szrj 					   bool exclude_virtual_thunks = false);
120038fd1498Szrj 
120138fd1498Szrj   /* Likewise indicate that a node is needed, i.e. reachable via some
120238fd1498Szrj      external means.  */
120338fd1498Szrj   inline void mark_force_output (void);
120438fd1498Szrj 
120538fd1498Szrj   /* Return true when function can be marked local.  */
120638fd1498Szrj   bool local_p (void);
120738fd1498Szrj 
120838fd1498Szrj   /* Return true if cgraph_node can be made local for API change.
120938fd1498Szrj      Extern inline functions and C++ COMDAT functions can be made local
121038fd1498Szrj      at the expense of possible code size growth if function is used in multiple
121138fd1498Szrj      compilation units.  */
121238fd1498Szrj   bool can_be_local_p (void);
121338fd1498Szrj 
121438fd1498Szrj   /* Return true when cgraph_node can not return or throw and thus
121538fd1498Szrj      it is safe to ignore its side effects for IPA analysis.  */
121638fd1498Szrj   bool cannot_return_p (void);
121738fd1498Szrj 
121838fd1498Szrj   /* Return true when function cgraph_node and all its aliases are only called
121938fd1498Szrj      directly.
122038fd1498Szrj      i.e. it is not externally visible, address was not taken and
122138fd1498Szrj      it is not used in any other non-standard way.  */
122238fd1498Szrj   bool only_called_directly_p (void);
122338fd1498Szrj 
122438fd1498Szrj   /* Return true when function is only called directly or it has alias.
122538fd1498Szrj      i.e. it is not externally visible, address was not taken and
122638fd1498Szrj      it is not used in any other non-standard way.  */
122738fd1498Szrj   inline bool only_called_directly_or_aliased_p (void);
122838fd1498Szrj 
122938fd1498Szrj   /* Return true when function cgraph_node can be expected to be removed
123038fd1498Szrj      from program when direct calls in this compilation unit are removed.
123138fd1498Szrj 
123238fd1498Szrj      As a special case COMDAT functions are
123338fd1498Szrj      cgraph_can_remove_if_no_direct_calls_p while the are not
123438fd1498Szrj      cgraph_only_called_directly_p (it is possible they are called from other
123538fd1498Szrj      unit)
123638fd1498Szrj 
123738fd1498Szrj      This function behaves as cgraph_only_called_directly_p because eliminating
123838fd1498Szrj      all uses of COMDAT function does not make it necessarily disappear from
123938fd1498Szrj      the program unless we are compiling whole program or we do LTO.  In this
124038fd1498Szrj      case we know we win since dynamic linking will not really discard the
124138fd1498Szrj      linkonce section.
124238fd1498Szrj 
124338fd1498Szrj      If WILL_INLINE is true, assume that function will be inlined into all the
124438fd1498Szrj      direct calls.  */
124538fd1498Szrj   bool will_be_removed_from_program_if_no_direct_calls_p
124638fd1498Szrj 	 (bool will_inline = false);
124738fd1498Szrj 
124838fd1498Szrj   /* Return true when function can be removed from callgraph
124938fd1498Szrj      if all direct calls and references are eliminated.  The function does
125038fd1498Szrj      not take into account comdat groups.  */
125138fd1498Szrj   bool can_remove_if_no_direct_calls_and_refs_p (void);
125238fd1498Szrj 
125338fd1498Szrj   /* Return true when function cgraph_node and its aliases can be removed from
125438fd1498Szrj      callgraph if all direct calls are eliminated.
125538fd1498Szrj      If WILL_INLINE is true, assume that function will be inlined into all the
125638fd1498Szrj      direct calls.  */
125738fd1498Szrj   bool can_remove_if_no_direct_calls_p (bool will_inline = false);
125838fd1498Szrj 
125938fd1498Szrj   /* Return true when callgraph node is a function with Gimple body defined
126038fd1498Szrj      in current unit.  Functions can also be define externally or they
126138fd1498Szrj      can be thunks with no Gimple representation.
126238fd1498Szrj 
126338fd1498Szrj      Note that at WPA stage, the function body may not be present in memory.  */
126438fd1498Szrj   inline bool has_gimple_body_p (void);
126538fd1498Szrj 
1266*e215fc28Szrj   /* Return true if this node represents a former, i.e. an expanded, thunk.  */
1267*e215fc28Szrj   inline bool former_thunk_p (void);
1268*e215fc28Szrj 
126938fd1498Szrj   /* Return true if function should be optimized for size.  */
127038fd1498Szrj   bool optimize_for_size_p (void);
127138fd1498Szrj 
127238fd1498Szrj   /* Dump the callgraph to file F.  */
127338fd1498Szrj   static void dump_cgraph (FILE *f);
127438fd1498Szrj 
127538fd1498Szrj   /* Dump the call graph to stderr.  */
127638fd1498Szrj   static inline
debug_cgraphcgraph_node127738fd1498Szrj   void debug_cgraph (void)
127838fd1498Szrj   {
127938fd1498Szrj     dump_cgraph (stderr);
128038fd1498Szrj   }
128138fd1498Szrj 
128238fd1498Szrj   /* Record that DECL1 and DECL2 are semantically identical function
128338fd1498Szrj      versions.  */
128438fd1498Szrj   static void record_function_versions (tree decl1, tree decl2);
128538fd1498Szrj 
128638fd1498Szrj   /* Remove the cgraph_function_version_info and cgraph_node for DECL.  This
128738fd1498Szrj      DECL is a duplicate declaration.  */
128838fd1498Szrj   static void delete_function_version_by_decl (tree decl);
128938fd1498Szrj 
129038fd1498Szrj   /* Add the function FNDECL to the call graph.
129138fd1498Szrj      Unlike finalize_function, this function is intended to be used
129238fd1498Szrj      by middle end and allows insertion of new function at arbitrary point
129338fd1498Szrj      of compilation.  The function can be either in high, low or SSA form
129438fd1498Szrj      GIMPLE.
129538fd1498Szrj 
129638fd1498Szrj      The function is assumed to be reachable and have address taken (so no
129738fd1498Szrj      API breaking optimizations are performed on it).
129838fd1498Szrj 
129938fd1498Szrj      Main work done by this function is to enqueue the function for later
130038fd1498Szrj      processing to avoid need the passes to be re-entrant.  */
130138fd1498Szrj   static void add_new_function (tree fndecl, bool lowered);
130238fd1498Szrj 
130338fd1498Szrj   /* Return callgraph node for given symbol and check it is a function. */
getcgraph_node130438fd1498Szrj   static inline cgraph_node *get (const_tree decl)
130538fd1498Szrj   {
130638fd1498Szrj     gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL);
130738fd1498Szrj     return dyn_cast <cgraph_node *> (symtab_node::get (decl));
130838fd1498Szrj   }
130938fd1498Szrj 
131038fd1498Szrj   /* DECL has been parsed.  Take it, queue it, compile it at the whim of the
131138fd1498Szrj      logic in effect.  If NO_COLLECT is true, then our caller cannot stand to
131238fd1498Szrj      have the garbage collector run at the moment.  We would need to either
131338fd1498Szrj      create a new GC context, or just not compile right now.  */
131438fd1498Szrj   static void finalize_function (tree, bool);
131538fd1498Szrj 
131638fd1498Szrj   /* Return cgraph node assigned to DECL.  Create new one when needed.  */
131738fd1498Szrj   static cgraph_node * create (tree decl);
131838fd1498Szrj 
131938fd1498Szrj   /* Try to find a call graph node for declaration DECL and if it does not
132038fd1498Szrj      exist or if it corresponds to an inline clone, create a new one.  */
132138fd1498Szrj   static cgraph_node * get_create (tree);
132238fd1498Szrj 
132338fd1498Szrj   /* Return local info for the compiled function.  */
132438fd1498Szrj   static cgraph_local_info *local_info (tree decl);
132538fd1498Szrj 
132638fd1498Szrj   /* Return local info for the compiled function.  */
132738fd1498Szrj   static struct cgraph_rtl_info *rtl_info (tree);
132838fd1498Szrj 
132938fd1498Szrj   /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
133038fd1498Szrj      Return NULL if there's no such node.  */
133138fd1498Szrj   static cgraph_node *get_for_asmname (tree asmname);
133238fd1498Szrj 
133338fd1498Szrj   /* Attempt to mark ALIAS as an alias to DECL.  Return alias node if
133438fd1498Szrj      successful and NULL otherwise.
133538fd1498Szrj      Same body aliases are output whenever the body of DECL is output,
133638fd1498Szrj      and cgraph_node::get (ALIAS) transparently
133738fd1498Szrj      returns cgraph_node::get (DECL).  */
133838fd1498Szrj   static cgraph_node * create_same_body_alias (tree alias, tree decl);
133938fd1498Szrj 
134038fd1498Szrj   /* Verify whole cgraph structure.  */
134138fd1498Szrj   static void DEBUG_FUNCTION verify_cgraph_nodes (void);
134238fd1498Szrj 
134338fd1498Szrj   /* Verify cgraph, if consistency checking is enabled.  */
134438fd1498Szrj   static inline void checking_verify_cgraph_nodes (void);
134538fd1498Szrj 
134638fd1498Szrj   /* Worker to bring NODE local.  */
134738fd1498Szrj   static bool make_local (cgraph_node *node, void *);
134838fd1498Szrj 
134938fd1498Szrj   /* Mark ALIAS as an alias to DECL.  DECL_NODE is cgraph node representing
135038fd1498Szrj      the function body is associated
135138fd1498Szrj      with (not necessarily cgraph_node (DECL).  */
135238fd1498Szrj   static cgraph_node *create_alias (tree alias, tree target);
135338fd1498Szrj 
135438fd1498Szrj   /* Return true if NODE has thunk.  */
135538fd1498Szrj   static bool has_thunk_p (cgraph_node *node, void *);
135638fd1498Szrj 
135738fd1498Szrj   cgraph_edge *callees;
135838fd1498Szrj   cgraph_edge *callers;
135938fd1498Szrj   /* List of edges representing indirect calls with a yet undetermined
136038fd1498Szrj      callee.  */
136138fd1498Szrj   cgraph_edge *indirect_calls;
136238fd1498Szrj   /* For nested functions points to function the node is nested in.  */
136338fd1498Szrj   cgraph_node *origin;
136438fd1498Szrj   /* Points to first nested function, if any.  */
136538fd1498Szrj   cgraph_node *nested;
136638fd1498Szrj   /* Pointer to the next function with same origin, if any.  */
136738fd1498Szrj   cgraph_node *next_nested;
136838fd1498Szrj   /* Pointer to the next clone.  */
136938fd1498Szrj   cgraph_node *next_sibling_clone;
137038fd1498Szrj   cgraph_node *prev_sibling_clone;
137138fd1498Szrj   cgraph_node *clones;
137238fd1498Szrj   cgraph_node *clone_of;
137338fd1498Szrj   /* If instrumentation_clone is 1 then instrumented_version points
137438fd1498Szrj      to the original function used to make instrumented version.
137538fd1498Szrj      Otherwise points to instrumented version of the function.  */
137638fd1498Szrj   cgraph_node *instrumented_version;
137738fd1498Szrj   /* If instrumentation_clone is 1 then orig_decl is the original
137838fd1498Szrj      function declaration.  */
137938fd1498Szrj   tree orig_decl;
138038fd1498Szrj   /* For functions with many calls sites it holds map from call expression
138138fd1498Szrj      to the edge to speed up cgraph_edge function.  */
138238fd1498Szrj   hash_table<cgraph_edge_hasher> *GTY(()) call_site_hash;
138338fd1498Szrj   /* Declaration node used to be clone of. */
138438fd1498Szrj   tree former_clone_of;
138538fd1498Szrj 
138638fd1498Szrj   /* If this is a SIMD clone, this points to the SIMD specific
138738fd1498Szrj      information for it.  */
138838fd1498Szrj   cgraph_simd_clone *simdclone;
138938fd1498Szrj   /* If this function has SIMD clones, this points to the first clone.  */
139038fd1498Szrj   cgraph_node *simd_clones;
139138fd1498Szrj 
139238fd1498Szrj   /* Interprocedural passes scheduled to have their transform functions
139338fd1498Szrj      applied next time we execute local pass on them.  We maintain it
139438fd1498Szrj      per-function in order to allow IPA passes to introduce new functions.  */
139538fd1498Szrj   vec<ipa_opt_pass> GTY((skip)) ipa_transforms_to_apply;
139638fd1498Szrj 
139738fd1498Szrj   cgraph_local_info local;
139838fd1498Szrj   cgraph_global_info global;
139938fd1498Szrj   struct cgraph_rtl_info *rtl;
140038fd1498Szrj   cgraph_clone_info clone;
140138fd1498Szrj   cgraph_thunk_info thunk;
140238fd1498Szrj 
140338fd1498Szrj   /* Expected number of executions: calculated in profile.c.  */
140438fd1498Szrj   profile_count count;
140538fd1498Szrj   /* How to scale counts at materialization time; used to merge
140638fd1498Szrj      LTO units with different number of profile runs.  */
140738fd1498Szrj   int count_materialization_scale;
140838fd1498Szrj   /* Unique id of the node.  */
140938fd1498Szrj   int uid;
141038fd1498Szrj   /* Summary unique id of the node.  */
141138fd1498Szrj   int summary_uid;
141238fd1498Szrj   /* ID assigned by the profiling.  */
141338fd1498Szrj   unsigned int profile_id;
141438fd1498Szrj   /* Time profiler: first run of function.  */
141538fd1498Szrj   int tp_first_run;
141638fd1498Szrj 
141738fd1498Szrj   /* Set when decl is an abstract function pointed to by the
141838fd1498Szrj      ABSTRACT_DECL_ORIGIN of a reachable function.  */
141938fd1498Szrj   unsigned used_as_abstract_origin : 1;
142038fd1498Szrj   /* Set once the function is lowered (i.e. its CFG is built).  */
142138fd1498Szrj   unsigned lowered : 1;
142238fd1498Szrj   /* Set once the function has been instantiated and its callee
142338fd1498Szrj      lists created.  */
142438fd1498Szrj   unsigned process : 1;
142538fd1498Szrj   /* How commonly executed the node is.  Initialized during branch
142638fd1498Szrj      probabilities pass.  */
142738fd1498Szrj   ENUM_BITFIELD (node_frequency) frequency : 2;
142838fd1498Szrj   /* True when function can only be called at startup (from static ctor).  */
142938fd1498Szrj   unsigned only_called_at_startup : 1;
143038fd1498Szrj   /* True when function can only be called at startup (from static dtor).  */
143138fd1498Szrj   unsigned only_called_at_exit : 1;
143238fd1498Szrj   /* True when function is the transactional clone of a function which
143338fd1498Szrj      is called only from inside transactions.  */
143438fd1498Szrj   /* ?? We should be able to remove this.  We have enough bits in
143538fd1498Szrj      cgraph to calculate it.  */
143638fd1498Szrj   unsigned tm_clone : 1;
143738fd1498Szrj   /* True if this decl is a dispatcher for function versions.  */
143838fd1498Szrj   unsigned dispatcher_function : 1;
143938fd1498Szrj   /* True if this decl calls a COMDAT-local function.  This is set up in
144038fd1498Szrj      compute_fn_summary and inline_call.  */
144138fd1498Szrj   unsigned calls_comdat_local : 1;
144238fd1498Szrj   /* True if node has been created by merge operation in IPA-ICF.  */
144338fd1498Szrj   unsigned icf_merged: 1;
144438fd1498Szrj   /* True when function is clone created for Pointer Bounds Checker
144538fd1498Szrj      instrumentation.  */
144638fd1498Szrj   unsigned instrumentation_clone : 1;
144738fd1498Szrj   /* True if call to node can't result in a call to free, munmap or
144838fd1498Szrj      other operation that could make previously non-trapping memory
144938fd1498Szrj      accesses trapping.  */
145038fd1498Szrj   unsigned nonfreeing_fn : 1;
145138fd1498Szrj   /* True if there was multiple COMDAT bodies merged by lto-symtab.  */
145238fd1498Szrj   unsigned merged_comdat : 1;
145338fd1498Szrj   /* True if function was created to be executed in parallel.  */
145438fd1498Szrj   unsigned parallelized_function : 1;
145538fd1498Szrj   /* True if function is part split out by ipa-split.  */
145638fd1498Szrj   unsigned split_part : 1;
145738fd1498Szrj   /* True if the function appears as possible target of indirect call.  */
145838fd1498Szrj   unsigned indirect_call_target : 1;
145938fd1498Szrj 
146038fd1498Szrj private:
146138fd1498Szrj   /* Worker for call_for_symbol_and_aliases.  */
146238fd1498Szrj   bool call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
146338fd1498Szrj 						        void *),
146438fd1498Szrj 				      void *data, bool include_overwritable);
146538fd1498Szrj };
146638fd1498Szrj 
146738fd1498Szrj /* A cgraph node set is a collection of cgraph nodes.  A cgraph node
146838fd1498Szrj    can appear in multiple sets.  */
146938fd1498Szrj struct cgraph_node_set_def
147038fd1498Szrj {
147138fd1498Szrj   hash_map<cgraph_node *, size_t> *map;
147238fd1498Szrj   vec<cgraph_node *> nodes;
147338fd1498Szrj };
147438fd1498Szrj 
147538fd1498Szrj typedef cgraph_node_set_def *cgraph_node_set;
147638fd1498Szrj typedef struct varpool_node_set_def *varpool_node_set;
147738fd1498Szrj 
147838fd1498Szrj class varpool_node;
147938fd1498Szrj 
148038fd1498Szrj /* A varpool node set is a collection of varpool nodes.  A varpool node
148138fd1498Szrj    can appear in multiple sets.  */
148238fd1498Szrj struct varpool_node_set_def
148338fd1498Szrj {
148438fd1498Szrj   hash_map<varpool_node *, size_t> * map;
148538fd1498Szrj   vec<varpool_node *> nodes;
148638fd1498Szrj };
148738fd1498Szrj 
148838fd1498Szrj /* Iterator structure for cgraph node sets.  */
148938fd1498Szrj struct cgraph_node_set_iterator
149038fd1498Szrj {
149138fd1498Szrj   cgraph_node_set set;
149238fd1498Szrj   unsigned index;
149338fd1498Szrj };
149438fd1498Szrj 
149538fd1498Szrj /* Iterator structure for varpool node sets.  */
149638fd1498Szrj struct varpool_node_set_iterator
149738fd1498Szrj {
149838fd1498Szrj   varpool_node_set set;
149938fd1498Szrj   unsigned index;
150038fd1498Szrj };
150138fd1498Szrj 
150238fd1498Szrj /* Context of polymorphic call. It represent information about the type of
150338fd1498Szrj    instance that may reach the call.  This is used by ipa-devirt walkers of the
150438fd1498Szrj    type inheritance graph.  */
150538fd1498Szrj 
class()150638fd1498Szrj class GTY(()) ipa_polymorphic_call_context {
150738fd1498Szrj public:
150838fd1498Szrj   /* The called object appears in an object of type OUTER_TYPE
150938fd1498Szrj      at offset OFFSET.  When information is not 100% reliable, we
151038fd1498Szrj      use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */
151138fd1498Szrj   HOST_WIDE_INT offset;
151238fd1498Szrj   HOST_WIDE_INT speculative_offset;
151338fd1498Szrj   tree outer_type;
151438fd1498Szrj   tree speculative_outer_type;
151538fd1498Szrj   /* True if outer object may be in construction or destruction.  */
151638fd1498Szrj   unsigned maybe_in_construction : 1;
151738fd1498Szrj   /* True if outer object may be of derived type.  */
151838fd1498Szrj   unsigned maybe_derived_type : 1;
151938fd1498Szrj   /* True if speculative outer object may be of derived type.  We always
152038fd1498Szrj      speculate that construction does not happen.  */
152138fd1498Szrj   unsigned speculative_maybe_derived_type : 1;
152238fd1498Szrj   /* True if the context is invalid and all calls should be redirected
152338fd1498Szrj      to BUILTIN_UNREACHABLE.  */
152438fd1498Szrj   unsigned invalid : 1;
152538fd1498Szrj   /* True if the outer type is dynamic.  */
152638fd1498Szrj   unsigned dynamic : 1;
152738fd1498Szrj 
152838fd1498Szrj   /* Build empty "I know nothing" context.  */
152938fd1498Szrj   ipa_polymorphic_call_context ();
153038fd1498Szrj   /* Build polymorphic call context for indirect call E.  */
153138fd1498Szrj   ipa_polymorphic_call_context (cgraph_edge *e);
153238fd1498Szrj   /* Build polymorphic call context for IP invariant CST.
153338fd1498Szrj      If specified, OTR_TYPE specify the type of polymorphic call
153438fd1498Szrj      that takes CST+OFFSET as a prameter.  */
153538fd1498Szrj   ipa_polymorphic_call_context (tree cst, tree otr_type = NULL,
153638fd1498Szrj 				HOST_WIDE_INT offset = 0);
153738fd1498Szrj   /* Build context for pointer REF contained in FNDECL at statement STMT.
153838fd1498Szrj      if INSTANCE is non-NULL, return pointer to the object described by
153938fd1498Szrj      the context.  */
154038fd1498Szrj   ipa_polymorphic_call_context (tree fndecl, tree ref, gimple *stmt,
154138fd1498Szrj 				tree *instance = NULL);
154238fd1498Szrj 
154338fd1498Szrj   /* Look for vtable stores or constructor calls to work out dynamic type
154438fd1498Szrj      of memory location.  */
154538fd1498Szrj   bool get_dynamic_type (tree, tree, tree, gimple *);
154638fd1498Szrj 
154738fd1498Szrj   /* Make context non-speculative.  */
154838fd1498Szrj   void clear_speculation ();
154938fd1498Szrj 
155038fd1498Szrj   /* Produce context specifying all derrived types of OTR_TYPE.  If OTR_TYPE is
155138fd1498Szrj      NULL, the context is set to dummy "I know nothing" setting.  */
155238fd1498Szrj   void clear_outer_type (tree otr_type = NULL);
155338fd1498Szrj 
155438fd1498Szrj   /* Walk container types and modify context to point to actual class
155538fd1498Szrj      containing OTR_TYPE (if non-NULL) as base class.
155638fd1498Szrj      Return true if resulting context is valid.
155738fd1498Szrj 
155838fd1498Szrj      When CONSIDER_PLACEMENT_NEW is false, reject contexts that may be made
155938fd1498Szrj      valid only via allocation of new polymorphic type inside by means
156038fd1498Szrj      of placement new.
156138fd1498Szrj 
156238fd1498Szrj      When CONSIDER_BASES is false, only look for actual fields, not base types
156338fd1498Szrj      of TYPE.  */
156438fd1498Szrj   bool restrict_to_inner_class (tree otr_type,
156538fd1498Szrj 				bool consider_placement_new = true,
156638fd1498Szrj 				bool consider_bases = true);
156738fd1498Szrj 
156838fd1498Szrj   /* Adjust all offsets in contexts by given number of bits.  */
156938fd1498Szrj   void offset_by (HOST_WIDE_INT);
157038fd1498Szrj   /* Use when we can not track dynamic type change.  This speculatively assume
157138fd1498Szrj      type change is not happening.  */
157238fd1498Szrj   void possible_dynamic_type_change (bool, tree otr_type = NULL);
157338fd1498Szrj   /* Assume that both THIS and a given context is valid and strenghten THIS
157438fd1498Szrj      if possible.  Return true if any strenghtening was made.
157538fd1498Szrj      If actual type the context is being used in is known, OTR_TYPE should be
157638fd1498Szrj      set accordingly. This improves quality of combined result.  */
157738fd1498Szrj   bool combine_with (ipa_polymorphic_call_context, tree otr_type = NULL);
157838fd1498Szrj   bool meet_with (ipa_polymorphic_call_context, tree otr_type = NULL);
157938fd1498Szrj 
158038fd1498Szrj   /* Return TRUE if context is fully useless.  */
158138fd1498Szrj   bool useless_p () const;
158238fd1498Szrj   /* Return TRUE if this context conveys the same information as X.  */
158338fd1498Szrj   bool equal_to (const ipa_polymorphic_call_context &x) const;
158438fd1498Szrj 
158538fd1498Szrj   /* Dump human readable context to F.  If NEWLINE is true, it will be
158638fd1498Szrj      terminated by a newline.  */
158738fd1498Szrj   void dump (FILE *f, bool newline = true) const;
158838fd1498Szrj   void DEBUG_FUNCTION debug () const;
158938fd1498Szrj 
159038fd1498Szrj   /* LTO streaming.  */
159138fd1498Szrj   void stream_out (struct output_block *) const;
159238fd1498Szrj   void stream_in (struct lto_input_block *, struct data_in *data_in);
159338fd1498Szrj 
159438fd1498Szrj private:
159538fd1498Szrj   bool combine_speculation_with (tree, HOST_WIDE_INT, bool, tree);
159638fd1498Szrj   bool meet_speculation_with (tree, HOST_WIDE_INT, bool, tree);
159738fd1498Szrj   void set_by_decl (tree, HOST_WIDE_INT);
159838fd1498Szrj   bool set_by_invariant (tree, tree, HOST_WIDE_INT);
159938fd1498Szrj   bool speculation_consistent_p (tree, HOST_WIDE_INT, bool, tree) const;
160038fd1498Szrj   void make_speculative (tree otr_type = NULL);
160138fd1498Szrj };
160238fd1498Szrj 
160338fd1498Szrj /* Structure containing additional information about an indirect call.  */
160438fd1498Szrj 
160538fd1498Szrj struct GTY(()) cgraph_indirect_call_info
160638fd1498Szrj {
160738fd1498Szrj   /* When agg_content is set, an offset where the call pointer is located
160838fd1498Szrj      within the aggregate.  */
160938fd1498Szrj   HOST_WIDE_INT offset;
161038fd1498Szrj   /* Context of the polymorphic call; use only when POLYMORPHIC flag is set.  */
161138fd1498Szrj   ipa_polymorphic_call_context context;
161238fd1498Szrj   /* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set).  */
161338fd1498Szrj   HOST_WIDE_INT otr_token;
161438fd1498Szrj   /* Type of the object from OBJ_TYPE_REF_OBJECT. */
161538fd1498Szrj   tree otr_type;
161638fd1498Szrj   /* Index of the parameter that is called.  */
161738fd1498Szrj   int param_index;
161838fd1498Szrj   /* ECF flags determined from the caller.  */
161938fd1498Szrj   int ecf_flags;
162038fd1498Szrj   /* Profile_id of common target obtrained from profile.  */
162138fd1498Szrj   int common_target_id;
162238fd1498Szrj   /* Probability that call will land in function with COMMON_TARGET_ID.  */
162338fd1498Szrj   int common_target_probability;
162438fd1498Szrj 
162538fd1498Szrj   /* Set when the call is a virtual call with the parameter being the
162638fd1498Szrj      associated object pointer rather than a simple direct call.  */
162738fd1498Szrj   unsigned polymorphic : 1;
162838fd1498Szrj   /* Set when the call is a call of a pointer loaded from contents of an
162938fd1498Szrj      aggregate at offset.  */
163038fd1498Szrj   unsigned agg_contents : 1;
163138fd1498Szrj   /* Set when this is a call through a member pointer.  */
163238fd1498Szrj   unsigned member_ptr : 1;
163338fd1498Szrj   /* When the agg_contents bit is set, this one determines whether the
163438fd1498Szrj      destination is loaded from a parameter passed by reference. */
163538fd1498Szrj   unsigned by_ref : 1;
163638fd1498Szrj   /* When the agg_contents bit is set, this one determines whether we can
163738fd1498Szrj      deduce from the function body that the loaded value from the reference is
163838fd1498Szrj      never modified between the invocation of the function and the load
163938fd1498Szrj      point.  */
164038fd1498Szrj   unsigned guaranteed_unmodified : 1;
164138fd1498Szrj   /* For polymorphic calls this specify whether the virtual table pointer
164238fd1498Szrj      may have changed in between function entry and the call.  */
164338fd1498Szrj   unsigned vptr_changed : 1;
164438fd1498Szrj };
164538fd1498Szrj 
164638fd1498Szrj struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"),
164738fd1498Szrj 	    for_user)) cgraph_edge {
164838fd1498Szrj   friend class cgraph_node;
164938fd1498Szrj 
165038fd1498Szrj   /* Remove the edge in the cgraph.  */
165138fd1498Szrj   void remove (void);
165238fd1498Szrj 
165338fd1498Szrj   /* Change field call_stmt of edge to NEW_STMT.
165438fd1498Szrj      If UPDATE_SPECULATIVE and E is any component of speculative
165538fd1498Szrj      edge, then update all components.  */
165638fd1498Szrj   void set_call_stmt (gcall *new_stmt, bool update_speculative = true);
165738fd1498Szrj 
165838fd1498Szrj   /* Redirect callee of the edge to N.  The function does not update underlying
165938fd1498Szrj      call expression.  */
166038fd1498Szrj   void redirect_callee (cgraph_node *n);
166138fd1498Szrj 
166238fd1498Szrj   /* If the edge does not lead to a thunk, simply redirect it to N.  Otherwise
166338fd1498Szrj      create one or more equivalent thunks for N and redirect E to the first in
166438fd1498Szrj      the chain.  Note that it is then necessary to call
166538fd1498Szrj      n->expand_all_artificial_thunks once all callers are redirected.  */
166638fd1498Szrj   void redirect_callee_duplicating_thunks (cgraph_node *n);
166738fd1498Szrj 
166838fd1498Szrj   /* Make an indirect edge with an unknown callee an ordinary edge leading to
166938fd1498Szrj      CALLEE.  DELTA is an integer constant that is to be added to the this
167038fd1498Szrj      pointer (first parameter) to compensate for skipping
167138fd1498Szrj      a thunk adjustment.  */
167238fd1498Szrj   cgraph_edge *make_direct (cgraph_node *callee);
167338fd1498Szrj 
167438fd1498Szrj   /* Turn edge into speculative call calling N2. Update
167538fd1498Szrj      the profile so the direct call is taken COUNT times
167638fd1498Szrj      with FREQUENCY.  */
167738fd1498Szrj   cgraph_edge *make_speculative (cgraph_node *n2, profile_count direct_count);
167838fd1498Szrj 
167938fd1498Szrj    /* Given speculative call edge, return all three components.  */
168038fd1498Szrj   void speculative_call_info (cgraph_edge *&direct, cgraph_edge *&indirect,
168138fd1498Szrj 			      ipa_ref *&reference);
168238fd1498Szrj 
168338fd1498Szrj   /* Speculative call edge turned out to be direct call to CALLE_DECL.
168438fd1498Szrj      Remove the speculative call sequence and return edge representing the call.
168538fd1498Szrj      It is up to caller to redirect the call as appropriate. */
168638fd1498Szrj   cgraph_edge *resolve_speculation (tree callee_decl = NULL);
168738fd1498Szrj 
168838fd1498Szrj   /* If necessary, change the function declaration in the call statement
168938fd1498Szrj      associated with the edge so that it corresponds to the edge callee.  */
169038fd1498Szrj   gimple *redirect_call_stmt_to_callee (void);
169138fd1498Szrj 
169238fd1498Szrj   /* Create clone of edge in the node N represented
169338fd1498Szrj      by CALL_EXPR the callgraph.  */
169438fd1498Szrj   cgraph_edge * clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid,
169538fd1498Szrj 		       profile_count num, profile_count den,
169638fd1498Szrj 		       bool update_original);
169738fd1498Szrj 
169838fd1498Szrj   /* Verify edge count and frequency.  */
169938fd1498Szrj   bool verify_count ();
170038fd1498Szrj 
170138fd1498Szrj   /* Return true when call of edge can not lead to return from caller
170238fd1498Szrj      and thus it is safe to ignore its side effects for IPA analysis
170338fd1498Szrj      when computing side effects of the caller.  */
170438fd1498Szrj   bool cannot_lead_to_return_p (void);
170538fd1498Szrj 
170638fd1498Szrj   /* Return true when the edge represents a direct recursion.  */
170738fd1498Szrj   bool recursive_p (void);
170838fd1498Szrj 
170938fd1498Szrj   /* Return true if the call can be hot.  */
171038fd1498Szrj   bool maybe_hot_p (void);
171138fd1498Szrj 
171238fd1498Szrj   /* Rebuild cgraph edges for current function node.  This needs to be run after
171338fd1498Szrj      passes that don't update the cgraph.  */
171438fd1498Szrj   static unsigned int rebuild_edges (void);
171538fd1498Szrj 
171638fd1498Szrj   /* Rebuild cgraph references for current function node.  This needs to be run
171738fd1498Szrj      after passes that don't update the cgraph.  */
171838fd1498Szrj   static void rebuild_references (void);
171938fd1498Szrj 
172038fd1498Szrj   /* Expected number of executions: calculated in profile.c.  */
172138fd1498Szrj   profile_count count;
172238fd1498Szrj   cgraph_node *caller;
172338fd1498Szrj   cgraph_node *callee;
172438fd1498Szrj   cgraph_edge *prev_caller;
172538fd1498Szrj   cgraph_edge *next_caller;
172638fd1498Szrj   cgraph_edge *prev_callee;
172738fd1498Szrj   cgraph_edge *next_callee;
172838fd1498Szrj   gcall *call_stmt;
172938fd1498Szrj   /* Additional information about an indirect call.  Not cleared when an edge
173038fd1498Szrj      becomes direct.  */
173138fd1498Szrj   cgraph_indirect_call_info *indirect_info;
173238fd1498Szrj   PTR GTY ((skip (""))) aux;
173338fd1498Szrj   /* When equal to CIF_OK, inline this call.  Otherwise, points to the
173438fd1498Szrj      explanation why function was not inlined.  */
173538fd1498Szrj   enum cgraph_inline_failed_t inline_failed;
173638fd1498Szrj   /* The stmt_uid of call_stmt.  This is used by LTO to recover the call_stmt
173738fd1498Szrj      when the function is serialized in.  */
173838fd1498Szrj   unsigned int lto_stmt_uid;
173938fd1498Szrj   /* Unique id of the edge.  */
174038fd1498Szrj   int uid;
174138fd1498Szrj   /* Whether this edge was made direct by indirect inlining.  */
174238fd1498Szrj   unsigned int indirect_inlining_edge : 1;
174338fd1498Szrj   /* Whether this edge describes an indirect call with an undetermined
174438fd1498Szrj      callee.  */
174538fd1498Szrj   unsigned int indirect_unknown_callee : 1;
174638fd1498Szrj   /* Whether this edge is still a dangling  */
174738fd1498Szrj   /* True if the corresponding CALL stmt cannot be inlined.  */
174838fd1498Szrj   unsigned int call_stmt_cannot_inline_p : 1;
174938fd1498Szrj   /* Can this call throw externally?  */
175038fd1498Szrj   unsigned int can_throw_external : 1;
175138fd1498Szrj   /* Edges with SPECULATIVE flag represents indirect calls that was
175238fd1498Szrj      speculatively turned into direct (i.e. by profile feedback).
175338fd1498Szrj      The final code sequence will have form:
175438fd1498Szrj 
175538fd1498Szrj      if (call_target == expected_fn)
175638fd1498Szrj        expected_fn ();
175738fd1498Szrj      else
175838fd1498Szrj        call_target ();
175938fd1498Szrj 
176038fd1498Szrj      Every speculative call is represented by three components attached
176138fd1498Szrj      to a same call statement:
176238fd1498Szrj      1) a direct call (to expected_fn)
176338fd1498Szrj      2) an indirect call (to call_target)
176438fd1498Szrj      3) a IPA_REF_ADDR refrence to expected_fn.
176538fd1498Szrj 
176638fd1498Szrj      Optimizers may later redirect direct call to clone, so 1) and 3)
176738fd1498Szrj      do not need to necesarily agree with destination.  */
176838fd1498Szrj   unsigned int speculative : 1;
176938fd1498Szrj   /* Set to true when caller is a constructor or destructor of polymorphic
177038fd1498Szrj      type.  */
177138fd1498Szrj   unsigned in_polymorphic_cdtor : 1;
177238fd1498Szrj 
177338fd1498Szrj   /* Return true if call must bind to current definition.  */
177438fd1498Szrj   bool binds_to_current_def_p ();
177538fd1498Szrj 
177638fd1498Szrj   /* Expected frequency of executions within the function.
177738fd1498Szrj      When set to CGRAPH_FREQ_BASE, the edge is expected to be called once
177838fd1498Szrj      per function call.  The range is 0 to CGRAPH_FREQ_MAX.  */
177938fd1498Szrj   int frequency ();
178038fd1498Szrj 
178138fd1498Szrj   /* Expected frequency of executions within the function.  */
178238fd1498Szrj   sreal sreal_frequency ();
178338fd1498Szrj private:
178438fd1498Szrj   /* Remove the edge from the list of the callers of the callee.  */
178538fd1498Szrj   void remove_caller (void);
178638fd1498Szrj 
178738fd1498Szrj   /* Remove the edge from the list of the callees of the caller.  */
178838fd1498Szrj   void remove_callee (void);
178938fd1498Szrj 
179038fd1498Szrj   /* Set callee N of call graph edge and add it to the corresponding set of
179138fd1498Szrj      callers. */
179238fd1498Szrj   void set_callee (cgraph_node *n);
179338fd1498Szrj 
179438fd1498Szrj   /* Output flags of edge to a file F.  */
179538fd1498Szrj   void dump_edge_flags (FILE *f);
179638fd1498Szrj 
179738fd1498Szrj   /* Verify that call graph edge corresponds to DECL from the associated
179838fd1498Szrj      statement.  Return true if the verification should fail.  */
179938fd1498Szrj   bool verify_corresponds_to_fndecl (tree decl);
180038fd1498Szrj };
180138fd1498Szrj 
180238fd1498Szrj #define CGRAPH_FREQ_BASE 1000
180338fd1498Szrj #define CGRAPH_FREQ_MAX 100000
180438fd1498Szrj 
180538fd1498Szrj /* The varpool data structure.
180638fd1498Szrj    Each static variable decl has assigned varpool_node.  */
180738fd1498Szrj 
180838fd1498Szrj class GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node {
180938fd1498Szrj public:
181038fd1498Szrj   /* Dump given varpool node to F.  */
181138fd1498Szrj   void dump (FILE *f);
181238fd1498Szrj 
181338fd1498Szrj   /* Dump given varpool node to stderr.  */
181438fd1498Szrj   void DEBUG_FUNCTION debug (void);
181538fd1498Szrj 
181638fd1498Szrj   /* Remove variable from symbol table.  */
181738fd1498Szrj   void remove (void);
181838fd1498Szrj 
181938fd1498Szrj   /* Remove node initializer when it is no longer needed.  */
182038fd1498Szrj   void remove_initializer (void);
182138fd1498Szrj 
182238fd1498Szrj   void analyze (void);
182338fd1498Szrj 
182438fd1498Szrj   /* Return variable availability.  */
182538fd1498Szrj   availability get_availability (symtab_node *ref = NULL);
182638fd1498Szrj 
182738fd1498Szrj   /* When doing LTO, read variable's constructor from disk if
182838fd1498Szrj      it is not already present.  */
182938fd1498Szrj   tree get_constructor (void);
183038fd1498Szrj 
183138fd1498Szrj   /* Return true if variable has constructor that can be used for folding.  */
183238fd1498Szrj   bool ctor_useable_for_folding_p (void);
183338fd1498Szrj 
183438fd1498Szrj   /* For given variable pool node, walk the alias chain to return the function
183538fd1498Szrj      the variable is alias of. Do not walk through thunks.
183638fd1498Szrj      When AVAILABILITY is non-NULL, get minimal availability in the chain.
183738fd1498Szrj      When REF is non-NULL, assume that reference happens in symbol REF
183838fd1498Szrj      when determining the availability.  */
183938fd1498Szrj   inline varpool_node *ultimate_alias_target
184038fd1498Szrj     (availability *availability = NULL, symtab_node *ref = NULL);
184138fd1498Szrj 
184238fd1498Szrj   /* Return node that alias is aliasing.  */
184338fd1498Szrj   inline varpool_node *get_alias_target (void);
184438fd1498Szrj 
184538fd1498Szrj   /* Output one variable, if necessary.  Return whether we output it.  */
184638fd1498Szrj   bool assemble_decl (void);
184738fd1498Szrj 
184838fd1498Szrj   /* For variables in named sections make sure get_variable_section
184938fd1498Szrj      is called before we switch to those sections.  Then section
185038fd1498Szrj      conflicts between read-only and read-only requiring relocations
185138fd1498Szrj      sections can be resolved.  */
185238fd1498Szrj   void finalize_named_section_flags (void);
185338fd1498Szrj 
185438fd1498Szrj   /* Call calback on varpool symbol and aliases associated to varpool symbol.
185538fd1498Szrj      When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
185638fd1498Szrj      skipped. */
185738fd1498Szrj   bool call_for_symbol_and_aliases (bool (*callback) (varpool_node *, void *),
185838fd1498Szrj 				    void *data,
185938fd1498Szrj 				    bool include_overwritable);
186038fd1498Szrj 
186138fd1498Szrj   /* Return true when variable should be considered externally visible.  */
186238fd1498Szrj   bool externally_visible_p (void);
186338fd1498Szrj 
186438fd1498Szrj   /* Return true when all references to variable must be visible
186538fd1498Szrj      in ipa_ref_list.
186638fd1498Szrj      i.e. if the variable is not externally visible or not used in some magic
186738fd1498Szrj      way (asm statement or such).
186838fd1498Szrj      The magic uses are all summarized in force_output flag.  */
186938fd1498Szrj   inline bool all_refs_explicit_p ();
187038fd1498Szrj 
187138fd1498Szrj   /* Return true when variable can be removed from variable pool
187238fd1498Szrj      if all direct calls are eliminated.  */
187338fd1498Szrj   inline bool can_remove_if_no_refs_p (void);
187438fd1498Szrj 
187538fd1498Szrj   /* Add the variable DECL to the varpool.
187638fd1498Szrj      Unlike finalize_decl function is intended to be used
187738fd1498Szrj      by middle end and allows insertion of new variable at arbitrary point
187838fd1498Szrj      of compilation.  */
187938fd1498Szrj   static void add (tree decl);
188038fd1498Szrj 
188138fd1498Szrj   /* Return varpool node for given symbol and check it is a function. */
188238fd1498Szrj   static inline varpool_node *get (const_tree decl);
188338fd1498Szrj 
188438fd1498Szrj   /* Mark DECL as finalized.  By finalizing the declaration, frontend instruct
188538fd1498Szrj      the middle end to output the variable to asm file, if needed or externally
188638fd1498Szrj      visible.  */
188738fd1498Szrj   static void finalize_decl (tree decl);
188838fd1498Szrj 
188938fd1498Szrj   /* Attempt to mark ALIAS as an alias to DECL.  Return TRUE if successful.
189038fd1498Szrj      Extra name aliases are output whenever DECL is output.  */
189138fd1498Szrj   static varpool_node * create_extra_name_alias (tree alias, tree decl);
189238fd1498Szrj 
189338fd1498Szrj   /* Attempt to mark ALIAS as an alias to DECL.  Return TRUE if successful.
189438fd1498Szrj      Extra name aliases are output whenever DECL is output.  */
189538fd1498Szrj   static varpool_node * create_alias (tree, tree);
189638fd1498Szrj 
189738fd1498Szrj   /* Dump the variable pool to F.  */
189838fd1498Szrj   static void dump_varpool (FILE *f);
189938fd1498Szrj 
190038fd1498Szrj   /* Dump the variable pool to stderr.  */
190138fd1498Szrj   static void DEBUG_FUNCTION debug_varpool (void);
190238fd1498Szrj 
190338fd1498Szrj   /* Allocate new callgraph node and insert it into basic data structures.  */
190438fd1498Szrj   static varpool_node *create_empty (void);
190538fd1498Szrj 
190638fd1498Szrj   /* Return varpool node assigned to DECL.  Create new one when needed.  */
190738fd1498Szrj   static varpool_node *get_create (tree decl);
190838fd1498Szrj 
190938fd1498Szrj   /* Given an assembler name, lookup node.  */
191038fd1498Szrj   static varpool_node *get_for_asmname (tree asmname);
191138fd1498Szrj 
191238fd1498Szrj   /* Set when variable is scheduled to be assembled.  */
191338fd1498Szrj   unsigned output : 1;
191438fd1498Szrj 
191538fd1498Szrj   /* Set when variable has statically initialized pointer
191638fd1498Szrj      or is a static bounds variable and needs initalization.  */
191738fd1498Szrj   unsigned need_bounds_init : 1;
191838fd1498Szrj 
191938fd1498Szrj   /* Set if the variable is dynamically initialized, except for
192038fd1498Szrj      function local statics.   */
192138fd1498Szrj   unsigned dynamically_initialized : 1;
192238fd1498Szrj 
192338fd1498Szrj   ENUM_BITFIELD(tls_model) tls_model : 3;
192438fd1498Szrj 
192538fd1498Szrj   /* Set if the variable is known to be used by single function only.
192638fd1498Szrj      This is computed by ipa_signle_use pass and used by late optimizations
192738fd1498Szrj      in places where optimization would be valid for local static variable
192838fd1498Szrj      if we did not do any inter-procedural code movement.  */
192938fd1498Szrj   unsigned used_by_single_function : 1;
193038fd1498Szrj 
193138fd1498Szrj private:
193238fd1498Szrj   /* Assemble thunks and aliases associated to varpool node.  */
193338fd1498Szrj   void assemble_aliases (void);
193438fd1498Szrj 
193538fd1498Szrj   /* Worker for call_for_node_and_aliases.  */
193638fd1498Szrj   bool call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *, void *),
193738fd1498Szrj 				      void *data,
193838fd1498Szrj 				      bool include_overwritable);
193938fd1498Szrj };
194038fd1498Szrj 
194138fd1498Szrj /* Every top level asm statement is put into a asm_node.  */
194238fd1498Szrj 
194338fd1498Szrj struct GTY(()) asm_node {
194438fd1498Szrj 
194538fd1498Szrj 
194638fd1498Szrj   /* Next asm node.  */
194738fd1498Szrj   asm_node *next;
194838fd1498Szrj   /* String for this asm node.  */
194938fd1498Szrj   tree asm_str;
195038fd1498Szrj   /* Ordering of all cgraph nodes.  */
195138fd1498Szrj   int order;
195238fd1498Szrj };
195338fd1498Szrj 
195438fd1498Szrj /* Report whether or not THIS symtab node is a function, aka cgraph_node.  */
195538fd1498Szrj 
195638fd1498Szrj template <>
195738fd1498Szrj template <>
195838fd1498Szrj inline bool
test(symtab_node * p)195938fd1498Szrj is_a_helper <cgraph_node *>::test (symtab_node *p)
196038fd1498Szrj {
196138fd1498Szrj   return p && p->type == SYMTAB_FUNCTION;
196238fd1498Szrj }
196338fd1498Szrj 
196438fd1498Szrj /* Report whether or not THIS symtab node is a vriable, aka varpool_node.  */
196538fd1498Szrj 
196638fd1498Szrj template <>
196738fd1498Szrj template <>
196838fd1498Szrj inline bool
test(symtab_node * p)196938fd1498Szrj is_a_helper <varpool_node *>::test (symtab_node *p)
197038fd1498Szrj {
197138fd1498Szrj   return p && p->type == SYMTAB_VARIABLE;
197238fd1498Szrj }
197338fd1498Szrj 
197438fd1498Szrj /* Macros to access the next item in the list of free cgraph nodes and
197538fd1498Szrj    edges. */
197638fd1498Szrj #define NEXT_FREE_NODE(NODE) dyn_cast<cgraph_node *> ((NODE)->next)
197738fd1498Szrj #define SET_NEXT_FREE_NODE(NODE,NODE2) ((NODE))->next = NODE2
197838fd1498Szrj #define NEXT_FREE_EDGE(EDGE) (EDGE)->prev_caller
197938fd1498Szrj 
198038fd1498Szrj typedef void (*cgraph_edge_hook)(cgraph_edge *, void *);
198138fd1498Szrj typedef void (*cgraph_node_hook)(cgraph_node *, void *);
198238fd1498Szrj typedef void (*varpool_node_hook)(varpool_node *, void *);
198338fd1498Szrj typedef void (*cgraph_2edge_hook)(cgraph_edge *, cgraph_edge *, void *);
198438fd1498Szrj typedef void (*cgraph_2node_hook)(cgraph_node *, cgraph_node *, void *);
198538fd1498Szrj 
198638fd1498Szrj struct cgraph_edge_hook_list;
198738fd1498Szrj struct cgraph_node_hook_list;
198838fd1498Szrj struct varpool_node_hook_list;
198938fd1498Szrj struct cgraph_2edge_hook_list;
199038fd1498Szrj struct cgraph_2node_hook_list;
199138fd1498Szrj 
199238fd1498Szrj /* Map from a symbol to initialization/finalization priorities.  */
199338fd1498Szrj struct GTY(()) symbol_priority_map {
199438fd1498Szrj   priority_type init;
199538fd1498Szrj   priority_type fini;
199638fd1498Szrj };
199738fd1498Szrj 
199838fd1498Szrj enum symtab_state
199938fd1498Szrj {
200038fd1498Szrj   /* Frontend is parsing and finalizing functions.  */
200138fd1498Szrj   PARSING,
200238fd1498Szrj   /* Callgraph is being constructed.  It is safe to add new functions.  */
200338fd1498Szrj   CONSTRUCTION,
200438fd1498Szrj   /* Callgraph is being streamed-in at LTO time.  */
200538fd1498Szrj   LTO_STREAMING,
200638fd1498Szrj   /* Callgraph is built and early IPA passes are being run.  */
200738fd1498Szrj   IPA,
200838fd1498Szrj   /* Callgraph is built and all functions are transformed to SSA form.  */
200938fd1498Szrj   IPA_SSA,
201038fd1498Szrj   /* All inline decisions are done; it is now possible to remove extern inline
201138fd1498Szrj      functions and virtual call targets.  */
201238fd1498Szrj   IPA_SSA_AFTER_INLINING,
201338fd1498Szrj   /* Functions are now ordered and being passed to RTL expanders.  */
201438fd1498Szrj   EXPANSION,
201538fd1498Szrj   /* All cgraph expansion is done.  */
201638fd1498Szrj   FINISHED
201738fd1498Szrj };
201838fd1498Szrj 
201938fd1498Szrj struct asmname_hasher : ggc_ptr_hash <symtab_node>
202038fd1498Szrj {
202138fd1498Szrj   typedef const_tree compare_type;
202238fd1498Szrj 
202338fd1498Szrj   static hashval_t hash (symtab_node *n);
202438fd1498Szrj   static bool equal (symtab_node *n, const_tree t);
202538fd1498Szrj };
202638fd1498Szrj 
202738fd1498Szrj class GTY((tag ("SYMTAB"))) symbol_table
202838fd1498Szrj {
202938fd1498Szrj public:
203038fd1498Szrj   friend class symtab_node;
203138fd1498Szrj   friend class cgraph_node;
203238fd1498Szrj   friend class cgraph_edge;
203338fd1498Szrj 
symbol_table()203438fd1498Szrj   symbol_table (): cgraph_max_summary_uid (1)
203538fd1498Szrj   {
203638fd1498Szrj   }
203738fd1498Szrj 
203838fd1498Szrj   /* Initialize callgraph dump file.  */
203938fd1498Szrj   void initialize (void);
204038fd1498Szrj 
204138fd1498Szrj   /* Register a top-level asm statement ASM_STR.  */
204238fd1498Szrj   inline asm_node *finalize_toplevel_asm (tree asm_str);
204338fd1498Szrj 
204438fd1498Szrj   /* Analyze the whole compilation unit once it is parsed completely.  */
204538fd1498Szrj   void finalize_compilation_unit (void);
204638fd1498Szrj 
204738fd1498Szrj   /* C++ frontend produce same body aliases all over the place, even before PCH
204838fd1498Szrj      gets streamed out. It relies on us linking the aliases with their function
204938fd1498Szrj      in order to do the fixups, but ipa-ref is not PCH safe.  Consequentely we
205038fd1498Szrj      first produce aliases without links, but once C++ FE is sure he won't sream
205138fd1498Szrj      PCH we build the links via this function.  */
205238fd1498Szrj   void process_same_body_aliases (void);
205338fd1498Szrj 
205438fd1498Szrj   /* Perform simple optimizations based on callgraph.  */
205538fd1498Szrj   void compile (void);
205638fd1498Szrj 
205738fd1498Szrj   /* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these
205838fd1498Szrj      functions into callgraph in a way so they look like ordinary reachable
205938fd1498Szrj      functions inserted into callgraph already at construction time.  */
206038fd1498Szrj   void process_new_functions (void);
206138fd1498Szrj 
206238fd1498Szrj   /* Once all functions from compilation unit are in memory, produce all clones
206338fd1498Szrj      and update all calls.  We might also do this on demand if we don't want to
206438fd1498Szrj      bring all functions to memory prior compilation, but current WHOPR
206538fd1498Szrj      implementation does that and it is bit easier to keep everything right
206638fd1498Szrj      in this order.  */
206738fd1498Szrj   void materialize_all_clones (void);
206838fd1498Szrj 
206938fd1498Szrj   /* Register a symbol NODE.  */
207038fd1498Szrj   inline void register_symbol (symtab_node *node);
207138fd1498Szrj 
207238fd1498Szrj   inline void
clear_asm_symbols(void)207338fd1498Szrj   clear_asm_symbols (void)
207438fd1498Szrj   {
207538fd1498Szrj     asmnodes = NULL;
207638fd1498Szrj     asm_last_node = NULL;
207738fd1498Szrj   }
207838fd1498Szrj 
207938fd1498Szrj   /* Perform reachability analysis and reclaim all unreachable nodes.  */
208038fd1498Szrj   bool remove_unreachable_nodes (FILE *file);
208138fd1498Szrj 
208238fd1498Szrj   /* Optimization of function bodies might've rendered some variables as
208338fd1498Szrj      unnecessary so we want to avoid these from being compiled.  Re-do
208438fd1498Szrj      reachability starting from variables that are either externally visible
208538fd1498Szrj      or was referred from the asm output routines.  */
208638fd1498Szrj   void remove_unreferenced_decls (void);
208738fd1498Szrj 
208838fd1498Szrj   /* Unregister a symbol NODE.  */
208938fd1498Szrj   inline void unregister (symtab_node *node);
209038fd1498Szrj 
209138fd1498Szrj   /* Allocate new callgraph node and insert it into basic data structures.  */
209238fd1498Szrj   cgraph_node *create_empty (void);
209338fd1498Szrj 
209438fd1498Szrj   /* Release a callgraph NODE with UID and put in to the list
209538fd1498Szrj      of free nodes.  */
209638fd1498Szrj   void release_symbol (cgraph_node *node, int uid);
209738fd1498Szrj 
209838fd1498Szrj   /* Output all variables enqueued to be assembled.  */
209938fd1498Szrj   bool output_variables (void);
210038fd1498Szrj 
210138fd1498Szrj   /* Weakrefs may be associated to external decls and thus not output
210238fd1498Szrj      at expansion time.  Emit all necessary aliases.  */
210338fd1498Szrj   void output_weakrefs (void);
210438fd1498Szrj 
210538fd1498Szrj   /* Return first static symbol with definition.  */
210638fd1498Szrj   inline symtab_node *first_symbol (void);
210738fd1498Szrj 
210838fd1498Szrj   /* Return first assembler symbol.  */
210938fd1498Szrj   inline asm_node *
first_asm_symbol(void)211038fd1498Szrj   first_asm_symbol (void)
211138fd1498Szrj   {
211238fd1498Szrj     return asmnodes;
211338fd1498Szrj   }
211438fd1498Szrj 
211538fd1498Szrj   /* Return first static symbol with definition.  */
211638fd1498Szrj   inline symtab_node *first_defined_symbol (void);
211738fd1498Szrj 
211838fd1498Szrj   /* Return first variable.  */
211938fd1498Szrj   inline varpool_node *first_variable (void);
212038fd1498Szrj 
212138fd1498Szrj   /* Return next variable after NODE.  */
212238fd1498Szrj   inline varpool_node *next_variable (varpool_node *node);
212338fd1498Szrj 
212438fd1498Szrj   /* Return first static variable with initializer.  */
212538fd1498Szrj   inline varpool_node *first_static_initializer (void);
212638fd1498Szrj 
212738fd1498Szrj   /* Return next static variable with initializer after NODE.  */
212838fd1498Szrj   inline varpool_node *next_static_initializer (varpool_node *node);
212938fd1498Szrj 
213038fd1498Szrj   /* Return first static variable with definition.  */
213138fd1498Szrj   inline varpool_node *first_defined_variable (void);
213238fd1498Szrj 
213338fd1498Szrj   /* Return next static variable with definition after NODE.  */
213438fd1498Szrj   inline varpool_node *next_defined_variable (varpool_node *node);
213538fd1498Szrj 
213638fd1498Szrj   /* Return first function with body defined.  */
213738fd1498Szrj   inline cgraph_node *first_defined_function (void);
213838fd1498Szrj 
213938fd1498Szrj   /* Return next function with body defined after NODE.  */
214038fd1498Szrj   inline cgraph_node *next_defined_function (cgraph_node *node);
214138fd1498Szrj 
214238fd1498Szrj   /* Return first function.  */
214338fd1498Szrj   inline cgraph_node *first_function (void);
214438fd1498Szrj 
214538fd1498Szrj   /* Return next function.  */
214638fd1498Szrj   inline cgraph_node *next_function (cgraph_node *node);
214738fd1498Szrj 
214838fd1498Szrj   /* Return first function with body defined.  */
214938fd1498Szrj   cgraph_node *first_function_with_gimple_body (void);
215038fd1498Szrj 
215138fd1498Szrj   /* Return next reachable static variable with initializer after NODE.  */
215238fd1498Szrj   inline cgraph_node *next_function_with_gimple_body (cgraph_node *node);
215338fd1498Szrj 
215438fd1498Szrj   /* Register HOOK to be called with DATA on each removed edge.  */
215538fd1498Szrj   cgraph_edge_hook_list *add_edge_removal_hook (cgraph_edge_hook hook,
215638fd1498Szrj 						void *data);
215738fd1498Szrj 
215838fd1498Szrj   /* Remove ENTRY from the list of hooks called on removing edges.  */
215938fd1498Szrj   void remove_edge_removal_hook (cgraph_edge_hook_list *entry);
216038fd1498Szrj 
216138fd1498Szrj   /* Register HOOK to be called with DATA on each removed node.  */
216238fd1498Szrj   cgraph_node_hook_list *add_cgraph_removal_hook (cgraph_node_hook hook,
216338fd1498Szrj 						  void *data);
216438fd1498Szrj 
216538fd1498Szrj   /* Remove ENTRY from the list of hooks called on removing nodes.  */
216638fd1498Szrj   void remove_cgraph_removal_hook (cgraph_node_hook_list *entry);
216738fd1498Szrj 
216838fd1498Szrj   /* Register HOOK to be called with DATA on each removed node.  */
216938fd1498Szrj   varpool_node_hook_list *add_varpool_removal_hook (varpool_node_hook hook,
217038fd1498Szrj 						    void *data);
217138fd1498Szrj 
217238fd1498Szrj   /* Remove ENTRY from the list of hooks called on removing nodes.  */
217338fd1498Szrj   void remove_varpool_removal_hook (varpool_node_hook_list *entry);
217438fd1498Szrj 
217538fd1498Szrj   /* Register HOOK to be called with DATA on each inserted node.  */
217638fd1498Szrj   cgraph_node_hook_list *add_cgraph_insertion_hook (cgraph_node_hook hook,
217738fd1498Szrj 						    void *data);
217838fd1498Szrj 
217938fd1498Szrj   /* Remove ENTRY from the list of hooks called on inserted nodes.  */
218038fd1498Szrj   void remove_cgraph_insertion_hook (cgraph_node_hook_list *entry);
218138fd1498Szrj 
218238fd1498Szrj   /* Register HOOK to be called with DATA on each inserted node.  */
218338fd1498Szrj   varpool_node_hook_list *add_varpool_insertion_hook (varpool_node_hook hook,
218438fd1498Szrj 						      void *data);
218538fd1498Szrj 
218638fd1498Szrj   /* Remove ENTRY from the list of hooks called on inserted nodes.  */
218738fd1498Szrj   void remove_varpool_insertion_hook (varpool_node_hook_list *entry);
218838fd1498Szrj 
218938fd1498Szrj   /* Register HOOK to be called with DATA on each duplicated edge.  */
219038fd1498Szrj   cgraph_2edge_hook_list *add_edge_duplication_hook (cgraph_2edge_hook hook,
219138fd1498Szrj 						     void *data);
219238fd1498Szrj   /* Remove ENTRY from the list of hooks called on duplicating edges.  */
219338fd1498Szrj   void remove_edge_duplication_hook (cgraph_2edge_hook_list *entry);
219438fd1498Szrj 
219538fd1498Szrj   /* Register HOOK to be called with DATA on each duplicated node.  */
219638fd1498Szrj   cgraph_2node_hook_list *add_cgraph_duplication_hook (cgraph_2node_hook hook,
219738fd1498Szrj 						       void *data);
219838fd1498Szrj 
219938fd1498Szrj   /* Remove ENTRY from the list of hooks called on duplicating nodes.  */
220038fd1498Szrj   void remove_cgraph_duplication_hook (cgraph_2node_hook_list *entry);
220138fd1498Szrj 
220238fd1498Szrj   /* Call all edge removal hooks.  */
220338fd1498Szrj   void call_edge_removal_hooks (cgraph_edge *e);
220438fd1498Szrj 
220538fd1498Szrj   /* Call all node insertion hooks.  */
220638fd1498Szrj   void call_cgraph_insertion_hooks (cgraph_node *node);
220738fd1498Szrj 
220838fd1498Szrj   /* Call all node removal hooks.  */
220938fd1498Szrj   void call_cgraph_removal_hooks (cgraph_node *node);
221038fd1498Szrj 
221138fd1498Szrj   /* Call all node duplication hooks.  */
221238fd1498Szrj   void call_cgraph_duplication_hooks (cgraph_node *node, cgraph_node *node2);
221338fd1498Szrj 
221438fd1498Szrj   /* Call all edge duplication hooks.  */
221538fd1498Szrj   void call_edge_duplication_hooks (cgraph_edge *cs1, cgraph_edge *cs2);
221638fd1498Szrj 
221738fd1498Szrj   /* Call all node removal hooks.  */
221838fd1498Szrj   void call_varpool_removal_hooks (varpool_node *node);
221938fd1498Szrj 
222038fd1498Szrj   /* Call all node insertion hooks.  */
222138fd1498Szrj   void call_varpool_insertion_hooks (varpool_node *node);
222238fd1498Szrj 
222338fd1498Szrj   /* Arrange node to be first in its entry of assembler_name_hash.  */
222438fd1498Szrj   void symtab_prevail_in_asm_name_hash (symtab_node *node);
222538fd1498Szrj 
222638fd1498Szrj   /* Initalize asm name hash unless.  */
222738fd1498Szrj   void symtab_initialize_asm_name_hash (void);
222838fd1498Szrj 
222938fd1498Szrj   /* Set the DECL_ASSEMBLER_NAME and update symtab hashtables.  */
223038fd1498Szrj   void change_decl_assembler_name (tree decl, tree name);
223138fd1498Szrj 
223238fd1498Szrj   /* Dump symbol table to F.  */
223338fd1498Szrj   void dump (FILE *f);
223438fd1498Szrj 
223538fd1498Szrj   /* Dump symbol table to stderr.  */
223638fd1498Szrj   void DEBUG_FUNCTION debug (void);
223738fd1498Szrj 
223838fd1498Szrj   /* Return true if assembler names NAME1 and NAME2 leads to the same symbol
223938fd1498Szrj      name.  */
224038fd1498Szrj   static bool assembler_names_equal_p (const char *name1, const char *name2);
224138fd1498Szrj 
224238fd1498Szrj   int cgraph_count;
224338fd1498Szrj   int cgraph_max_uid;
224438fd1498Szrj   int cgraph_max_summary_uid;
224538fd1498Szrj 
224638fd1498Szrj   int edges_count;
224738fd1498Szrj   int edges_max_uid;
224838fd1498Szrj 
224938fd1498Szrj   symtab_node* GTY(()) nodes;
225038fd1498Szrj   asm_node* GTY(()) asmnodes;
225138fd1498Szrj   asm_node* GTY(()) asm_last_node;
225238fd1498Szrj   cgraph_node* GTY(()) free_nodes;
225338fd1498Szrj 
225438fd1498Szrj   /* Head of a linked list of unused (freed) call graph edges.
225538fd1498Szrj      Do not GTY((delete)) this list so UIDs gets reliably recycled.  */
225638fd1498Szrj   cgraph_edge * GTY(()) free_edges;
225738fd1498Szrj 
225838fd1498Szrj   /* The order index of the next symtab node to be created.  This is
225938fd1498Szrj      used so that we can sort the cgraph nodes in order by when we saw
226038fd1498Szrj      them, to support -fno-toplevel-reorder.  */
226138fd1498Szrj   int order;
226238fd1498Szrj 
226338fd1498Szrj   /* Set when whole unit has been analyzed so we can access global info.  */
226438fd1498Szrj   bool global_info_ready;
226538fd1498Szrj   /* What state callgraph is in right now.  */
226638fd1498Szrj   enum symtab_state state;
226738fd1498Szrj   /* Set when the cgraph is fully build and the basic flags are computed.  */
226838fd1498Szrj   bool function_flags_ready;
226938fd1498Szrj 
227038fd1498Szrj   bool cpp_implicit_aliases_done;
227138fd1498Szrj 
227238fd1498Szrj   /* Hash table used to hold sectoons.  */
227338fd1498Szrj   hash_table<section_name_hasher> *GTY(()) section_hash;
227438fd1498Szrj 
227538fd1498Szrj   /* Hash table used to convert assembler names into nodes.  */
227638fd1498Szrj   hash_table<asmname_hasher> *assembler_name_hash;
227738fd1498Szrj 
227838fd1498Szrj   /* Hash table used to hold init priorities.  */
227938fd1498Szrj   hash_map<symtab_node *, symbol_priority_map> *init_priority_hash;
228038fd1498Szrj 
228138fd1498Szrj   FILE* GTY ((skip)) dump_file;
228238fd1498Szrj 
228338fd1498Szrj   /* Return symbol used to separate symbol name from suffix.  */
228438fd1498Szrj   static char symbol_suffix_separator ();
228538fd1498Szrj 
228638fd1498Szrj   FILE* GTY ((skip)) ipa_clones_dump_file;
228738fd1498Szrj 
228838fd1498Szrj   hash_set <const cgraph_node *> GTY ((skip)) cloned_nodes;
228938fd1498Szrj 
229038fd1498Szrj private:
229138fd1498Szrj   /* Allocate new callgraph node.  */
229238fd1498Szrj   inline cgraph_node * allocate_cgraph_symbol (void);
229338fd1498Szrj 
229438fd1498Szrj   /* Allocate a cgraph_edge structure and fill it with data according to the
229538fd1498Szrj      parameters of which only CALLEE can be NULL (when creating an indirect call
229638fd1498Szrj      edge).  */
229738fd1498Szrj   cgraph_edge *create_edge (cgraph_node *caller, cgraph_node *callee,
229838fd1498Szrj 			    gcall *call_stmt, profile_count count,
229938fd1498Szrj 			    bool indir_unknown_callee);
230038fd1498Szrj 
230138fd1498Szrj   /* Put the edge onto the free list.  */
230238fd1498Szrj   void free_edge (cgraph_edge *e);
230338fd1498Szrj 
230438fd1498Szrj   /* Insert NODE to assembler name hash.  */
230538fd1498Szrj   void insert_to_assembler_name_hash (symtab_node *node, bool with_clones);
230638fd1498Szrj 
230738fd1498Szrj   /* Remove NODE from assembler name hash.  */
230838fd1498Szrj   void unlink_from_assembler_name_hash (symtab_node *node, bool with_clones);
230938fd1498Szrj 
231038fd1498Szrj   /* Hash asmnames ignoring the user specified marks.  */
231138fd1498Szrj   static hashval_t decl_assembler_name_hash (const_tree asmname);
231238fd1498Szrj 
231338fd1498Szrj   /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL.  */
231438fd1498Szrj   static bool decl_assembler_name_equal (tree decl, const_tree asmname);
231538fd1498Szrj 
231638fd1498Szrj   friend struct asmname_hasher;
231738fd1498Szrj 
231838fd1498Szrj   /* List of hooks triggered when an edge is removed.  */
231938fd1498Szrj   cgraph_edge_hook_list * GTY((skip)) m_first_edge_removal_hook;
232038fd1498Szrj   /* List of hooks triggem_red when a cgraph node is removed.  */
232138fd1498Szrj   cgraph_node_hook_list * GTY((skip)) m_first_cgraph_removal_hook;
232238fd1498Szrj   /* List of hooks triggered when an edge is duplicated.  */
232338fd1498Szrj   cgraph_2edge_hook_list * GTY((skip)) m_first_edge_duplicated_hook;
232438fd1498Szrj   /* List of hooks triggered when a node is duplicated.  */
232538fd1498Szrj   cgraph_2node_hook_list * GTY((skip)) m_first_cgraph_duplicated_hook;
232638fd1498Szrj   /* List of hooks triggered when an function is inserted.  */
232738fd1498Szrj   cgraph_node_hook_list * GTY((skip)) m_first_cgraph_insertion_hook;
232838fd1498Szrj   /* List of hooks triggered when an variable is inserted.  */
232938fd1498Szrj   varpool_node_hook_list * GTY((skip)) m_first_varpool_insertion_hook;
233038fd1498Szrj   /* List of hooks triggered when a node is removed.  */
233138fd1498Szrj   varpool_node_hook_list * GTY((skip)) m_first_varpool_removal_hook;
233238fd1498Szrj };
233338fd1498Szrj 
233438fd1498Szrj extern GTY(()) symbol_table *symtab;
233538fd1498Szrj 
233638fd1498Szrj extern vec<cgraph_node *> cgraph_new_nodes;
233738fd1498Szrj 
233838fd1498Szrj inline hashval_t
hash(symtab_node * n)233938fd1498Szrj asmname_hasher::hash (symtab_node *n)
234038fd1498Szrj {
234138fd1498Szrj   return symbol_table::decl_assembler_name_hash
234238fd1498Szrj     (DECL_ASSEMBLER_NAME (n->decl));
234338fd1498Szrj }
234438fd1498Szrj 
234538fd1498Szrj inline bool
equal(symtab_node * n,const_tree t)234638fd1498Szrj asmname_hasher::equal (symtab_node *n, const_tree t)
234738fd1498Szrj {
234838fd1498Szrj   return symbol_table::decl_assembler_name_equal (n->decl, t);
234938fd1498Szrj }
235038fd1498Szrj 
235138fd1498Szrj /* In cgraph.c  */
235238fd1498Szrj void cgraph_c_finalize (void);
235338fd1498Szrj void release_function_body (tree);
235438fd1498Szrj cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
235538fd1498Szrj 
235638fd1498Szrj void cgraph_update_edges_for_call_stmt (gimple *, tree, gimple *);
235738fd1498Szrj bool cgraph_function_possibly_inlined_p (tree);
235838fd1498Szrj 
235938fd1498Szrj const char* cgraph_inline_failed_string (cgraph_inline_failed_t);
236038fd1498Szrj cgraph_inline_failed_type_t cgraph_inline_failed_type (cgraph_inline_failed_t);
236138fd1498Szrj 
236238fd1498Szrj extern bool gimple_check_call_matching_types (gimple *, tree, bool);
236338fd1498Szrj 
236438fd1498Szrj /* In cgraphunit.c  */
236538fd1498Szrj void cgraphunit_c_finalize (void);
236638fd1498Szrj 
236738fd1498Szrj /*  Initialize datastructures so DECL is a function in lowered gimple form.
236838fd1498Szrj     IN_SSA is true if the gimple is in SSA.  */
236938fd1498Szrj basic_block init_lowered_empty_function (tree, bool, profile_count);
237038fd1498Szrj 
237138fd1498Szrj tree thunk_adjust (gimple_stmt_iterator *, tree, bool, HOST_WIDE_INT, tree);
237238fd1498Szrj /* In cgraphclones.c  */
237338fd1498Szrj 
237438fd1498Szrj tree clone_function_name_1 (const char *, const char *);
237538fd1498Szrj tree clone_function_name (tree decl, const char *);
237638fd1498Szrj 
237738fd1498Szrj void tree_function_versioning (tree, tree, vec<ipa_replace_map *, va_gc> *,
237838fd1498Szrj 			       bool, bitmap, bool, bitmap, basic_block);
237938fd1498Szrj 
238038fd1498Szrj void dump_callgraph_transformation (const cgraph_node *original,
238138fd1498Szrj 				    const cgraph_node *clone,
238238fd1498Szrj 				    const char *suffix);
238338fd1498Szrj tree cgraph_build_function_type_skip_args (tree orig_type, bitmap args_to_skip,
238438fd1498Szrj 					   bool skip_return);
238538fd1498Szrj 
238638fd1498Szrj /* In cgraphbuild.c  */
238738fd1498Szrj int compute_call_stmt_bb_frequency (tree, basic_block bb);
238838fd1498Szrj void record_references_in_initializer (tree, bool);
238938fd1498Szrj 
239038fd1498Szrj /* In ipa.c  */
239138fd1498Szrj void cgraph_build_static_cdtor (char which, tree body, int priority);
239238fd1498Szrj bool ipa_discover_readonly_nonaddressable_vars (void);
239338fd1498Szrj 
239438fd1498Szrj /* In varpool.c  */
239538fd1498Szrj tree ctor_for_folding (tree);
239638fd1498Szrj 
239738fd1498Szrj /* In tree-chkp.c  */
239838fd1498Szrj extern bool chkp_function_instrumented_p (tree fndecl);
239938fd1498Szrj 
240038fd1498Szrj /* In ipa-inline-analysis.c  */
240138fd1498Szrj void initialize_inline_failed (struct cgraph_edge *);
240238fd1498Szrj bool speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining);
240338fd1498Szrj 
240438fd1498Szrj /* Return true when the symbol is real symbol, i.e. it is not inline clone
240538fd1498Szrj    or abstract function kept for debug info purposes only.  */
240638fd1498Szrj inline bool
real_symbol_p(void)240738fd1498Szrj symtab_node::real_symbol_p (void)
240838fd1498Szrj {
240938fd1498Szrj   cgraph_node *cnode;
241038fd1498Szrj 
241138fd1498Szrj   if (DECL_ABSTRACT_P (decl))
241238fd1498Szrj     return false;
241338fd1498Szrj   if (transparent_alias && definition)
241438fd1498Szrj     return false;
241538fd1498Szrj   if (!is_a <cgraph_node *> (this))
241638fd1498Szrj     return true;
241738fd1498Szrj   cnode = dyn_cast <cgraph_node *> (this);
241838fd1498Szrj   if (cnode->global.inlined_to)
241938fd1498Szrj     return false;
242038fd1498Szrj   return true;
242138fd1498Szrj }
242238fd1498Szrj 
242338fd1498Szrj /* Return true if DECL should have entry in symbol table if used.
242438fd1498Szrj    Those are functions and static & external veriables*/
242538fd1498Szrj 
242638fd1498Szrj static inline bool
decl_in_symtab_p(const_tree decl)242738fd1498Szrj decl_in_symtab_p (const_tree decl)
242838fd1498Szrj {
242938fd1498Szrj   return (TREE_CODE (decl) == FUNCTION_DECL
243038fd1498Szrj           || (TREE_CODE (decl) == VAR_DECL
243138fd1498Szrj 	      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))));
243238fd1498Szrj }
243338fd1498Szrj 
243438fd1498Szrj inline bool
in_same_comdat_group_p(symtab_node * target)243538fd1498Szrj symtab_node::in_same_comdat_group_p (symtab_node *target)
243638fd1498Szrj {
243738fd1498Szrj   symtab_node *source = this;
243838fd1498Szrj 
243938fd1498Szrj   if (cgraph_node *cn = dyn_cast <cgraph_node *> (target))
244038fd1498Szrj     {
244138fd1498Szrj       if (cn->global.inlined_to)
244238fd1498Szrj 	source = cn->global.inlined_to;
244338fd1498Szrj     }
244438fd1498Szrj   if (cgraph_node *cn = dyn_cast <cgraph_node *> (target))
244538fd1498Szrj     {
244638fd1498Szrj       if (cn->global.inlined_to)
244738fd1498Szrj 	target = cn->global.inlined_to;
244838fd1498Szrj     }
244938fd1498Szrj 
245038fd1498Szrj   return source->get_comdat_group () == target->get_comdat_group ();
245138fd1498Szrj }
245238fd1498Szrj 
245338fd1498Szrj /* Return node that alias is aliasing.  */
245438fd1498Szrj 
245538fd1498Szrj inline symtab_node *
get_alias_target(void)245638fd1498Szrj symtab_node::get_alias_target (void)
245738fd1498Szrj {
245838fd1498Szrj   ipa_ref *ref = NULL;
245938fd1498Szrj   iterate_reference (0, ref);
246038fd1498Szrj   if (ref->use == IPA_REF_CHKP)
246138fd1498Szrj     iterate_reference (1, ref);
246238fd1498Szrj   gcc_checking_assert (ref->use == IPA_REF_ALIAS);
246338fd1498Szrj   return ref->referred;
246438fd1498Szrj }
246538fd1498Szrj 
246638fd1498Szrj /* Return next reachable static symbol with initializer after the node.  */
246738fd1498Szrj 
246838fd1498Szrj inline symtab_node *
next_defined_symbol(void)246938fd1498Szrj symtab_node::next_defined_symbol (void)
247038fd1498Szrj {
247138fd1498Szrj   symtab_node *node1 = next;
247238fd1498Szrj 
247338fd1498Szrj   for (; node1; node1 = node1->next)
247438fd1498Szrj     if (node1->definition)
247538fd1498Szrj       return node1;
247638fd1498Szrj 
247738fd1498Szrj   return NULL;
247838fd1498Szrj }
247938fd1498Szrj 
248038fd1498Szrj /* Iterates I-th reference in the list, REF is also set.  */
248138fd1498Szrj 
248238fd1498Szrj inline ipa_ref *
iterate_reference(unsigned i,ipa_ref * & ref)248338fd1498Szrj symtab_node::iterate_reference (unsigned i, ipa_ref *&ref)
248438fd1498Szrj {
248538fd1498Szrj   vec_safe_iterate (ref_list.references, i, &ref);
248638fd1498Szrj 
248738fd1498Szrj   return ref;
248838fd1498Szrj }
248938fd1498Szrj 
249038fd1498Szrj /* Iterates I-th referring item in the list, REF is also set.  */
249138fd1498Szrj 
249238fd1498Szrj inline ipa_ref *
iterate_referring(unsigned i,ipa_ref * & ref)249338fd1498Szrj symtab_node::iterate_referring (unsigned i, ipa_ref *&ref)
249438fd1498Szrj {
249538fd1498Szrj   ref_list.referring.iterate (i, &ref);
249638fd1498Szrj 
249738fd1498Szrj   return ref;
249838fd1498Szrj }
249938fd1498Szrj 
250038fd1498Szrj /* Iterates I-th referring alias item in the list, REF is also set.  */
250138fd1498Szrj 
250238fd1498Szrj inline ipa_ref *
iterate_direct_aliases(unsigned i,ipa_ref * & ref)250338fd1498Szrj symtab_node::iterate_direct_aliases (unsigned i, ipa_ref *&ref)
250438fd1498Szrj {
250538fd1498Szrj   ref_list.referring.iterate (i, &ref);
250638fd1498Szrj 
250738fd1498Szrj   if (ref && ref->use != IPA_REF_ALIAS)
250838fd1498Szrj     return NULL;
250938fd1498Szrj 
251038fd1498Szrj   return ref;
251138fd1498Szrj }
251238fd1498Szrj 
251338fd1498Szrj /* Return true if list contains an alias.  */
251438fd1498Szrj 
251538fd1498Szrj inline bool
has_aliases_p(void)251638fd1498Szrj symtab_node::has_aliases_p (void)
251738fd1498Szrj {
251838fd1498Szrj   ipa_ref *ref = NULL;
251938fd1498Szrj 
252038fd1498Szrj   return (iterate_direct_aliases (0, ref) != NULL);
252138fd1498Szrj }
252238fd1498Szrj 
252338fd1498Szrj /* Return true when RESOLUTION indicate that linker will use
252438fd1498Szrj    the symbol from non-LTO object files.  */
252538fd1498Szrj 
252638fd1498Szrj inline bool
resolution_used_from_other_file_p(enum ld_plugin_symbol_resolution resolution)252738fd1498Szrj resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
252838fd1498Szrj {
252938fd1498Szrj   return (resolution == LDPR_PREVAILING_DEF
253038fd1498Szrj 	  || resolution == LDPR_PREEMPTED_REG
253138fd1498Szrj 	  || resolution == LDPR_RESOLVED_EXEC
253238fd1498Szrj 	  || resolution == LDPR_RESOLVED_DYN);
253338fd1498Szrj }
253438fd1498Szrj 
253538fd1498Szrj /* Return true when symtab_node is known to be used from other (non-LTO)
253638fd1498Szrj    object file. Known only when doing LTO via linker plugin.  */
253738fd1498Szrj 
253838fd1498Szrj inline bool
used_from_object_file_p(void)253938fd1498Szrj symtab_node::used_from_object_file_p (void)
254038fd1498Szrj {
254138fd1498Szrj   if (!TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
254238fd1498Szrj     return false;
254338fd1498Szrj   if (resolution_used_from_other_file_p (resolution))
254438fd1498Szrj     return true;
254538fd1498Szrj   return false;
254638fd1498Szrj }
254738fd1498Szrj 
254838fd1498Szrj /* Return varpool node for given symbol and check it is a function. */
254938fd1498Szrj 
255038fd1498Szrj inline varpool_node *
get(const_tree decl)255138fd1498Szrj varpool_node::get (const_tree decl)
255238fd1498Szrj {
255338fd1498Szrj   gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
255438fd1498Szrj   return dyn_cast<varpool_node *> (symtab_node::get (decl));
255538fd1498Szrj }
255638fd1498Szrj 
255738fd1498Szrj /* Register a symbol NODE.  */
255838fd1498Szrj 
255938fd1498Szrj inline void
register_symbol(symtab_node * node)256038fd1498Szrj symbol_table::register_symbol (symtab_node *node)
256138fd1498Szrj {
256238fd1498Szrj   node->next = nodes;
256338fd1498Szrj   node->previous = NULL;
256438fd1498Szrj 
256538fd1498Szrj   if (nodes)
256638fd1498Szrj     nodes->previous = node;
256738fd1498Szrj   nodes = node;
256838fd1498Szrj 
256938fd1498Szrj   node->order = order++;
257038fd1498Szrj }
257138fd1498Szrj 
257238fd1498Szrj /* Register a top-level asm statement ASM_STR.  */
257338fd1498Szrj 
257438fd1498Szrj asm_node *
finalize_toplevel_asm(tree asm_str)257538fd1498Szrj symbol_table::finalize_toplevel_asm (tree asm_str)
257638fd1498Szrj {
257738fd1498Szrj   asm_node *node;
257838fd1498Szrj 
257938fd1498Szrj   node = ggc_cleared_alloc<asm_node> ();
258038fd1498Szrj   node->asm_str = asm_str;
258138fd1498Szrj   node->order = order++;
258238fd1498Szrj   node->next = NULL;
258338fd1498Szrj 
258438fd1498Szrj   if (asmnodes == NULL)
258538fd1498Szrj     asmnodes = node;
258638fd1498Szrj   else
258738fd1498Szrj     asm_last_node->next = node;
258838fd1498Szrj 
258938fd1498Szrj   asm_last_node = node;
259038fd1498Szrj   return node;
259138fd1498Szrj }
259238fd1498Szrj 
259338fd1498Szrj /* Unregister a symbol NODE.  */
259438fd1498Szrj inline void
unregister(symtab_node * node)259538fd1498Szrj symbol_table::unregister (symtab_node *node)
259638fd1498Szrj {
259738fd1498Szrj   if (node->previous)
259838fd1498Szrj     node->previous->next = node->next;
259938fd1498Szrj   else
260038fd1498Szrj     nodes = node->next;
260138fd1498Szrj 
260238fd1498Szrj   if (node->next)
260338fd1498Szrj     node->next->previous = node->previous;
260438fd1498Szrj 
260538fd1498Szrj   node->next = NULL;
260638fd1498Szrj   node->previous = NULL;
260738fd1498Szrj }
260838fd1498Szrj 
260938fd1498Szrj /* Release a callgraph NODE with UID and put in to the list of free nodes.  */
261038fd1498Szrj 
261138fd1498Szrj inline void
release_symbol(cgraph_node * node,int uid)261238fd1498Szrj symbol_table::release_symbol (cgraph_node *node, int uid)
261338fd1498Szrj {
261438fd1498Szrj   cgraph_count--;
261538fd1498Szrj 
261638fd1498Szrj   /* Clear out the node to NULL all pointers and add the node to the free
261738fd1498Szrj      list.  */
261838fd1498Szrj   memset (node, 0, sizeof (*node));
261938fd1498Szrj   node->type = SYMTAB_FUNCTION;
262038fd1498Szrj   node->uid = uid;
262138fd1498Szrj   SET_NEXT_FREE_NODE (node, free_nodes);
262238fd1498Szrj   free_nodes = node;
262338fd1498Szrj }
262438fd1498Szrj 
262538fd1498Szrj /* Allocate new callgraph node.  */
262638fd1498Szrj 
262738fd1498Szrj inline cgraph_node *
allocate_cgraph_symbol(void)262838fd1498Szrj symbol_table::allocate_cgraph_symbol (void)
262938fd1498Szrj {
263038fd1498Szrj   cgraph_node *node;
263138fd1498Szrj 
263238fd1498Szrj   if (free_nodes)
263338fd1498Szrj     {
263438fd1498Szrj       node = free_nodes;
263538fd1498Szrj       free_nodes = NEXT_FREE_NODE (node);
263638fd1498Szrj     }
263738fd1498Szrj   else
263838fd1498Szrj     {
263938fd1498Szrj       node = ggc_cleared_alloc<cgraph_node> ();
264038fd1498Szrj       node->uid = cgraph_max_uid++;
264138fd1498Szrj     }
264238fd1498Szrj 
264338fd1498Szrj   node->summary_uid = cgraph_max_summary_uid++;
264438fd1498Szrj   return node;
264538fd1498Szrj }
264638fd1498Szrj 
264738fd1498Szrj 
264838fd1498Szrj /* Return first static symbol with definition.  */
264938fd1498Szrj inline symtab_node *
first_symbol(void)265038fd1498Szrj symbol_table::first_symbol (void)
265138fd1498Szrj {
265238fd1498Szrj   return nodes;
265338fd1498Szrj }
265438fd1498Szrj 
265538fd1498Szrj /* Walk all symbols.  */
265638fd1498Szrj #define FOR_EACH_SYMBOL(node) \
265738fd1498Szrj    for ((node) = symtab->first_symbol (); (node); (node) = (node)->next)
265838fd1498Szrj 
265938fd1498Szrj /* Return first static symbol with definition.  */
266038fd1498Szrj inline symtab_node *
first_defined_symbol(void)266138fd1498Szrj symbol_table::first_defined_symbol (void)
266238fd1498Szrj {
266338fd1498Szrj   symtab_node *node;
266438fd1498Szrj 
266538fd1498Szrj   for (node = nodes; node; node = node->next)
266638fd1498Szrj     if (node->definition)
266738fd1498Szrj       return node;
266838fd1498Szrj 
266938fd1498Szrj   return NULL;
267038fd1498Szrj }
267138fd1498Szrj 
267238fd1498Szrj /* Walk all symbols with definitions in current unit.  */
267338fd1498Szrj #define FOR_EACH_DEFINED_SYMBOL(node) \
267438fd1498Szrj    for ((node) = symtab->first_defined_symbol (); (node); \
267538fd1498Szrj 	(node) = node->next_defined_symbol ())
267638fd1498Szrj 
267738fd1498Szrj /* Return first variable.  */
267838fd1498Szrj inline varpool_node *
first_variable(void)267938fd1498Szrj symbol_table::first_variable (void)
268038fd1498Szrj {
268138fd1498Szrj   symtab_node *node;
268238fd1498Szrj   for (node = nodes; node; node = node->next)
268338fd1498Szrj     if (varpool_node *vnode = dyn_cast <varpool_node *> (node))
268438fd1498Szrj       return vnode;
268538fd1498Szrj   return NULL;
268638fd1498Szrj }
268738fd1498Szrj 
268838fd1498Szrj /* Return next variable after NODE.  */
268938fd1498Szrj inline varpool_node *
next_variable(varpool_node * node)269038fd1498Szrj symbol_table::next_variable (varpool_node *node)
269138fd1498Szrj {
269238fd1498Szrj   symtab_node *node1 = node->next;
269338fd1498Szrj   for (; node1; node1 = node1->next)
269438fd1498Szrj     if (varpool_node *vnode1 = dyn_cast <varpool_node *> (node1))
269538fd1498Szrj       return vnode1;
269638fd1498Szrj   return NULL;
269738fd1498Szrj }
269838fd1498Szrj /* Walk all variables.  */
269938fd1498Szrj #define FOR_EACH_VARIABLE(node) \
270038fd1498Szrj    for ((node) = symtab->first_variable (); \
270138fd1498Szrj         (node); \
270238fd1498Szrj 	(node) = symtab->next_variable ((node)))
270338fd1498Szrj 
270438fd1498Szrj /* Return first static variable with initializer.  */
270538fd1498Szrj inline varpool_node *
first_static_initializer(void)270638fd1498Szrj symbol_table::first_static_initializer (void)
270738fd1498Szrj {
270838fd1498Szrj   symtab_node *node;
270938fd1498Szrj   for (node = nodes; node; node = node->next)
271038fd1498Szrj     {
271138fd1498Szrj       varpool_node *vnode = dyn_cast <varpool_node *> (node);
271238fd1498Szrj       if (vnode && DECL_INITIAL (node->decl))
271338fd1498Szrj 	return vnode;
271438fd1498Szrj     }
271538fd1498Szrj   return NULL;
271638fd1498Szrj }
271738fd1498Szrj 
271838fd1498Szrj /* Return next static variable with initializer after NODE.  */
271938fd1498Szrj inline varpool_node *
next_static_initializer(varpool_node * node)272038fd1498Szrj symbol_table::next_static_initializer (varpool_node *node)
272138fd1498Szrj {
272238fd1498Szrj   symtab_node *node1 = node->next;
272338fd1498Szrj   for (; node1; node1 = node1->next)
272438fd1498Szrj     {
272538fd1498Szrj       varpool_node *vnode1 = dyn_cast <varpool_node *> (node1);
272638fd1498Szrj       if (vnode1 && DECL_INITIAL (node1->decl))
272738fd1498Szrj 	return vnode1;
272838fd1498Szrj     }
272938fd1498Szrj   return NULL;
273038fd1498Szrj }
273138fd1498Szrj 
273238fd1498Szrj /* Walk all static variables with initializer set.  */
273338fd1498Szrj #define FOR_EACH_STATIC_INITIALIZER(node) \
273438fd1498Szrj    for ((node) = symtab->first_static_initializer (); (node); \
273538fd1498Szrj 	(node) = symtab->next_static_initializer (node))
273638fd1498Szrj 
273738fd1498Szrj /* Return first static variable with definition.  */
273838fd1498Szrj inline varpool_node *
first_defined_variable(void)273938fd1498Szrj symbol_table::first_defined_variable (void)
274038fd1498Szrj {
274138fd1498Szrj   symtab_node *node;
274238fd1498Szrj   for (node = nodes; node; node = node->next)
274338fd1498Szrj     {
274438fd1498Szrj       varpool_node *vnode = dyn_cast <varpool_node *> (node);
274538fd1498Szrj       if (vnode && vnode->definition)
274638fd1498Szrj 	return vnode;
274738fd1498Szrj     }
274838fd1498Szrj   return NULL;
274938fd1498Szrj }
275038fd1498Szrj 
275138fd1498Szrj /* Return next static variable with definition after NODE.  */
275238fd1498Szrj inline varpool_node *
next_defined_variable(varpool_node * node)275338fd1498Szrj symbol_table::next_defined_variable (varpool_node *node)
275438fd1498Szrj {
275538fd1498Szrj   symtab_node *node1 = node->next;
275638fd1498Szrj   for (; node1; node1 = node1->next)
275738fd1498Szrj     {
275838fd1498Szrj       varpool_node *vnode1 = dyn_cast <varpool_node *> (node1);
275938fd1498Szrj       if (vnode1 && vnode1->definition)
276038fd1498Szrj 	return vnode1;
276138fd1498Szrj     }
276238fd1498Szrj   return NULL;
276338fd1498Szrj }
276438fd1498Szrj /* Walk all variables with definitions in current unit.  */
276538fd1498Szrj #define FOR_EACH_DEFINED_VARIABLE(node) \
276638fd1498Szrj    for ((node) = symtab->first_defined_variable (); (node); \
276738fd1498Szrj 	(node) = symtab->next_defined_variable (node))
276838fd1498Szrj 
276938fd1498Szrj /* Return first function with body defined.  */
277038fd1498Szrj inline cgraph_node *
first_defined_function(void)277138fd1498Szrj symbol_table::first_defined_function (void)
277238fd1498Szrj {
277338fd1498Szrj   symtab_node *node;
277438fd1498Szrj   for (node = nodes; node; node = node->next)
277538fd1498Szrj     {
277638fd1498Szrj       cgraph_node *cn = dyn_cast <cgraph_node *> (node);
277738fd1498Szrj       if (cn && cn->definition)
277838fd1498Szrj 	return cn;
277938fd1498Szrj     }
278038fd1498Szrj   return NULL;
278138fd1498Szrj }
278238fd1498Szrj 
278338fd1498Szrj /* Return next function with body defined after NODE.  */
278438fd1498Szrj inline cgraph_node *
next_defined_function(cgraph_node * node)278538fd1498Szrj symbol_table::next_defined_function (cgraph_node *node)
278638fd1498Szrj {
278738fd1498Szrj   symtab_node *node1 = node->next;
278838fd1498Szrj   for (; node1; node1 = node1->next)
278938fd1498Szrj     {
279038fd1498Szrj       cgraph_node *cn1 = dyn_cast <cgraph_node *> (node1);
279138fd1498Szrj       if (cn1 && cn1->definition)
279238fd1498Szrj 	return cn1;
279338fd1498Szrj     }
279438fd1498Szrj   return NULL;
279538fd1498Szrj }
279638fd1498Szrj 
279738fd1498Szrj /* Walk all functions with body defined.  */
279838fd1498Szrj #define FOR_EACH_DEFINED_FUNCTION(node) \
279938fd1498Szrj    for ((node) = symtab->first_defined_function (); (node); \
280038fd1498Szrj 	(node) = symtab->next_defined_function ((node)))
280138fd1498Szrj 
280238fd1498Szrj /* Return first function.  */
280338fd1498Szrj inline cgraph_node *
first_function(void)280438fd1498Szrj symbol_table::first_function (void)
280538fd1498Szrj {
280638fd1498Szrj   symtab_node *node;
280738fd1498Szrj   for (node = nodes; node; node = node->next)
280838fd1498Szrj     if (cgraph_node *cn = dyn_cast <cgraph_node *> (node))
280938fd1498Szrj       return cn;
281038fd1498Szrj   return NULL;
281138fd1498Szrj }
281238fd1498Szrj 
281338fd1498Szrj /* Return next function.  */
281438fd1498Szrj inline cgraph_node *
next_function(cgraph_node * node)281538fd1498Szrj symbol_table::next_function (cgraph_node *node)
281638fd1498Szrj {
281738fd1498Szrj   symtab_node *node1 = node->next;
281838fd1498Szrj   for (; node1; node1 = node1->next)
281938fd1498Szrj     if (cgraph_node *cn1 = dyn_cast <cgraph_node *> (node1))
282038fd1498Szrj       return cn1;
282138fd1498Szrj   return NULL;
282238fd1498Szrj }
282338fd1498Szrj 
282438fd1498Szrj /* Return first function with body defined.  */
282538fd1498Szrj inline cgraph_node *
first_function_with_gimple_body(void)282638fd1498Szrj symbol_table::first_function_with_gimple_body (void)
282738fd1498Szrj {
282838fd1498Szrj   symtab_node *node;
282938fd1498Szrj   for (node = nodes; node; node = node->next)
283038fd1498Szrj     {
283138fd1498Szrj       cgraph_node *cn = dyn_cast <cgraph_node *> (node);
283238fd1498Szrj       if (cn && cn->has_gimple_body_p ())
283338fd1498Szrj 	return cn;
283438fd1498Szrj     }
283538fd1498Szrj   return NULL;
283638fd1498Szrj }
283738fd1498Szrj 
283838fd1498Szrj /* Return next reachable static variable with initializer after NODE.  */
283938fd1498Szrj inline cgraph_node *
next_function_with_gimple_body(cgraph_node * node)284038fd1498Szrj symbol_table::next_function_with_gimple_body (cgraph_node *node)
284138fd1498Szrj {
284238fd1498Szrj   symtab_node *node1 = node->next;
284338fd1498Szrj   for (; node1; node1 = node1->next)
284438fd1498Szrj     {
284538fd1498Szrj       cgraph_node *cn1 = dyn_cast <cgraph_node *> (node1);
284638fd1498Szrj       if (cn1 && cn1->has_gimple_body_p ())
284738fd1498Szrj 	return cn1;
284838fd1498Szrj     }
284938fd1498Szrj   return NULL;
285038fd1498Szrj }
285138fd1498Szrj 
285238fd1498Szrj /* Walk all functions.  */
285338fd1498Szrj #define FOR_EACH_FUNCTION(node) \
285438fd1498Szrj    for ((node) = symtab->first_function (); (node); \
285538fd1498Szrj 	(node) = symtab->next_function ((node)))
285638fd1498Szrj 
285738fd1498Szrj /* Return true when callgraph node is a function with Gimple body defined
285838fd1498Szrj    in current unit.  Functions can also be define externally or they
285938fd1498Szrj    can be thunks with no Gimple representation.
286038fd1498Szrj 
286138fd1498Szrj    Note that at WPA stage, the function body may not be present in memory.  */
286238fd1498Szrj 
286338fd1498Szrj inline bool
has_gimple_body_p(void)286438fd1498Szrj cgraph_node::has_gimple_body_p (void)
286538fd1498Szrj {
286638fd1498Szrj   return definition && !thunk.thunk_p && !alias;
286738fd1498Szrj }
286838fd1498Szrj 
2869*e215fc28Szrj /* Return true if this node represents a former, i.e. an expanded, thunk.  */
2870*e215fc28Szrj 
2871*e215fc28Szrj inline bool
former_thunk_p(void)2872*e215fc28Szrj cgraph_node::former_thunk_p (void)
2873*e215fc28Szrj {
2874*e215fc28Szrj   return (!thunk.thunk_p
2875*e215fc28Szrj 	  && (thunk.fixed_offset
2876*e215fc28Szrj 	      || thunk.virtual_offset_p));
2877*e215fc28Szrj }
2878*e215fc28Szrj 
287938fd1498Szrj /* Walk all functions with body defined.  */
288038fd1498Szrj #define FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) \
288138fd1498Szrj    for ((node) = symtab->first_function_with_gimple_body (); (node); \
288238fd1498Szrj 	(node) = symtab->next_function_with_gimple_body (node))
288338fd1498Szrj 
288438fd1498Szrj /* Uniquize all constants that appear in memory.
288538fd1498Szrj    Each constant in memory thus far output is recorded
288638fd1498Szrj    in `const_desc_table'.  */
288738fd1498Szrj 
288838fd1498Szrj struct GTY((for_user)) constant_descriptor_tree {
288938fd1498Szrj   /* A MEM for the constant.  */
289038fd1498Szrj   rtx rtl;
289138fd1498Szrj 
289238fd1498Szrj   /* The value of the constant.  */
289338fd1498Szrj   tree value;
289438fd1498Szrj 
289538fd1498Szrj   /* Hash of value.  Computing the hash from value each time
289638fd1498Szrj      hashfn is called can't work properly, as that means recursive
289738fd1498Szrj      use of the hash table during hash table expansion.  */
289838fd1498Szrj   hashval_t hash;
289938fd1498Szrj };
290038fd1498Szrj 
290138fd1498Szrj /* Return true when function is only called directly or it has alias.
290238fd1498Szrj    i.e. it is not externally visible, address was not taken and
290338fd1498Szrj    it is not used in any other non-standard way.  */
290438fd1498Szrj 
290538fd1498Szrj inline bool
only_called_directly_or_aliased_p(void)290638fd1498Szrj cgraph_node::only_called_directly_or_aliased_p (void)
290738fd1498Szrj {
290838fd1498Szrj   gcc_assert (!global.inlined_to);
290938fd1498Szrj   return (!force_output && !address_taken
291058e805e6Szrj 	  && !ifunc_resolver
291138fd1498Szrj 	  && !used_from_other_partition
291238fd1498Szrj 	  && !DECL_VIRTUAL_P (decl)
291338fd1498Szrj 	  && !DECL_STATIC_CONSTRUCTOR (decl)
291438fd1498Szrj 	  && !DECL_STATIC_DESTRUCTOR (decl)
291538fd1498Szrj 	  && !used_from_object_file_p ()
291638fd1498Szrj 	  && !externally_visible);
291738fd1498Szrj }
291838fd1498Szrj 
291938fd1498Szrj /* Return true when function can be removed from callgraph
292038fd1498Szrj    if all direct calls are eliminated.  */
292138fd1498Szrj 
292238fd1498Szrj inline bool
can_remove_if_no_direct_calls_and_refs_p(void)292338fd1498Szrj cgraph_node::can_remove_if_no_direct_calls_and_refs_p (void)
292438fd1498Szrj {
292538fd1498Szrj   gcc_checking_assert (!global.inlined_to);
292638fd1498Szrj   /* Instrumentation clones should not be removed before
292738fd1498Szrj      instrumentation happens.  New callers may appear after
292838fd1498Szrj      instrumentation.  */
292938fd1498Szrj   if (instrumentation_clone
293038fd1498Szrj       && !chkp_function_instrumented_p (decl))
293138fd1498Szrj     return false;
293238fd1498Szrj   /* Extern inlines can always go, we will use the external definition.  */
293338fd1498Szrj   if (DECL_EXTERNAL (decl))
293438fd1498Szrj     return true;
293538fd1498Szrj   /* When function is needed, we can not remove it.  */
293638fd1498Szrj   if (force_output || used_from_other_partition)
293738fd1498Szrj     return false;
293838fd1498Szrj   if (DECL_STATIC_CONSTRUCTOR (decl)
293938fd1498Szrj       || DECL_STATIC_DESTRUCTOR (decl))
294038fd1498Szrj     return false;
294138fd1498Szrj   /* Only COMDAT functions can be removed if externally visible.  */
294238fd1498Szrj   if (externally_visible
294338fd1498Szrj       && (!DECL_COMDAT (decl)
294438fd1498Szrj 	  || forced_by_abi
294538fd1498Szrj 	  || used_from_object_file_p ()))
294638fd1498Szrj     return false;
294738fd1498Szrj   return true;
294838fd1498Szrj }
294938fd1498Szrj 
295038fd1498Szrj /* Verify cgraph, if consistency checking is enabled.  */
295138fd1498Szrj 
295238fd1498Szrj inline void
checking_verify_cgraph_nodes(void)295338fd1498Szrj cgraph_node::checking_verify_cgraph_nodes (void)
295438fd1498Szrj {
295538fd1498Szrj   if (flag_checking)
295638fd1498Szrj     cgraph_node::verify_cgraph_nodes ();
295738fd1498Szrj }
295838fd1498Szrj 
295938fd1498Szrj /* Return true when variable can be removed from variable pool
296038fd1498Szrj    if all direct calls are eliminated.  */
296138fd1498Szrj 
296238fd1498Szrj inline bool
can_remove_if_no_refs_p(void)296338fd1498Szrj varpool_node::can_remove_if_no_refs_p (void)
296438fd1498Szrj {
296538fd1498Szrj   if (DECL_EXTERNAL (decl))
296638fd1498Szrj     return true;
296738fd1498Szrj   return (!force_output && !used_from_other_partition
296838fd1498Szrj 	  && ((DECL_COMDAT (decl)
296938fd1498Szrj 	       && !forced_by_abi
297038fd1498Szrj 	       && !used_from_object_file_p ())
297138fd1498Szrj 	      || !externally_visible
297238fd1498Szrj 	      || DECL_HAS_VALUE_EXPR_P (decl)));
297338fd1498Szrj }
297438fd1498Szrj 
297538fd1498Szrj /* Return true when all references to variable must be visible in ipa_ref_list.
297638fd1498Szrj    i.e. if the variable is not externally visible or not used in some magic
297738fd1498Szrj    way (asm statement or such).
297838fd1498Szrj    The magic uses are all summarized in force_output flag.  */
297938fd1498Szrj 
298038fd1498Szrj inline bool
all_refs_explicit_p()298138fd1498Szrj varpool_node::all_refs_explicit_p ()
298238fd1498Szrj {
298338fd1498Szrj   return (definition
298438fd1498Szrj 	  && !externally_visible
298538fd1498Szrj 	  && !used_from_other_partition
298638fd1498Szrj 	  && !force_output);
298738fd1498Szrj }
298838fd1498Szrj 
298938fd1498Szrj struct tree_descriptor_hasher : ggc_ptr_hash<constant_descriptor_tree>
299038fd1498Szrj {
299138fd1498Szrj   static hashval_t hash (constant_descriptor_tree *);
299238fd1498Szrj   static bool equal (constant_descriptor_tree *, constant_descriptor_tree *);
299338fd1498Szrj };
299438fd1498Szrj 
299538fd1498Szrj /* Constant pool accessor function.  */
299638fd1498Szrj hash_table<tree_descriptor_hasher> *constant_pool_htab (void);
299738fd1498Szrj 
299838fd1498Szrj /* Return node that alias is aliasing.  */
299938fd1498Szrj 
300038fd1498Szrj inline cgraph_node *
get_alias_target(void)300138fd1498Szrj cgraph_node::get_alias_target (void)
300238fd1498Szrj {
300338fd1498Szrj   return dyn_cast <cgraph_node *> (symtab_node::get_alias_target ());
300438fd1498Szrj }
300538fd1498Szrj 
300638fd1498Szrj /* Return node that alias is aliasing.  */
300738fd1498Szrj 
300838fd1498Szrj inline varpool_node *
get_alias_target(void)300938fd1498Szrj varpool_node::get_alias_target (void)
301038fd1498Szrj {
301138fd1498Szrj   return dyn_cast <varpool_node *> (symtab_node::get_alias_target ());
301238fd1498Szrj }
301338fd1498Szrj 
301438fd1498Szrj /* Walk the alias chain to return the symbol NODE is alias of.
301538fd1498Szrj    If NODE is not an alias, return NODE.
301638fd1498Szrj    When AVAILABILITY is non-NULL, get minimal availability in the chain.
301738fd1498Szrj    When REF is non-NULL, assume that reference happens in symbol REF
301838fd1498Szrj    when determining the availability.  */
301938fd1498Szrj 
302038fd1498Szrj inline symtab_node *
ultimate_alias_target(enum availability * availability,symtab_node * ref)302138fd1498Szrj symtab_node::ultimate_alias_target (enum availability *availability,
302238fd1498Szrj 				    symtab_node *ref)
302338fd1498Szrj {
302438fd1498Szrj   if (!alias)
302538fd1498Szrj     {
302638fd1498Szrj       if (availability)
302738fd1498Szrj 	*availability = get_availability (ref);
302838fd1498Szrj       return this;
302938fd1498Szrj     }
303038fd1498Szrj 
303138fd1498Szrj   return ultimate_alias_target_1 (availability, ref);
303238fd1498Szrj }
303338fd1498Szrj 
303438fd1498Szrj /* Given function symbol, walk the alias chain to return the function node
303538fd1498Szrj    is alias of. Do not walk through thunks.
303638fd1498Szrj    When AVAILABILITY is non-NULL, get minimal availability in the chain.
303738fd1498Szrj    When REF is non-NULL, assume that reference happens in symbol REF
303838fd1498Szrj    when determining the availability.  */
303938fd1498Szrj 
304038fd1498Szrj inline cgraph_node *
ultimate_alias_target(enum availability * availability,symtab_node * ref)304138fd1498Szrj cgraph_node::ultimate_alias_target (enum availability *availability,
304238fd1498Szrj 				    symtab_node *ref)
304338fd1498Szrj {
304438fd1498Szrj   cgraph_node *n = dyn_cast <cgraph_node *>
304538fd1498Szrj     (symtab_node::ultimate_alias_target (availability, ref));
304638fd1498Szrj   if (!n && availability)
304738fd1498Szrj     *availability = AVAIL_NOT_AVAILABLE;
304838fd1498Szrj   return n;
304938fd1498Szrj }
305038fd1498Szrj 
305138fd1498Szrj /* For given variable pool node, walk the alias chain to return the function
305238fd1498Szrj    the variable is alias of. Do not walk through thunks.
305338fd1498Szrj    When AVAILABILITY is non-NULL, get minimal availability in the chain.
305438fd1498Szrj    When REF is non-NULL, assume that reference happens in symbol REF
305538fd1498Szrj    when determining the availability.  */
305638fd1498Szrj 
305738fd1498Szrj inline varpool_node *
ultimate_alias_target(availability * availability,symtab_node * ref)305838fd1498Szrj varpool_node::ultimate_alias_target (availability *availability,
305938fd1498Szrj 				     symtab_node *ref)
306038fd1498Szrj {
306138fd1498Szrj   varpool_node *n = dyn_cast <varpool_node *>
306238fd1498Szrj     (symtab_node::ultimate_alias_target (availability, ref));
306338fd1498Szrj 
306438fd1498Szrj   if (!n && availability)
306538fd1498Szrj     *availability = AVAIL_NOT_AVAILABLE;
306638fd1498Szrj   return n;
306738fd1498Szrj }
306838fd1498Szrj 
306938fd1498Szrj /* Set callee N of call graph edge and add it to the corresponding set of
307038fd1498Szrj    callers. */
307138fd1498Szrj 
307238fd1498Szrj inline void
set_callee(cgraph_node * n)307338fd1498Szrj cgraph_edge::set_callee (cgraph_node *n)
307438fd1498Szrj {
307538fd1498Szrj   prev_caller = NULL;
307638fd1498Szrj   if (n->callers)
307738fd1498Szrj     n->callers->prev_caller = this;
307838fd1498Szrj   next_caller = n->callers;
307938fd1498Szrj   n->callers = this;
308038fd1498Szrj   callee = n;
308138fd1498Szrj }
308238fd1498Szrj 
308338fd1498Szrj /* Redirect callee of the edge to N.  The function does not update underlying
308438fd1498Szrj    call expression.  */
308538fd1498Szrj 
308638fd1498Szrj inline void
redirect_callee(cgraph_node * n)308738fd1498Szrj cgraph_edge::redirect_callee (cgraph_node *n)
308838fd1498Szrj {
308938fd1498Szrj   /* Remove from callers list of the current callee.  */
309038fd1498Szrj   remove_callee ();
309138fd1498Szrj 
309238fd1498Szrj   /* Insert to callers list of the new callee.  */
309338fd1498Szrj   set_callee (n);
309438fd1498Szrj }
309538fd1498Szrj 
309638fd1498Szrj /* Return true when the edge represents a direct recursion.  */
309738fd1498Szrj 
309838fd1498Szrj inline bool
recursive_p(void)309938fd1498Szrj cgraph_edge::recursive_p (void)
310038fd1498Szrj {
310138fd1498Szrj   cgraph_node *c = callee->ultimate_alias_target ();
310238fd1498Szrj   if (caller->global.inlined_to)
310338fd1498Szrj     return caller->global.inlined_to->decl == c->decl;
310438fd1498Szrj   else
310538fd1498Szrj     return caller->decl == c->decl;
310638fd1498Szrj }
310738fd1498Szrj 
310838fd1498Szrj /* Remove the edge from the list of the callers of the callee.  */
310938fd1498Szrj 
311038fd1498Szrj inline void
remove_callee(void)311138fd1498Szrj cgraph_edge::remove_callee (void)
311238fd1498Szrj {
311338fd1498Szrj   gcc_assert (!indirect_unknown_callee);
311438fd1498Szrj   if (prev_caller)
311538fd1498Szrj     prev_caller->next_caller = next_caller;
311638fd1498Szrj   if (next_caller)
311738fd1498Szrj     next_caller->prev_caller = prev_caller;
311838fd1498Szrj   if (!prev_caller)
311938fd1498Szrj     callee->callers = next_caller;
312038fd1498Szrj }
312138fd1498Szrj 
312238fd1498Szrj /* Return true if call must bind to current definition.  */
312338fd1498Szrj 
312438fd1498Szrj inline bool
binds_to_current_def_p()312538fd1498Szrj cgraph_edge::binds_to_current_def_p ()
312638fd1498Szrj {
312738fd1498Szrj   if (callee)
312838fd1498Szrj     return callee->binds_to_current_def_p (caller);
312938fd1498Szrj   else
313038fd1498Szrj     return false;
313138fd1498Szrj }
313238fd1498Szrj 
313338fd1498Szrj /* Expected frequency of executions within the function.
313438fd1498Szrj    When set to CGRAPH_FREQ_BASE, the edge is expected to be called once
313538fd1498Szrj    per function call.  The range is 0 to CGRAPH_FREQ_MAX.  */
313638fd1498Szrj 
313738fd1498Szrj inline int
frequency()313838fd1498Szrj cgraph_edge::frequency ()
313938fd1498Szrj {
314038fd1498Szrj   return count.to_cgraph_frequency (caller->global.inlined_to
314138fd1498Szrj 				    ? caller->global.inlined_to->count
314238fd1498Szrj 				    : caller->count);
314338fd1498Szrj }
314438fd1498Szrj 
314538fd1498Szrj 
314638fd1498Szrj /* Return true if the TM_CLONE bit is set for a given FNDECL.  */
314738fd1498Szrj static inline bool
decl_is_tm_clone(const_tree fndecl)314838fd1498Szrj decl_is_tm_clone (const_tree fndecl)
314938fd1498Szrj {
315038fd1498Szrj   cgraph_node *n = cgraph_node::get (fndecl);
315138fd1498Szrj   if (n)
315238fd1498Szrj     return n->tm_clone;
315338fd1498Szrj   return false;
315438fd1498Szrj }
315538fd1498Szrj 
315638fd1498Szrj /* Likewise indicate that a node is needed, i.e. reachable via some
315738fd1498Szrj    external means.  */
315838fd1498Szrj 
315938fd1498Szrj inline void
mark_force_output(void)316038fd1498Szrj cgraph_node::mark_force_output (void)
316138fd1498Szrj {
316238fd1498Szrj   force_output = 1;
316338fd1498Szrj   gcc_checking_assert (!global.inlined_to);
316438fd1498Szrj }
316538fd1498Szrj 
316638fd1498Szrj /* Return true if function should be optimized for size.  */
316738fd1498Szrj 
316838fd1498Szrj inline bool
optimize_for_size_p(void)316938fd1498Szrj cgraph_node::optimize_for_size_p (void)
317038fd1498Szrj {
317138fd1498Szrj   if (opt_for_fn (decl, optimize_size))
317238fd1498Szrj     return true;
317338fd1498Szrj   if (frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
317438fd1498Szrj     return true;
317538fd1498Szrj   else
317638fd1498Szrj     return false;
317738fd1498Szrj }
317838fd1498Szrj 
317938fd1498Szrj /* Return symtab_node for NODE or create one if it is not present
318038fd1498Szrj    in symtab.  */
318138fd1498Szrj 
318238fd1498Szrj inline symtab_node *
get_create(tree node)318338fd1498Szrj symtab_node::get_create (tree node)
318438fd1498Szrj {
318538fd1498Szrj   if (TREE_CODE (node) == VAR_DECL)
318638fd1498Szrj     return varpool_node::get_create (node);
318738fd1498Szrj   else
318838fd1498Szrj     return cgraph_node::get_create (node);
318938fd1498Szrj }
319038fd1498Szrj 
319138fd1498Szrj /* Return availability of NODE when referenced from REF.  */
319238fd1498Szrj 
319338fd1498Szrj inline enum availability
get_availability(symtab_node * ref)319438fd1498Szrj symtab_node::get_availability (symtab_node *ref)
319538fd1498Szrj {
319638fd1498Szrj   if (is_a <cgraph_node *> (this))
319738fd1498Szrj     return dyn_cast <cgraph_node *> (this)->get_availability (ref);
319838fd1498Szrj   else
319938fd1498Szrj     return dyn_cast <varpool_node *> (this)->get_availability (ref);
320038fd1498Szrj }
320138fd1498Szrj 
320238fd1498Szrj /* Call calback on symtab node and aliases associated to this node.
320338fd1498Szrj    When INCLUDE_OVERWRITABLE is false, overwritable symbols are skipped. */
320438fd1498Szrj 
320538fd1498Szrj inline bool
call_for_symbol_and_aliases(bool (* callback)(symtab_node *,void *),void * data,bool include_overwritable)320638fd1498Szrj symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *,
320738fd1498Szrj 							    void *),
320838fd1498Szrj 					  void *data,
320938fd1498Szrj 					  bool include_overwritable)
321038fd1498Szrj {
321138fd1498Szrj   if (include_overwritable
321238fd1498Szrj       || get_availability () > AVAIL_INTERPOSABLE)
321338fd1498Szrj     {
321438fd1498Szrj       if (callback (this, data))
321538fd1498Szrj         return true;
321638fd1498Szrj     }
321738fd1498Szrj   if (has_aliases_p ())
321838fd1498Szrj     return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
321938fd1498Szrj   return false;
322038fd1498Szrj }
322138fd1498Szrj 
322238fd1498Szrj /* Call callback on function and aliases associated to the function.
322338fd1498Szrj    When INCLUDE_OVERWRITABLE is false, overwritable symbols are
322438fd1498Szrj    skipped.  */
322538fd1498Szrj 
322638fd1498Szrj inline bool
call_for_symbol_and_aliases(bool (* callback)(cgraph_node *,void *),void * data,bool include_overwritable)322738fd1498Szrj cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
322838fd1498Szrj 							    void *),
322938fd1498Szrj 					  void *data,
323038fd1498Szrj 					  bool include_overwritable)
323138fd1498Szrj {
323238fd1498Szrj   if (include_overwritable
323338fd1498Szrj       || get_availability () > AVAIL_INTERPOSABLE)
323438fd1498Szrj     {
323538fd1498Szrj       if (callback (this, data))
323638fd1498Szrj         return true;
323738fd1498Szrj     }
323838fd1498Szrj   if (has_aliases_p ())
323938fd1498Szrj     return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
324038fd1498Szrj   return false;
324138fd1498Szrj }
324238fd1498Szrj 
324338fd1498Szrj /* Call calback on varpool symbol and aliases associated to varpool symbol.
324438fd1498Szrj    When INCLUDE_OVERWRITABLE is false, overwritable symbols are
324538fd1498Szrj    skipped. */
324638fd1498Szrj 
324738fd1498Szrj inline bool
call_for_symbol_and_aliases(bool (* callback)(varpool_node *,void *),void * data,bool include_overwritable)324838fd1498Szrj varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *,
324938fd1498Szrj 							     void *),
325038fd1498Szrj 					   void *data,
325138fd1498Szrj 					   bool include_overwritable)
325238fd1498Szrj {
325338fd1498Szrj   if (include_overwritable
325438fd1498Szrj       || get_availability () > AVAIL_INTERPOSABLE)
325538fd1498Szrj     {
325638fd1498Szrj       if (callback (this, data))
325738fd1498Szrj         return true;
325838fd1498Szrj     }
325938fd1498Szrj   if (has_aliases_p ())
326038fd1498Szrj     return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
326138fd1498Szrj   return false;
326238fd1498Szrj }
326338fd1498Szrj 
326438fd1498Szrj /* Return true if refernece may be used in address compare.  */
326538fd1498Szrj 
326638fd1498Szrj inline bool
address_matters_p()326738fd1498Szrj ipa_ref::address_matters_p ()
326838fd1498Szrj {
326938fd1498Szrj   if (use != IPA_REF_ADDR)
327038fd1498Szrj     return false;
327138fd1498Szrj   /* Addresses taken from virtual tables are never compared.  */
327238fd1498Szrj   if (is_a <varpool_node *> (referring)
327338fd1498Szrj       && DECL_VIRTUAL_P (referring->decl))
327438fd1498Szrj     return false;
327538fd1498Szrj   return referred->address_can_be_compared_p ();
327638fd1498Szrj }
327738fd1498Szrj 
327838fd1498Szrj /* Build polymorphic call context for indirect call E.  */
327938fd1498Szrj 
328038fd1498Szrj inline
ipa_polymorphic_call_context(cgraph_edge * e)328138fd1498Szrj ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e)
328238fd1498Szrj {
328338fd1498Szrj   gcc_checking_assert (e->indirect_info->polymorphic);
328438fd1498Szrj   *this = e->indirect_info->context;
328538fd1498Szrj }
328638fd1498Szrj 
328738fd1498Szrj /* Build empty "I know nothing" context.  */
328838fd1498Szrj 
328938fd1498Szrj inline
ipa_polymorphic_call_context()329038fd1498Szrj ipa_polymorphic_call_context::ipa_polymorphic_call_context ()
329138fd1498Szrj {
329238fd1498Szrj   clear_speculation ();
329338fd1498Szrj   clear_outer_type ();
329438fd1498Szrj   invalid = false;
329538fd1498Szrj }
329638fd1498Szrj 
329738fd1498Szrj /* Make context non-speculative.  */
329838fd1498Szrj 
329938fd1498Szrj inline void
clear_speculation()330038fd1498Szrj ipa_polymorphic_call_context::clear_speculation ()
330138fd1498Szrj {
330238fd1498Szrj   speculative_outer_type = NULL;
330338fd1498Szrj   speculative_offset = 0;
330438fd1498Szrj   speculative_maybe_derived_type = false;
330538fd1498Szrj }
330638fd1498Szrj 
330738fd1498Szrj /* Produce context specifying all derrived types of OTR_TYPE.  If OTR_TYPE is
330838fd1498Szrj    NULL, the context is set to dummy "I know nothing" setting.  */
330938fd1498Szrj 
331038fd1498Szrj inline void
clear_outer_type(tree otr_type)331138fd1498Szrj ipa_polymorphic_call_context::clear_outer_type (tree otr_type)
331238fd1498Szrj {
331338fd1498Szrj   outer_type = otr_type ? TYPE_MAIN_VARIANT (otr_type) : NULL;
331438fd1498Szrj   offset = 0;
331538fd1498Szrj   maybe_derived_type = true;
331638fd1498Szrj   maybe_in_construction = true;
331738fd1498Szrj   dynamic = true;
331838fd1498Szrj }
331938fd1498Szrj 
332038fd1498Szrj /* Adjust all offsets in contexts by OFF bits.  */
332138fd1498Szrj 
332238fd1498Szrj inline void
offset_by(HOST_WIDE_INT off)332338fd1498Szrj ipa_polymorphic_call_context::offset_by (HOST_WIDE_INT off)
332438fd1498Szrj {
332538fd1498Szrj   if (outer_type)
332638fd1498Szrj     offset += off;
332738fd1498Szrj   if (speculative_outer_type)
332838fd1498Szrj     speculative_offset += off;
332938fd1498Szrj }
333038fd1498Szrj 
333138fd1498Szrj /* Return TRUE if context is fully useless.  */
333238fd1498Szrj 
333338fd1498Szrj inline bool
useless_p()333438fd1498Szrj ipa_polymorphic_call_context::useless_p () const
333538fd1498Szrj {
333638fd1498Szrj   return (!outer_type && !speculative_outer_type);
333738fd1498Szrj }
333838fd1498Szrj 
333938fd1498Szrj /* Return true if NODE is local.  Instrumentation clones are counted as local
334038fd1498Szrj    only when original function is local.  */
334138fd1498Szrj 
334238fd1498Szrj static inline bool
cgraph_local_p(cgraph_node * node)334338fd1498Szrj cgraph_local_p (cgraph_node *node)
334438fd1498Szrj {
334538fd1498Szrj   if (!node->instrumentation_clone || !node->instrumented_version)
334638fd1498Szrj     return node->local.local;
334738fd1498Szrj 
334838fd1498Szrj   return node->local.local && node->instrumented_version->local.local;
334938fd1498Szrj }
335038fd1498Szrj 
335138fd1498Szrj /* When using fprintf (or similar), problems can arise with
335238fd1498Szrj    transient generated strings.  Many string-generation APIs
335338fd1498Szrj    only support one result being alive at once (e.g. by
335438fd1498Szrj    returning a pointer to a statically-allocated buffer).
335538fd1498Szrj 
335638fd1498Szrj    If there is more than one generated string within one
335738fd1498Szrj    fprintf call: the first string gets evicted or overwritten
335838fd1498Szrj    by the second, before fprintf is fully evaluated.
335938fd1498Szrj    See e.g. PR/53136.
336038fd1498Szrj 
336138fd1498Szrj    This function provides a workaround for this, by providing
336238fd1498Szrj    a simple way to create copies of these transient strings,
336338fd1498Szrj    without the need to have explicit cleanup:
336438fd1498Szrj 
336538fd1498Szrj        fprintf (dumpfile, "string 1: %s string 2:%s\n",
336638fd1498Szrj                 xstrdup_for_dump (EXPR_1),
336738fd1498Szrj                 xstrdup_for_dump (EXPR_2));
336838fd1498Szrj 
336938fd1498Szrj    This is actually a simple wrapper around ggc_strdup, but
337038fd1498Szrj    the name documents the intent.  We require that no GC can occur
337138fd1498Szrj    within the fprintf call.  */
337238fd1498Szrj 
337338fd1498Szrj static inline const char *
xstrdup_for_dump(const char * transient_str)337438fd1498Szrj xstrdup_for_dump (const char *transient_str)
337538fd1498Szrj {
337638fd1498Szrj   return ggc_strdup (transient_str);
337738fd1498Szrj }
337838fd1498Szrj 
337938fd1498Szrj #endif  /* GCC_CGRAPH_H  */
3380