xref: /dragonfly/contrib/gcc-8.0/gcc/lto/lto.c (revision 58e805e6)
138fd1498Szrj /* Top-level LTO routines.
238fd1498Szrj    Copyright (C) 2009-2018 Free Software Foundation, Inc.
338fd1498Szrj    Contributed by CodeSourcery, Inc.
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 #include "config.h"
2238fd1498Szrj #include "system.h"
2338fd1498Szrj #include "coretypes.h"
2438fd1498Szrj #include "tm.h"
2538fd1498Szrj #include "function.h"
2638fd1498Szrj #include "bitmap.h"
2738fd1498Szrj #include "basic-block.h"
2838fd1498Szrj #include "tree.h"
2938fd1498Szrj #include "gimple.h"
3038fd1498Szrj #include "cfghooks.h"
3138fd1498Szrj #include "alloc-pool.h"
3238fd1498Szrj #include "tree-pass.h"
3338fd1498Szrj #include "tree-streamer.h"
3438fd1498Szrj #include "cgraph.h"
3538fd1498Szrj #include "opts.h"
3638fd1498Szrj #include "toplev.h"
3738fd1498Szrj #include "stor-layout.h"
3838fd1498Szrj #include "symbol-summary.h"
3938fd1498Szrj #include "tree-vrp.h"
4038fd1498Szrj #include "ipa-prop.h"
4138fd1498Szrj #include "common.h"
4238fd1498Szrj #include "debug.h"
4338fd1498Szrj #include "lto.h"
4438fd1498Szrj #include "lto-section-names.h"
4538fd1498Szrj #include "splay-tree.h"
4638fd1498Szrj #include "lto-partition.h"
4738fd1498Szrj #include "context.h"
4838fd1498Szrj #include "pass_manager.h"
4938fd1498Szrj #include "ipa-fnsummary.h"
5038fd1498Szrj #include "params.h"
5138fd1498Szrj #include "ipa-utils.h"
5238fd1498Szrj #include "gomp-constants.h"
5338fd1498Szrj #include "lto-symtab.h"
5438fd1498Szrj #include "stringpool.h"
5538fd1498Szrj #include "fold-const.h"
5638fd1498Szrj #include "attribs.h"
5738fd1498Szrj #include "builtins.h"
5838fd1498Szrj 
5938fd1498Szrj 
6038fd1498Szrj /* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver.  */
6138fd1498Szrj static int lto_parallelism;
6238fd1498Szrj 
6338fd1498Szrj static GTY(()) tree first_personality_decl;
6438fd1498Szrj 
6538fd1498Szrj static GTY(()) const unsigned char *lto_mode_identity_table;
6638fd1498Szrj 
6738fd1498Szrj /* Returns a hash code for P.  */
6838fd1498Szrj 
6938fd1498Szrj static hashval_t
hash_name(const void * p)7038fd1498Szrj hash_name (const void *p)
7138fd1498Szrj {
7238fd1498Szrj   const struct lto_section_slot *ds = (const struct lto_section_slot *) p;
7338fd1498Szrj   return (hashval_t) htab_hash_string (ds->name);
7438fd1498Szrj }
7538fd1498Szrj 
7638fd1498Szrj 
7738fd1498Szrj /* Returns nonzero if P1 and P2 are equal.  */
7838fd1498Szrj 
7938fd1498Szrj static int
eq_name(const void * p1,const void * p2)8038fd1498Szrj eq_name (const void *p1, const void *p2)
8138fd1498Szrj {
8238fd1498Szrj   const struct lto_section_slot *s1 =
8338fd1498Szrj     (const struct lto_section_slot *) p1;
8438fd1498Szrj   const struct lto_section_slot *s2 =
8538fd1498Szrj     (const struct lto_section_slot *) p2;
8638fd1498Szrj 
8738fd1498Szrj   return strcmp (s1->name, s2->name) == 0;
8838fd1498Szrj }
8938fd1498Szrj 
9038fd1498Szrj /* Free lto_section_slot */
9138fd1498Szrj 
9238fd1498Szrj static void
free_with_string(void * arg)9338fd1498Szrj free_with_string (void *arg)
9438fd1498Szrj {
9538fd1498Szrj   struct lto_section_slot *s = (struct lto_section_slot *)arg;
9638fd1498Szrj 
9738fd1498Szrj   free (CONST_CAST (char *, s->name));
9838fd1498Szrj   free (arg);
9938fd1498Szrj }
10038fd1498Szrj 
10138fd1498Szrj /* Create section hash table */
10238fd1498Szrj 
10338fd1498Szrj htab_t
lto_obj_create_section_hash_table(void)10438fd1498Szrj lto_obj_create_section_hash_table (void)
10538fd1498Szrj {
10638fd1498Szrj   return htab_create (37, hash_name, eq_name, free_with_string);
10738fd1498Szrj }
10838fd1498Szrj 
10938fd1498Szrj /* Delete an allocated integer KEY in the splay tree.  */
11038fd1498Szrj 
11138fd1498Szrj static void
lto_splay_tree_delete_id(splay_tree_key key)11238fd1498Szrj lto_splay_tree_delete_id (splay_tree_key key)
11338fd1498Szrj {
11438fd1498Szrj   free ((void *) key);
11538fd1498Szrj }
11638fd1498Szrj 
11738fd1498Szrj /* Compare splay tree node ids A and B.  */
11838fd1498Szrj 
11938fd1498Szrj static int
lto_splay_tree_compare_ids(splay_tree_key a,splay_tree_key b)12038fd1498Szrj lto_splay_tree_compare_ids (splay_tree_key a, splay_tree_key b)
12138fd1498Szrj {
12238fd1498Szrj   unsigned HOST_WIDE_INT ai;
12338fd1498Szrj   unsigned HOST_WIDE_INT bi;
12438fd1498Szrj 
12538fd1498Szrj   ai = *(unsigned HOST_WIDE_INT *) a;
12638fd1498Szrj   bi = *(unsigned HOST_WIDE_INT *) b;
12738fd1498Szrj 
12838fd1498Szrj   if (ai < bi)
12938fd1498Szrj     return -1;
13038fd1498Szrj   else if (ai > bi)
13138fd1498Szrj     return 1;
13238fd1498Szrj   return 0;
13338fd1498Szrj }
13438fd1498Szrj 
13538fd1498Szrj /* Look up splay tree node by ID in splay tree T.  */
13638fd1498Szrj 
13738fd1498Szrj static splay_tree_node
lto_splay_tree_lookup(splay_tree t,unsigned HOST_WIDE_INT id)13838fd1498Szrj lto_splay_tree_lookup (splay_tree t, unsigned HOST_WIDE_INT id)
13938fd1498Szrj {
14038fd1498Szrj   return splay_tree_lookup (t, (splay_tree_key) &id);
14138fd1498Szrj }
14238fd1498Szrj 
14338fd1498Szrj /* Check if KEY has ID.  */
14438fd1498Szrj 
14538fd1498Szrj static bool
lto_splay_tree_id_equal_p(splay_tree_key key,unsigned HOST_WIDE_INT id)14638fd1498Szrj lto_splay_tree_id_equal_p (splay_tree_key key, unsigned HOST_WIDE_INT id)
14738fd1498Szrj {
14838fd1498Szrj   return *(unsigned HOST_WIDE_INT *) key == id;
14938fd1498Szrj }
15038fd1498Szrj 
15138fd1498Szrj /* Insert a splay tree node into tree T with ID as key and FILE_DATA as value.
15238fd1498Szrj    The ID is allocated separately because we need HOST_WIDE_INTs which may
15338fd1498Szrj    be wider than a splay_tree_key. */
15438fd1498Szrj 
15538fd1498Szrj static void
lto_splay_tree_insert(splay_tree t,unsigned HOST_WIDE_INT id,struct lto_file_decl_data * file_data)15638fd1498Szrj lto_splay_tree_insert (splay_tree t, unsigned HOST_WIDE_INT id,
15738fd1498Szrj 		       struct lto_file_decl_data *file_data)
15838fd1498Szrj {
15938fd1498Szrj   unsigned HOST_WIDE_INT *idp = XCNEW (unsigned HOST_WIDE_INT);
16038fd1498Szrj   *idp = id;
16138fd1498Szrj   splay_tree_insert (t, (splay_tree_key) idp, (splay_tree_value) file_data);
16238fd1498Szrj }
16338fd1498Szrj 
16438fd1498Szrj /* Create a splay tree.  */
16538fd1498Szrj 
16638fd1498Szrj static splay_tree
lto_splay_tree_new(void)16738fd1498Szrj lto_splay_tree_new (void)
16838fd1498Szrj {
16938fd1498Szrj   return splay_tree_new (lto_splay_tree_compare_ids,
17038fd1498Szrj 	 	         lto_splay_tree_delete_id,
17138fd1498Szrj 			 NULL);
17238fd1498Szrj }
17338fd1498Szrj 
17438fd1498Szrj /* Return true when NODE has a clone that is analyzed (i.e. we need
17538fd1498Szrj    to load its body even if the node itself is not needed).  */
17638fd1498Szrj 
17738fd1498Szrj static bool
has_analyzed_clone_p(struct cgraph_node * node)17838fd1498Szrj has_analyzed_clone_p (struct cgraph_node *node)
17938fd1498Szrj {
18038fd1498Szrj   struct cgraph_node *orig = node;
18138fd1498Szrj   node = node->clones;
18238fd1498Szrj   if (node)
18338fd1498Szrj     while (node != orig)
18438fd1498Szrj       {
18538fd1498Szrj 	if (node->analyzed)
18638fd1498Szrj 	  return true;
18738fd1498Szrj 	if (node->clones)
18838fd1498Szrj 	  node = node->clones;
18938fd1498Szrj 	else if (node->next_sibling_clone)
19038fd1498Szrj 	  node = node->next_sibling_clone;
19138fd1498Szrj 	else
19238fd1498Szrj 	  {
19338fd1498Szrj 	    while (node != orig && !node->next_sibling_clone)
19438fd1498Szrj 	      node = node->clone_of;
19538fd1498Szrj 	    if (node != orig)
19638fd1498Szrj 	      node = node->next_sibling_clone;
19738fd1498Szrj 	  }
19838fd1498Szrj       }
19938fd1498Szrj   return false;
20038fd1498Szrj }
20138fd1498Szrj 
20238fd1498Szrj /* Read the function body for the function associated with NODE.  */
20338fd1498Szrj 
20438fd1498Szrj static void
lto_materialize_function(struct cgraph_node * node)20538fd1498Szrj lto_materialize_function (struct cgraph_node *node)
20638fd1498Szrj {
20738fd1498Szrj   tree decl;
20838fd1498Szrj 
20938fd1498Szrj   decl = node->decl;
21038fd1498Szrj   /* Read in functions with body (analyzed nodes)
21138fd1498Szrj      and also functions that are needed to produce virtual clones.  */
21238fd1498Szrj   if ((node->has_gimple_body_p () && node->analyzed)
21338fd1498Szrj       || node->used_as_abstract_origin
21438fd1498Szrj       || has_analyzed_clone_p (node))
21538fd1498Szrj     {
21638fd1498Szrj       /* Clones don't need to be read.  */
21738fd1498Szrj       if (node->clone_of)
21838fd1498Szrj 	return;
21938fd1498Szrj       if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl)
22038fd1498Szrj 	first_personality_decl = DECL_FUNCTION_PERSONALITY (decl);
22138fd1498Szrj     }
22238fd1498Szrj 
22338fd1498Szrj   /* Let the middle end know about the function.  */
22438fd1498Szrj   rest_of_decl_compilation (decl, 1, 0);
22538fd1498Szrj }
22638fd1498Szrj 
22738fd1498Szrj 
22838fd1498Szrj /* Decode the content of memory pointed to by DATA in the in decl
22938fd1498Szrj    state object STATE. DATA_IN points to a data_in structure for
23038fd1498Szrj    decoding. Return the address after the decoded object in the
23138fd1498Szrj    input.  */
23238fd1498Szrj 
23338fd1498Szrj static const uint32_t *
lto_read_in_decl_state(struct data_in * data_in,const uint32_t * data,struct lto_in_decl_state * state)23438fd1498Szrj lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
23538fd1498Szrj 			struct lto_in_decl_state *state)
23638fd1498Szrj {
23738fd1498Szrj   uint32_t ix;
23838fd1498Szrj   tree decl;
23938fd1498Szrj   uint32_t i, j;
24038fd1498Szrj 
24138fd1498Szrj   ix = *data++;
24238fd1498Szrj   state->compressed = ix & 1;
24338fd1498Szrj   ix /= 2;
24438fd1498Szrj   decl = streamer_tree_cache_get_tree (data_in->reader_cache, ix);
24538fd1498Szrj   if (!VAR_OR_FUNCTION_DECL_P (decl))
24638fd1498Szrj     {
24738fd1498Szrj       gcc_assert (decl == void_type_node);
24838fd1498Szrj       decl = NULL_TREE;
24938fd1498Szrj     }
25038fd1498Szrj   state->fn_decl = decl;
25138fd1498Szrj 
25238fd1498Szrj   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
25338fd1498Szrj     {
25438fd1498Szrj       uint32_t size = *data++;
25538fd1498Szrj       vec<tree, va_gc> *decls = NULL;
25638fd1498Szrj       vec_alloc (decls, size);
25738fd1498Szrj 
25838fd1498Szrj       for (j = 0; j < size; j++)
25938fd1498Szrj 	vec_safe_push (decls,
26038fd1498Szrj 		       streamer_tree_cache_get_tree (data_in->reader_cache,
26138fd1498Szrj 						     data[j]));
26238fd1498Szrj 
26338fd1498Szrj       state->streams[i] = decls;
26438fd1498Szrj       data += size;
26538fd1498Szrj     }
26638fd1498Szrj 
26738fd1498Szrj   return data;
26838fd1498Szrj }
26938fd1498Szrj 
27038fd1498Szrj 
27138fd1498Szrj /* Global canonical type table.  */
27238fd1498Szrj static htab_t gimple_canonical_types;
27338fd1498Szrj static hash_map<const_tree, hashval_t> *canonical_type_hash_cache;
27438fd1498Szrj static unsigned long num_canonical_type_hash_entries;
27538fd1498Szrj static unsigned long num_canonical_type_hash_queries;
27638fd1498Szrj 
27738fd1498Szrj static void iterative_hash_canonical_type (tree type, inchash::hash &hstate);
27838fd1498Szrj static hashval_t gimple_canonical_type_hash (const void *p);
27938fd1498Szrj static void gimple_register_canonical_type_1 (tree t, hashval_t hash);
28038fd1498Szrj 
28138fd1498Szrj /* Returning a hash value for gimple type TYPE.
28238fd1498Szrj 
28338fd1498Szrj    The hash value returned is equal for types considered compatible
28438fd1498Szrj    by gimple_canonical_types_compatible_p.  */
28538fd1498Szrj 
28638fd1498Szrj static hashval_t
hash_canonical_type(tree type)28738fd1498Szrj hash_canonical_type (tree type)
28838fd1498Szrj {
28938fd1498Szrj   inchash::hash hstate;
29038fd1498Szrj   enum tree_code code;
29138fd1498Szrj 
29238fd1498Szrj   /* We compute alias sets only for types that needs them.
29338fd1498Szrj      Be sure we do not recurse to something else as we can not hash incomplete
29438fd1498Szrj      types in a way they would have same hash value as compatible complete
29538fd1498Szrj      types.  */
29638fd1498Szrj   gcc_checking_assert (type_with_alias_set_p (type));
29738fd1498Szrj 
29838fd1498Szrj   /* Combine a few common features of types so that types are grouped into
29938fd1498Szrj      smaller sets; when searching for existing matching types to merge,
30038fd1498Szrj      only existing types having the same features as the new type will be
30138fd1498Szrj      checked.  */
30238fd1498Szrj   code = tree_code_for_canonical_type_merging (TREE_CODE (type));
30338fd1498Szrj   hstate.add_int (code);
30438fd1498Szrj   hstate.add_int (TYPE_MODE (type));
30538fd1498Szrj 
30638fd1498Szrj   /* Incorporate common features of numerical types.  */
30738fd1498Szrj   if (INTEGRAL_TYPE_P (type)
30838fd1498Szrj       || SCALAR_FLOAT_TYPE_P (type)
30938fd1498Szrj       || FIXED_POINT_TYPE_P (type)
31038fd1498Szrj       || TREE_CODE (type) == OFFSET_TYPE
31138fd1498Szrj       || POINTER_TYPE_P (type))
31238fd1498Szrj     {
31338fd1498Szrj       hstate.add_int (TYPE_PRECISION (type));
31438fd1498Szrj       if (!type_with_interoperable_signedness (type))
31538fd1498Szrj         hstate.add_int (TYPE_UNSIGNED (type));
31638fd1498Szrj     }
31738fd1498Szrj 
31838fd1498Szrj   if (VECTOR_TYPE_P (type))
31938fd1498Szrj     {
32038fd1498Szrj       hstate.add_poly_int (TYPE_VECTOR_SUBPARTS (type));
32138fd1498Szrj       hstate.add_int (TYPE_UNSIGNED (type));
32238fd1498Szrj     }
32338fd1498Szrj 
32438fd1498Szrj   if (TREE_CODE (type) == COMPLEX_TYPE)
32538fd1498Szrj     hstate.add_int (TYPE_UNSIGNED (type));
32638fd1498Szrj 
32738fd1498Szrj   /* Fortran's C_SIGNED_CHAR is !TYPE_STRING_FLAG but needs to be
32838fd1498Szrj      interoperable with "signed char".  Unless all frontends are revisited to
32938fd1498Szrj      agree on these types, we must ignore the flag completely.  */
33038fd1498Szrj 
33138fd1498Szrj   /* Fortran standard define C_PTR type that is compatible with every
33238fd1498Szrj      C pointer.  For this reason we need to glob all pointers into one.
33338fd1498Szrj      Still pointers in different address spaces are not compatible.  */
33438fd1498Szrj   if (POINTER_TYPE_P (type))
33538fd1498Szrj     hstate.add_int (TYPE_ADDR_SPACE (TREE_TYPE (type)));
33638fd1498Szrj 
33738fd1498Szrj   /* For array types hash the domain bounds and the string flag.  */
33838fd1498Szrj   if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
33938fd1498Szrj     {
34038fd1498Szrj       hstate.add_int (TYPE_STRING_FLAG (type));
34138fd1498Szrj       /* OMP lowering can introduce error_mark_node in place of
34238fd1498Szrj 	 random local decls in types.  */
34338fd1498Szrj       if (TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
34438fd1498Szrj 	inchash::add_expr (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), hstate);
34538fd1498Szrj       if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
34638fd1498Szrj 	inchash::add_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), hstate);
34738fd1498Szrj     }
34838fd1498Szrj 
34938fd1498Szrj   /* Recurse for aggregates with a single element type.  */
35038fd1498Szrj   if (TREE_CODE (type) == ARRAY_TYPE
35138fd1498Szrj       || TREE_CODE (type) == COMPLEX_TYPE
35238fd1498Szrj       || TREE_CODE (type) == VECTOR_TYPE)
35338fd1498Szrj     iterative_hash_canonical_type (TREE_TYPE (type), hstate);
35438fd1498Szrj 
35538fd1498Szrj   /* Incorporate function return and argument types.  */
35638fd1498Szrj   if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
35738fd1498Szrj     {
35838fd1498Szrj       unsigned na;
35938fd1498Szrj       tree p;
36038fd1498Szrj 
36138fd1498Szrj       iterative_hash_canonical_type (TREE_TYPE (type), hstate);
36238fd1498Szrj 
36338fd1498Szrj       for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
36438fd1498Szrj 	{
36538fd1498Szrj 	  iterative_hash_canonical_type (TREE_VALUE (p), hstate);
36638fd1498Szrj 	  na++;
36738fd1498Szrj 	}
36838fd1498Szrj 
36938fd1498Szrj       hstate.add_int (na);
37038fd1498Szrj     }
37138fd1498Szrj 
37238fd1498Szrj   if (RECORD_OR_UNION_TYPE_P (type))
37338fd1498Szrj     {
37438fd1498Szrj       unsigned nf;
37538fd1498Szrj       tree f;
37638fd1498Szrj 
37738fd1498Szrj       for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
37838fd1498Szrj 	if (TREE_CODE (f) == FIELD_DECL
37938fd1498Szrj 	    && (! DECL_SIZE (f)
38038fd1498Szrj 		|| ! integer_zerop (DECL_SIZE (f))))
38138fd1498Szrj 	  {
38238fd1498Szrj 	    iterative_hash_canonical_type (TREE_TYPE (f), hstate);
38338fd1498Szrj 	    nf++;
38438fd1498Szrj 	  }
38538fd1498Szrj 
38638fd1498Szrj       hstate.add_int (nf);
38738fd1498Szrj     }
38838fd1498Szrj 
38938fd1498Szrj   return hstate.end();
39038fd1498Szrj }
39138fd1498Szrj 
39238fd1498Szrj /* Returning a hash value for gimple type TYPE combined with VAL.  */
39338fd1498Szrj 
39438fd1498Szrj static void
iterative_hash_canonical_type(tree type,inchash::hash & hstate)39538fd1498Szrj iterative_hash_canonical_type (tree type, inchash::hash &hstate)
39638fd1498Szrj {
39738fd1498Szrj   hashval_t v;
39838fd1498Szrj 
39938fd1498Szrj   /* All type variants have same TYPE_CANONICAL.  */
40038fd1498Szrj   type = TYPE_MAIN_VARIANT (type);
40138fd1498Szrj 
40238fd1498Szrj   if (!canonical_type_used_p (type))
40338fd1498Szrj     v = hash_canonical_type (type);
40438fd1498Szrj   /* An already processed type.  */
40538fd1498Szrj   else if (TYPE_CANONICAL (type))
40638fd1498Szrj     {
40738fd1498Szrj       type = TYPE_CANONICAL (type);
40838fd1498Szrj       v = gimple_canonical_type_hash (type);
40938fd1498Szrj     }
41038fd1498Szrj   else
41138fd1498Szrj     {
41238fd1498Szrj       /* Canonical types should not be able to form SCCs by design, this
41338fd1498Szrj 	 recursion is just because we do not register canonical types in
41438fd1498Szrj 	 optimal order.  To avoid quadratic behavior also register the
41538fd1498Szrj 	 type here.  */
41638fd1498Szrj       v = hash_canonical_type (type);
41738fd1498Szrj       gimple_register_canonical_type_1 (type, v);
41838fd1498Szrj     }
41938fd1498Szrj   hstate.add_int (v);
42038fd1498Szrj }
42138fd1498Szrj 
42238fd1498Szrj /* Returns the hash for a canonical type P.  */
42338fd1498Szrj 
42438fd1498Szrj static hashval_t
gimple_canonical_type_hash(const void * p)42538fd1498Szrj gimple_canonical_type_hash (const void *p)
42638fd1498Szrj {
42738fd1498Szrj   num_canonical_type_hash_queries++;
42838fd1498Szrj   hashval_t *slot = canonical_type_hash_cache->get ((const_tree) p);
42938fd1498Szrj   gcc_assert (slot != NULL);
43038fd1498Szrj   return *slot;
43138fd1498Szrj }
43238fd1498Szrj 
43338fd1498Szrj 
43438fd1498Szrj 
43538fd1498Szrj /* Returns nonzero if P1 and P2 are equal.  */
43638fd1498Szrj 
43738fd1498Szrj static int
gimple_canonical_type_eq(const void * p1,const void * p2)43838fd1498Szrj gimple_canonical_type_eq (const void *p1, const void *p2)
43938fd1498Szrj {
44038fd1498Szrj   const_tree t1 = (const_tree) p1;
44138fd1498Szrj   const_tree t2 = (const_tree) p2;
44238fd1498Szrj   return gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1),
44338fd1498Szrj 					      CONST_CAST_TREE (t2));
44438fd1498Szrj }
44538fd1498Szrj 
44638fd1498Szrj /* Main worker for gimple_register_canonical_type.  */
44738fd1498Szrj 
44838fd1498Szrj static void
gimple_register_canonical_type_1(tree t,hashval_t hash)44938fd1498Szrj gimple_register_canonical_type_1 (tree t, hashval_t hash)
45038fd1498Szrj {
45138fd1498Szrj   void **slot;
45238fd1498Szrj 
45338fd1498Szrj   gcc_checking_assert (TYPE_P (t) && !TYPE_CANONICAL (t)
45438fd1498Szrj 		       && type_with_alias_set_p (t)
45538fd1498Szrj 		       && canonical_type_used_p (t));
45638fd1498Szrj 
45738fd1498Szrj   slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash, INSERT);
45838fd1498Szrj   if (*slot)
45938fd1498Szrj     {
46038fd1498Szrj       tree new_type = (tree)(*slot);
46138fd1498Szrj       gcc_checking_assert (new_type != t);
46238fd1498Szrj       TYPE_CANONICAL (t) = new_type;
46338fd1498Szrj     }
46438fd1498Szrj   else
46538fd1498Szrj     {
46638fd1498Szrj       TYPE_CANONICAL (t) = t;
46738fd1498Szrj       *slot = (void *) t;
46838fd1498Szrj       /* Cache the just computed hash value.  */
46938fd1498Szrj       num_canonical_type_hash_entries++;
47038fd1498Szrj       bool existed_p = canonical_type_hash_cache->put (t, hash);
47138fd1498Szrj       gcc_assert (!existed_p);
47238fd1498Szrj     }
47338fd1498Szrj }
47438fd1498Szrj 
47538fd1498Szrj /* Register type T in the global type table gimple_types and set
47638fd1498Szrj    TYPE_CANONICAL of T accordingly.
47738fd1498Szrj    This is used by LTO to merge structurally equivalent types for
47838fd1498Szrj    type-based aliasing purposes across different TUs and languages.
47938fd1498Szrj 
48038fd1498Szrj    ???  This merging does not exactly match how the tree.c middle-end
48138fd1498Szrj    functions will assign TYPE_CANONICAL when new types are created
48238fd1498Szrj    during optimization (which at least happens for pointer and array
48338fd1498Szrj    types).  */
48438fd1498Szrj 
48538fd1498Szrj static void
gimple_register_canonical_type(tree t)48638fd1498Szrj gimple_register_canonical_type (tree t)
48738fd1498Szrj {
48838fd1498Szrj   if (TYPE_CANONICAL (t) || !type_with_alias_set_p (t)
48938fd1498Szrj       || !canonical_type_used_p (t))
49038fd1498Szrj     return;
49138fd1498Szrj 
49238fd1498Szrj   /* Canonical types are same among all complete variants.  */
49338fd1498Szrj   if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (t)))
49438fd1498Szrj     TYPE_CANONICAL (t) = TYPE_CANONICAL (TYPE_MAIN_VARIANT (t));
49538fd1498Szrj   else
49638fd1498Szrj     {
49738fd1498Szrj       gimple_register_canonical_type_1 (TYPE_MAIN_VARIANT (t),
49838fd1498Szrj 					hash_canonical_type (TYPE_MAIN_VARIANT (t)));
49938fd1498Szrj       TYPE_CANONICAL (t) = TYPE_CANONICAL (TYPE_MAIN_VARIANT (t));
50038fd1498Szrj     }
50138fd1498Szrj }
50238fd1498Szrj 
50338fd1498Szrj /* Re-compute TYPE_CANONICAL for NODE and related types.  */
50438fd1498Szrj 
50538fd1498Szrj static void
lto_register_canonical_types(tree node,bool first_p)50638fd1498Szrj lto_register_canonical_types (tree node, bool first_p)
50738fd1498Szrj {
50838fd1498Szrj   if (!node
50938fd1498Szrj       || !TYPE_P (node))
51038fd1498Szrj     return;
51138fd1498Szrj 
51238fd1498Szrj   if (first_p)
51338fd1498Szrj     TYPE_CANONICAL (node) = NULL_TREE;
51438fd1498Szrj 
51538fd1498Szrj   if (POINTER_TYPE_P (node)
51638fd1498Szrj       || TREE_CODE (node) == COMPLEX_TYPE
51738fd1498Szrj       || TREE_CODE (node) == ARRAY_TYPE)
51838fd1498Szrj     lto_register_canonical_types (TREE_TYPE (node), first_p);
51938fd1498Szrj 
52038fd1498Szrj  if (!first_p)
52138fd1498Szrj     gimple_register_canonical_type (node);
52238fd1498Szrj }
52338fd1498Szrj 
52438fd1498Szrj 
52538fd1498Szrj /* Remember trees that contains references to declarations.  */
52638fd1498Szrj static GTY(()) vec <tree, va_gc> *tree_with_vars;
52738fd1498Szrj 
52838fd1498Szrj #define CHECK_VAR(tt) \
52938fd1498Szrj   do \
53038fd1498Szrj     { \
53138fd1498Szrj       if ((tt) && VAR_OR_FUNCTION_DECL_P (tt) \
53238fd1498Szrj 	  && (TREE_PUBLIC (tt) || DECL_EXTERNAL (tt))) \
53338fd1498Szrj 	return true; \
53438fd1498Szrj     } while (0)
53538fd1498Szrj 
53638fd1498Szrj #define CHECK_NO_VAR(tt) \
53738fd1498Szrj   gcc_checking_assert (!(tt) || !VAR_OR_FUNCTION_DECL_P (tt))
53838fd1498Szrj 
53938fd1498Szrj /* Check presence of pointers to decls in fields of a tree_typed T.  */
54038fd1498Szrj 
54138fd1498Szrj static inline bool
mentions_vars_p_typed(tree t)54238fd1498Szrj mentions_vars_p_typed (tree t)
54338fd1498Szrj {
54438fd1498Szrj   CHECK_NO_VAR (TREE_TYPE (t));
54538fd1498Szrj   return false;
54638fd1498Szrj }
54738fd1498Szrj 
54838fd1498Szrj /* Check presence of pointers to decls in fields of a tree_common T.  */
54938fd1498Szrj 
55038fd1498Szrj static inline bool
mentions_vars_p_common(tree t)55138fd1498Szrj mentions_vars_p_common (tree t)
55238fd1498Szrj {
55338fd1498Szrj   if (mentions_vars_p_typed (t))
55438fd1498Szrj     return true;
55538fd1498Szrj   CHECK_NO_VAR (TREE_CHAIN (t));
55638fd1498Szrj   return false;
55738fd1498Szrj }
55838fd1498Szrj 
55938fd1498Szrj /* Check presence of pointers to decls in fields of a decl_minimal T.  */
56038fd1498Szrj 
56138fd1498Szrj static inline bool
mentions_vars_p_decl_minimal(tree t)56238fd1498Szrj mentions_vars_p_decl_minimal (tree t)
56338fd1498Szrj {
56438fd1498Szrj   if (mentions_vars_p_common (t))
56538fd1498Szrj     return true;
56638fd1498Szrj   CHECK_NO_VAR (DECL_NAME (t));
56738fd1498Szrj   CHECK_VAR (DECL_CONTEXT (t));
56838fd1498Szrj   return false;
56938fd1498Szrj }
57038fd1498Szrj 
57138fd1498Szrj /* Check presence of pointers to decls in fields of a decl_common T.  */
57238fd1498Szrj 
57338fd1498Szrj static inline bool
mentions_vars_p_decl_common(tree t)57438fd1498Szrj mentions_vars_p_decl_common (tree t)
57538fd1498Szrj {
57638fd1498Szrj   if (mentions_vars_p_decl_minimal (t))
57738fd1498Szrj     return true;
57838fd1498Szrj   CHECK_VAR (DECL_SIZE (t));
57938fd1498Szrj   CHECK_VAR (DECL_SIZE_UNIT (t));
58038fd1498Szrj   CHECK_VAR (DECL_INITIAL (t));
58138fd1498Szrj   CHECK_NO_VAR (DECL_ATTRIBUTES (t));
58238fd1498Szrj   CHECK_VAR (DECL_ABSTRACT_ORIGIN (t));
58338fd1498Szrj   return false;
58438fd1498Szrj }
58538fd1498Szrj 
58638fd1498Szrj /* Check presence of pointers to decls in fields of a decl_with_vis T.  */
58738fd1498Szrj 
58838fd1498Szrj static inline bool
mentions_vars_p_decl_with_vis(tree t)58938fd1498Szrj mentions_vars_p_decl_with_vis (tree t)
59038fd1498Szrj {
59138fd1498Szrj   if (mentions_vars_p_decl_common (t))
59238fd1498Szrj     return true;
59338fd1498Szrj 
59438fd1498Szrj   /* Accessor macro has side-effects, use field-name here. */
59538fd1498Szrj   CHECK_NO_VAR (DECL_ASSEMBLER_NAME_RAW (t));
59638fd1498Szrj   return false;
59738fd1498Szrj }
59838fd1498Szrj 
59938fd1498Szrj /* Check presence of pointers to decls in fields of a decl_non_common T.  */
60038fd1498Szrj 
60138fd1498Szrj static inline bool
mentions_vars_p_decl_non_common(tree t)60238fd1498Szrj mentions_vars_p_decl_non_common (tree t)
60338fd1498Szrj {
60438fd1498Szrj   if (mentions_vars_p_decl_with_vis (t))
60538fd1498Szrj     return true;
60638fd1498Szrj   CHECK_NO_VAR (DECL_RESULT_FLD (t));
60738fd1498Szrj   return false;
60838fd1498Szrj }
60938fd1498Szrj 
61038fd1498Szrj /* Check presence of pointers to decls in fields of a decl_non_common T.  */
61138fd1498Szrj 
61238fd1498Szrj static bool
mentions_vars_p_function(tree t)61338fd1498Szrj mentions_vars_p_function (tree t)
61438fd1498Szrj {
61538fd1498Szrj   if (mentions_vars_p_decl_non_common (t))
61638fd1498Szrj     return true;
61738fd1498Szrj   CHECK_NO_VAR (DECL_ARGUMENTS (t));
61838fd1498Szrj   CHECK_NO_VAR (DECL_VINDEX (t));
61938fd1498Szrj   CHECK_VAR (DECL_FUNCTION_PERSONALITY (t));
62038fd1498Szrj   return false;
62138fd1498Szrj }
62238fd1498Szrj 
62338fd1498Szrj /* Check presence of pointers to decls in fields of a field_decl T.  */
62438fd1498Szrj 
62538fd1498Szrj static bool
mentions_vars_p_field_decl(tree t)62638fd1498Szrj mentions_vars_p_field_decl (tree t)
62738fd1498Szrj {
62838fd1498Szrj   if (mentions_vars_p_decl_common (t))
62938fd1498Szrj     return true;
63038fd1498Szrj   CHECK_VAR (DECL_FIELD_OFFSET (t));
63138fd1498Szrj   CHECK_NO_VAR (DECL_BIT_FIELD_TYPE (t));
63238fd1498Szrj   CHECK_NO_VAR (DECL_QUALIFIER (t));
63338fd1498Szrj   CHECK_NO_VAR (DECL_FIELD_BIT_OFFSET (t));
63438fd1498Szrj   CHECK_NO_VAR (DECL_FCONTEXT (t));
63538fd1498Szrj   return false;
63638fd1498Szrj }
63738fd1498Szrj 
63838fd1498Szrj /* Check presence of pointers to decls in fields of a type T.  */
63938fd1498Szrj 
64038fd1498Szrj static bool
mentions_vars_p_type(tree t)64138fd1498Szrj mentions_vars_p_type (tree t)
64238fd1498Szrj {
64338fd1498Szrj   if (mentions_vars_p_common (t))
64438fd1498Szrj     return true;
64538fd1498Szrj   CHECK_NO_VAR (TYPE_CACHED_VALUES (t));
64638fd1498Szrj   CHECK_VAR (TYPE_SIZE (t));
64738fd1498Szrj   CHECK_VAR (TYPE_SIZE_UNIT (t));
64838fd1498Szrj   CHECK_NO_VAR (TYPE_ATTRIBUTES (t));
64938fd1498Szrj   CHECK_NO_VAR (TYPE_NAME (t));
65038fd1498Szrj 
65138fd1498Szrj   CHECK_VAR (TYPE_MIN_VALUE_RAW (t));
65238fd1498Szrj   CHECK_VAR (TYPE_MAX_VALUE_RAW (t));
65338fd1498Szrj 
65438fd1498Szrj   /* Accessor is for derived node types only. */
65538fd1498Szrj   CHECK_NO_VAR (TYPE_LANG_SLOT_1 (t));
65638fd1498Szrj 
65738fd1498Szrj   CHECK_VAR (TYPE_CONTEXT (t));
65838fd1498Szrj   CHECK_NO_VAR (TYPE_CANONICAL (t));
65938fd1498Szrj   CHECK_NO_VAR (TYPE_MAIN_VARIANT (t));
66038fd1498Szrj   CHECK_NO_VAR (TYPE_NEXT_VARIANT (t));
66138fd1498Szrj   return false;
66238fd1498Szrj }
66338fd1498Szrj 
66438fd1498Szrj /* Check presence of pointers to decls in fields of a BINFO T.  */
66538fd1498Szrj 
66638fd1498Szrj static bool
mentions_vars_p_binfo(tree t)66738fd1498Szrj mentions_vars_p_binfo (tree t)
66838fd1498Szrj {
66938fd1498Szrj   unsigned HOST_WIDE_INT i, n;
67038fd1498Szrj 
67138fd1498Szrj   if (mentions_vars_p_common (t))
67238fd1498Szrj     return true;
67338fd1498Szrj   CHECK_VAR (BINFO_VTABLE (t));
67438fd1498Szrj   CHECK_NO_VAR (BINFO_OFFSET (t));
67538fd1498Szrj   CHECK_NO_VAR (BINFO_VIRTUALS (t));
67638fd1498Szrj   CHECK_NO_VAR (BINFO_VPTR_FIELD (t));
67738fd1498Szrj   n = vec_safe_length (BINFO_BASE_ACCESSES (t));
67838fd1498Szrj   for (i = 0; i < n; i++)
67938fd1498Szrj     CHECK_NO_VAR (BINFO_BASE_ACCESS (t, i));
68038fd1498Szrj   /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
68138fd1498Szrj      and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
68238fd1498Szrj   n = BINFO_N_BASE_BINFOS (t);
68338fd1498Szrj   for (i = 0; i < n; i++)
68438fd1498Szrj     CHECK_NO_VAR (BINFO_BASE_BINFO (t, i));
68538fd1498Szrj   return false;
68638fd1498Szrj }
68738fd1498Szrj 
68838fd1498Szrj /* Check presence of pointers to decls in fields of a CONSTRUCTOR T.  */
68938fd1498Szrj 
69038fd1498Szrj static bool
mentions_vars_p_constructor(tree t)69138fd1498Szrj mentions_vars_p_constructor (tree t)
69238fd1498Szrj {
69338fd1498Szrj   unsigned HOST_WIDE_INT idx;
69438fd1498Szrj   constructor_elt *ce;
69538fd1498Szrj 
69638fd1498Szrj   if (mentions_vars_p_typed (t))
69738fd1498Szrj     return true;
69838fd1498Szrj 
69938fd1498Szrj   for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); idx++)
70038fd1498Szrj     {
70138fd1498Szrj       CHECK_NO_VAR (ce->index);
70238fd1498Szrj       CHECK_VAR (ce->value);
70338fd1498Szrj     }
70438fd1498Szrj   return false;
70538fd1498Szrj }
70638fd1498Szrj 
70738fd1498Szrj /* Check presence of pointers to decls in fields of an expression tree T.  */
70838fd1498Szrj 
70938fd1498Szrj static bool
mentions_vars_p_expr(tree t)71038fd1498Szrj mentions_vars_p_expr (tree t)
71138fd1498Szrj {
71238fd1498Szrj   int i;
71338fd1498Szrj   if (mentions_vars_p_typed (t))
71438fd1498Szrj     return true;
71538fd1498Szrj   for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
71638fd1498Szrj     CHECK_VAR (TREE_OPERAND (t, i));
71738fd1498Szrj   return false;
71838fd1498Szrj }
71938fd1498Szrj 
72038fd1498Szrj /* Check presence of pointers to decls in fields of an OMP_CLAUSE T.  */
72138fd1498Szrj 
72238fd1498Szrj static bool
mentions_vars_p_omp_clause(tree t)72338fd1498Szrj mentions_vars_p_omp_clause (tree t)
72438fd1498Szrj {
72538fd1498Szrj   int i;
72638fd1498Szrj   if (mentions_vars_p_common (t))
72738fd1498Szrj     return true;
72838fd1498Szrj   for (i = omp_clause_num_ops[OMP_CLAUSE_CODE (t)] - 1; i >= 0; --i)
72938fd1498Szrj     CHECK_VAR (OMP_CLAUSE_OPERAND (t, i));
73038fd1498Szrj   return false;
73138fd1498Szrj }
73238fd1498Szrj 
73338fd1498Szrj /* Check presence of pointers to decls that needs later fixup in T.  */
73438fd1498Szrj 
73538fd1498Szrj static bool
mentions_vars_p(tree t)73638fd1498Szrj mentions_vars_p (tree t)
73738fd1498Szrj {
73838fd1498Szrj   switch (TREE_CODE (t))
73938fd1498Szrj     {
74038fd1498Szrj     case IDENTIFIER_NODE:
74138fd1498Szrj       break;
74238fd1498Szrj 
74338fd1498Szrj     case TREE_LIST:
74438fd1498Szrj       CHECK_VAR (TREE_VALUE (t));
74538fd1498Szrj       CHECK_VAR (TREE_PURPOSE (t));
74638fd1498Szrj       CHECK_NO_VAR (TREE_CHAIN (t));
74738fd1498Szrj       break;
74838fd1498Szrj 
74938fd1498Szrj     case FIELD_DECL:
75038fd1498Szrj       return mentions_vars_p_field_decl (t);
75138fd1498Szrj 
75238fd1498Szrj     case LABEL_DECL:
75338fd1498Szrj     case CONST_DECL:
75438fd1498Szrj     case PARM_DECL:
75538fd1498Szrj     case RESULT_DECL:
75638fd1498Szrj     case IMPORTED_DECL:
75738fd1498Szrj     case NAMESPACE_DECL:
75838fd1498Szrj     case NAMELIST_DECL:
75938fd1498Szrj       return mentions_vars_p_decl_common (t);
76038fd1498Szrj 
76138fd1498Szrj     case VAR_DECL:
76238fd1498Szrj       return mentions_vars_p_decl_with_vis (t);
76338fd1498Szrj 
76438fd1498Szrj     case TYPE_DECL:
76538fd1498Szrj       return mentions_vars_p_decl_non_common (t);
76638fd1498Szrj 
76738fd1498Szrj     case FUNCTION_DECL:
76838fd1498Szrj       return mentions_vars_p_function (t);
76938fd1498Szrj 
77038fd1498Szrj     case TREE_BINFO:
77138fd1498Szrj       return mentions_vars_p_binfo (t);
77238fd1498Szrj 
77338fd1498Szrj     case PLACEHOLDER_EXPR:
77438fd1498Szrj       return mentions_vars_p_common (t);
77538fd1498Szrj 
77638fd1498Szrj     case BLOCK:
77738fd1498Szrj     case TRANSLATION_UNIT_DECL:
77838fd1498Szrj     case OPTIMIZATION_NODE:
77938fd1498Szrj     case TARGET_OPTION_NODE:
78038fd1498Szrj       break;
78138fd1498Szrj 
78238fd1498Szrj     case CONSTRUCTOR:
78338fd1498Szrj       return mentions_vars_p_constructor (t);
78438fd1498Szrj 
78538fd1498Szrj     case OMP_CLAUSE:
78638fd1498Szrj       return mentions_vars_p_omp_clause (t);
78738fd1498Szrj 
78838fd1498Szrj     default:
78938fd1498Szrj       if (TYPE_P (t))
79038fd1498Szrj 	{
79138fd1498Szrj 	  if (mentions_vars_p_type (t))
79238fd1498Szrj 	    return true;
79338fd1498Szrj 	}
79438fd1498Szrj       else if (EXPR_P (t))
79538fd1498Szrj 	{
79638fd1498Szrj 	  if (mentions_vars_p_expr (t))
79738fd1498Szrj 	    return true;
79838fd1498Szrj 	}
79938fd1498Szrj       else if (CONSTANT_CLASS_P (t))
80038fd1498Szrj 	CHECK_NO_VAR (TREE_TYPE (t));
80138fd1498Szrj       else
80238fd1498Szrj 	gcc_unreachable ();
80338fd1498Szrj     }
80438fd1498Szrj   return false;
80538fd1498Szrj }
80638fd1498Szrj 
80738fd1498Szrj 
80838fd1498Szrj /* Return the resolution for the decl with index INDEX from DATA_IN. */
80938fd1498Szrj 
81038fd1498Szrj static enum ld_plugin_symbol_resolution
get_resolution(struct data_in * data_in,unsigned index)81138fd1498Szrj get_resolution (struct data_in *data_in, unsigned index)
81238fd1498Szrj {
81338fd1498Szrj   if (data_in->globals_resolution.exists ())
81438fd1498Szrj     {
81538fd1498Szrj       ld_plugin_symbol_resolution_t ret;
81638fd1498Szrj       /* We can have references to not emitted functions in
81738fd1498Szrj 	 DECL_FUNCTION_PERSONALITY at least.  So we can and have
81838fd1498Szrj 	 to indeed return LDPR_UNKNOWN in some cases.   */
81938fd1498Szrj       if (data_in->globals_resolution.length () <= index)
82038fd1498Szrj 	return LDPR_UNKNOWN;
82138fd1498Szrj       ret = data_in->globals_resolution[index];
82238fd1498Szrj       return ret;
82338fd1498Szrj     }
82438fd1498Szrj   else
82538fd1498Szrj     /* Delay resolution finding until decl merging.  */
82638fd1498Szrj     return LDPR_UNKNOWN;
82738fd1498Szrj }
82838fd1498Szrj 
82938fd1498Szrj /* We need to record resolutions until symbol table is read.  */
83038fd1498Szrj static void
register_resolution(struct lto_file_decl_data * file_data,tree decl,enum ld_plugin_symbol_resolution resolution)83138fd1498Szrj register_resolution (struct lto_file_decl_data *file_data, tree decl,
83238fd1498Szrj 		     enum ld_plugin_symbol_resolution resolution)
83338fd1498Szrj {
83438fd1498Szrj   bool existed;
83538fd1498Szrj   if (resolution == LDPR_UNKNOWN)
83638fd1498Szrj     return;
83738fd1498Szrj   if (!file_data->resolution_map)
83838fd1498Szrj     file_data->resolution_map
83938fd1498Szrj       = new hash_map<tree, ld_plugin_symbol_resolution>;
84038fd1498Szrj   ld_plugin_symbol_resolution_t &res
84138fd1498Szrj      = file_data->resolution_map->get_or_insert (decl, &existed);
84238fd1498Szrj   if (!existed
84338fd1498Szrj       || resolution == LDPR_PREVAILING_DEF_IRONLY
84438fd1498Szrj       || resolution == LDPR_PREVAILING_DEF
84538fd1498Szrj       || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
84638fd1498Szrj     res = resolution;
84738fd1498Szrj }
84838fd1498Szrj 
84938fd1498Szrj /* Register DECL with the global symbol table and change its
85038fd1498Szrj    name if necessary to avoid name clashes for static globals across
85138fd1498Szrj    different files.  */
85238fd1498Szrj 
85338fd1498Szrj static void
lto_register_var_decl_in_symtab(struct data_in * data_in,tree decl,unsigned ix)85438fd1498Szrj lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl,
85538fd1498Szrj 				 unsigned ix)
85638fd1498Szrj {
85738fd1498Szrj   tree context;
85838fd1498Szrj 
85938fd1498Szrj   /* Variable has file scope, not local.  */
86038fd1498Szrj   if (!TREE_PUBLIC (decl)
86138fd1498Szrj       && !((context = decl_function_context (decl))
86238fd1498Szrj 	   && auto_var_in_fn_p (decl, context)))
86338fd1498Szrj     rest_of_decl_compilation (decl, 1, 0);
86438fd1498Szrj 
86538fd1498Szrj   /* If this variable has already been declared, queue the
86638fd1498Szrj      declaration for merging.  */
86738fd1498Szrj   if (TREE_PUBLIC (decl))
86838fd1498Szrj     register_resolution (data_in->file_data,
86938fd1498Szrj 			 decl, get_resolution (data_in, ix));
87038fd1498Szrj }
87138fd1498Szrj 
87238fd1498Szrj 
87338fd1498Szrj /* Register DECL with the global symbol table and change its
87438fd1498Szrj    name if necessary to avoid name clashes for static globals across
87538fd1498Szrj    different files.  DATA_IN contains descriptors and tables for the
87638fd1498Szrj    file being read.  */
87738fd1498Szrj 
87838fd1498Szrj static void
lto_register_function_decl_in_symtab(struct data_in * data_in,tree decl,unsigned ix)87938fd1498Szrj lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl,
88038fd1498Szrj 				      unsigned ix)
88138fd1498Szrj {
88238fd1498Szrj   /* If this variable has already been declared, queue the
88338fd1498Szrj      declaration for merging.  */
88438fd1498Szrj   if (TREE_PUBLIC (decl) && !DECL_ABSTRACT_P (decl))
88538fd1498Szrj     register_resolution (data_in->file_data,
88638fd1498Szrj 			 decl, get_resolution (data_in, ix));
88738fd1498Szrj }
88838fd1498Szrj 
88938fd1498Szrj /* Check if T is a decl and needs register its resolution info.  */
89038fd1498Szrj 
89138fd1498Szrj static void
lto_maybe_register_decl(struct data_in * data_in,tree t,unsigned ix)89238fd1498Szrj lto_maybe_register_decl (struct data_in *data_in, tree t, unsigned ix)
89338fd1498Szrj {
89438fd1498Szrj   if (TREE_CODE (t) == VAR_DECL)
89538fd1498Szrj     lto_register_var_decl_in_symtab (data_in, t, ix);
89638fd1498Szrj   else if (TREE_CODE (t) == FUNCTION_DECL
89738fd1498Szrj 	   && !DECL_BUILT_IN (t))
89838fd1498Szrj     lto_register_function_decl_in_symtab (data_in, t, ix);
89938fd1498Szrj }
90038fd1498Szrj 
90138fd1498Szrj 
90238fd1498Szrj /* For the type T re-materialize it in the type variant list and
90338fd1498Szrj    the pointer/reference-to chains.  */
90438fd1498Szrj 
90538fd1498Szrj static void
lto_fixup_prevailing_type(tree t)90638fd1498Szrj lto_fixup_prevailing_type (tree t)
90738fd1498Szrj {
90838fd1498Szrj   /* The following re-creates proper variant lists while fixing up
90938fd1498Szrj      the variant leaders.  We do not stream TYPE_NEXT_VARIANT so the
91038fd1498Szrj      variant list state before fixup is broken.  */
91138fd1498Szrj 
91238fd1498Szrj   /* If we are not our own variant leader link us into our new leaders
91338fd1498Szrj      variant list.  */
91438fd1498Szrj   if (TYPE_MAIN_VARIANT (t) != t)
91538fd1498Szrj     {
91638fd1498Szrj       tree mv = TYPE_MAIN_VARIANT (t);
91738fd1498Szrj       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (mv);
91838fd1498Szrj       TYPE_NEXT_VARIANT (mv) = t;
91938fd1498Szrj     }
92038fd1498Szrj 
92138fd1498Szrj   /* The following reconstructs the pointer chains
92238fd1498Szrj      of the new pointed-to type if we are a main variant.  We do
92338fd1498Szrj      not stream those so they are broken before fixup.  */
92438fd1498Szrj   if (TREE_CODE (t) == POINTER_TYPE
92538fd1498Szrj       && TYPE_MAIN_VARIANT (t) == t)
92638fd1498Szrj     {
92738fd1498Szrj       TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t));
92838fd1498Szrj       TYPE_POINTER_TO (TREE_TYPE (t)) = t;
92938fd1498Szrj     }
93038fd1498Szrj   else if (TREE_CODE (t) == REFERENCE_TYPE
93138fd1498Szrj 	   && TYPE_MAIN_VARIANT (t) == t)
93238fd1498Szrj     {
93338fd1498Szrj       TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t));
93438fd1498Szrj       TYPE_REFERENCE_TO (TREE_TYPE (t)) = t;
93538fd1498Szrj     }
93638fd1498Szrj }
93738fd1498Szrj 
93838fd1498Szrj 
93938fd1498Szrj /* We keep prevailing tree SCCs in a hashtable with manual collision
94038fd1498Szrj    handling (in case all hashes compare the same) and keep the colliding
94138fd1498Szrj    entries in the tree_scc->next chain.  */
94238fd1498Szrj 
94338fd1498Szrj struct tree_scc
94438fd1498Szrj {
94538fd1498Szrj   tree_scc *next;
94638fd1498Szrj   /* Hash of the whole SCC.  */
94738fd1498Szrj   hashval_t hash;
94838fd1498Szrj   /* Number of trees in the SCC.  */
94938fd1498Szrj   unsigned len;
95038fd1498Szrj   /* Number of possible entries into the SCC (tree nodes [0..entry_len-1]
95138fd1498Szrj      which share the same individual tree hash).  */
95238fd1498Szrj   unsigned entry_len;
95338fd1498Szrj   /* The members of the SCC.
95438fd1498Szrj      We only need to remember the first entry node candidate for prevailing
95538fd1498Szrj      SCCs (but of course have access to all entries for SCCs we are
95638fd1498Szrj      processing).
95738fd1498Szrj      ???  For prevailing SCCs we really only need hash and the first
95838fd1498Szrj      entry candidate, but that's too awkward to implement.  */
95938fd1498Szrj   tree entries[1];
96038fd1498Szrj };
96138fd1498Szrj 
96238fd1498Szrj struct tree_scc_hasher : nofree_ptr_hash <tree_scc>
96338fd1498Szrj {
96438fd1498Szrj   static inline hashval_t hash (const tree_scc *);
96538fd1498Szrj   static inline bool equal (const tree_scc *, const tree_scc *);
96638fd1498Szrj };
96738fd1498Szrj 
96838fd1498Szrj hashval_t
hash(const tree_scc * scc)96938fd1498Szrj tree_scc_hasher::hash (const tree_scc *scc)
97038fd1498Szrj {
97138fd1498Szrj   return scc->hash;
97238fd1498Szrj }
97338fd1498Szrj 
97438fd1498Szrj bool
equal(const tree_scc * scc1,const tree_scc * scc2)97538fd1498Szrj tree_scc_hasher::equal (const tree_scc *scc1, const tree_scc *scc2)
97638fd1498Szrj {
97738fd1498Szrj   if (scc1->hash != scc2->hash
97838fd1498Szrj       || scc1->len != scc2->len
97938fd1498Szrj       || scc1->entry_len != scc2->entry_len)
98038fd1498Szrj     return false;
98138fd1498Szrj   return true;
98238fd1498Szrj }
98338fd1498Szrj 
98438fd1498Szrj static hash_table<tree_scc_hasher> *tree_scc_hash;
98538fd1498Szrj static struct obstack tree_scc_hash_obstack;
98638fd1498Szrj 
98738fd1498Szrj static unsigned long num_merged_types;
98838fd1498Szrj static unsigned long num_prevailing_types;
98938fd1498Szrj static unsigned long num_type_scc_trees;
99038fd1498Szrj static unsigned long total_scc_size;
99138fd1498Szrj static unsigned long num_sccs_read;
99238fd1498Szrj static unsigned long total_scc_size_merged;
99338fd1498Szrj static unsigned long num_sccs_merged;
99438fd1498Szrj static unsigned long num_scc_compares;
99538fd1498Szrj static unsigned long num_scc_compare_collisions;
99638fd1498Szrj 
99738fd1498Szrj 
99838fd1498Szrj /* Compare the two entries T1 and T2 of two SCCs that are possibly equal,
99938fd1498Szrj    recursing through in-SCC tree edges.  Returns true if the SCCs entered
100038fd1498Szrj    through T1 and T2 are equal and fills in *MAP with the pairs of
100138fd1498Szrj    SCC entries we visited, starting with (*MAP)[0] = T1 and (*MAP)[1] = T2.  */
100238fd1498Szrj 
100338fd1498Szrj static bool
compare_tree_sccs_1(tree t1,tree t2,tree ** map)100438fd1498Szrj compare_tree_sccs_1 (tree t1, tree t2, tree **map)
100538fd1498Szrj {
100638fd1498Szrj   enum tree_code code;
100738fd1498Szrj 
100838fd1498Szrj   /* Mark already visited nodes.  */
100938fd1498Szrj   TREE_ASM_WRITTEN (t2) = 1;
101038fd1498Szrj 
101138fd1498Szrj   /* Push the pair onto map.  */
101238fd1498Szrj   (*map)[0] = t1;
101338fd1498Szrj   (*map)[1] = t2;
101438fd1498Szrj   *map = *map + 2;
101538fd1498Szrj 
101638fd1498Szrj   /* Compare value-fields.  */
101738fd1498Szrj #define compare_values(X) \
101838fd1498Szrj   do { \
101938fd1498Szrj     if (X(t1) != X(t2)) \
102038fd1498Szrj       return false; \
102138fd1498Szrj   } while (0)
102238fd1498Szrj 
102338fd1498Szrj   compare_values (TREE_CODE);
102438fd1498Szrj   code = TREE_CODE (t1);
102538fd1498Szrj 
102638fd1498Szrj   if (!TYPE_P (t1))
102738fd1498Szrj     {
102838fd1498Szrj       compare_values (TREE_SIDE_EFFECTS);
102938fd1498Szrj       compare_values (TREE_CONSTANT);
103038fd1498Szrj       compare_values (TREE_READONLY);
103138fd1498Szrj       compare_values (TREE_PUBLIC);
103238fd1498Szrj     }
103338fd1498Szrj   compare_values (TREE_ADDRESSABLE);
103438fd1498Szrj   compare_values (TREE_THIS_VOLATILE);
103538fd1498Szrj   if (DECL_P (t1))
103638fd1498Szrj     compare_values (DECL_UNSIGNED);
103738fd1498Szrj   else if (TYPE_P (t1))
103838fd1498Szrj     compare_values (TYPE_UNSIGNED);
103938fd1498Szrj   if (TYPE_P (t1))
104038fd1498Szrj     compare_values (TYPE_ARTIFICIAL);
104138fd1498Szrj   else
104238fd1498Szrj     compare_values (TREE_NO_WARNING);
104338fd1498Szrj   compare_values (TREE_NOTHROW);
104438fd1498Szrj   compare_values (TREE_STATIC);
104538fd1498Szrj   if (code != TREE_BINFO)
104638fd1498Szrj     compare_values (TREE_PRIVATE);
104738fd1498Szrj   compare_values (TREE_PROTECTED);
104838fd1498Szrj   compare_values (TREE_DEPRECATED);
104938fd1498Szrj   if (TYPE_P (t1))
105038fd1498Szrj     {
105138fd1498Szrj       if (AGGREGATE_TYPE_P (t1))
105238fd1498Szrj 	compare_values (TYPE_REVERSE_STORAGE_ORDER);
105338fd1498Szrj       else
105438fd1498Szrj 	compare_values (TYPE_SATURATING);
105538fd1498Szrj       compare_values (TYPE_ADDR_SPACE);
105638fd1498Szrj     }
105738fd1498Szrj   else if (code == SSA_NAME)
105838fd1498Szrj     compare_values (SSA_NAME_IS_DEFAULT_DEF);
105938fd1498Szrj 
106038fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
106138fd1498Szrj     {
106238fd1498Szrj       if (wi::to_wide (t1) != wi::to_wide (t2))
106338fd1498Szrj 	return false;
106438fd1498Szrj     }
106538fd1498Szrj 
106638fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
106738fd1498Szrj     {
106838fd1498Szrj       /* ???  No suitable compare routine available.  */
106938fd1498Szrj       REAL_VALUE_TYPE r1 = TREE_REAL_CST (t1);
107038fd1498Szrj       REAL_VALUE_TYPE r2 = TREE_REAL_CST (t2);
107138fd1498Szrj       if (r1.cl != r2.cl
107238fd1498Szrj 	  || r1.decimal != r2.decimal
107338fd1498Szrj 	  || r1.sign != r2.sign
107438fd1498Szrj 	  || r1.signalling != r2.signalling
107538fd1498Szrj 	  || r1.canonical != r2.canonical
107638fd1498Szrj 	  || r1.uexp != r2.uexp)
107738fd1498Szrj 	return false;
107838fd1498Szrj       for (unsigned i = 0; i < SIGSZ; ++i)
107938fd1498Szrj 	if (r1.sig[i] != r2.sig[i])
108038fd1498Szrj 	  return false;
108138fd1498Szrj     }
108238fd1498Szrj 
108338fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_FIXED_CST))
108438fd1498Szrj     if (!fixed_compare (EQ_EXPR,
108538fd1498Szrj 			TREE_FIXED_CST_PTR (t1), TREE_FIXED_CST_PTR (t2)))
108638fd1498Szrj       return false;
108738fd1498Szrj 
108838fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
108938fd1498Szrj     {
109038fd1498Szrj       compare_values (VECTOR_CST_LOG2_NPATTERNS);
109138fd1498Szrj       compare_values (VECTOR_CST_NELTS_PER_PATTERN);
109238fd1498Szrj     }
109338fd1498Szrj 
109438fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
109538fd1498Szrj     {
109638fd1498Szrj       compare_values (DECL_MODE);
109738fd1498Szrj       compare_values (DECL_NONLOCAL);
109838fd1498Szrj       compare_values (DECL_VIRTUAL_P);
109938fd1498Szrj       compare_values (DECL_IGNORED_P);
110038fd1498Szrj       compare_values (DECL_ABSTRACT_P);
110138fd1498Szrj       compare_values (DECL_ARTIFICIAL);
110238fd1498Szrj       compare_values (DECL_USER_ALIGN);
110338fd1498Szrj       compare_values (DECL_PRESERVE_P);
110438fd1498Szrj       compare_values (DECL_EXTERNAL);
110538fd1498Szrj       compare_values (DECL_GIMPLE_REG_P);
110638fd1498Szrj       compare_values (DECL_ALIGN);
110738fd1498Szrj       if (code == LABEL_DECL)
110838fd1498Szrj 	{
110938fd1498Szrj 	  compare_values (EH_LANDING_PAD_NR);
111038fd1498Szrj 	  compare_values (LABEL_DECL_UID);
111138fd1498Szrj 	}
111238fd1498Szrj       else if (code == FIELD_DECL)
111338fd1498Szrj 	{
111438fd1498Szrj 	  compare_values (DECL_PACKED);
111538fd1498Szrj 	  compare_values (DECL_NONADDRESSABLE_P);
111638fd1498Szrj 	  compare_values (DECL_PADDING_P);
111738fd1498Szrj 	  compare_values (DECL_OFFSET_ALIGN);
111838fd1498Szrj 	}
111938fd1498Szrj       else if (code == VAR_DECL)
112038fd1498Szrj 	{
112138fd1498Szrj 	  compare_values (DECL_HAS_DEBUG_EXPR_P);
112238fd1498Szrj 	  compare_values (DECL_NONLOCAL_FRAME);
112338fd1498Szrj 	}
112438fd1498Szrj       if (code == RESULT_DECL
112538fd1498Szrj 	  || code == PARM_DECL
112638fd1498Szrj 	  || code == VAR_DECL)
112738fd1498Szrj 	{
112838fd1498Szrj 	  compare_values (DECL_BY_REFERENCE);
112938fd1498Szrj 	  if (code == VAR_DECL
113038fd1498Szrj 	      || code == PARM_DECL)
113138fd1498Szrj 	    compare_values (DECL_HAS_VALUE_EXPR_P);
113238fd1498Szrj 	}
113338fd1498Szrj     }
113438fd1498Szrj 
113538fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL))
113638fd1498Szrj     compare_values (DECL_REGISTER);
113738fd1498Szrj 
113838fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
113938fd1498Szrj     {
114038fd1498Szrj       compare_values (DECL_COMMON);
114138fd1498Szrj       compare_values (DECL_DLLIMPORT_P);
114238fd1498Szrj       compare_values (DECL_WEAK);
114338fd1498Szrj       compare_values (DECL_SEEN_IN_BIND_EXPR_P);
114438fd1498Szrj       compare_values (DECL_COMDAT);
114538fd1498Szrj       compare_values (DECL_VISIBILITY);
114638fd1498Szrj       compare_values (DECL_VISIBILITY_SPECIFIED);
114738fd1498Szrj       if (code == VAR_DECL)
114838fd1498Szrj 	{
114938fd1498Szrj 	  compare_values (DECL_HARD_REGISTER);
115038fd1498Szrj           /* DECL_IN_TEXT_SECTION is set during final asm output only.  */
115138fd1498Szrj 	  compare_values (DECL_IN_CONSTANT_POOL);
115238fd1498Szrj 	}
115338fd1498Szrj     }
115438fd1498Szrj 
115538fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
115638fd1498Szrj     {
115738fd1498Szrj       compare_values (DECL_BUILT_IN_CLASS);
115838fd1498Szrj       compare_values (DECL_STATIC_CONSTRUCTOR);
115938fd1498Szrj       compare_values (DECL_STATIC_DESTRUCTOR);
116038fd1498Szrj       compare_values (DECL_UNINLINABLE);
116138fd1498Szrj       compare_values (DECL_POSSIBLY_INLINED);
116238fd1498Szrj       compare_values (DECL_IS_NOVOPS);
116338fd1498Szrj       compare_values (DECL_IS_RETURNS_TWICE);
116438fd1498Szrj       compare_values (DECL_IS_MALLOC);
116538fd1498Szrj       compare_values (DECL_IS_OPERATOR_NEW);
116638fd1498Szrj       compare_values (DECL_DECLARED_INLINE_P);
116738fd1498Szrj       compare_values (DECL_STATIC_CHAIN);
116838fd1498Szrj       compare_values (DECL_NO_INLINE_WARNING_P);
116938fd1498Szrj       compare_values (DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT);
117038fd1498Szrj       compare_values (DECL_NO_LIMIT_STACK);
117138fd1498Szrj       compare_values (DECL_DISREGARD_INLINE_LIMITS);
117238fd1498Szrj       compare_values (DECL_PURE_P);
117338fd1498Szrj       compare_values (DECL_LOOPING_CONST_OR_PURE_P);
117438fd1498Szrj       compare_values (DECL_FINAL_P);
117538fd1498Szrj       compare_values (DECL_CXX_CONSTRUCTOR_P);
117638fd1498Szrj       compare_values (DECL_CXX_DESTRUCTOR_P);
117738fd1498Szrj       if (DECL_BUILT_IN_CLASS (t1) != NOT_BUILT_IN)
117838fd1498Szrj 	compare_values (DECL_FUNCTION_CODE);
117938fd1498Szrj     }
118038fd1498Szrj 
118138fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
118238fd1498Szrj     {
118338fd1498Szrj       compare_values (TYPE_MODE);
118438fd1498Szrj       compare_values (TYPE_STRING_FLAG);
118538fd1498Szrj       compare_values (TYPE_NEEDS_CONSTRUCTING);
118638fd1498Szrj       if (RECORD_OR_UNION_TYPE_P (t1))
118738fd1498Szrj 	{
118838fd1498Szrj 	  compare_values (TYPE_TRANSPARENT_AGGR);
118938fd1498Szrj 	  compare_values (TYPE_FINAL_P);
119038fd1498Szrj 	}
119138fd1498Szrj       else if (code == ARRAY_TYPE)
119238fd1498Szrj 	compare_values (TYPE_NONALIASED_COMPONENT);
119338fd1498Szrj       if (AGGREGATE_TYPE_P (t1))
119438fd1498Szrj 	compare_values (TYPE_TYPELESS_STORAGE);
119538fd1498Szrj       compare_values (TYPE_EMPTY_P);
119638fd1498Szrj       compare_values (TYPE_PACKED);
119738fd1498Szrj       compare_values (TYPE_RESTRICT);
119838fd1498Szrj       compare_values (TYPE_USER_ALIGN);
119938fd1498Szrj       compare_values (TYPE_READONLY);
120038fd1498Szrj       compare_values (TYPE_PRECISION);
120138fd1498Szrj       compare_values (TYPE_ALIGN);
120238fd1498Szrj       /* Do not compare TYPE_ALIAS_SET.  Doing so introduce ordering issues
120338fd1498Szrj          with calls to get_alias_set which may initialize it for streamed
120438fd1498Szrj  	 in types.  */
120538fd1498Szrj     }
120638fd1498Szrj 
120738fd1498Szrj   /* We don't want to compare locations, so there is nothing do compare
120838fd1498Szrj      for TS_EXP.  */
120938fd1498Szrj 
121038fd1498Szrj   /* BLOCKs are function local and we don't merge anything there, so
121138fd1498Szrj      simply refuse to merge.  */
121238fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
121338fd1498Szrj     return false;
121438fd1498Szrj 
121538fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
121638fd1498Szrj     if (strcmp (TRANSLATION_UNIT_LANGUAGE (t1),
121738fd1498Szrj 		TRANSLATION_UNIT_LANGUAGE (t2)) != 0)
121838fd1498Szrj       return false;
121938fd1498Szrj 
122038fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
122138fd1498Szrj     if (!cl_target_option_eq (TREE_TARGET_OPTION (t1), TREE_TARGET_OPTION (t2)))
122238fd1498Szrj       return false;
122338fd1498Szrj 
122438fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
122538fd1498Szrj     if (memcmp (TREE_OPTIMIZATION (t1), TREE_OPTIMIZATION (t2),
122638fd1498Szrj 		sizeof (struct cl_optimization)) != 0)
122738fd1498Szrj       return false;
122838fd1498Szrj 
122938fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
123038fd1498Szrj     if (vec_safe_length (BINFO_BASE_ACCESSES (t1))
123138fd1498Szrj 	!= vec_safe_length (BINFO_BASE_ACCESSES (t2)))
123238fd1498Szrj       return false;
123338fd1498Szrj 
123438fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
123538fd1498Szrj     compare_values (CONSTRUCTOR_NELTS);
123638fd1498Szrj 
123738fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER))
123838fd1498Szrj     if (IDENTIFIER_LENGTH (t1) != IDENTIFIER_LENGTH (t2)
123938fd1498Szrj 	|| memcmp (IDENTIFIER_POINTER (t1), IDENTIFIER_POINTER (t2),
124038fd1498Szrj 		   IDENTIFIER_LENGTH (t1)) != 0)
124138fd1498Szrj       return false;
124238fd1498Szrj 
124338fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_STRING))
124438fd1498Szrj     if (TREE_STRING_LENGTH (t1) != TREE_STRING_LENGTH (t2)
124538fd1498Szrj 	|| memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
124638fd1498Szrj 		   TREE_STRING_LENGTH (t1)) != 0)
124738fd1498Szrj       return false;
124838fd1498Szrj 
124938fd1498Szrj   if (code == OMP_CLAUSE)
125038fd1498Szrj     {
125138fd1498Szrj       compare_values (OMP_CLAUSE_CODE);
125238fd1498Szrj       switch (OMP_CLAUSE_CODE (t1))
125338fd1498Szrj 	{
125438fd1498Szrj 	case OMP_CLAUSE_DEFAULT:
125538fd1498Szrj 	  compare_values (OMP_CLAUSE_DEFAULT_KIND);
125638fd1498Szrj 	  break;
125738fd1498Szrj 	case OMP_CLAUSE_SCHEDULE:
125838fd1498Szrj 	  compare_values (OMP_CLAUSE_SCHEDULE_KIND);
125938fd1498Szrj 	  break;
126038fd1498Szrj 	case OMP_CLAUSE_DEPEND:
126138fd1498Szrj 	  compare_values (OMP_CLAUSE_DEPEND_KIND);
126238fd1498Szrj 	  break;
126338fd1498Szrj 	case OMP_CLAUSE_MAP:
126438fd1498Szrj 	  compare_values (OMP_CLAUSE_MAP_KIND);
126538fd1498Szrj 	  break;
126638fd1498Szrj 	case OMP_CLAUSE_PROC_BIND:
126738fd1498Szrj 	  compare_values (OMP_CLAUSE_PROC_BIND_KIND);
126838fd1498Szrj 	  break;
126938fd1498Szrj 	case OMP_CLAUSE_REDUCTION:
127038fd1498Szrj 	  compare_values (OMP_CLAUSE_REDUCTION_CODE);
127138fd1498Szrj 	  compare_values (OMP_CLAUSE_REDUCTION_GIMPLE_INIT);
127238fd1498Szrj 	  compare_values (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE);
127338fd1498Szrj 	  break;
127438fd1498Szrj 	default:
127538fd1498Szrj 	  break;
127638fd1498Szrj 	}
127738fd1498Szrj     }
127838fd1498Szrj 
127938fd1498Szrj #undef compare_values
128038fd1498Szrj 
128138fd1498Szrj 
128238fd1498Szrj   /* Compare pointer fields.  */
128338fd1498Szrj 
128438fd1498Szrj   /* Recurse.  Search & Replaced from DFS_write_tree_body.
128538fd1498Szrj      Folding the early checks into the compare_tree_edges recursion
128638fd1498Szrj      macro makes debugging way quicker as you are able to break on
128738fd1498Szrj      compare_tree_sccs_1 and simply finish until a call returns false
128838fd1498Szrj      to spot the SCC members with the difference.  */
128938fd1498Szrj #define compare_tree_edges(E1, E2) \
129038fd1498Szrj   do { \
129138fd1498Szrj     tree t1_ = (E1), t2_ = (E2); \
129238fd1498Szrj     if (t1_ != t2_ \
129338fd1498Szrj 	&& (!t1_ || !t2_ \
129438fd1498Szrj 	    || !TREE_VISITED (t2_) \
129538fd1498Szrj 	    || (!TREE_ASM_WRITTEN (t2_) \
129638fd1498Szrj 		&& !compare_tree_sccs_1 (t1_, t2_, map)))) \
129738fd1498Szrj       return false; \
129838fd1498Szrj     /* Only non-NULL trees outside of the SCC may compare equal.  */ \
129938fd1498Szrj     gcc_checking_assert (t1_ != t2_ || (!t2_ || !TREE_VISITED (t2_))); \
130038fd1498Szrj   } while (0)
130138fd1498Szrj 
130238fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
130338fd1498Szrj     {
130438fd1498Szrj       if (code != IDENTIFIER_NODE)
130538fd1498Szrj 	compare_tree_edges (TREE_TYPE (t1), TREE_TYPE (t2));
130638fd1498Szrj     }
130738fd1498Szrj 
130838fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
130938fd1498Szrj     {
131038fd1498Szrj       /* Note that the number of elements for EXPR has already been emitted
131138fd1498Szrj 	 in EXPR's header (see streamer_write_tree_header).  */
131238fd1498Szrj       unsigned int count = vector_cst_encoded_nelts (t1);
131338fd1498Szrj       for (unsigned int i = 0; i < count; ++i)
131438fd1498Szrj 	compare_tree_edges (VECTOR_CST_ENCODED_ELT (t1, i),
131538fd1498Szrj 			    VECTOR_CST_ENCODED_ELT (t2, i));
131638fd1498Szrj     }
131738fd1498Szrj 
131838fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
131938fd1498Szrj     {
132038fd1498Szrj       compare_tree_edges (TREE_REALPART (t1), TREE_REALPART (t2));
132138fd1498Szrj       compare_tree_edges (TREE_IMAGPART (t1), TREE_IMAGPART (t2));
132238fd1498Szrj     }
132338fd1498Szrj 
132438fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
132538fd1498Szrj     {
132638fd1498Szrj       compare_tree_edges (DECL_NAME (t1), DECL_NAME (t2));
132738fd1498Szrj       /* ???  Global decls from different TUs have non-matching
132838fd1498Szrj 	 TRANSLATION_UNIT_DECLs.  Only consider a small set of
132938fd1498Szrj 	 decls equivalent, we should not end up merging others.  */
133038fd1498Szrj       if ((code == TYPE_DECL
133138fd1498Szrj 	   || code == NAMESPACE_DECL
133238fd1498Szrj 	   || code == IMPORTED_DECL
133338fd1498Szrj 	   || code == CONST_DECL
133438fd1498Szrj 	   || (VAR_OR_FUNCTION_DECL_P (t1)
133538fd1498Szrj 	       && (TREE_PUBLIC (t1) || DECL_EXTERNAL (t1))))
133638fd1498Szrj 	  && DECL_FILE_SCOPE_P (t1) && DECL_FILE_SCOPE_P (t2))
133738fd1498Szrj 	;
133838fd1498Szrj       else
133938fd1498Szrj 	compare_tree_edges (DECL_CONTEXT (t1), DECL_CONTEXT (t2));
134038fd1498Szrj     }
134138fd1498Szrj 
134238fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
134338fd1498Szrj     {
134438fd1498Szrj       compare_tree_edges (DECL_SIZE (t1), DECL_SIZE (t2));
134538fd1498Szrj       compare_tree_edges (DECL_SIZE_UNIT (t1), DECL_SIZE_UNIT (t2));
134638fd1498Szrj       compare_tree_edges (DECL_ATTRIBUTES (t1), DECL_ATTRIBUTES (t2));
134738fd1498Szrj       compare_tree_edges (DECL_ABSTRACT_ORIGIN (t1), DECL_ABSTRACT_ORIGIN (t2));
134838fd1498Szrj       if ((code == VAR_DECL
134938fd1498Szrj 	   || code == PARM_DECL)
135038fd1498Szrj 	  && DECL_HAS_VALUE_EXPR_P (t1))
135138fd1498Szrj 	compare_tree_edges (DECL_VALUE_EXPR (t1), DECL_VALUE_EXPR (t2));
135238fd1498Szrj       if (code == VAR_DECL
135338fd1498Szrj 	  && DECL_HAS_DEBUG_EXPR_P (t1))
135438fd1498Szrj 	compare_tree_edges (DECL_DEBUG_EXPR (t1), DECL_DEBUG_EXPR (t2));
135538fd1498Szrj       /* LTO specific edges.  */
135638fd1498Szrj       if (code != FUNCTION_DECL
135738fd1498Szrj 	  && code != TRANSLATION_UNIT_DECL)
135838fd1498Szrj 	compare_tree_edges (DECL_INITIAL (t1), DECL_INITIAL (t2));
135938fd1498Szrj     }
136038fd1498Szrj 
136138fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
136238fd1498Szrj     {
136338fd1498Szrj       if (code == FUNCTION_DECL)
136438fd1498Szrj 	{
136538fd1498Szrj 	  tree a1, a2;
136638fd1498Szrj 	  for (a1 = DECL_ARGUMENTS (t1), a2 = DECL_ARGUMENTS (t2);
136738fd1498Szrj 	       a1 || a2;
136838fd1498Szrj 	       a1 = TREE_CHAIN (a1), a2 = TREE_CHAIN (a2))
136938fd1498Szrj 	    compare_tree_edges (a1, a2);
137038fd1498Szrj 	  compare_tree_edges (DECL_RESULT (t1), DECL_RESULT (t2));
137138fd1498Szrj 	}
137238fd1498Szrj       else if (code == TYPE_DECL)
137338fd1498Szrj 	compare_tree_edges (DECL_ORIGINAL_TYPE (t1), DECL_ORIGINAL_TYPE (t2));
137438fd1498Szrj     }
137538fd1498Szrj 
137638fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
137738fd1498Szrj     {
137838fd1498Szrj       /* Make sure we don't inadvertently set the assembler name.  */
137938fd1498Szrj       if (DECL_ASSEMBLER_NAME_SET_P (t1))
138038fd1498Szrj 	compare_tree_edges (DECL_ASSEMBLER_NAME (t1),
138138fd1498Szrj 			    DECL_ASSEMBLER_NAME (t2));
138238fd1498Szrj     }
138338fd1498Szrj 
138438fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
138538fd1498Szrj     {
138638fd1498Szrj       compare_tree_edges (DECL_FIELD_OFFSET (t1), DECL_FIELD_OFFSET (t2));
138738fd1498Szrj       compare_tree_edges (DECL_BIT_FIELD_TYPE (t1), DECL_BIT_FIELD_TYPE (t2));
138838fd1498Szrj       compare_tree_edges (DECL_BIT_FIELD_REPRESENTATIVE (t1),
138938fd1498Szrj 			  DECL_BIT_FIELD_REPRESENTATIVE (t2));
139038fd1498Szrj       compare_tree_edges (DECL_FIELD_BIT_OFFSET (t1),
139138fd1498Szrj 			  DECL_FIELD_BIT_OFFSET (t2));
139238fd1498Szrj       compare_tree_edges (DECL_FCONTEXT (t1), DECL_FCONTEXT (t2));
139338fd1498Szrj     }
139438fd1498Szrj 
139538fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
139638fd1498Szrj     {
139738fd1498Szrj       compare_tree_edges (DECL_FUNCTION_PERSONALITY (t1),
139838fd1498Szrj 			  DECL_FUNCTION_PERSONALITY (t2));
139938fd1498Szrj       compare_tree_edges (DECL_VINDEX (t1), DECL_VINDEX (t2));
140038fd1498Szrj       compare_tree_edges (DECL_FUNCTION_SPECIFIC_TARGET (t1),
140138fd1498Szrj 			  DECL_FUNCTION_SPECIFIC_TARGET (t2));
140238fd1498Szrj       compare_tree_edges (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t1),
140338fd1498Szrj 			  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t2));
140438fd1498Szrj     }
140538fd1498Szrj 
140638fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
140738fd1498Szrj     {
140838fd1498Szrj       compare_tree_edges (TYPE_SIZE (t1), TYPE_SIZE (t2));
140938fd1498Szrj       compare_tree_edges (TYPE_SIZE_UNIT (t1), TYPE_SIZE_UNIT (t2));
141038fd1498Szrj       compare_tree_edges (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2));
141138fd1498Szrj       compare_tree_edges (TYPE_NAME (t1), TYPE_NAME (t2));
141238fd1498Szrj       /* Do not compare TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
141338fd1498Szrj 	 reconstructed during fixup.  */
141438fd1498Szrj       /* Do not compare TYPE_NEXT_VARIANT, we reconstruct the variant lists
141538fd1498Szrj 	 during fixup.  */
141638fd1498Szrj       compare_tree_edges (TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2));
141738fd1498Szrj       /* ???  Global types from different TUs have non-matching
141838fd1498Szrj 	 TRANSLATION_UNIT_DECLs.  Still merge them if they are otherwise
141938fd1498Szrj 	 equal.  */
142038fd1498Szrj       if (TYPE_FILE_SCOPE_P (t1) && TYPE_FILE_SCOPE_P (t2))
142138fd1498Szrj 	;
142238fd1498Szrj       else
142338fd1498Szrj 	compare_tree_edges (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
142438fd1498Szrj       /* TYPE_CANONICAL is re-computed during type merging, so do not
142538fd1498Szrj 	 compare it here.  */
142638fd1498Szrj       compare_tree_edges (TYPE_STUB_DECL (t1), TYPE_STUB_DECL (t2));
142738fd1498Szrj     }
142838fd1498Szrj 
142938fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
143038fd1498Szrj     {
143138fd1498Szrj       if (code == ENUMERAL_TYPE)
143238fd1498Szrj 	compare_tree_edges (TYPE_VALUES (t1), TYPE_VALUES (t2));
143338fd1498Szrj       else if (code == ARRAY_TYPE)
143438fd1498Szrj 	compare_tree_edges (TYPE_DOMAIN (t1), TYPE_DOMAIN (t2));
143538fd1498Szrj       else if (RECORD_OR_UNION_TYPE_P (t1))
143638fd1498Szrj 	{
143738fd1498Szrj 	  tree f1, f2;
143838fd1498Szrj 	  for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
143938fd1498Szrj 	       f1 || f2;
144038fd1498Szrj 	       f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
144138fd1498Szrj 	    compare_tree_edges (f1, f2);
144238fd1498Szrj 	}
144338fd1498Szrj       else if (code == FUNCTION_TYPE
144438fd1498Szrj 	       || code == METHOD_TYPE)
144538fd1498Szrj 	compare_tree_edges (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2));
144638fd1498Szrj 
144738fd1498Szrj       if (!POINTER_TYPE_P (t1))
144838fd1498Szrj 	compare_tree_edges (TYPE_MIN_VALUE_RAW (t1), TYPE_MIN_VALUE_RAW (t2));
144938fd1498Szrj       compare_tree_edges (TYPE_MAX_VALUE_RAW (t1), TYPE_MAX_VALUE_RAW (t2));
145038fd1498Szrj     }
145138fd1498Szrj 
145238fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_LIST))
145338fd1498Szrj     {
145438fd1498Szrj       compare_tree_edges (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
145538fd1498Szrj       compare_tree_edges (TREE_VALUE (t1), TREE_VALUE (t2));
145638fd1498Szrj       compare_tree_edges (TREE_CHAIN (t1), TREE_CHAIN (t2));
145738fd1498Szrj     }
145838fd1498Szrj 
145938fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_VEC))
146038fd1498Szrj     for (int i = 0; i < TREE_VEC_LENGTH (t1); i++)
146138fd1498Szrj       compare_tree_edges (TREE_VEC_ELT (t1, i), TREE_VEC_ELT (t2, i));
146238fd1498Szrj 
146338fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_EXP))
146438fd1498Szrj     {
146538fd1498Szrj       for (int i = 0; i < TREE_OPERAND_LENGTH (t1); i++)
146638fd1498Szrj 	compare_tree_edges (TREE_OPERAND (t1, i),
146738fd1498Szrj 			    TREE_OPERAND (t2, i));
146838fd1498Szrj 
146938fd1498Szrj       /* BLOCKs are function local and we don't merge anything there.  */
147038fd1498Szrj       if (TREE_BLOCK (t1) || TREE_BLOCK (t2))
147138fd1498Szrj 	return false;
147238fd1498Szrj     }
147338fd1498Szrj 
147438fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
147538fd1498Szrj     {
147638fd1498Szrj       unsigned i;
147738fd1498Szrj       tree t;
147838fd1498Szrj       /* Lengths have already been compared above.  */
147938fd1498Szrj       FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (t1), i, t)
148038fd1498Szrj 	compare_tree_edges (t, BINFO_BASE_BINFO (t2, i));
148138fd1498Szrj       FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (t1), i, t)
148238fd1498Szrj 	compare_tree_edges (t, BINFO_BASE_ACCESS (t2, i));
148338fd1498Szrj       compare_tree_edges (BINFO_OFFSET (t1), BINFO_OFFSET (t2));
148438fd1498Szrj       compare_tree_edges (BINFO_VTABLE (t1), BINFO_VTABLE (t2));
148538fd1498Szrj       compare_tree_edges (BINFO_VPTR_FIELD (t1), BINFO_VPTR_FIELD (t2));
148638fd1498Szrj       /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
148738fd1498Szrj 	 and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
148838fd1498Szrj     }
148938fd1498Szrj 
149038fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
149138fd1498Szrj     {
149238fd1498Szrj       unsigned i;
149338fd1498Szrj       tree index, value;
149438fd1498Szrj       /* Lengths have already been compared above.  */
149538fd1498Szrj       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t1), i, index, value)
149638fd1498Szrj 	{
149738fd1498Szrj 	  compare_tree_edges (index, CONSTRUCTOR_ELT (t2, i)->index);
149838fd1498Szrj 	  compare_tree_edges (value, CONSTRUCTOR_ELT (t2, i)->value);
149938fd1498Szrj 	}
150038fd1498Szrj     }
150138fd1498Szrj 
150238fd1498Szrj   if (code == OMP_CLAUSE)
150338fd1498Szrj     {
150438fd1498Szrj       int i;
150538fd1498Szrj 
150638fd1498Szrj       for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t1)]; i++)
150738fd1498Szrj 	compare_tree_edges (OMP_CLAUSE_OPERAND (t1, i),
150838fd1498Szrj 			    OMP_CLAUSE_OPERAND (t2, i));
150938fd1498Szrj       compare_tree_edges (OMP_CLAUSE_CHAIN (t1), OMP_CLAUSE_CHAIN (t2));
151038fd1498Szrj     }
151138fd1498Szrj 
151238fd1498Szrj #undef compare_tree_edges
151338fd1498Szrj 
151438fd1498Szrj   return true;
151538fd1498Szrj }
151638fd1498Szrj 
151738fd1498Szrj /* Compare the tree scc SCC to the prevailing candidate PSCC, filling
151838fd1498Szrj    out MAP if they are equal.  */
151938fd1498Szrj 
152038fd1498Szrj static bool
compare_tree_sccs(tree_scc * pscc,tree_scc * scc,tree * map)152138fd1498Szrj compare_tree_sccs (tree_scc *pscc, tree_scc *scc,
152238fd1498Szrj 		   tree *map)
152338fd1498Szrj {
152438fd1498Szrj   /* Assume SCC entry hashes are sorted after their cardinality.  Which
152538fd1498Szrj      means we can simply take the first n-tuple of equal hashes
152638fd1498Szrj      (which is recorded as entry_len) and do n SCC entry candidate
152738fd1498Szrj      comparisons.  */
152838fd1498Szrj   for (unsigned i = 0; i < pscc->entry_len; ++i)
152938fd1498Szrj     {
153038fd1498Szrj       tree *mapp = map;
153138fd1498Szrj       num_scc_compare_collisions++;
153238fd1498Szrj       if (compare_tree_sccs_1 (pscc->entries[0], scc->entries[i], &mapp))
153338fd1498Szrj 	{
153438fd1498Szrj 	  /* Equal - no need to reset TREE_VISITED or TREE_ASM_WRITTEN
153538fd1498Szrj 	     on the scc as all trees will be freed.  */
153638fd1498Szrj 	  return true;
153738fd1498Szrj 	}
153838fd1498Szrj       /* Reset TREE_ASM_WRITTEN on scc for the next compare or in case
153938fd1498Szrj          the SCC prevails.  */
154038fd1498Szrj       for (unsigned j = 0; j < scc->len; ++j)
154138fd1498Szrj 	TREE_ASM_WRITTEN (scc->entries[j]) = 0;
154238fd1498Szrj     }
154338fd1498Szrj 
154438fd1498Szrj   return false;
154538fd1498Szrj }
154638fd1498Szrj 
154738fd1498Szrj /* QSort sort function to sort a map of two pointers after the 2nd
154838fd1498Szrj    pointer.  */
154938fd1498Szrj 
155038fd1498Szrj static int
cmp_tree(const void * p1_,const void * p2_)155138fd1498Szrj cmp_tree (const void *p1_, const void *p2_)
155238fd1498Szrj {
155338fd1498Szrj   tree *p1 = (tree *)(const_cast<void *>(p1_));
155438fd1498Szrj   tree *p2 = (tree *)(const_cast<void *>(p2_));
155538fd1498Szrj   if (p1[1] == p2[1])
155638fd1498Szrj     return 0;
155738fd1498Szrj   return ((uintptr_t)p1[1] < (uintptr_t)p2[1]) ? -1 : 1;
155838fd1498Szrj }
155938fd1498Szrj 
156038fd1498Szrj /* Try to unify the SCC with nodes FROM to FROM + LEN in CACHE and
156138fd1498Szrj    hash value SCC_HASH with an already recorded SCC.  Return true if
156238fd1498Szrj    that was successful, otherwise return false.  */
156338fd1498Szrj 
156438fd1498Szrj static bool
unify_scc(struct data_in * data_in,unsigned from,unsigned len,unsigned scc_entry_len,hashval_t scc_hash)156538fd1498Szrj unify_scc (struct data_in *data_in, unsigned from,
156638fd1498Szrj 	   unsigned len, unsigned scc_entry_len, hashval_t scc_hash)
156738fd1498Szrj {
156838fd1498Szrj   bool unified_p = false;
156938fd1498Szrj   struct streamer_tree_cache_d *cache = data_in->reader_cache;
157038fd1498Szrj   tree_scc *scc
157138fd1498Szrj     = (tree_scc *) alloca (sizeof (tree_scc) + (len - 1) * sizeof (tree));
157238fd1498Szrj   scc->next = NULL;
157338fd1498Szrj   scc->hash = scc_hash;
157438fd1498Szrj   scc->len = len;
157538fd1498Szrj   scc->entry_len = scc_entry_len;
157638fd1498Szrj   for (unsigned i = 0; i < len; ++i)
157738fd1498Szrj     {
157838fd1498Szrj       tree t = streamer_tree_cache_get_tree (cache, from + i);
157938fd1498Szrj       scc->entries[i] = t;
158038fd1498Szrj       /* Do not merge SCCs with local entities inside them.  Also do
158138fd1498Szrj 	 not merge TRANSLATION_UNIT_DECLs.  */
158238fd1498Szrj       if (TREE_CODE (t) == TRANSLATION_UNIT_DECL
158338fd1498Szrj 	  || (VAR_OR_FUNCTION_DECL_P (t)
158438fd1498Szrj 	      && !(TREE_PUBLIC (t) || DECL_EXTERNAL (t)))
158538fd1498Szrj 	  || TREE_CODE (t) == LABEL_DECL)
158638fd1498Szrj 	{
158738fd1498Szrj 	  /* Avoid doing any work for these cases and do not worry to
158838fd1498Szrj 	     record the SCCs for further merging.  */
158938fd1498Szrj 	  return false;
159038fd1498Szrj 	}
159138fd1498Szrj     }
159238fd1498Szrj 
159338fd1498Szrj   /* Look for the list of candidate SCCs to compare against.  */
159438fd1498Szrj   tree_scc **slot;
159538fd1498Szrj   slot = tree_scc_hash->find_slot_with_hash (scc, scc_hash, INSERT);
159638fd1498Szrj   if (*slot)
159738fd1498Szrj     {
159838fd1498Szrj       /* Try unifying against each candidate.  */
159938fd1498Szrj       num_scc_compares++;
160038fd1498Szrj 
160138fd1498Szrj       /* Set TREE_VISITED on the scc so we can easily identify tree nodes
160238fd1498Szrj 	 outside of the scc when following tree edges.  Make sure
160338fd1498Szrj 	 that TREE_ASM_WRITTEN is unset so we can use it as 2nd bit
160438fd1498Szrj 	 to track whether we visited the SCC member during the compare.
160538fd1498Szrj 	 We cannot use TREE_VISITED on the pscc members as the extended
160638fd1498Szrj 	 scc and pscc can overlap.  */
160738fd1498Szrj       for (unsigned i = 0; i < scc->len; ++i)
160838fd1498Szrj 	{
160938fd1498Szrj 	  TREE_VISITED (scc->entries[i]) = 1;
161038fd1498Szrj 	  gcc_checking_assert (!TREE_ASM_WRITTEN (scc->entries[i]));
161138fd1498Szrj 	}
161238fd1498Szrj 
161338fd1498Szrj       tree *map = XALLOCAVEC (tree, 2 * len);
161438fd1498Szrj       for (tree_scc *pscc = *slot; pscc; pscc = pscc->next)
161538fd1498Szrj 	{
161638fd1498Szrj 	  if (!compare_tree_sccs (pscc, scc, map))
161738fd1498Szrj 	    continue;
161838fd1498Szrj 
161938fd1498Szrj 	  /* Found an equal SCC.  */
162038fd1498Szrj 	  unified_p = true;
162138fd1498Szrj 	  num_scc_compare_collisions--;
162238fd1498Szrj 	  num_sccs_merged++;
162338fd1498Szrj 	  total_scc_size_merged += len;
162438fd1498Szrj 
162538fd1498Szrj 	  if (flag_checking)
162638fd1498Szrj 	    for (unsigned i = 0; i < len; ++i)
162738fd1498Szrj 	      {
162838fd1498Szrj 		tree t = map[2*i+1];
162938fd1498Szrj 		enum tree_code code = TREE_CODE (t);
163038fd1498Szrj 		/* IDENTIFIER_NODEs should be singletons and are merged by the
163138fd1498Szrj 		   streamer.  The others should be singletons, too, and we
163238fd1498Szrj 		   should not merge them in any way.  */
163338fd1498Szrj 		gcc_assert (code != TRANSLATION_UNIT_DECL
163438fd1498Szrj 			    && code != IDENTIFIER_NODE);
163538fd1498Szrj 	      }
163638fd1498Szrj 
163738fd1498Szrj 	  /* Fixup the streamer cache with the prevailing nodes according
163838fd1498Szrj 	     to the tree node mapping computed by compare_tree_sccs.  */
163938fd1498Szrj 	  if (len == 1)
164038fd1498Szrj 	    {
164138fd1498Szrj 	      lto_maybe_register_decl (data_in, pscc->entries[0], from);
164238fd1498Szrj 	      streamer_tree_cache_replace_tree (cache, pscc->entries[0], from);
164338fd1498Szrj 	    }
164438fd1498Szrj 	  else
164538fd1498Szrj 	    {
164638fd1498Szrj 	      tree *map2 = XALLOCAVEC (tree, 2 * len);
164738fd1498Szrj 	      for (unsigned i = 0; i < len; ++i)
164838fd1498Szrj 		{
164938fd1498Szrj 		  map2[i*2] = (tree)(uintptr_t)(from + i);
165038fd1498Szrj 		  map2[i*2+1] = scc->entries[i];
165138fd1498Szrj 		}
165238fd1498Szrj 	      qsort (map2, len, 2 * sizeof (tree), cmp_tree);
165338fd1498Szrj 	      qsort (map, len, 2 * sizeof (tree), cmp_tree);
165438fd1498Szrj 	      for (unsigned i = 0; i < len; ++i)
165538fd1498Szrj 		{
165638fd1498Szrj 		  lto_maybe_register_decl (data_in, map[2*i],
165738fd1498Szrj 					   (uintptr_t)map2[2*i]);
165838fd1498Szrj 		  streamer_tree_cache_replace_tree (cache, map[2*i],
165938fd1498Szrj 						    (uintptr_t)map2[2*i]);
166038fd1498Szrj 		}
166138fd1498Szrj 	    }
166238fd1498Szrj 
166338fd1498Szrj 	  /* Free the tree nodes from the read SCC.  */
166438fd1498Szrj 	  data_in->location_cache.revert_location_cache ();
166538fd1498Szrj 	  for (unsigned i = 0; i < len; ++i)
166638fd1498Szrj 	    {
166738fd1498Szrj 	      if (TYPE_P (scc->entries[i]))
166838fd1498Szrj 		num_merged_types++;
166938fd1498Szrj 	      free_node (scc->entries[i]);
167038fd1498Szrj 	    }
167138fd1498Szrj 
167238fd1498Szrj 	  /* Drop DIE references.  */
167338fd1498Szrj 	  dref_queue.truncate (0);
167438fd1498Szrj 
167538fd1498Szrj 	  break;
167638fd1498Szrj 	}
167738fd1498Szrj 
167838fd1498Szrj       /* Reset TREE_VISITED if we didn't unify the SCC with another.  */
167938fd1498Szrj       if (!unified_p)
168038fd1498Szrj 	for (unsigned i = 0; i < scc->len; ++i)
168138fd1498Szrj 	  TREE_VISITED (scc->entries[i]) = 0;
168238fd1498Szrj     }
168338fd1498Szrj 
168438fd1498Szrj   /* If we didn't unify it to any candidate duplicate the relevant
168538fd1498Szrj      pieces to permanent storage and link it into the chain.  */
168638fd1498Szrj   if (!unified_p)
168738fd1498Szrj     {
168838fd1498Szrj       tree_scc *pscc
168938fd1498Szrj 	= XOBNEWVAR (&tree_scc_hash_obstack, tree_scc, sizeof (tree_scc));
169038fd1498Szrj       memcpy (pscc, scc, sizeof (tree_scc));
169138fd1498Szrj       pscc->next = (*slot);
169238fd1498Szrj       *slot = pscc;
169338fd1498Szrj     }
169438fd1498Szrj   return unified_p;
169538fd1498Szrj }
169638fd1498Szrj 
169738fd1498Szrj 
169838fd1498Szrj /* Compare types based on source file location.  */
169938fd1498Szrj 
170038fd1498Szrj static int
cmp_type_location(const void * p1_,const void * p2_)170138fd1498Szrj cmp_type_location (const void *p1_, const void *p2_)
170238fd1498Szrj {
170338fd1498Szrj   tree *p1 = (tree*)(const_cast<void *>(p1_));
170438fd1498Szrj   tree *p2 = (tree*)(const_cast<void *>(p2_));
170538fd1498Szrj   if (*p1 == *p2)
170638fd1498Szrj     return 0;
170738fd1498Szrj 
170838fd1498Szrj   tree tname1 = TYPE_NAME (*p1);
170938fd1498Szrj   tree tname2 = TYPE_NAME (*p2);
171038fd1498Szrj 
171138fd1498Szrj   const char *f1 = DECL_SOURCE_FILE (tname1);
171238fd1498Szrj   const char *f2 = DECL_SOURCE_FILE (tname2);
171338fd1498Szrj 
171438fd1498Szrj   int r = strcmp (f1, f2);
171538fd1498Szrj   if (r == 0)
171638fd1498Szrj     {
171738fd1498Szrj       int l1 = DECL_SOURCE_LINE (tname1);
171838fd1498Szrj       int l2 = DECL_SOURCE_LINE (tname2);
171938fd1498Szrj       if (l1 == l2)
172038fd1498Szrj        {
172138fd1498Szrj 	 int l1 = DECL_SOURCE_COLUMN (tname1);
172238fd1498Szrj 	 int l2 = DECL_SOURCE_COLUMN (tname2);
172338fd1498Szrj 	 return l1 - l2;
172438fd1498Szrj        }
172538fd1498Szrj       else
172638fd1498Szrj        return l1 - l2;
172738fd1498Szrj     }
172838fd1498Szrj   else
172938fd1498Szrj     return r;
173038fd1498Szrj }
173138fd1498Szrj 
173238fd1498Szrj /* Read all the symbols from buffer DATA, using descriptors in DECL_DATA.
173338fd1498Szrj    RESOLUTIONS is the set of symbols picked by the linker (read from the
173438fd1498Szrj    resolution file when the linker plugin is being used).  */
173538fd1498Szrj 
173638fd1498Szrj static void
lto_read_decls(struct lto_file_decl_data * decl_data,const void * data,vec<ld_plugin_symbol_resolution_t> resolutions)173738fd1498Szrj lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
173838fd1498Szrj 		vec<ld_plugin_symbol_resolution_t> resolutions)
173938fd1498Szrj {
174038fd1498Szrj   const struct lto_decl_header *header = (const struct lto_decl_header *) data;
174138fd1498Szrj   const int decl_offset = sizeof (struct lto_decl_header);
174238fd1498Szrj   const int main_offset = decl_offset + header->decl_state_size;
174338fd1498Szrj   const int string_offset = main_offset + header->main_size;
174438fd1498Szrj   struct data_in *data_in;
174538fd1498Szrj   unsigned int i;
174638fd1498Szrj   const uint32_t *data_ptr, *data_end;
174738fd1498Szrj   uint32_t num_decl_states;
174838fd1498Szrj   auto_vec<tree> odr_types;
174938fd1498Szrj 
175038fd1498Szrj   lto_input_block ib_main ((const char *) data + main_offset,
175138fd1498Szrj 			   header->main_size, decl_data->mode_table);
175238fd1498Szrj 
175338fd1498Szrj   data_in = lto_data_in_create (decl_data, (const char *) data + string_offset,
175438fd1498Szrj 				header->string_size, resolutions);
175538fd1498Szrj 
175638fd1498Szrj   /* We do not uniquify the pre-loaded cache entries, those are middle-end
175738fd1498Szrj      internal types that should not be merged.  */
175838fd1498Szrj 
175938fd1498Szrj   /* Read the global declarations and types.  */
176038fd1498Szrj   while (ib_main.p < ib_main.len)
176138fd1498Szrj     {
176238fd1498Szrj       tree t;
176338fd1498Szrj       unsigned from = data_in->reader_cache->nodes.length ();
176438fd1498Szrj       /* Read and uniquify SCCs as in the input stream.  */
176538fd1498Szrj       enum LTO_tags tag = streamer_read_record_start (&ib_main);
176638fd1498Szrj       if (tag == LTO_tree_scc)
176738fd1498Szrj 	{
176838fd1498Szrj 	  unsigned len_;
176938fd1498Szrj 	  unsigned scc_entry_len;
177038fd1498Szrj 	  hashval_t scc_hash = lto_input_scc (&ib_main, data_in, &len_,
177138fd1498Szrj 					      &scc_entry_len);
177238fd1498Szrj 	  unsigned len = data_in->reader_cache->nodes.length () - from;
177338fd1498Szrj 	  gcc_assert (len == len_);
177438fd1498Szrj 
177538fd1498Szrj 	  total_scc_size += len;
177638fd1498Szrj 	  num_sccs_read++;
177738fd1498Szrj 
177838fd1498Szrj 	  /* We have the special case of size-1 SCCs that are pre-merged
177938fd1498Szrj 	     by means of identifier and string sharing for example.
178038fd1498Szrj 	     ???  Maybe we should avoid streaming those as SCCs.  */
178138fd1498Szrj 	  tree first = streamer_tree_cache_get_tree (data_in->reader_cache,
178238fd1498Szrj 						     from);
178338fd1498Szrj 	  if (len == 1
178438fd1498Szrj 	      && (TREE_CODE (first) == IDENTIFIER_NODE
178538fd1498Szrj 		  || TREE_CODE (first) == INTEGER_CST))
178638fd1498Szrj 	    continue;
178738fd1498Szrj 
178838fd1498Szrj 	  /* Try to unify the SCC with already existing ones.  */
178938fd1498Szrj 	  if (!flag_ltrans
179038fd1498Szrj 	      && unify_scc (data_in, from,
179138fd1498Szrj 			    len, scc_entry_len, scc_hash))
179238fd1498Szrj 	    continue;
179338fd1498Szrj 
179438fd1498Szrj 	  /* Tree merging failed, mark entries in location cache as
179538fd1498Szrj 	     permanent.  */
179638fd1498Szrj 	  data_in->location_cache.accept_location_cache ();
179738fd1498Szrj 
179838fd1498Szrj 	  bool seen_type = false;
179938fd1498Szrj 	  for (unsigned i = 0; i < len; ++i)
180038fd1498Szrj 	    {
180138fd1498Szrj 	      tree t = streamer_tree_cache_get_tree (data_in->reader_cache,
180238fd1498Szrj 						     from + i);
180338fd1498Szrj 	      /* Reconstruct the type variant and pointer-to/reference-to
180438fd1498Szrj 		 chains.  */
180538fd1498Szrj 	      if (TYPE_P (t))
180638fd1498Szrj 		{
180738fd1498Szrj 		  seen_type = true;
180838fd1498Szrj 		  num_prevailing_types++;
180938fd1498Szrj 		  lto_fixup_prevailing_type (t);
181038fd1498Szrj 
181138fd1498Szrj 		  /* Compute the canonical type of all types.
181238fd1498Szrj 		     Because SCC components are streamed in random (hash) order
181338fd1498Szrj 		     we may have encountered the type before while registering
181438fd1498Szrj 		     type canonical of a derived type in the same SCC.  */
181538fd1498Szrj 		  if (!TYPE_CANONICAL (t))
181638fd1498Szrj 		    gimple_register_canonical_type (t);
181738fd1498Szrj 		  if (odr_type_p (t))
181838fd1498Szrj 		    odr_types.safe_push (t);
181938fd1498Szrj 		}
182038fd1498Szrj 	      /* Link shared INTEGER_CSTs into TYPE_CACHED_VALUEs of its
182138fd1498Szrj 		 type which is also member of this SCC.  */
182238fd1498Szrj 	      if (TREE_CODE (t) == INTEGER_CST
182338fd1498Szrj 		  && !TREE_OVERFLOW (t))
182438fd1498Szrj 		cache_integer_cst (t);
182538fd1498Szrj 	      if (!flag_ltrans)
182638fd1498Szrj 		{
182738fd1498Szrj 		  lto_maybe_register_decl (data_in, t, from + i);
182838fd1498Szrj 		  /* Scan the tree for references to global functions or
182938fd1498Szrj 		     variables and record those for later fixup.  */
183038fd1498Szrj 		  if (mentions_vars_p (t))
183138fd1498Szrj 		    vec_safe_push (tree_with_vars, t);
183238fd1498Szrj 		}
183338fd1498Szrj 	    }
183438fd1498Szrj 
183538fd1498Szrj 	  /* Register DECLs with the debuginfo machinery.  */
183638fd1498Szrj 	  while (!dref_queue.is_empty ())
183738fd1498Szrj 	    {
183838fd1498Szrj 	      dref_entry e = dref_queue.pop ();
183938fd1498Szrj 	      debug_hooks->register_external_die (e.decl, e.sym, e.off);
184038fd1498Szrj 	    }
184138fd1498Szrj 
184238fd1498Szrj 	  if (seen_type)
184338fd1498Szrj 	    num_type_scc_trees += len;
184438fd1498Szrj 	}
184538fd1498Szrj       else
184638fd1498Szrj 	{
184738fd1498Szrj 	  /* Pickle stray references.  */
184838fd1498Szrj 	  t = lto_input_tree_1 (&ib_main, data_in, tag, 0);
184938fd1498Szrj 	  gcc_assert (t && data_in->reader_cache->nodes.length () == from);
185038fd1498Szrj 	}
185138fd1498Szrj     }
185238fd1498Szrj   data_in->location_cache.apply_location_cache ();
185338fd1498Szrj 
185438fd1498Szrj   /* Read in lto_in_decl_state objects.  */
185538fd1498Szrj   data_ptr = (const uint32_t *) ((const char*) data + decl_offset);
185638fd1498Szrj   data_end =
185738fd1498Szrj      (const uint32_t *) ((const char*) data_ptr + header->decl_state_size);
185838fd1498Szrj   num_decl_states = *data_ptr++;
185938fd1498Szrj 
186038fd1498Szrj   gcc_assert (num_decl_states > 0);
186138fd1498Szrj   decl_data->global_decl_state = lto_new_in_decl_state ();
186238fd1498Szrj   data_ptr = lto_read_in_decl_state (data_in, data_ptr,
186338fd1498Szrj 				     decl_data->global_decl_state);
186438fd1498Szrj 
186538fd1498Szrj   /* Read in per-function decl states and enter them in hash table.  */
186638fd1498Szrj   decl_data->function_decl_states =
186738fd1498Szrj     hash_table<decl_state_hasher>::create_ggc (37);
186838fd1498Szrj 
186938fd1498Szrj   for (i = 1; i < num_decl_states; i++)
187038fd1498Szrj     {
187138fd1498Szrj       struct lto_in_decl_state *state = lto_new_in_decl_state ();
187238fd1498Szrj 
187338fd1498Szrj       data_ptr = lto_read_in_decl_state (data_in, data_ptr, state);
187438fd1498Szrj       lto_in_decl_state **slot
187538fd1498Szrj 	= decl_data->function_decl_states->find_slot (state, INSERT);
187638fd1498Szrj       gcc_assert (*slot == NULL);
187738fd1498Szrj       *slot = state;
187838fd1498Szrj     }
187938fd1498Szrj 
188038fd1498Szrj   /* Sort types for the file before registering in ODR machinery.  */
188138fd1498Szrj   if (lto_location_cache::current_cache)
188238fd1498Szrj     lto_location_cache::current_cache->apply_location_cache ();
188338fd1498Szrj   odr_types.qsort (cmp_type_location);
188438fd1498Szrj 
188538fd1498Szrj   /* Register ODR types.  */
188638fd1498Szrj   for (unsigned i = 0; i < odr_types.length (); i++)
188738fd1498Szrj     register_odr_type (odr_types[i]);
188838fd1498Szrj 
188938fd1498Szrj   if (data_ptr != data_end)
189038fd1498Szrj     internal_error ("bytecode stream: garbage at the end of symbols section");
189138fd1498Szrj 
189238fd1498Szrj   /* Set the current decl state to be the global state. */
189338fd1498Szrj   decl_data->current_decl_state = decl_data->global_decl_state;
189438fd1498Szrj 
189538fd1498Szrj   lto_data_in_delete (data_in);
189638fd1498Szrj }
189738fd1498Szrj 
189838fd1498Szrj /* Custom version of strtoll, which is not portable.  */
189938fd1498Szrj 
190038fd1498Szrj static int64_t
lto_parse_hex(const char * p)190138fd1498Szrj lto_parse_hex (const char *p)
190238fd1498Szrj {
190338fd1498Szrj   int64_t ret = 0;
190438fd1498Szrj 
190538fd1498Szrj   for (; *p != '\0'; ++p)
190638fd1498Szrj     {
190738fd1498Szrj       char c = *p;
190838fd1498Szrj       unsigned char part;
190938fd1498Szrj       ret <<= 4;
191038fd1498Szrj       if (c >= '0' && c <= '9')
191138fd1498Szrj         part = c - '0';
191238fd1498Szrj       else if (c >= 'a' && c <= 'f')
191338fd1498Szrj         part = c - 'a' + 10;
191438fd1498Szrj       else if (c >= 'A' && c <= 'F')
191538fd1498Szrj         part = c - 'A' + 10;
191638fd1498Szrj       else
191738fd1498Szrj         internal_error ("could not parse hex number");
191838fd1498Szrj       ret |= part;
191938fd1498Szrj     }
192038fd1498Szrj 
192138fd1498Szrj   return ret;
192238fd1498Szrj }
192338fd1498Szrj 
192438fd1498Szrj /* Read resolution for file named FILE_NAME. The resolution is read from
192538fd1498Szrj    RESOLUTION. */
192638fd1498Szrj 
192738fd1498Szrj static void
lto_resolution_read(splay_tree file_ids,FILE * resolution,lto_file * file)192838fd1498Szrj lto_resolution_read (splay_tree file_ids, FILE *resolution, lto_file *file)
192938fd1498Szrj {
193038fd1498Szrj   /* We require that objects in the resolution file are in the same
193138fd1498Szrj      order as the lto1 command line. */
193238fd1498Szrj   unsigned int name_len;
193338fd1498Szrj   char *obj_name;
193438fd1498Szrj   unsigned int num_symbols;
193538fd1498Szrj   unsigned int i;
193638fd1498Szrj   struct lto_file_decl_data *file_data;
193738fd1498Szrj   splay_tree_node nd = NULL;
193838fd1498Szrj 
193938fd1498Szrj   if (!resolution)
194038fd1498Szrj     return;
194138fd1498Szrj 
194238fd1498Szrj   name_len = strlen (file->filename);
194338fd1498Szrj   obj_name = XNEWVEC (char, name_len + 1);
194438fd1498Szrj   fscanf (resolution, " ");   /* Read white space. */
194538fd1498Szrj 
194638fd1498Szrj   fread (obj_name, sizeof (char), name_len, resolution);
194738fd1498Szrj   obj_name[name_len] = '\0';
194838fd1498Szrj   if (filename_cmp (obj_name, file->filename) != 0)
194938fd1498Szrj     internal_error ("unexpected file name %s in linker resolution file. "
195038fd1498Szrj 		    "Expected %s", obj_name, file->filename);
195138fd1498Szrj   if (file->offset != 0)
195238fd1498Szrj     {
195338fd1498Szrj       int t;
195438fd1498Szrj       char offset_p[17];
195538fd1498Szrj       int64_t offset;
195638fd1498Szrj       t = fscanf (resolution, "@0x%16s", offset_p);
195738fd1498Szrj       if (t != 1)
195838fd1498Szrj         internal_error ("could not parse file offset");
195938fd1498Szrj       offset = lto_parse_hex (offset_p);
196038fd1498Szrj       if (offset != file->offset)
196138fd1498Szrj         internal_error ("unexpected offset");
196238fd1498Szrj     }
196338fd1498Szrj 
196438fd1498Szrj   free (obj_name);
196538fd1498Szrj 
196638fd1498Szrj   fscanf (resolution, "%u", &num_symbols);
196738fd1498Szrj 
196838fd1498Szrj   for (i = 0; i < num_symbols; i++)
196938fd1498Szrj     {
197038fd1498Szrj       int t;
197138fd1498Szrj       unsigned index;
197238fd1498Szrj       unsigned HOST_WIDE_INT id;
197338fd1498Szrj       char r_str[27];
197438fd1498Szrj       enum ld_plugin_symbol_resolution r = (enum ld_plugin_symbol_resolution) 0;
197538fd1498Szrj       unsigned int j;
197638fd1498Szrj       unsigned int lto_resolution_str_len =
197738fd1498Szrj 	sizeof (lto_resolution_str) / sizeof (char *);
197838fd1498Szrj       res_pair rp;
197938fd1498Szrj 
198038fd1498Szrj       t = fscanf (resolution, "%u " HOST_WIDE_INT_PRINT_HEX_PURE " %26s %*[^\n]\n",
198138fd1498Szrj 		  &index, &id, r_str);
198238fd1498Szrj       if (t != 3)
198338fd1498Szrj         internal_error ("invalid line in the resolution file");
198438fd1498Szrj 
198538fd1498Szrj       for (j = 0; j < lto_resolution_str_len; j++)
198638fd1498Szrj 	{
198738fd1498Szrj 	  if (strcmp (lto_resolution_str[j], r_str) == 0)
198838fd1498Szrj 	    {
198938fd1498Szrj 	      r = (enum ld_plugin_symbol_resolution) j;
199038fd1498Szrj 	      break;
199138fd1498Szrj 	    }
199238fd1498Szrj 	}
199338fd1498Szrj       if (j == lto_resolution_str_len)
199438fd1498Szrj 	internal_error ("invalid resolution in the resolution file");
199538fd1498Szrj 
199638fd1498Szrj       if (!(nd && lto_splay_tree_id_equal_p (nd->key, id)))
199738fd1498Szrj 	{
199838fd1498Szrj 	  nd = lto_splay_tree_lookup (file_ids, id);
199938fd1498Szrj 	  if (nd == NULL)
200038fd1498Szrj 	    internal_error ("resolution sub id %wx not in object file", id);
200138fd1498Szrj 	}
200238fd1498Szrj 
200338fd1498Szrj       file_data = (struct lto_file_decl_data *)nd->value;
200438fd1498Szrj       /* The indexes are very sparse. To save memory save them in a compact
200538fd1498Szrj          format that is only unpacked later when the subfile is processed. */
200638fd1498Szrj       rp.res = r;
200738fd1498Szrj       rp.index = index;
200838fd1498Szrj       file_data->respairs.safe_push (rp);
200938fd1498Szrj       if (file_data->max_index < index)
201038fd1498Szrj         file_data->max_index = index;
201138fd1498Szrj     }
201238fd1498Szrj }
201338fd1498Szrj 
201438fd1498Szrj /* List of file_decl_datas */
201538fd1498Szrj struct file_data_list
201638fd1498Szrj   {
201738fd1498Szrj     struct lto_file_decl_data *first, *last;
201838fd1498Szrj   };
201938fd1498Szrj 
202038fd1498Szrj /* Is the name for a id'ed LTO section? */
202138fd1498Szrj 
202238fd1498Szrj static int
lto_section_with_id(const char * name,unsigned HOST_WIDE_INT * id)202338fd1498Szrj lto_section_with_id (const char *name, unsigned HOST_WIDE_INT *id)
202438fd1498Szrj {
202538fd1498Szrj   const char *s;
202638fd1498Szrj 
202738fd1498Szrj   if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
202838fd1498Szrj     return 0;
202938fd1498Szrj   s = strrchr (name, '.');
203038fd1498Szrj   if (!s)
203138fd1498Szrj     return 0;
203238fd1498Szrj   /* If the section is not suffixed with an ID return.  */
203338fd1498Szrj   if ((size_t)(s - name) == strlen (section_name_prefix))
203438fd1498Szrj     return 0;
203538fd1498Szrj   return sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
203638fd1498Szrj }
203738fd1498Szrj 
203838fd1498Szrj /* Create file_data of each sub file id */
203938fd1498Szrj 
204038fd1498Szrj static int
create_subid_section_table(struct lto_section_slot * ls,splay_tree file_ids,struct file_data_list * list)204138fd1498Szrj create_subid_section_table (struct lto_section_slot *ls, splay_tree file_ids,
204238fd1498Szrj                             struct file_data_list *list)
204338fd1498Szrj {
204438fd1498Szrj   struct lto_section_slot s_slot, *new_slot;
204538fd1498Szrj   unsigned HOST_WIDE_INT id;
204638fd1498Szrj   splay_tree_node nd;
204738fd1498Szrj   void **hash_slot;
204838fd1498Szrj   char *new_name;
204938fd1498Szrj   struct lto_file_decl_data *file_data;
205038fd1498Szrj 
205138fd1498Szrj   if (!lto_section_with_id (ls->name, &id))
205238fd1498Szrj     return 1;
205338fd1498Szrj 
205438fd1498Szrj   /* Find hash table of sub module id */
205538fd1498Szrj   nd = lto_splay_tree_lookup (file_ids, id);
205638fd1498Szrj   if (nd != NULL)
205738fd1498Szrj     {
205838fd1498Szrj       file_data = (struct lto_file_decl_data *)nd->value;
205938fd1498Szrj     }
206038fd1498Szrj   else
206138fd1498Szrj     {
206238fd1498Szrj       file_data = ggc_alloc<lto_file_decl_data> ();
206338fd1498Szrj       memset(file_data, 0, sizeof (struct lto_file_decl_data));
206438fd1498Szrj       file_data->id = id;
206538fd1498Szrj       file_data->section_hash_table = lto_obj_create_section_hash_table ();
206638fd1498Szrj       lto_splay_tree_insert (file_ids, id, file_data);
206738fd1498Szrj 
206838fd1498Szrj       /* Maintain list in linker order */
206938fd1498Szrj       if (!list->first)
207038fd1498Szrj         list->first = file_data;
207138fd1498Szrj       if (list->last)
207238fd1498Szrj         list->last->next = file_data;
207338fd1498Szrj       list->last = file_data;
207438fd1498Szrj     }
207538fd1498Szrj 
207638fd1498Szrj   /* Copy section into sub module hash table */
207738fd1498Szrj   new_name = XDUPVEC (char, ls->name, strlen (ls->name) + 1);
207838fd1498Szrj   s_slot.name = new_name;
207938fd1498Szrj   hash_slot = htab_find_slot (file_data->section_hash_table, &s_slot, INSERT);
208038fd1498Szrj   gcc_assert (*hash_slot == NULL);
208138fd1498Szrj 
208238fd1498Szrj   new_slot = XDUP (struct lto_section_slot, ls);
208338fd1498Szrj   new_slot->name = new_name;
208438fd1498Szrj   *hash_slot = new_slot;
208538fd1498Szrj   return 1;
208638fd1498Szrj }
208738fd1498Szrj 
208838fd1498Szrj /* Read declarations and other initializations for a FILE_DATA. */
208938fd1498Szrj 
209038fd1498Szrj static void
lto_file_finalize(struct lto_file_decl_data * file_data,lto_file * file)209138fd1498Szrj lto_file_finalize (struct lto_file_decl_data *file_data, lto_file *file)
209238fd1498Szrj {
209338fd1498Szrj   const char *data;
209438fd1498Szrj   size_t len;
209538fd1498Szrj   vec<ld_plugin_symbol_resolution_t>
209638fd1498Szrj 	resolutions = vNULL;
209738fd1498Szrj   int i;
209838fd1498Szrj   res_pair *rp;
209938fd1498Szrj 
210038fd1498Szrj   /* Create vector for fast access of resolution. We do this lazily
210138fd1498Szrj      to save memory. */
210238fd1498Szrj   resolutions.safe_grow_cleared (file_data->max_index + 1);
210338fd1498Szrj   for (i = 0; file_data->respairs.iterate (i, &rp); i++)
210438fd1498Szrj     resolutions[rp->index] = rp->res;
210538fd1498Szrj   file_data->respairs.release ();
210638fd1498Szrj 
210738fd1498Szrj   file_data->renaming_hash_table = lto_create_renaming_table ();
210838fd1498Szrj   file_data->file_name = file->filename;
210938fd1498Szrj #ifdef ACCEL_COMPILER
211038fd1498Szrj   lto_input_mode_table (file_data);
211138fd1498Szrj #else
211238fd1498Szrj   file_data->mode_table = lto_mode_identity_table;
211338fd1498Szrj #endif
211438fd1498Szrj   data = lto_get_section_data (file_data, LTO_section_decls, NULL, &len);
211538fd1498Szrj   if (data == NULL)
211638fd1498Szrj     {
211738fd1498Szrj       internal_error ("cannot read LTO decls from %s", file_data->file_name);
211838fd1498Szrj       return;
211938fd1498Szrj     }
212038fd1498Szrj   /* Frees resolutions */
212138fd1498Szrj   lto_read_decls (file_data, data, resolutions);
212238fd1498Szrj   lto_free_section_data (file_data, LTO_section_decls, NULL, data, len);
212338fd1498Szrj }
212438fd1498Szrj 
212538fd1498Szrj /* Finalize FILE_DATA in FILE and increase COUNT. */
212638fd1498Szrj 
212738fd1498Szrj static int
lto_create_files_from_ids(lto_file * file,struct lto_file_decl_data * file_data,int * count)212838fd1498Szrj lto_create_files_from_ids (lto_file *file, struct lto_file_decl_data *file_data,
212938fd1498Szrj 			   int *count)
213038fd1498Szrj {
213138fd1498Szrj   lto_file_finalize (file_data, file);
213238fd1498Szrj   if (symtab->dump_file)
213338fd1498Szrj     fprintf (symtab->dump_file,
213438fd1498Szrj 	     "Creating file %s with sub id " HOST_WIDE_INT_PRINT_HEX "\n",
213538fd1498Szrj 	     file_data->file_name, file_data->id);
213638fd1498Szrj   (*count)++;
213738fd1498Szrj   return 0;
213838fd1498Szrj }
213938fd1498Szrj 
214038fd1498Szrj /* Generate a TREE representation for all types and external decls
214138fd1498Szrj    entities in FILE.
214238fd1498Szrj 
214338fd1498Szrj    Read all of the globals out of the file.  Then read the cgraph
214438fd1498Szrj    and process the .o index into the cgraph nodes so that it can open
214538fd1498Szrj    the .o file to load the functions and ipa information.   */
214638fd1498Szrj 
214738fd1498Szrj static struct lto_file_decl_data *
lto_file_read(lto_file * file,FILE * resolution_file,int * count)214838fd1498Szrj lto_file_read (lto_file *file, FILE *resolution_file, int *count)
214938fd1498Szrj {
215038fd1498Szrj   struct lto_file_decl_data *file_data = NULL;
215138fd1498Szrj   splay_tree file_ids;
215238fd1498Szrj   htab_t section_hash_table;
215338fd1498Szrj   struct lto_section_slot *section;
215438fd1498Szrj   struct file_data_list file_list;
215538fd1498Szrj   struct lto_section_list section_list;
215638fd1498Szrj 
215738fd1498Szrj   memset (&section_list, 0, sizeof (struct lto_section_list));
215838fd1498Szrj   section_hash_table = lto_obj_build_section_table (file, &section_list);
215938fd1498Szrj 
216038fd1498Szrj   /* Find all sub modules in the object and put their sections into new hash
216138fd1498Szrj      tables in a splay tree. */
216238fd1498Szrj   file_ids = lto_splay_tree_new ();
216338fd1498Szrj   memset (&file_list, 0, sizeof (struct file_data_list));
216438fd1498Szrj   for (section = section_list.first; section != NULL; section = section->next)
216538fd1498Szrj     create_subid_section_table (section, file_ids, &file_list);
216638fd1498Szrj 
216738fd1498Szrj   /* Add resolutions to file ids */
216838fd1498Szrj   lto_resolution_read (file_ids, resolution_file, file);
216938fd1498Szrj 
217038fd1498Szrj   /* Finalize each lto file for each submodule in the merged object */
217138fd1498Szrj   for (file_data = file_list.first; file_data != NULL; file_data = file_data->next)
217238fd1498Szrj     lto_create_files_from_ids (file, file_data, count);
217338fd1498Szrj 
217438fd1498Szrj   splay_tree_delete (file_ids);
217538fd1498Szrj   htab_delete (section_hash_table);
217638fd1498Szrj 
217738fd1498Szrj   return file_list.first;
217838fd1498Szrj }
217938fd1498Szrj 
218038fd1498Szrj #if HAVE_MMAP_FILE && HAVE_SYSCONF && defined _SC_PAGE_SIZE
218138fd1498Szrj #define LTO_MMAP_IO 1
218238fd1498Szrj #endif
218338fd1498Szrj 
218438fd1498Szrj #if LTO_MMAP_IO
218538fd1498Szrj /* Page size of machine is used for mmap and munmap calls.  */
218638fd1498Szrj static size_t page_mask;
218738fd1498Szrj #endif
218838fd1498Szrj 
218938fd1498Szrj /* Get the section data of length LEN from FILENAME starting at
219038fd1498Szrj    OFFSET.  The data segment must be freed by the caller when the
219138fd1498Szrj    caller is finished.  Returns NULL if all was not well.  */
219238fd1498Szrj 
219338fd1498Szrj static char *
lto_read_section_data(struct lto_file_decl_data * file_data,intptr_t offset,size_t len)219438fd1498Szrj lto_read_section_data (struct lto_file_decl_data *file_data,
219538fd1498Szrj 		       intptr_t offset, size_t len)
219638fd1498Szrj {
219738fd1498Szrj   char *result;
219838fd1498Szrj   static int fd = -1;
219938fd1498Szrj   static char *fd_name;
220038fd1498Szrj #if LTO_MMAP_IO
220138fd1498Szrj   intptr_t computed_len;
220238fd1498Szrj   intptr_t computed_offset;
220338fd1498Szrj   intptr_t diff;
220438fd1498Szrj #endif
220538fd1498Szrj 
220638fd1498Szrj   /* Keep a single-entry file-descriptor cache.  The last file we
220738fd1498Szrj      touched will get closed at exit.
220838fd1498Szrj      ???  Eventually we want to add a more sophisticated larger cache
220938fd1498Szrj      or rather fix function body streaming to not stream them in
221038fd1498Szrj      practically random order.  */
221138fd1498Szrj   if (fd != -1
221238fd1498Szrj       && filename_cmp (fd_name, file_data->file_name) != 0)
221338fd1498Szrj     {
221438fd1498Szrj       free (fd_name);
221538fd1498Szrj       close (fd);
221638fd1498Szrj       fd = -1;
221738fd1498Szrj     }
221838fd1498Szrj   if (fd == -1)
221938fd1498Szrj     {
222038fd1498Szrj       fd = open (file_data->file_name, O_RDONLY|O_BINARY);
222138fd1498Szrj       if (fd == -1)
222238fd1498Szrj         {
222338fd1498Szrj 	  fatal_error (input_location, "Cannot open %s", file_data->file_name);
222438fd1498Szrj 	  return NULL;
222538fd1498Szrj         }
222638fd1498Szrj       fd_name = xstrdup (file_data->file_name);
222738fd1498Szrj     }
222838fd1498Szrj 
222938fd1498Szrj #if LTO_MMAP_IO
223038fd1498Szrj   if (!page_mask)
223138fd1498Szrj     {
223238fd1498Szrj       size_t page_size = sysconf (_SC_PAGE_SIZE);
223338fd1498Szrj       page_mask = ~(page_size - 1);
223438fd1498Szrj     }
223538fd1498Szrj 
223638fd1498Szrj   computed_offset = offset & page_mask;
223738fd1498Szrj   diff = offset - computed_offset;
223838fd1498Szrj   computed_len = len + diff;
223938fd1498Szrj 
224038fd1498Szrj   result = (char *) mmap (NULL, computed_len, PROT_READ, MAP_PRIVATE,
224138fd1498Szrj 			  fd, computed_offset);
224238fd1498Szrj   if (result == MAP_FAILED)
224338fd1498Szrj     {
224438fd1498Szrj       fatal_error (input_location, "Cannot map %s", file_data->file_name);
224538fd1498Szrj       return NULL;
224638fd1498Szrj     }
224738fd1498Szrj 
224838fd1498Szrj   return result + diff;
224938fd1498Szrj #else
225038fd1498Szrj   result = (char *) xmalloc (len);
225138fd1498Szrj   if (lseek (fd, offset, SEEK_SET) != offset
225238fd1498Szrj       || read (fd, result, len) != (ssize_t) len)
225338fd1498Szrj     {
225438fd1498Szrj       free (result);
225538fd1498Szrj       fatal_error (input_location, "Cannot read %s", file_data->file_name);
225638fd1498Szrj       result = NULL;
225738fd1498Szrj     }
225838fd1498Szrj #ifdef __MINGW32__
225938fd1498Szrj   /* Native windows doesn't supports delayed unlink on opened file. So
226038fd1498Szrj      we close file here again. This produces higher I/O load, but at least
226138fd1498Szrj      it prevents to have dangling file handles preventing unlink.  */
226238fd1498Szrj   free (fd_name);
226338fd1498Szrj   fd_name = NULL;
226438fd1498Szrj   close (fd);
226538fd1498Szrj   fd = -1;
226638fd1498Szrj #endif
226738fd1498Szrj   return result;
226838fd1498Szrj #endif
226938fd1498Szrj }
227038fd1498Szrj 
227138fd1498Szrj 
227238fd1498Szrj /* Get the section data from FILE_DATA of SECTION_TYPE with NAME.
227338fd1498Szrj    NAME will be NULL unless the section type is for a function
227438fd1498Szrj    body.  */
227538fd1498Szrj 
227638fd1498Szrj static const char *
get_section_data(struct lto_file_decl_data * file_data,enum lto_section_type section_type,const char * name,size_t * len)227738fd1498Szrj get_section_data (struct lto_file_decl_data *file_data,
227838fd1498Szrj 		      enum lto_section_type section_type,
227938fd1498Szrj 		      const char *name,
228038fd1498Szrj 		      size_t *len)
228138fd1498Szrj {
228238fd1498Szrj   htab_t section_hash_table = file_data->section_hash_table;
228338fd1498Szrj   struct lto_section_slot *f_slot;
228438fd1498Szrj   struct lto_section_slot s_slot;
228538fd1498Szrj   const char *section_name = lto_get_section_name (section_type, name, file_data);
228638fd1498Szrj   char *data = NULL;
228738fd1498Szrj 
228838fd1498Szrj   *len = 0;
228938fd1498Szrj   s_slot.name = section_name;
229038fd1498Szrj   f_slot = (struct lto_section_slot *) htab_find (section_hash_table, &s_slot);
229138fd1498Szrj   if (f_slot)
229238fd1498Szrj     {
229338fd1498Szrj       data = lto_read_section_data (file_data, f_slot->start, f_slot->len);
229438fd1498Szrj       *len = f_slot->len;
229538fd1498Szrj     }
229638fd1498Szrj 
229738fd1498Szrj   free (CONST_CAST (char *, section_name));
229838fd1498Szrj   return data;
229938fd1498Szrj }
230038fd1498Szrj 
230138fd1498Szrj 
230238fd1498Szrj /* Free the section data from FILE_DATA of SECTION_TYPE with NAME that
230338fd1498Szrj    starts at OFFSET and has LEN bytes.  */
230438fd1498Szrj 
230538fd1498Szrj static void
free_section_data(struct lto_file_decl_data * file_data ATTRIBUTE_UNUSED,enum lto_section_type section_type ATTRIBUTE_UNUSED,const char * name ATTRIBUTE_UNUSED,const char * offset,size_t len ATTRIBUTE_UNUSED)230638fd1498Szrj free_section_data (struct lto_file_decl_data *file_data ATTRIBUTE_UNUSED,
230738fd1498Szrj 		   enum lto_section_type section_type ATTRIBUTE_UNUSED,
230838fd1498Szrj 		   const char *name ATTRIBUTE_UNUSED,
230938fd1498Szrj 		   const char *offset, size_t len ATTRIBUTE_UNUSED)
231038fd1498Szrj {
231138fd1498Szrj #if LTO_MMAP_IO
231238fd1498Szrj   intptr_t computed_len;
231338fd1498Szrj   intptr_t computed_offset;
231438fd1498Szrj   intptr_t diff;
231538fd1498Szrj #endif
231638fd1498Szrj 
231738fd1498Szrj #if LTO_MMAP_IO
231838fd1498Szrj   computed_offset = ((intptr_t) offset) & page_mask;
231938fd1498Szrj   diff = (intptr_t) offset - computed_offset;
232038fd1498Szrj   computed_len = len + diff;
232138fd1498Szrj 
232238fd1498Szrj   munmap ((caddr_t) computed_offset, computed_len);
232338fd1498Szrj #else
232438fd1498Szrj   free (CONST_CAST(char *, offset));
232538fd1498Szrj #endif
232638fd1498Szrj }
232738fd1498Szrj 
232838fd1498Szrj static lto_file *current_lto_file;
232938fd1498Szrj 
233038fd1498Szrj /* Actually stream out ENCODER into TEMP_FILENAME.  */
233138fd1498Szrj 
233238fd1498Szrj static void
do_stream_out(char * temp_filename,lto_symtab_encoder_t encoder)233338fd1498Szrj do_stream_out (char *temp_filename, lto_symtab_encoder_t encoder)
233438fd1498Szrj {
233538fd1498Szrj   lto_file *file = lto_obj_file_open (temp_filename, true);
233638fd1498Szrj   if (!file)
233738fd1498Szrj     fatal_error (input_location, "lto_obj_file_open() failed");
233838fd1498Szrj   lto_set_current_out_file (file);
233938fd1498Szrj 
234038fd1498Szrj   ipa_write_optimization_summaries (encoder);
234138fd1498Szrj 
234238fd1498Szrj   free (CONST_CAST (char *, file->filename));
234338fd1498Szrj 
234438fd1498Szrj   lto_set_current_out_file (NULL);
234538fd1498Szrj   lto_obj_file_close (file);
234638fd1498Szrj   free (file);
234738fd1498Szrj }
234838fd1498Szrj 
234938fd1498Szrj /* Wait for forked process and signal errors.  */
235038fd1498Szrj #ifdef HAVE_WORKING_FORK
235138fd1498Szrj static void
wait_for_child()235238fd1498Szrj wait_for_child ()
235338fd1498Szrj {
235438fd1498Szrj   int status;
235538fd1498Szrj   do
235638fd1498Szrj     {
235738fd1498Szrj #ifndef WCONTINUED
235838fd1498Szrj #define WCONTINUED 0
235938fd1498Szrj #endif
236038fd1498Szrj       int w = waitpid (0, &status, WUNTRACED | WCONTINUED);
236138fd1498Szrj       if (w == -1)
236238fd1498Szrj 	fatal_error (input_location, "waitpid failed");
236338fd1498Szrj 
236438fd1498Szrj       if (WIFEXITED (status) && WEXITSTATUS (status))
236538fd1498Szrj 	fatal_error (input_location, "streaming subprocess failed");
236638fd1498Szrj       else if (WIFSIGNALED (status))
236738fd1498Szrj 	fatal_error (input_location,
236838fd1498Szrj 		     "streaming subprocess was killed by signal");
236938fd1498Szrj     }
237038fd1498Szrj   while (!WIFEXITED (status) && !WIFSIGNALED (status));
237138fd1498Szrj }
237238fd1498Szrj #endif
237338fd1498Szrj 
237438fd1498Szrj /* Stream out ENCODER into TEMP_FILENAME
237538fd1498Szrj    Fork if that seems to help.  */
237638fd1498Szrj 
237738fd1498Szrj static void
stream_out(char * temp_filename,lto_symtab_encoder_t encoder,bool ARG_UNUSED (last))237838fd1498Szrj stream_out (char *temp_filename, lto_symtab_encoder_t encoder,
237938fd1498Szrj 	    bool ARG_UNUSED (last))
238038fd1498Szrj {
238138fd1498Szrj #ifdef HAVE_WORKING_FORK
238238fd1498Szrj   static int nruns;
238338fd1498Szrj 
238438fd1498Szrj   if (lto_parallelism <= 1)
238538fd1498Szrj     {
238638fd1498Szrj       do_stream_out (temp_filename, encoder);
238738fd1498Szrj       return;
238838fd1498Szrj     }
238938fd1498Szrj 
239038fd1498Szrj   /* Do not run more than LTO_PARALLELISM streamings
239138fd1498Szrj      FIXME: we ignore limits on jobserver.  */
239238fd1498Szrj   if (lto_parallelism > 0 && nruns >= lto_parallelism)
239338fd1498Szrj     {
239438fd1498Szrj       wait_for_child ();
239538fd1498Szrj       nruns --;
239638fd1498Szrj     }
239738fd1498Szrj   /* If this is not the last parallel partition, execute new
239838fd1498Szrj      streaming process.  */
239938fd1498Szrj   if (!last)
240038fd1498Szrj     {
240138fd1498Szrj       pid_t cpid = fork ();
240238fd1498Szrj 
240338fd1498Szrj       if (!cpid)
240438fd1498Szrj 	{
240538fd1498Szrj 	  setproctitle ("lto1-wpa-streaming");
240638fd1498Szrj 	  do_stream_out (temp_filename, encoder);
240738fd1498Szrj 	  exit (0);
240838fd1498Szrj 	}
240938fd1498Szrj       /* Fork failed; lets do the job ourseleves.  */
241038fd1498Szrj       else if (cpid == -1)
241138fd1498Szrj         do_stream_out (temp_filename, encoder);
241238fd1498Szrj       else
241338fd1498Szrj 	nruns++;
241438fd1498Szrj     }
241538fd1498Szrj   /* Last partition; stream it and wait for all children to die.  */
241638fd1498Szrj   else
241738fd1498Szrj     {
241838fd1498Szrj       int i;
241938fd1498Szrj       do_stream_out (temp_filename, encoder);
242038fd1498Szrj       for (i = 0; i < nruns; i++)
242138fd1498Szrj 	wait_for_child ();
242238fd1498Szrj     }
242338fd1498Szrj   asm_nodes_output = true;
242438fd1498Szrj #else
242538fd1498Szrj   do_stream_out (temp_filename, encoder);
242638fd1498Szrj #endif
242738fd1498Szrj }
242838fd1498Szrj 
242938fd1498Szrj /* Write all output files in WPA mode and the file with the list of
243038fd1498Szrj    LTRANS units.  */
243138fd1498Szrj 
243238fd1498Szrj static void
lto_wpa_write_files(void)243338fd1498Szrj lto_wpa_write_files (void)
243438fd1498Szrj {
243538fd1498Szrj   unsigned i, n_sets;
243638fd1498Szrj   ltrans_partition part;
243738fd1498Szrj   FILE *ltrans_output_list_stream;
243838fd1498Szrj   char *temp_filename;
2439*58e805e6Szrj   auto_vec <char *>temp_filenames;
2440*58e805e6Szrj   auto_vec <int>temp_priority;
244138fd1498Szrj   size_t blen;
244238fd1498Szrj 
244338fd1498Szrj   /* Open the LTRANS output list.  */
244438fd1498Szrj   if (!ltrans_output_list)
244538fd1498Szrj     fatal_error (input_location, "no LTRANS output list filename provided");
244638fd1498Szrj 
244738fd1498Szrj   timevar_push (TV_WHOPR_WPA);
244838fd1498Szrj 
244938fd1498Szrj   FOR_EACH_VEC_ELT (ltrans_partitions, i, part)
245038fd1498Szrj     lto_stats.num_output_symtab_nodes += lto_symtab_encoder_size (part->encoder);
245138fd1498Szrj 
245238fd1498Szrj   timevar_pop (TV_WHOPR_WPA);
245338fd1498Szrj 
245438fd1498Szrj   timevar_push (TV_WHOPR_WPA_IO);
245538fd1498Szrj 
245638fd1498Szrj   /* Generate a prefix for the LTRANS unit files.  */
245738fd1498Szrj   blen = strlen (ltrans_output_list);
245838fd1498Szrj   temp_filename = (char *) xmalloc (blen + sizeof ("2147483648.o"));
245938fd1498Szrj   strcpy (temp_filename, ltrans_output_list);
246038fd1498Szrj   if (blen > sizeof (".out")
246138fd1498Szrj       && strcmp (temp_filename + blen - sizeof (".out") + 1,
246238fd1498Szrj 		 ".out") == 0)
246338fd1498Szrj     temp_filename[blen - sizeof (".out") + 1] = '\0';
246438fd1498Szrj   blen = strlen (temp_filename);
246538fd1498Szrj 
246638fd1498Szrj   n_sets = ltrans_partitions.length ();
246738fd1498Szrj 
246838fd1498Szrj   for (i = 0; i < n_sets; i++)
246938fd1498Szrj     {
247038fd1498Szrj       ltrans_partition part = ltrans_partitions[i];
247138fd1498Szrj 
247238fd1498Szrj       /* Write all the nodes in SET.  */
247338fd1498Szrj       sprintf (temp_filename + blen, "%u.o", i);
247438fd1498Szrj 
247538fd1498Szrj       if (!quiet_flag)
247638fd1498Szrj 	fprintf (stderr, " %s (%s %i insns)", temp_filename, part->name, part->insns);
247738fd1498Szrj       if (symtab->dump_file)
247838fd1498Szrj 	{
247938fd1498Szrj           lto_symtab_encoder_iterator lsei;
248038fd1498Szrj 
248138fd1498Szrj 	  fprintf (symtab->dump_file, "Writing partition %s to file %s, %i insns\n",
248238fd1498Szrj 		   part->name, temp_filename, part->insns);
248338fd1498Szrj 	  fprintf (symtab->dump_file, "  Symbols in partition: ");
248438fd1498Szrj 	  for (lsei = lsei_start_in_partition (part->encoder); !lsei_end_p (lsei);
248538fd1498Szrj 	       lsei_next_in_partition (&lsei))
248638fd1498Szrj 	    {
248738fd1498Szrj 	      symtab_node *node = lsei_node (lsei);
248838fd1498Szrj 	      fprintf (symtab->dump_file, "%s ", node->asm_name ());
248938fd1498Szrj 	    }
249038fd1498Szrj 	  fprintf (symtab->dump_file, "\n  Symbols in boundary: ");
249138fd1498Szrj 	  for (lsei = lsei_start (part->encoder); !lsei_end_p (lsei);
249238fd1498Szrj 	       lsei_next (&lsei))
249338fd1498Szrj 	    {
249438fd1498Szrj 	      symtab_node *node = lsei_node (lsei);
249538fd1498Szrj 	      if (!lto_symtab_encoder_in_partition_p (part->encoder, node))
249638fd1498Szrj 		{
249738fd1498Szrj 		  fprintf (symtab->dump_file, "%s ", node->asm_name ());
249838fd1498Szrj 		  cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
249938fd1498Szrj 		  if (cnode
250038fd1498Szrj 		      && lto_symtab_encoder_encode_body_p (part->encoder, cnode))
250138fd1498Szrj 		    fprintf (symtab->dump_file, "(body included)");
250238fd1498Szrj 		  else
250338fd1498Szrj 		    {
250438fd1498Szrj 		      varpool_node *vnode = dyn_cast <varpool_node *> (node);
250538fd1498Szrj 		      if (vnode
250638fd1498Szrj 			  && lto_symtab_encoder_encode_initializer_p (part->encoder, vnode))
250738fd1498Szrj 			fprintf (symtab->dump_file, "(initializer included)");
250838fd1498Szrj 		    }
250938fd1498Szrj 		}
251038fd1498Szrj 	    }
251138fd1498Szrj 	  fprintf (symtab->dump_file, "\n");
251238fd1498Szrj 	}
251338fd1498Szrj       gcc_checking_assert (lto_symtab_encoder_size (part->encoder) || !i);
251438fd1498Szrj 
251538fd1498Szrj       stream_out (temp_filename, part->encoder, i == n_sets - 1);
251638fd1498Szrj 
251738fd1498Szrj       part->encoder = NULL;
251838fd1498Szrj 
2519*58e805e6Szrj       temp_priority.safe_push (part->insns);
252038fd1498Szrj       temp_filenames.safe_push (xstrdup (temp_filename));
252138fd1498Szrj     }
252238fd1498Szrj   ltrans_output_list_stream = fopen (ltrans_output_list, "w");
252338fd1498Szrj   if (ltrans_output_list_stream == NULL)
252438fd1498Szrj     fatal_error (input_location,
252538fd1498Szrj 		 "opening LTRANS output list %s: %m", ltrans_output_list);
252638fd1498Szrj   for (i = 0; i < n_sets; i++)
252738fd1498Szrj     {
252838fd1498Szrj       unsigned int len = strlen (temp_filenames[i]);
2529*58e805e6Szrj       if (fprintf (ltrans_output_list_stream, "%i\n", temp_priority[i]) < 0
2530*58e805e6Szrj 	  || fwrite (temp_filenames[i], 1, len, ltrans_output_list_stream) < len
253138fd1498Szrj 	  || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1)
253238fd1498Szrj 	fatal_error (input_location, "writing to LTRANS output list %s: %m",
253338fd1498Szrj 		     ltrans_output_list);
253438fd1498Szrj      free (temp_filenames[i]);
253538fd1498Szrj     }
253638fd1498Szrj 
253738fd1498Szrj   lto_stats.num_output_files += n_sets;
253838fd1498Szrj 
253938fd1498Szrj   /* Close the LTRANS output list.  */
254038fd1498Szrj   if (fclose (ltrans_output_list_stream))
254138fd1498Szrj     fatal_error (input_location,
254238fd1498Szrj 		 "closing LTRANS output list %s: %m", ltrans_output_list);
254338fd1498Szrj 
254438fd1498Szrj   free_ltrans_partitions();
254538fd1498Szrj   free (temp_filename);
254638fd1498Szrj 
254738fd1498Szrj   timevar_pop (TV_WHOPR_WPA_IO);
254838fd1498Szrj }
254938fd1498Szrj 
255038fd1498Szrj 
255138fd1498Szrj /* If TT is a variable or function decl replace it with its
255238fd1498Szrj    prevailing variant.  */
255338fd1498Szrj #define LTO_SET_PREVAIL(tt) \
255438fd1498Szrj   do {\
255538fd1498Szrj     if ((tt) && VAR_OR_FUNCTION_DECL_P (tt) \
255638fd1498Szrj 	&& (TREE_PUBLIC (tt) || DECL_EXTERNAL (tt))) \
255738fd1498Szrj       { \
255838fd1498Szrj         tt = lto_symtab_prevailing_decl (tt); \
255938fd1498Szrj 	fixed = true; \
256038fd1498Szrj       } \
256138fd1498Szrj   } while (0)
256238fd1498Szrj 
256338fd1498Szrj /* Ensure that TT isn't a replacable var of function decl.  */
256438fd1498Szrj #define LTO_NO_PREVAIL(tt) \
256538fd1498Szrj   gcc_checking_assert (!(tt) || !VAR_OR_FUNCTION_DECL_P (tt))
256638fd1498Szrj 
256738fd1498Szrj /* Given a tree T replace all fields referring to variables or functions
256838fd1498Szrj    with their prevailing variant.  */
256938fd1498Szrj static void
lto_fixup_prevailing_decls(tree t)257038fd1498Szrj lto_fixup_prevailing_decls (tree t)
257138fd1498Szrj {
257238fd1498Szrj   enum tree_code code = TREE_CODE (t);
257338fd1498Szrj   bool fixed = false;
257438fd1498Szrj 
257538fd1498Szrj   gcc_checking_assert (code != TREE_BINFO);
257638fd1498Szrj   LTO_NO_PREVAIL (TREE_TYPE (t));
257738fd1498Szrj   if (CODE_CONTAINS_STRUCT (code, TS_COMMON)
257838fd1498Szrj       /* lto_symtab_prevail_decl use TREE_CHAIN to link to the prevailing decl.
257938fd1498Szrj 	 in the case T is a prevailed declaration we would ICE here. */
258038fd1498Szrj       && !VAR_OR_FUNCTION_DECL_P (t))
258138fd1498Szrj     LTO_NO_PREVAIL (TREE_CHAIN (t));
258238fd1498Szrj   if (DECL_P (t))
258338fd1498Szrj     {
258438fd1498Szrj       LTO_NO_PREVAIL (DECL_NAME (t));
258538fd1498Szrj       LTO_SET_PREVAIL (DECL_CONTEXT (t));
258638fd1498Szrj       if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
258738fd1498Szrj 	{
258838fd1498Szrj 	  LTO_SET_PREVAIL (DECL_SIZE (t));
258938fd1498Szrj 	  LTO_SET_PREVAIL (DECL_SIZE_UNIT (t));
259038fd1498Szrj 	  LTO_SET_PREVAIL (DECL_INITIAL (t));
259138fd1498Szrj 	  LTO_NO_PREVAIL (DECL_ATTRIBUTES (t));
259238fd1498Szrj 	  LTO_SET_PREVAIL (DECL_ABSTRACT_ORIGIN (t));
259338fd1498Szrj 	}
259438fd1498Szrj       if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
259538fd1498Szrj 	{
259638fd1498Szrj 	  LTO_NO_PREVAIL (DECL_ASSEMBLER_NAME_RAW (t));
259738fd1498Szrj 	}
259838fd1498Szrj       if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
259938fd1498Szrj 	{
260038fd1498Szrj 	  LTO_NO_PREVAIL (DECL_RESULT_FLD (t));
260138fd1498Szrj 	}
260238fd1498Szrj       if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
260338fd1498Szrj 	{
260438fd1498Szrj 	  LTO_NO_PREVAIL (DECL_ARGUMENTS (t));
260538fd1498Szrj 	  LTO_SET_PREVAIL (DECL_FUNCTION_PERSONALITY (t));
260638fd1498Szrj 	  LTO_NO_PREVAIL (DECL_VINDEX (t));
260738fd1498Szrj 	}
260838fd1498Szrj       if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
260938fd1498Szrj 	{
261038fd1498Szrj 	  LTO_SET_PREVAIL (DECL_FIELD_OFFSET (t));
261138fd1498Szrj 	  LTO_NO_PREVAIL (DECL_BIT_FIELD_TYPE (t));
261238fd1498Szrj 	  LTO_NO_PREVAIL (DECL_QUALIFIER (t));
261338fd1498Szrj 	  LTO_NO_PREVAIL (DECL_FIELD_BIT_OFFSET (t));
261438fd1498Szrj 	  LTO_NO_PREVAIL (DECL_FCONTEXT (t));
261538fd1498Szrj 	}
261638fd1498Szrj     }
261738fd1498Szrj   else if (TYPE_P (t))
261838fd1498Szrj     {
261938fd1498Szrj       LTO_NO_PREVAIL (TYPE_CACHED_VALUES (t));
262038fd1498Szrj       LTO_SET_PREVAIL (TYPE_SIZE (t));
262138fd1498Szrj       LTO_SET_PREVAIL (TYPE_SIZE_UNIT (t));
262238fd1498Szrj       LTO_NO_PREVAIL (TYPE_ATTRIBUTES (t));
262338fd1498Szrj       LTO_NO_PREVAIL (TYPE_NAME (t));
262438fd1498Szrj 
262538fd1498Szrj       LTO_SET_PREVAIL (TYPE_MIN_VALUE_RAW (t));
262638fd1498Szrj       LTO_SET_PREVAIL (TYPE_MAX_VALUE_RAW (t));
262738fd1498Szrj       LTO_NO_PREVAIL (TYPE_LANG_SLOT_1 (t));
262838fd1498Szrj 
262938fd1498Szrj       LTO_SET_PREVAIL (TYPE_CONTEXT (t));
263038fd1498Szrj 
263138fd1498Szrj       LTO_NO_PREVAIL (TYPE_CANONICAL (t));
263238fd1498Szrj       LTO_NO_PREVAIL (TYPE_MAIN_VARIANT (t));
263338fd1498Szrj       LTO_NO_PREVAIL (TYPE_NEXT_VARIANT (t));
263438fd1498Szrj     }
263538fd1498Szrj   else if (EXPR_P (t))
263638fd1498Szrj     {
263738fd1498Szrj       int i;
263838fd1498Szrj       for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
263938fd1498Szrj 	LTO_SET_PREVAIL (TREE_OPERAND (t, i));
264038fd1498Szrj     }
264138fd1498Szrj   else if (TREE_CODE (t) == CONSTRUCTOR)
264238fd1498Szrj     {
264338fd1498Szrj       unsigned i;
264438fd1498Szrj       tree val;
264538fd1498Szrj       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), i, val)
264638fd1498Szrj 	LTO_SET_PREVAIL (val);
264738fd1498Szrj     }
264838fd1498Szrj   else
264938fd1498Szrj     {
265038fd1498Szrj       switch (code)
265138fd1498Szrj 	{
265238fd1498Szrj 	case TREE_LIST:
265338fd1498Szrj 	  LTO_SET_PREVAIL (TREE_VALUE (t));
265438fd1498Szrj 	  LTO_SET_PREVAIL (TREE_PURPOSE (t));
265538fd1498Szrj 	  LTO_NO_PREVAIL (TREE_PURPOSE (t));
265638fd1498Szrj 	  break;
265738fd1498Szrj 	default:
265838fd1498Szrj 	  gcc_unreachable ();
265938fd1498Szrj 	}
266038fd1498Szrj     }
266138fd1498Szrj   /* If we fixed nothing, then we missed something seen by
266238fd1498Szrj      mentions_vars_p.  */
266338fd1498Szrj   gcc_checking_assert (fixed);
266438fd1498Szrj }
266538fd1498Szrj #undef LTO_SET_PREVAIL
266638fd1498Szrj #undef LTO_NO_PREVAIL
266738fd1498Szrj 
266838fd1498Szrj /* Helper function of lto_fixup_decls. Walks the var and fn streams in STATE,
266938fd1498Szrj    replaces var and function decls with the corresponding prevailing def.  */
267038fd1498Szrj 
267138fd1498Szrj static void
lto_fixup_state(struct lto_in_decl_state * state)267238fd1498Szrj lto_fixup_state (struct lto_in_decl_state *state)
267338fd1498Szrj {
267438fd1498Szrj   unsigned i, si;
267538fd1498Szrj 
267638fd1498Szrj   /* Although we only want to replace FUNCTION_DECLs and VAR_DECLs,
267738fd1498Szrj      we still need to walk from all DECLs to find the reachable
267838fd1498Szrj      FUNCTION_DECLs and VAR_DECLs.  */
267938fd1498Szrj   for (si = 0; si < LTO_N_DECL_STREAMS; si++)
268038fd1498Szrj     {
268138fd1498Szrj       vec<tree, va_gc> *trees = state->streams[si];
268238fd1498Szrj       for (i = 0; i < vec_safe_length (trees); i++)
268338fd1498Szrj 	{
268438fd1498Szrj 	  tree t = (*trees)[i];
268538fd1498Szrj 	  if (flag_checking && TYPE_P (t))
268638fd1498Szrj 	    verify_type (t);
268738fd1498Szrj 	  if (VAR_OR_FUNCTION_DECL_P (t)
268838fd1498Szrj 	      && (TREE_PUBLIC (t) || DECL_EXTERNAL (t)))
268938fd1498Szrj 	    (*trees)[i] = lto_symtab_prevailing_decl (t);
269038fd1498Szrj 	}
269138fd1498Szrj     }
269238fd1498Szrj }
269338fd1498Szrj 
269438fd1498Szrj /* Fix the decls from all FILES. Replaces each decl with the corresponding
269538fd1498Szrj    prevailing one.  */
269638fd1498Szrj 
269738fd1498Szrj static void
lto_fixup_decls(struct lto_file_decl_data ** files)269838fd1498Szrj lto_fixup_decls (struct lto_file_decl_data **files)
269938fd1498Szrj {
270038fd1498Szrj   unsigned int i;
270138fd1498Szrj   tree t;
270238fd1498Szrj 
270338fd1498Szrj   if (tree_with_vars)
270438fd1498Szrj     FOR_EACH_VEC_ELT ((*tree_with_vars), i, t)
270538fd1498Szrj       lto_fixup_prevailing_decls (t);
270638fd1498Szrj 
270738fd1498Szrj   for (i = 0; files[i]; i++)
270838fd1498Szrj     {
270938fd1498Szrj       struct lto_file_decl_data *file = files[i];
271038fd1498Szrj       struct lto_in_decl_state *state = file->global_decl_state;
271138fd1498Szrj       lto_fixup_state (state);
271238fd1498Szrj 
271338fd1498Szrj       hash_table<decl_state_hasher>::iterator iter;
271438fd1498Szrj       lto_in_decl_state *elt;
271538fd1498Szrj       FOR_EACH_HASH_TABLE_ELEMENT (*file->function_decl_states, elt,
271638fd1498Szrj 				   lto_in_decl_state *, iter)
271738fd1498Szrj 	lto_fixup_state (elt);
271838fd1498Szrj     }
271938fd1498Szrj }
272038fd1498Szrj 
272138fd1498Szrj static GTY((length ("lto_stats.num_input_files + 1"))) struct lto_file_decl_data **all_file_decl_data;
272238fd1498Szrj 
272338fd1498Szrj /* Turn file datas for sub files into a single array, so that they look
272438fd1498Szrj    like separate files for further passes. */
272538fd1498Szrj 
272638fd1498Szrj static void
lto_flatten_files(struct lto_file_decl_data ** orig,int count,int last_file_ix)272738fd1498Szrj lto_flatten_files (struct lto_file_decl_data **orig, int count, int last_file_ix)
272838fd1498Szrj {
272938fd1498Szrj   struct lto_file_decl_data *n, *next;
273038fd1498Szrj   int i, k;
273138fd1498Szrj 
273238fd1498Szrj   lto_stats.num_input_files = count;
273338fd1498Szrj   all_file_decl_data
273438fd1498Szrj     = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (count + 1);
273538fd1498Szrj   /* Set the hooks so that all of the ipa passes can read in their data.  */
273638fd1498Szrj   lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data);
273738fd1498Szrj   for (i = 0, k = 0; i < last_file_ix; i++)
273838fd1498Szrj     {
273938fd1498Szrj       for (n = orig[i]; n != NULL; n = next)
274038fd1498Szrj 	{
274138fd1498Szrj 	  all_file_decl_data[k++] = n;
274238fd1498Szrj 	  next = n->next;
274338fd1498Szrj 	  n->next = NULL;
274438fd1498Szrj 	}
274538fd1498Szrj     }
274638fd1498Szrj   all_file_decl_data[k] = NULL;
274738fd1498Szrj   gcc_assert (k == count);
274838fd1498Szrj }
274938fd1498Szrj 
275038fd1498Szrj /* Input file data before flattening (i.e. splitting them to subfiles to support
275138fd1498Szrj    incremental linking.  */
275238fd1498Szrj static int real_file_count;
275338fd1498Szrj static GTY((length ("real_file_count + 1"))) struct lto_file_decl_data **real_file_decl_data;
275438fd1498Szrj 
275538fd1498Szrj static void print_lto_report_1 (void);
275638fd1498Szrj 
275738fd1498Szrj /* Read all the symbols from the input files FNAMES.  NFILES is the
275838fd1498Szrj    number of files requested in the command line.  Instantiate a
275938fd1498Szrj    global call graph by aggregating all the sub-graphs found in each
276038fd1498Szrj    file.  */
276138fd1498Szrj 
276238fd1498Szrj static void
read_cgraph_and_symbols(unsigned nfiles,const char ** fnames)276338fd1498Szrj read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
276438fd1498Szrj {
276538fd1498Szrj   unsigned int i, last_file_ix;
276638fd1498Szrj   FILE *resolution;
276738fd1498Szrj   int count = 0;
276838fd1498Szrj   struct lto_file_decl_data **decl_data;
276938fd1498Szrj   symtab_node *snode;
277038fd1498Szrj 
277138fd1498Szrj   symtab->initialize ();
277238fd1498Szrj 
277338fd1498Szrj   timevar_push (TV_IPA_LTO_DECL_IN);
277438fd1498Szrj 
277538fd1498Szrj #ifdef ACCEL_COMPILER
277638fd1498Szrj   section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX;
277738fd1498Szrj   lto_stream_offload_p = true;
277838fd1498Szrj #endif
277938fd1498Szrj 
278038fd1498Szrj   real_file_decl_data
278138fd1498Szrj     = decl_data = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (nfiles + 1);
278238fd1498Szrj   real_file_count = nfiles;
278338fd1498Szrj 
278438fd1498Szrj   /* Read the resolution file.  */
278538fd1498Szrj   resolution = NULL;
278638fd1498Szrj   if (resolution_file_name)
278738fd1498Szrj     {
278838fd1498Szrj       int t;
278938fd1498Szrj       unsigned num_objects;
279038fd1498Szrj 
279138fd1498Szrj       resolution = fopen (resolution_file_name, "r");
279238fd1498Szrj       if (resolution == NULL)
279338fd1498Szrj 	fatal_error (input_location,
279438fd1498Szrj 		     "could not open symbol resolution file: %m");
279538fd1498Szrj 
279638fd1498Szrj       t = fscanf (resolution, "%u", &num_objects);
279738fd1498Szrj       gcc_assert (t == 1);
279838fd1498Szrj 
279938fd1498Szrj       /* True, since the plugin splits the archives.  */
280038fd1498Szrj       gcc_assert (num_objects == nfiles);
280138fd1498Szrj     }
280238fd1498Szrj   symtab->state = LTO_STREAMING;
280338fd1498Szrj 
280438fd1498Szrj   canonical_type_hash_cache = new hash_map<const_tree, hashval_t> (251);
280538fd1498Szrj   gimple_canonical_types = htab_create (16381, gimple_canonical_type_hash,
280638fd1498Szrj 					gimple_canonical_type_eq, NULL);
280738fd1498Szrj   gcc_obstack_init (&tree_scc_hash_obstack);
280838fd1498Szrj   tree_scc_hash = new hash_table<tree_scc_hasher> (4096);
280938fd1498Szrj 
281038fd1498Szrj   /* Register the common node types with the canonical type machinery so
281138fd1498Szrj      we properly share alias-sets across languages and TUs.  Do not
281238fd1498Szrj      expose the common nodes as type merge target - those that should be
281338fd1498Szrj      are already exposed so by pre-loading the LTO streamer caches.
281438fd1498Szrj      Do two passes - first clear TYPE_CANONICAL and then re-compute it.  */
281538fd1498Szrj   for (i = 0; i < itk_none; ++i)
281638fd1498Szrj     lto_register_canonical_types (integer_types[i], true);
281738fd1498Szrj   for (i = 0; i < stk_type_kind_last; ++i)
281838fd1498Szrj     lto_register_canonical_types (sizetype_tab[i], true);
281938fd1498Szrj   for (i = 0; i < TI_MAX; ++i)
282038fd1498Szrj     lto_register_canonical_types (global_trees[i], true);
282138fd1498Szrj   for (i = 0; i < itk_none; ++i)
282238fd1498Szrj     lto_register_canonical_types (integer_types[i], false);
282338fd1498Szrj   for (i = 0; i < stk_type_kind_last; ++i)
282438fd1498Szrj     lto_register_canonical_types (sizetype_tab[i], false);
282538fd1498Szrj   for (i = 0; i < TI_MAX; ++i)
282638fd1498Szrj     lto_register_canonical_types (global_trees[i], false);
282738fd1498Szrj 
282838fd1498Szrj   if (!quiet_flag)
282938fd1498Szrj     fprintf (stderr, "Reading object files:");
283038fd1498Szrj 
283138fd1498Szrj   /* Read all of the object files specified on the command line.  */
283238fd1498Szrj   for (i = 0, last_file_ix = 0; i < nfiles; ++i)
283338fd1498Szrj     {
283438fd1498Szrj       struct lto_file_decl_data *file_data = NULL;
283538fd1498Szrj       if (!quiet_flag)
283638fd1498Szrj 	{
283738fd1498Szrj 	  fprintf (stderr, " %s", fnames[i]);
283838fd1498Szrj 	  fflush (stderr);
283938fd1498Szrj 	}
284038fd1498Szrj 
284138fd1498Szrj       current_lto_file = lto_obj_file_open (fnames[i], false);
284238fd1498Szrj       if (!current_lto_file)
284338fd1498Szrj 	break;
284438fd1498Szrj 
284538fd1498Szrj       file_data = lto_file_read (current_lto_file, resolution, &count);
284638fd1498Szrj       if (!file_data)
284738fd1498Szrj 	{
284838fd1498Szrj 	  lto_obj_file_close (current_lto_file);
284938fd1498Szrj 	  free (current_lto_file);
285038fd1498Szrj 	  current_lto_file = NULL;
285138fd1498Szrj 	  break;
285238fd1498Szrj 	}
285338fd1498Szrj 
285438fd1498Szrj       decl_data[last_file_ix++] = file_data;
285538fd1498Szrj 
285638fd1498Szrj       lto_obj_file_close (current_lto_file);
285738fd1498Szrj       free (current_lto_file);
285838fd1498Szrj       current_lto_file = NULL;
285938fd1498Szrj     }
286038fd1498Szrj 
286138fd1498Szrj   lto_flatten_files (decl_data, count, last_file_ix);
286238fd1498Szrj   lto_stats.num_input_files = count;
286338fd1498Szrj   ggc_free(decl_data);
286438fd1498Szrj   real_file_decl_data = NULL;
286538fd1498Szrj 
286638fd1498Szrj   if (resolution_file_name)
286738fd1498Szrj     fclose (resolution);
286838fd1498Szrj 
286938fd1498Szrj   /* Show the LTO report before launching LTRANS.  */
287038fd1498Szrj   if (flag_lto_report || (flag_wpa && flag_lto_report_wpa))
287138fd1498Szrj     print_lto_report_1 ();
287238fd1498Szrj 
287338fd1498Szrj   /* Free gimple type merging datastructures.  */
287438fd1498Szrj   delete tree_scc_hash;
287538fd1498Szrj   tree_scc_hash = NULL;
287638fd1498Szrj   obstack_free (&tree_scc_hash_obstack, NULL);
287738fd1498Szrj   htab_delete (gimple_canonical_types);
287838fd1498Szrj   gimple_canonical_types = NULL;
287938fd1498Szrj   delete canonical_type_hash_cache;
288038fd1498Szrj   canonical_type_hash_cache = NULL;
288138fd1498Szrj 
288238fd1498Szrj   /* At this stage we know that majority of GGC memory is reachable.
288338fd1498Szrj      Growing the limits prevents unnecesary invocation of GGC.  */
288438fd1498Szrj   ggc_grow ();
288538fd1498Szrj   ggc_collect ();
288638fd1498Szrj 
288738fd1498Szrj   /* Set the hooks so that all of the ipa passes can read in their data.  */
288838fd1498Szrj   lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data);
288938fd1498Szrj 
289038fd1498Szrj   timevar_pop (TV_IPA_LTO_DECL_IN);
289138fd1498Szrj 
289238fd1498Szrj   if (!quiet_flag)
289338fd1498Szrj     fprintf (stderr, "\nReading the callgraph\n");
289438fd1498Szrj 
289538fd1498Szrj   timevar_push (TV_IPA_LTO_CGRAPH_IO);
289638fd1498Szrj   /* Read the symtab.  */
289738fd1498Szrj   input_symtab ();
289838fd1498Szrj 
289938fd1498Szrj   input_offload_tables (!flag_ltrans);
290038fd1498Szrj 
290138fd1498Szrj   /* Store resolutions into the symbol table.  */
290238fd1498Szrj 
290338fd1498Szrj   FOR_EACH_SYMBOL (snode)
290438fd1498Szrj     if (snode->externally_visible && snode->real_symbol_p ()
290538fd1498Szrj 	&& snode->lto_file_data && snode->lto_file_data->resolution_map
290638fd1498Szrj 	&& !is_builtin_fn (snode->decl)
290738fd1498Szrj 	&& !(VAR_P (snode->decl) && DECL_HARD_REGISTER (snode->decl)))
290838fd1498Szrj       {
290938fd1498Szrj 	ld_plugin_symbol_resolution_t *res;
291038fd1498Szrj 
291138fd1498Szrj 	res = snode->lto_file_data->resolution_map->get (snode->decl);
291238fd1498Szrj 	if (!res || *res == LDPR_UNKNOWN)
291338fd1498Szrj 	  {
291438fd1498Szrj 	    if (snode->output_to_lto_symbol_table_p ())
291538fd1498Szrj 	      fatal_error (input_location, "missing resolution data for %s",
291638fd1498Szrj 		           IDENTIFIER_POINTER
291738fd1498Szrj 			     (DECL_ASSEMBLER_NAME (snode->decl)));
291838fd1498Szrj 	  }
291938fd1498Szrj 	else
292038fd1498Szrj           snode->resolution = *res;
292138fd1498Szrj       }
292238fd1498Szrj   for (i = 0; all_file_decl_data[i]; i++)
292338fd1498Szrj     if (all_file_decl_data[i]->resolution_map)
292438fd1498Szrj       {
292538fd1498Szrj         delete all_file_decl_data[i]->resolution_map;
292638fd1498Szrj         all_file_decl_data[i]->resolution_map = NULL;
292738fd1498Szrj       }
292838fd1498Szrj 
292938fd1498Szrj   timevar_pop (TV_IPA_LTO_CGRAPH_IO);
293038fd1498Szrj 
293138fd1498Szrj   if (!quiet_flag)
293238fd1498Szrj     fprintf (stderr, "Merging declarations\n");
293338fd1498Szrj 
293438fd1498Szrj   timevar_push (TV_IPA_LTO_DECL_MERGE);
293538fd1498Szrj   /* Merge global decls.  In ltrans mode we read merged cgraph, we do not
293638fd1498Szrj      need to care about resolving symbols again, we only need to replace
293738fd1498Szrj      duplicated declarations read from the callgraph and from function
293838fd1498Szrj      sections.  */
293938fd1498Szrj   if (!flag_ltrans)
294038fd1498Szrj     {
294138fd1498Szrj       lto_symtab_merge_decls ();
294238fd1498Szrj 
294338fd1498Szrj       /* If there were errors during symbol merging bail out, we have no
294438fd1498Szrj 	 good way to recover here.  */
294538fd1498Szrj       if (seen_error ())
294638fd1498Szrj 	fatal_error (input_location,
294738fd1498Szrj 		     "errors during merging of translation units");
294838fd1498Szrj 
294938fd1498Szrj       /* Fixup all decls.  */
295038fd1498Szrj       lto_fixup_decls (all_file_decl_data);
295138fd1498Szrj     }
295238fd1498Szrj   if (tree_with_vars)
295338fd1498Szrj     ggc_free (tree_with_vars);
295438fd1498Szrj   tree_with_vars = NULL;
295538fd1498Szrj   ggc_collect ();
295638fd1498Szrj 
295738fd1498Szrj   timevar_pop (TV_IPA_LTO_DECL_MERGE);
295838fd1498Szrj   /* Each pass will set the appropriate timer.  */
295938fd1498Szrj 
296038fd1498Szrj   if (!quiet_flag)
296138fd1498Szrj     fprintf (stderr, "Reading summaries\n");
296238fd1498Szrj 
296338fd1498Szrj   /* Read the IPA summary data.  */
296438fd1498Szrj   if (flag_ltrans)
296538fd1498Szrj     ipa_read_optimization_summaries ();
296638fd1498Szrj   else
296738fd1498Szrj     ipa_read_summaries ();
296838fd1498Szrj 
296938fd1498Szrj   for (i = 0; all_file_decl_data[i]; i++)
297038fd1498Szrj     {
297138fd1498Szrj       gcc_assert (all_file_decl_data[i]->symtab_node_encoder);
297238fd1498Szrj       lto_symtab_encoder_delete (all_file_decl_data[i]->symtab_node_encoder);
297338fd1498Szrj       all_file_decl_data[i]->symtab_node_encoder = NULL;
297438fd1498Szrj       lto_free_function_in_decl_state (all_file_decl_data[i]->global_decl_state);
297538fd1498Szrj       all_file_decl_data[i]->global_decl_state = NULL;
297638fd1498Szrj       all_file_decl_data[i]->current_decl_state = NULL;
297738fd1498Szrj     }
297838fd1498Szrj 
297938fd1498Szrj   /* Finally merge the cgraph according to the decl merging decisions.  */
298038fd1498Szrj   timevar_push (TV_IPA_LTO_CGRAPH_MERGE);
298138fd1498Szrj   if (symtab->dump_file)
298238fd1498Szrj     {
298338fd1498Szrj       fprintf (symtab->dump_file, "Before merging:\n");
298438fd1498Szrj       symtab->dump (symtab->dump_file);
298538fd1498Szrj     }
298638fd1498Szrj   if (!flag_ltrans)
298738fd1498Szrj     {
298838fd1498Szrj       lto_symtab_merge_symbols ();
298938fd1498Szrj       /* Removal of unreachable symbols is needed to make verify_symtab to pass;
299038fd1498Szrj 	 we are still having duplicated comdat groups containing local statics.
299138fd1498Szrj 	 We could also just remove them while merging.  */
299238fd1498Szrj       symtab->remove_unreachable_nodes (dump_file);
299338fd1498Szrj     }
299438fd1498Szrj   ggc_collect ();
299538fd1498Szrj   symtab->state = IPA_SSA;
299638fd1498Szrj   /* FIXME: Technically all node removals happening here are useless, because
299738fd1498Szrj      WPA should not stream them.  */
299838fd1498Szrj   if (flag_ltrans)
299938fd1498Szrj     symtab->remove_unreachable_nodes (dump_file);
300038fd1498Szrj 
300138fd1498Szrj   timevar_pop (TV_IPA_LTO_CGRAPH_MERGE);
300238fd1498Szrj 
300338fd1498Szrj   /* Indicate that the cgraph is built and ready.  */
300438fd1498Szrj   symtab->function_flags_ready = true;
300538fd1498Szrj 
300638fd1498Szrj   ggc_free (all_file_decl_data);
300738fd1498Szrj   all_file_decl_data = NULL;
300838fd1498Szrj }
300938fd1498Szrj 
301038fd1498Szrj 
301138fd1498Szrj /* Materialize all the bodies for all the nodes in the callgraph.  */
301238fd1498Szrj 
301338fd1498Szrj static void
materialize_cgraph(void)301438fd1498Szrj materialize_cgraph (void)
301538fd1498Szrj {
301638fd1498Szrj   struct cgraph_node *node;
301738fd1498Szrj   timevar_id_t lto_timer;
301838fd1498Szrj 
301938fd1498Szrj   if (!quiet_flag)
302038fd1498Szrj     fprintf (stderr,
302138fd1498Szrj 	     flag_wpa ? "Materializing decls:" : "Reading function bodies:");
302238fd1498Szrj 
302338fd1498Szrj 
302438fd1498Szrj   FOR_EACH_FUNCTION (node)
302538fd1498Szrj     {
302638fd1498Szrj       if (node->lto_file_data)
302738fd1498Szrj 	{
302838fd1498Szrj 	  lto_materialize_function (node);
302938fd1498Szrj 	  lto_stats.num_input_cgraph_nodes++;
303038fd1498Szrj 	}
303138fd1498Szrj     }
303238fd1498Szrj 
303338fd1498Szrj 
303438fd1498Szrj   /* Start the appropriate timer depending on the mode that we are
303538fd1498Szrj      operating in.  */
303638fd1498Szrj   lto_timer = (flag_wpa) ? TV_WHOPR_WPA
303738fd1498Szrj 	      : (flag_ltrans) ? TV_WHOPR_LTRANS
303838fd1498Szrj 	      : TV_LTO;
303938fd1498Szrj   timevar_push (lto_timer);
304038fd1498Szrj 
304138fd1498Szrj   current_function_decl = NULL;
304238fd1498Szrj   set_cfun (NULL);
304338fd1498Szrj 
304438fd1498Szrj   if (!quiet_flag)
304538fd1498Szrj     fprintf (stderr, "\n");
304638fd1498Szrj 
304738fd1498Szrj   timevar_pop (lto_timer);
304838fd1498Szrj }
304938fd1498Szrj 
305038fd1498Szrj 
305138fd1498Szrj /* Show various memory usage statistics related to LTO.  */
305238fd1498Szrj static void
print_lto_report_1(void)305338fd1498Szrj print_lto_report_1 (void)
305438fd1498Szrj {
305538fd1498Szrj   const char *pfx = (flag_lto) ? "LTO" : (flag_wpa) ? "WPA" : "LTRANS";
305638fd1498Szrj   fprintf (stderr, "%s statistics\n", pfx);
305738fd1498Szrj 
305838fd1498Szrj   fprintf (stderr, "[%s] read %lu SCCs of average size %f\n",
305938fd1498Szrj 	   pfx, num_sccs_read, total_scc_size / (double)num_sccs_read);
306038fd1498Szrj   fprintf (stderr, "[%s] %lu tree bodies read in total\n", pfx, total_scc_size);
306138fd1498Szrj   if (flag_wpa && tree_scc_hash)
306238fd1498Szrj     {
306338fd1498Szrj       fprintf (stderr, "[%s] tree SCC table: size %ld, %ld elements, "
306438fd1498Szrj 	       "collision ratio: %f\n", pfx,
306538fd1498Szrj 	       (long) tree_scc_hash->size (),
306638fd1498Szrj 	       (long) tree_scc_hash->elements (),
306738fd1498Szrj 	       tree_scc_hash->collisions ());
306838fd1498Szrj       hash_table<tree_scc_hasher>::iterator hiter;
306938fd1498Szrj       tree_scc *scc, *max_scc = NULL;
307038fd1498Szrj       unsigned max_length = 0;
307138fd1498Szrj       FOR_EACH_HASH_TABLE_ELEMENT (*tree_scc_hash, scc, x, hiter)
307238fd1498Szrj 	{
307338fd1498Szrj 	  unsigned length = 0;
307438fd1498Szrj 	  tree_scc *s = scc;
307538fd1498Szrj 	  for (; s; s = s->next)
307638fd1498Szrj 	    length++;
307738fd1498Szrj 	  if (length > max_length)
307838fd1498Szrj 	    {
307938fd1498Szrj 	      max_length = length;
308038fd1498Szrj 	      max_scc = scc;
308138fd1498Szrj 	    }
308238fd1498Szrj 	}
308338fd1498Szrj       fprintf (stderr, "[%s] tree SCC max chain length %u (size %u)\n",
308438fd1498Szrj 	       pfx, max_length, max_scc->len);
308538fd1498Szrj       fprintf (stderr, "[%s] Compared %lu SCCs, %lu collisions (%f)\n", pfx,
308638fd1498Szrj 	       num_scc_compares, num_scc_compare_collisions,
308738fd1498Szrj 	       num_scc_compare_collisions / (double) num_scc_compares);
308838fd1498Szrj       fprintf (stderr, "[%s] Merged %lu SCCs\n", pfx, num_sccs_merged);
308938fd1498Szrj       fprintf (stderr, "[%s] Merged %lu tree bodies\n", pfx,
309038fd1498Szrj 	       total_scc_size_merged);
309138fd1498Szrj       fprintf (stderr, "[%s] Merged %lu types\n", pfx, num_merged_types);
309238fd1498Szrj       fprintf (stderr, "[%s] %lu types prevailed (%lu associated trees)\n",
309338fd1498Szrj 	       pfx, num_prevailing_types, num_type_scc_trees);
309438fd1498Szrj       fprintf (stderr, "[%s] GIMPLE canonical type table: size %ld, "
309538fd1498Szrj 	       "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
309638fd1498Szrj 	       (long) htab_size (gimple_canonical_types),
309738fd1498Szrj 	       (long) htab_elements (gimple_canonical_types),
309838fd1498Szrj 	       (long) gimple_canonical_types->searches,
309938fd1498Szrj 	       (long) gimple_canonical_types->collisions,
310038fd1498Szrj 	       htab_collisions (gimple_canonical_types));
310138fd1498Szrj       fprintf (stderr, "[%s] GIMPLE canonical type pointer-map: "
310238fd1498Szrj 	       "%lu elements, %ld searches\n", pfx,
310338fd1498Szrj 	       num_canonical_type_hash_entries,
310438fd1498Szrj 	       num_canonical_type_hash_queries);
310538fd1498Szrj     }
310638fd1498Szrj 
310738fd1498Szrj   print_lto_report (pfx);
310838fd1498Szrj }
310938fd1498Szrj 
311038fd1498Szrj /* Perform whole program analysis (WPA) on the callgraph and write out the
311138fd1498Szrj    optimization plan.  */
311238fd1498Szrj 
311338fd1498Szrj static void
do_whole_program_analysis(void)311438fd1498Szrj do_whole_program_analysis (void)
311538fd1498Szrj {
311638fd1498Szrj   symtab_node *node;
311738fd1498Szrj 
311838fd1498Szrj   lto_parallelism = 1;
311938fd1498Szrj 
312038fd1498Szrj   /* TODO: jobserver communicatoin is not supported, yet.  */
312138fd1498Szrj   if (!strcmp (flag_wpa, "jobserver"))
312238fd1498Szrj     lto_parallelism = -1;
312338fd1498Szrj   else
312438fd1498Szrj     {
312538fd1498Szrj       lto_parallelism = atoi (flag_wpa);
312638fd1498Szrj       if (lto_parallelism <= 0)
312738fd1498Szrj 	lto_parallelism = 0;
312838fd1498Szrj     }
312938fd1498Szrj 
313038fd1498Szrj   timevar_start (TV_PHASE_OPT_GEN);
313138fd1498Szrj 
313238fd1498Szrj   /* Note that since we are in WPA mode, materialize_cgraph will not
313338fd1498Szrj      actually read in all the function bodies.  It only materializes
313438fd1498Szrj      the decls and cgraph nodes so that analysis can be performed.  */
313538fd1498Szrj   materialize_cgraph ();
313638fd1498Szrj 
313738fd1498Szrj   /* Reading in the cgraph uses different timers, start timing WPA now.  */
313838fd1498Szrj   timevar_push (TV_WHOPR_WPA);
313938fd1498Szrj 
314038fd1498Szrj   if (pre_ipa_mem_report)
314138fd1498Szrj     {
314238fd1498Szrj       fprintf (stderr, "Memory consumption before IPA\n");
314338fd1498Szrj       dump_memory_report (false);
314438fd1498Szrj     }
314538fd1498Szrj 
314638fd1498Szrj   symtab->function_flags_ready = true;
314738fd1498Szrj 
314838fd1498Szrj   if (symtab->dump_file)
314938fd1498Szrj     symtab->dump (symtab->dump_file);
315038fd1498Szrj   bitmap_obstack_initialize (NULL);
315138fd1498Szrj   symtab->state = IPA_SSA;
315238fd1498Szrj 
315338fd1498Szrj   execute_ipa_pass_list (g->get_passes ()->all_regular_ipa_passes);
315438fd1498Szrj 
315538fd1498Szrj   /* When WPA analysis raises errors, do not bother to output anything.  */
315638fd1498Szrj   if (seen_error ())
315738fd1498Szrj     return;
315838fd1498Szrj 
315938fd1498Szrj   if (symtab->dump_file)
316038fd1498Szrj     {
316138fd1498Szrj       fprintf (symtab->dump_file, "Optimized ");
316238fd1498Szrj       symtab->dump (symtab->dump_file);
316338fd1498Szrj     }
316438fd1498Szrj 
316538fd1498Szrj   symtab_node::checking_verify_symtab_nodes ();
316638fd1498Szrj   bitmap_obstack_release (NULL);
316738fd1498Szrj 
316838fd1498Szrj   /* We are about to launch the final LTRANS phase, stop the WPA timer.  */
316938fd1498Szrj   timevar_pop (TV_WHOPR_WPA);
317038fd1498Szrj 
317138fd1498Szrj   timevar_push (TV_WHOPR_PARTITIONING);
317238fd1498Szrj   if (flag_lto_partition == LTO_PARTITION_1TO1)
317338fd1498Szrj     lto_1_to_1_map ();
317438fd1498Szrj   else if (flag_lto_partition == LTO_PARTITION_MAX)
317538fd1498Szrj     lto_max_map ();
317638fd1498Szrj   else if (flag_lto_partition == LTO_PARTITION_ONE)
317738fd1498Szrj     lto_balanced_map (1, INT_MAX);
317838fd1498Szrj   else if (flag_lto_partition == LTO_PARTITION_BALANCED)
317938fd1498Szrj     lto_balanced_map (PARAM_VALUE (PARAM_LTO_PARTITIONS),
318038fd1498Szrj 		      PARAM_VALUE (MAX_PARTITION_SIZE));
318138fd1498Szrj   else
318238fd1498Szrj     gcc_unreachable ();
318338fd1498Szrj 
318438fd1498Szrj   /* Inline summaries are needed for balanced partitioning.  Free them now so
318538fd1498Szrj      the memory can be used for streamer caches.  */
318638fd1498Szrj   ipa_free_fn_summary ();
318738fd1498Szrj 
318838fd1498Szrj   /* AUX pointers are used by partitioning code to bookkeep number of
318938fd1498Szrj      partitions symbol is in.  This is no longer needed.  */
319038fd1498Szrj   FOR_EACH_SYMBOL (node)
319138fd1498Szrj     node->aux = NULL;
319238fd1498Szrj 
319338fd1498Szrj   lto_stats.num_cgraph_partitions += ltrans_partitions.length ();
319438fd1498Szrj 
319538fd1498Szrj   /* Find out statics that need to be promoted
319638fd1498Szrj      to globals with hidden visibility because they are accessed from multiple
319738fd1498Szrj      partitions.  */
319838fd1498Szrj   lto_promote_cross_file_statics ();
319938fd1498Szrj   timevar_pop (TV_WHOPR_PARTITIONING);
320038fd1498Szrj 
320138fd1498Szrj   timevar_stop (TV_PHASE_OPT_GEN);
320238fd1498Szrj 
320338fd1498Szrj   /* Collect a last time - in lto_wpa_write_files we may end up forking
320438fd1498Szrj      with the idea that this doesn't increase memory usage.  So we
320538fd1498Szrj      absoultely do not want to collect after that.  */
320638fd1498Szrj   ggc_collect ();
320738fd1498Szrj 
320838fd1498Szrj   timevar_start (TV_PHASE_STREAM_OUT);
320938fd1498Szrj   if (!quiet_flag)
321038fd1498Szrj     {
321138fd1498Szrj       fprintf (stderr, "\nStreaming out");
321238fd1498Szrj       fflush (stderr);
321338fd1498Szrj     }
321438fd1498Szrj   lto_wpa_write_files ();
321538fd1498Szrj   if (!quiet_flag)
321638fd1498Szrj     fprintf (stderr, "\n");
321738fd1498Szrj   timevar_stop (TV_PHASE_STREAM_OUT);
321838fd1498Szrj 
321938fd1498Szrj   if (post_ipa_mem_report)
322038fd1498Szrj     {
322138fd1498Szrj       fprintf (stderr, "Memory consumption after IPA\n");
322238fd1498Szrj       dump_memory_report (false);
322338fd1498Szrj     }
322438fd1498Szrj 
322538fd1498Szrj   /* Show the LTO report before launching LTRANS.  */
322638fd1498Szrj   if (flag_lto_report || (flag_wpa && flag_lto_report_wpa))
322738fd1498Szrj     print_lto_report_1 ();
322838fd1498Szrj   if (mem_report_wpa)
322938fd1498Szrj     dump_memory_report (true);
323038fd1498Szrj }
323138fd1498Szrj 
323238fd1498Szrj 
323338fd1498Szrj static GTY(()) tree lto_eh_personality_decl;
323438fd1498Szrj 
323538fd1498Szrj /* Return the LTO personality function decl.  */
323638fd1498Szrj 
323738fd1498Szrj tree
lto_eh_personality(void)323838fd1498Szrj lto_eh_personality (void)
323938fd1498Szrj {
324038fd1498Szrj   if (!lto_eh_personality_decl)
324138fd1498Szrj     {
324238fd1498Szrj       /* Use the first personality DECL for our personality if we don't
324338fd1498Szrj 	 support multiple ones.  This ensures that we don't artificially
324438fd1498Szrj 	 create the need for them in a single-language program.  */
324538fd1498Szrj       if (first_personality_decl && !dwarf2out_do_cfi_asm ())
324638fd1498Szrj 	lto_eh_personality_decl = first_personality_decl;
324738fd1498Szrj       else
324838fd1498Szrj 	lto_eh_personality_decl = lhd_gcc_personality ();
324938fd1498Szrj     }
325038fd1498Szrj 
325138fd1498Szrj   return lto_eh_personality_decl;
325238fd1498Szrj }
325338fd1498Szrj 
325438fd1498Szrj /* Set the process name based on the LTO mode. */
325538fd1498Szrj 
325638fd1498Szrj static void
lto_process_name(void)325738fd1498Szrj lto_process_name (void)
325838fd1498Szrj {
325938fd1498Szrj   if (flag_lto)
326038fd1498Szrj     setproctitle ("lto1-lto");
326138fd1498Szrj   if (flag_wpa)
326238fd1498Szrj     setproctitle ("lto1-wpa");
326338fd1498Szrj   if (flag_ltrans)
326438fd1498Szrj     setproctitle ("lto1-ltrans");
326538fd1498Szrj }
326638fd1498Szrj 
326738fd1498Szrj 
326838fd1498Szrj /* Initialize the LTO front end.  */
326938fd1498Szrj 
327038fd1498Szrj static void
lto_init(void)327138fd1498Szrj lto_init (void)
327238fd1498Szrj {
327338fd1498Szrj   lto_process_name ();
327438fd1498Szrj   lto_streamer_hooks_init ();
327538fd1498Szrj   lto_reader_init ();
327638fd1498Szrj   lto_set_in_hooks (NULL, get_section_data, free_section_data);
327738fd1498Szrj   memset (&lto_stats, 0, sizeof (lto_stats));
327838fd1498Szrj   bitmap_obstack_initialize (NULL);
327938fd1498Szrj   gimple_register_cfg_hooks ();
328038fd1498Szrj #ifndef ACCEL_COMPILER
328138fd1498Szrj   unsigned char *table
328238fd1498Szrj     = ggc_vec_alloc<unsigned char> (MAX_MACHINE_MODE);
328338fd1498Szrj   for (int m = 0; m < MAX_MACHINE_MODE; m++)
328438fd1498Szrj     table[m] = m;
328538fd1498Szrj   lto_mode_identity_table = table;
328638fd1498Szrj #endif
328738fd1498Szrj }
328838fd1498Szrj 
328938fd1498Szrj /* Create artificial pointers for "omp declare target link" vars.  */
329038fd1498Szrj 
329138fd1498Szrj static void
offload_handle_link_vars(void)329238fd1498Szrj offload_handle_link_vars (void)
329338fd1498Szrj {
329438fd1498Szrj #ifdef ACCEL_COMPILER
329538fd1498Szrj   varpool_node *var;
329638fd1498Szrj   FOR_EACH_VARIABLE (var)
329738fd1498Szrj     if (lookup_attribute ("omp declare target link",
329838fd1498Szrj 			  DECL_ATTRIBUTES (var->decl)))
329938fd1498Szrj       {
330038fd1498Szrj 	tree type = build_pointer_type (TREE_TYPE (var->decl));
330138fd1498Szrj 	tree link_ptr_var = make_node (VAR_DECL);
330238fd1498Szrj 	TREE_TYPE (link_ptr_var) = type;
330338fd1498Szrj 	TREE_USED (link_ptr_var) = 1;
330438fd1498Szrj 	TREE_STATIC (link_ptr_var) = 1;
330538fd1498Szrj 	SET_DECL_MODE (link_ptr_var, TYPE_MODE (type));
330638fd1498Szrj 	DECL_SIZE (link_ptr_var) = TYPE_SIZE (type);
330738fd1498Szrj 	DECL_SIZE_UNIT (link_ptr_var) = TYPE_SIZE_UNIT (type);
330838fd1498Szrj 	DECL_ARTIFICIAL (link_ptr_var) = 1;
330938fd1498Szrj 	tree var_name = DECL_ASSEMBLER_NAME (var->decl);
331038fd1498Szrj 	char *new_name
331138fd1498Szrj 	  = ACONCAT ((IDENTIFIER_POINTER (var_name), "_linkptr", NULL));
331238fd1498Szrj 	DECL_NAME (link_ptr_var) = get_identifier (new_name);
331338fd1498Szrj 	SET_DECL_ASSEMBLER_NAME (link_ptr_var, DECL_NAME (link_ptr_var));
331438fd1498Szrj 	SET_DECL_VALUE_EXPR (var->decl, build_simple_mem_ref (link_ptr_var));
331538fd1498Szrj 	DECL_HAS_VALUE_EXPR_P (var->decl) = 1;
331638fd1498Szrj       }
331738fd1498Szrj #endif
331838fd1498Szrj }
331938fd1498Szrj 
332038fd1498Szrj 
332138fd1498Szrj /* Main entry point for the GIMPLE front end.  This front end has
332238fd1498Szrj    three main personalities:
332338fd1498Szrj 
332438fd1498Szrj    - LTO (-flto).  All the object files on the command line are
332538fd1498Szrj      loaded in memory and processed as a single translation unit.
332638fd1498Szrj      This is the traditional link-time optimization behavior.
332738fd1498Szrj 
332838fd1498Szrj    - WPA (-fwpa).  Only the callgraph and summary information for
332938fd1498Szrj      files in the command file are loaded.  A single callgraph
333038fd1498Szrj      (without function bodies) is instantiated for the whole set of
333138fd1498Szrj      files.  IPA passes are only allowed to analyze the call graph
333238fd1498Szrj      and make transformation decisions.  The callgraph is
333338fd1498Szrj      partitioned, each partition is written to a new object file
333438fd1498Szrj      together with the transformation decisions.
333538fd1498Szrj 
333638fd1498Szrj    - LTRANS (-fltrans).  Similar to -flto but it prevents the IPA
333738fd1498Szrj      summary files from running again.  Since WPA computed summary
333838fd1498Szrj      information and decided what transformations to apply, LTRANS
333938fd1498Szrj      simply applies them.  */
334038fd1498Szrj 
334138fd1498Szrj void
lto_main(void)334238fd1498Szrj lto_main (void)
334338fd1498Szrj {
334438fd1498Szrj   /* LTO is called as a front end, even though it is not a front end.
334538fd1498Szrj      Because it is called as a front end, TV_PHASE_PARSING and
334638fd1498Szrj      TV_PARSE_GLOBAL are active, and we need to turn them off while
334738fd1498Szrj      doing LTO.  Later we turn them back on so they are active up in
334838fd1498Szrj      toplev.c.  */
334938fd1498Szrj   timevar_pop (TV_PARSE_GLOBAL);
335038fd1498Szrj   timevar_stop (TV_PHASE_PARSING);
335138fd1498Szrj 
335238fd1498Szrj   timevar_start (TV_PHASE_SETUP);
335338fd1498Szrj 
335438fd1498Szrj   /* Initialize the LTO front end.  */
335538fd1498Szrj   lto_init ();
335638fd1498Szrj 
335738fd1498Szrj   timevar_stop (TV_PHASE_SETUP);
335838fd1498Szrj   timevar_start (TV_PHASE_STREAM_IN);
335938fd1498Szrj 
336038fd1498Szrj   /* Read all the symbols and call graph from all the files in the
336138fd1498Szrj      command line.  */
336238fd1498Szrj   read_cgraph_and_symbols (num_in_fnames, in_fnames);
336338fd1498Szrj 
336438fd1498Szrj   timevar_stop (TV_PHASE_STREAM_IN);
336538fd1498Szrj 
336638fd1498Szrj   if (!seen_error ())
336738fd1498Szrj     {
336838fd1498Szrj       offload_handle_link_vars ();
336938fd1498Szrj 
337038fd1498Szrj       /* If WPA is enabled analyze the whole call graph and create an
337138fd1498Szrj 	 optimization plan.  Otherwise, read in all the function
337238fd1498Szrj 	 bodies and continue with optimization.  */
337338fd1498Szrj       if (flag_wpa)
337438fd1498Szrj 	do_whole_program_analysis ();
337538fd1498Szrj       else
337638fd1498Szrj 	{
337738fd1498Szrj 	  timevar_start (TV_PHASE_OPT_GEN);
337838fd1498Szrj 
337938fd1498Szrj 	  materialize_cgraph ();
338038fd1498Szrj 	  if (!flag_ltrans)
338138fd1498Szrj 	    lto_promote_statics_nonwpa ();
338238fd1498Szrj 
338338fd1498Szrj 	  /* Annotate the CU DIE and mark the early debug phase as finished.  */
338438fd1498Szrj 	  debug_hooks->early_finish ("<artificial>");
338538fd1498Szrj 
338638fd1498Szrj 	  /* Let the middle end know that we have read and merged all of
338738fd1498Szrj 	     the input files.  */
338838fd1498Szrj 	  symtab->compile ();
338938fd1498Szrj 
339038fd1498Szrj 	  timevar_stop (TV_PHASE_OPT_GEN);
339138fd1498Szrj 
339238fd1498Szrj 	  /* FIXME lto, if the processes spawned by WPA fail, we miss
339338fd1498Szrj 	     the chance to print WPA's report, so WPA will call
339438fd1498Szrj 	     print_lto_report before launching LTRANS.  If LTRANS was
339538fd1498Szrj 	     launched directly by the driver we would not need to do
339638fd1498Szrj 	     this.  */
339738fd1498Szrj 	  if (flag_lto_report || (flag_wpa && flag_lto_report_wpa))
339838fd1498Szrj 	    print_lto_report_1 ();
339938fd1498Szrj 	}
340038fd1498Szrj     }
340138fd1498Szrj 
340238fd1498Szrj   /* Here we make LTO pretend to be a parser.  */
340338fd1498Szrj   timevar_start (TV_PHASE_PARSING);
340438fd1498Szrj   timevar_push (TV_PARSE_GLOBAL);
340538fd1498Szrj }
340638fd1498Szrj 
340738fd1498Szrj #include "gt-lto-lto.h"
3408