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 (§ion_list, 0, sizeof (struct lto_section_list));
215838fd1498Szrj section_hash_table = lto_obj_build_section_table (file, §ion_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 (<o_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