xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/lto-streamer.c (revision 867d70fc718005c0918b8b8b2f9d7f2d52d0a0db)
1 /* Miscellaneous utilities for GIMPLE streaming.  Things that are used
2    in both input and output are here.
3 
4    Copyright (C) 2009-2019 Free Software Foundation, Inc.
5    Contributed by Doug Kwan <dougkwan@google.com>
6 
7 This file is part of GCC.
8 
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13 
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22 
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "backend.h"
27 #include "tree.h"
28 #include "gimple.h"
29 #include "tree-streamer.h"
30 #include "cgraph.h"
31 #include "lto-streamer.h"
32 #include "toplev.h"
33 #include "lto-section-names.h"
34 
35 /* Statistics gathered during LTO, WPA and LTRANS.  */
36 struct lto_stats_d lto_stats;
37 
38 /* LTO uses bitmaps with different life-times.  So use a separate
39    obstack for all LTO bitmaps.  */
40 static bitmap_obstack lto_obstack;
41 static bool lto_obstack_initialized;
42 
43 const char *section_name_prefix = LTO_SECTION_NAME_PREFIX;
44 /* Set when streaming LTO for offloading compiler.  */
45 bool lto_stream_offload_p;
46 
47 FILE *streamer_dump_file;
48 
49 /* Return a string representing LTO tag TAG.  */
50 
51 const char *
52 lto_tag_name (enum LTO_tags tag)
53 {
54   if (lto_tag_is_tree_code_p (tag))
55     {
56       /* For tags representing tree nodes, return the name of the
57 	 associated tree code.  */
58       return get_tree_code_name (lto_tag_to_tree_code (tag));
59     }
60 
61   if (lto_tag_is_gimple_code_p (tag))
62     {
63       /* For tags representing gimple statements, return the name of
64 	 the associated gimple code.  */
65       return gimple_code_name[lto_tag_to_gimple_code (tag)];
66     }
67 
68   switch (tag)
69     {
70     case LTO_null:
71       return "LTO_null";
72     case LTO_bb0:
73       return "LTO_bb0";
74     case LTO_bb1:
75       return "LTO_bb1";
76     case LTO_eh_region:
77       return "LTO_eh_region";
78     case LTO_function:
79       return "LTO_function";
80     case LTO_eh_table:
81       return "LTO_eh_table";
82     case LTO_ert_cleanup:
83       return "LTO_ert_cleanup";
84     case LTO_ert_try:
85       return "LTO_ert_try";
86     case LTO_ert_allowed_exceptions:
87       return "LTO_ert_allowed_exceptions";
88     case LTO_ert_must_not_throw:
89       return "LTO_ert_must_not_throw";
90     case LTO_tree_pickle_reference:
91       return "LTO_tree_pickle_reference";
92     case LTO_field_decl_ref:
93       return "LTO_field_decl_ref";
94     case LTO_function_decl_ref:
95       return "LTO_function_decl_ref";
96     case LTO_label_decl_ref:
97       return "LTO_label_decl_ref";
98     case LTO_namespace_decl_ref:
99       return "LTO_namespace_decl_ref";
100     case LTO_result_decl_ref:
101       return "LTO_result_decl_ref";
102     case LTO_ssa_name_ref:
103       return "LTO_ssa_name_ref";
104     case LTO_type_decl_ref:
105       return "LTO_type_decl_ref";
106     case LTO_type_ref:
107       return "LTO_type_ref";
108     case LTO_global_decl_ref:
109       return "LTO_global_decl_ref";
110     default:
111       return "LTO_UNKNOWN";
112     }
113 }
114 
115 
116 /* Allocate a bitmap from heap.  Initializes the LTO obstack if necessary.  */
117 
118 bitmap
119 lto_bitmap_alloc (void)
120 {
121   if (!lto_obstack_initialized)
122     {
123       bitmap_obstack_initialize (&lto_obstack);
124       lto_obstack_initialized = true;
125     }
126   return BITMAP_ALLOC (&lto_obstack);
127 }
128 
129 /* Free bitmap B.  */
130 
131 void
132 lto_bitmap_free (bitmap b)
133 {
134   BITMAP_FREE (b);
135 }
136 
137 
138 /* Get a section name for a particular type or name.  The NAME field
139    is only used if SECTION_TYPE is LTO_section_function_body. For all
140    others it is ignored.  The callee of this function is responsible
141    to free the returned name.  */
142 
143 char *
144 lto_get_section_name (int section_type, const char *name, struct lto_file_decl_data *f)
145 {
146   const char *add;
147   char post[32];
148   const char *sep;
149 
150   if (section_type == LTO_section_function_body)
151     {
152       gcc_assert (name != NULL);
153       if (name[0] == '*')
154 	name++;
155       add = name;
156       sep = "";
157     }
158   else if (section_type < LTO_N_SECTION_TYPES)
159     {
160       add = lto_section_name[section_type];
161       sep = ".";
162     }
163   else
164     internal_error ("bytecode stream: unexpected LTO section %s", name);
165 
166   /* Make the section name unique so that ld -r combining sections
167      doesn't confuse the reader with merged sections.
168 
169      For options don't add a ID, the option reader cannot deal with them
170      and merging should be ok here. */
171   if (section_type == LTO_section_opts)
172     strcpy (post, "");
173   else if (f != NULL)
174     sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, f->id);
175   else
176     sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, get_random_seed (false));
177   return concat (section_name_prefix, sep, add, post, NULL);
178 }
179 
180 
181 /* Show various memory usage statistics related to LTO.  */
182 
183 void
184 print_lto_report (const char *s)
185 {
186   unsigned i;
187 
188   fprintf (stderr, "[%s] # of input files: "
189 	   HOST_WIDE_INT_PRINT_UNSIGNED "\n", s, lto_stats.num_input_files);
190 
191   fprintf (stderr, "[%s] # of input cgraph nodes: "
192 	   HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
193 	   lto_stats.num_input_cgraph_nodes);
194 
195   fprintf (stderr, "[%s] # of function bodies: "
196 	   HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
197 	   lto_stats.num_function_bodies);
198 
199   for (i = 0; i < NUM_TREE_CODES; i++)
200     if (lto_stats.num_trees[i])
201       fprintf (stderr, "[%s] # of '%s' objects read: "
202 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
203 	       get_tree_code_name ((enum tree_code) i), lto_stats.num_trees[i]);
204 
205   if (flag_lto)
206     {
207       fprintf (stderr, "[%s] Compression: "
208 	       HOST_WIDE_INT_PRINT_UNSIGNED " output bytes, "
209 	       HOST_WIDE_INT_PRINT_UNSIGNED " compressed bytes", s,
210 	       lto_stats.num_output_il_bytes,
211 	       lto_stats.num_compressed_il_bytes);
212       if (lto_stats.num_output_il_bytes > 0)
213 	{
214 	  const float dividend = (float) lto_stats.num_compressed_il_bytes;
215 	  const float divisor = (float) lto_stats.num_output_il_bytes;
216 	  fprintf (stderr, " (ratio: %f)", dividend / divisor);
217 	}
218       fprintf (stderr, "\n");
219     }
220 
221   if (flag_wpa)
222     {
223       fprintf (stderr, "[%s] # of output files: "
224 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
225 	       lto_stats.num_output_files);
226 
227       fprintf (stderr, "[%s] # of output symtab nodes: "
228 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
229 	       lto_stats.num_output_symtab_nodes);
230 
231       fprintf (stderr, "[%s] # of output tree pickle references: "
232 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
233 	       lto_stats.num_pickle_refs_output);
234       fprintf (stderr, "[%s] # of output tree bodies: "
235 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
236 	       lto_stats.num_tree_bodies_output);
237 
238       fprintf (stderr, "[%s] # callgraph partitions: "
239 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
240 	       lto_stats.num_cgraph_partitions);
241 
242       fprintf (stderr, "[%s] Compression: "
243 	       HOST_WIDE_INT_PRINT_UNSIGNED " input bytes, "
244 	       HOST_WIDE_INT_PRINT_UNSIGNED " uncompressed bytes", s,
245 	       lto_stats.num_input_il_bytes,
246 	       lto_stats.num_uncompressed_il_bytes);
247       if (lto_stats.num_input_il_bytes > 0)
248 	{
249 	  const float dividend = (float) lto_stats.num_uncompressed_il_bytes;
250 	  const float divisor = (float) lto_stats.num_input_il_bytes;
251 	  fprintf (stderr, " (ratio: %f)", dividend / divisor);
252 	}
253       fprintf (stderr, "\n");
254     }
255 
256   for (i = 0; i < LTO_N_SECTION_TYPES; i++)
257     fprintf (stderr, "[%s] Size of mmap'd section %s: "
258 	     HOST_WIDE_INT_PRINT_UNSIGNED " bytes\n", s,
259 	     lto_section_name[i], lto_stats.section_size[i]);
260 }
261 
262 /* Initialization common to the LTO reader and writer.  */
263 
264 void
265 lto_streamer_init (void)
266 {
267   /* Check that all the TS_* handled by the reader and writer routines
268      match exactly the structures defined in treestruct.def.  When a
269      new TS_* astructure is added, the streamer should be updated to
270      handle it.  */
271   if (flag_checking)
272     streamer_check_handled_ts_structures ();
273 }
274 
275 
276 /* Gate function for all LTO streaming passes.  */
277 
278 bool
279 gate_lto_out (void)
280 {
281   return ((flag_generate_lto || flag_generate_offload || in_lto_p)
282 	  /* Don't bother doing anything if the program has errors.  */
283 	  && !seen_error ());
284 }
285 
286 /* Check that the version MAJOR.MINOR is the correct version number.  */
287 
288 void
289 lto_check_version (int major, int minor, const char *file_name)
290 {
291   if (major != LTO_major_version || minor != LTO_minor_version)
292     fatal_error (input_location,
293 		 "bytecode stream in file %qs generated with LTO version "
294 		 "%d.%d instead of the expected %d.%d",
295 		 file_name,
296 		 major, minor,
297 		 LTO_major_version, LTO_minor_version);
298 }
299 
300 
301 /* Initialize all the streamer hooks used for streaming GIMPLE.  */
302 
303 void
304 lto_streamer_hooks_init (void)
305 {
306   streamer_hooks_init ();
307   streamer_hooks.write_tree = lto_output_tree;
308   streamer_hooks.read_tree = lto_input_tree;
309   streamer_hooks.input_location = lto_input_location;
310   streamer_hooks.output_location = lto_output_location;
311 }
312