1 /* Miscellaneous utilities for GIMPLE streaming.  Things that are used
2    in both input and output are here.
3 
4    Copyright (C) 2009-2020 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 const char *section_name_prefix = LTO_SECTION_NAME_PREFIX;
39 /* Set when streaming LTO for offloading compiler.  */
40 bool lto_stream_offload_p;
41 
42 FILE *streamer_dump_file;
43 
44 /* Return a string representing LTO tag TAG.  */
45 
46 const char *
lto_tag_name(enum LTO_tags tag)47 lto_tag_name (enum LTO_tags tag)
48 {
49   if (lto_tag_is_tree_code_p (tag))
50     {
51       /* For tags representing tree nodes, return the name of the
52 	 associated tree code.  */
53       return get_tree_code_name (lto_tag_to_tree_code (tag));
54     }
55 
56   if (lto_tag_is_gimple_code_p (tag))
57     {
58       /* For tags representing gimple statements, return the name of
59 	 the associated gimple code.  */
60       return gimple_code_name[lto_tag_to_gimple_code (tag)];
61     }
62 
63   switch (tag)
64     {
65     case LTO_null:
66       return "LTO_null";
67     case LTO_bb0:
68       return "LTO_bb0";
69     case LTO_bb1:
70       return "LTO_bb1";
71     case LTO_eh_region:
72       return "LTO_eh_region";
73     case LTO_function:
74       return "LTO_function";
75     case LTO_eh_table:
76       return "LTO_eh_table";
77     case LTO_ert_cleanup:
78       return "LTO_ert_cleanup";
79     case LTO_ert_try:
80       return "LTO_ert_try";
81     case LTO_ert_allowed_exceptions:
82       return "LTO_ert_allowed_exceptions";
83     case LTO_ert_must_not_throw:
84       return "LTO_ert_must_not_throw";
85     case LTO_tree_pickle_reference:
86       return "LTO_tree_pickle_reference";
87     case LTO_field_decl_ref:
88       return "LTO_field_decl_ref";
89     case LTO_function_decl_ref:
90       return "LTO_function_decl_ref";
91     case LTO_label_decl_ref:
92       return "LTO_label_decl_ref";
93     case LTO_namespace_decl_ref:
94       return "LTO_namespace_decl_ref";
95     case LTO_result_decl_ref:
96       return "LTO_result_decl_ref";
97     case LTO_ssa_name_ref:
98       return "LTO_ssa_name_ref";
99     case LTO_type_decl_ref:
100       return "LTO_type_decl_ref";
101     case LTO_type_ref:
102       return "LTO_type_ref";
103     case LTO_global_decl_ref:
104       return "LTO_global_decl_ref";
105     default:
106       return "LTO_UNKNOWN";
107     }
108 }
109 
110 
111 /* Get a section name for a particular type or name.  The NAME field
112    is only used if SECTION_TYPE is LTO_section_function_body. For all
113    others it is ignored.  The callee of this function is responsible
114    to free the returned name.  */
115 
116 char *
lto_get_section_name(int section_type,const char * name,int node_order,struct lto_file_decl_data * f)117 lto_get_section_name (int section_type, const char *name,
118 		      int node_order, struct lto_file_decl_data *f)
119 {
120   const char *add;
121   char post[32];
122   const char *sep;
123 
124   if (section_type == LTO_section_function_body)
125     {
126       gcc_assert (name != NULL);
127       if (name[0] == '*')
128 	name++;
129 
130       char *buffer = (char *)xmalloc (strlen (name) + 32);
131       sprintf (buffer, "%s.%d", name, node_order);
132 
133       add = buffer;
134       sep = "";
135     }
136   else if (section_type < LTO_N_SECTION_TYPES)
137     {
138       add = lto_section_name[section_type];
139       sep = ".";
140     }
141   else
142     internal_error ("bytecode stream: unexpected LTO section %s", name);
143 
144   /* Make the section name unique so that ld -r combining sections
145      doesn't confuse the reader with merged sections.
146 
147      For options don't add a ID, the option reader cannot deal with them
148      and merging should be ok here. */
149   if (section_type == LTO_section_opts)
150     strcpy (post, "");
151   else if (f != NULL)
152     sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, f->id);
153   else
154     sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, get_random_seed (false));
155   return concat (section_name_prefix, sep, add, post, NULL);
156 }
157 
158 
159 /* Show various memory usage statistics related to LTO.  */
160 
161 void
print_lto_report(const char * s)162 print_lto_report (const char *s)
163 {
164   unsigned i;
165 
166   fprintf (stderr, "[%s] # of input files: "
167 	   HOST_WIDE_INT_PRINT_UNSIGNED "\n", s, lto_stats.num_input_files);
168 
169   fprintf (stderr, "[%s] # of input cgraph nodes: "
170 	   HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
171 	   lto_stats.num_input_cgraph_nodes);
172 
173   fprintf (stderr, "[%s] # of function bodies: "
174 	   HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
175 	   lto_stats.num_function_bodies);
176 
177   for (i = 0; i < NUM_TREE_CODES; i++)
178     if (lto_stats.num_trees[i])
179       fprintf (stderr, "[%s] # of '%s' objects read: "
180 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
181 	       get_tree_code_name ((enum tree_code) i), lto_stats.num_trees[i]);
182 
183   if (flag_lto)
184     {
185       fprintf (stderr, "[%s] Compression: "
186 	       HOST_WIDE_INT_PRINT_UNSIGNED " output bytes, "
187 	       HOST_WIDE_INT_PRINT_UNSIGNED " compressed bytes", s,
188 	       lto_stats.num_output_il_bytes,
189 	       lto_stats.num_compressed_il_bytes);
190       if (lto_stats.num_output_il_bytes > 0)
191 	{
192 	  const float dividend = (float) lto_stats.num_compressed_il_bytes;
193 	  const float divisor = (float) lto_stats.num_output_il_bytes;
194 	  fprintf (stderr, " (ratio: %f)", dividend / divisor);
195 	}
196       fprintf (stderr, "\n");
197     }
198 
199   if (flag_wpa)
200     {
201       fprintf (stderr, "[%s] # of output files: "
202 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
203 	       lto_stats.num_output_files);
204 
205       fprintf (stderr, "[%s] # of output symtab nodes: "
206 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
207 	       lto_stats.num_output_symtab_nodes);
208 
209       fprintf (stderr, "[%s] # of output tree pickle references: "
210 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
211 	       lto_stats.num_pickle_refs_output);
212       fprintf (stderr, "[%s] # of output tree bodies: "
213 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
214 	       lto_stats.num_tree_bodies_output);
215 
216       fprintf (stderr, "[%s] # callgraph partitions: "
217 	       HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
218 	       lto_stats.num_cgraph_partitions);
219 
220       fprintf (stderr, "[%s] Compression: "
221 	       HOST_WIDE_INT_PRINT_UNSIGNED " input bytes, "
222 	       HOST_WIDE_INT_PRINT_UNSIGNED " uncompressed bytes", s,
223 	       lto_stats.num_input_il_bytes,
224 	       lto_stats.num_uncompressed_il_bytes);
225       if (lto_stats.num_input_il_bytes > 0)
226 	{
227 	  const float dividend = (float) lto_stats.num_uncompressed_il_bytes;
228 	  const float divisor = (float) lto_stats.num_input_il_bytes;
229 	  fprintf (stderr, " (ratio: %f)", dividend / divisor);
230 	}
231       fprintf (stderr, "\n");
232     }
233 
234   for (i = 0; i < LTO_N_SECTION_TYPES; i++)
235     fprintf (stderr, "[%s] Size of mmap'd section %s: "
236 	     HOST_WIDE_INT_PRINT_UNSIGNED " bytes\n", s,
237 	     lto_section_name[i], lto_stats.section_size[i]);
238 }
239 
240 /* Initialization common to the LTO reader and writer.  */
241 
242 void
lto_streamer_init(void)243 lto_streamer_init (void)
244 {
245   /* Check that all the TS_* handled by the reader and writer routines
246      match exactly the structures defined in treestruct.def.  When a
247      new TS_* astructure is added, the streamer should be updated to
248      handle it.  */
249   if (flag_checking)
250     streamer_check_handled_ts_structures ();
251 }
252 
253 
254 /* Gate function for all LTO streaming passes.  */
255 
256 bool
gate_lto_out(void)257 gate_lto_out (void)
258 {
259   return ((flag_generate_lto || flag_generate_offload || in_lto_p)
260 	  /* Don't bother doing anything if the program has errors.  */
261 	  && !seen_error ());
262 }
263 
264 /* Check that the version MAJOR.MINOR is the correct version number.  */
265 
266 void
lto_check_version(int major,int minor,const char * file_name)267 lto_check_version (int major, int minor, const char *file_name)
268 {
269   if (major != LTO_major_version || minor != LTO_minor_version)
270     fatal_error (input_location,
271 		 "bytecode stream in file %qs generated with LTO version "
272 		 "%d.%d instead of the expected %d.%d",
273 		 file_name,
274 		 major, minor,
275 		 LTO_major_version, LTO_minor_version);
276 }
277 
278 
279 /* Initialize all the streamer hooks used for streaming GIMPLE.  */
280 
281 void
lto_streamer_hooks_init(void)282 lto_streamer_hooks_init (void)
283 {
284   streamer_hooks_init ();
285   streamer_hooks.write_tree = lto_output_tree;
286   streamer_hooks.read_tree = lto_input_tree;
287   streamer_hooks.input_location = lto_input_location;
288   streamer_hooks.output_location = lto_output_location;
289 }
290