1 /* Functions for writing LTO sections.
2 
3    Copyright (C) 2009-2020 Free Software Foundation, Inc.
4    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12 
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "backend.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "gimple.h"
29 #include "cgraph.h"
30 #include "data-streamer.h"
31 #include "langhooks.h"
32 #include "lto-compress.h"
33 #include "print-tree.h"
34 
35 static vec<lto_out_decl_state_ptr> decl_state_stack;
36 
37 /* List of out decl states used by functions.  We use this to
38    generate the decl directory later. */
39 
40 vec<lto_out_decl_state_ptr> lto_function_decl_states;
41 
42 
43 /*****************************************************************************
44    Output routines shared by all of the serialization passes.
45 *****************************************************************************/
46 
47 
48 /* Flush compressed stream data function, sends NUM_CHARS from CHARS
49    to the append lang hook, OPAQUE is currently always NULL.  */
50 
51 static void
lto_append_data(const char * chars,unsigned int num_chars,void * opaque)52 lto_append_data (const char *chars, unsigned int num_chars, void *opaque)
53 {
54   gcc_assert (opaque == NULL);
55   lang_hooks.lto.append_data (chars, num_chars, opaque);
56 }
57 
58 /* Pointer to the current compression stream.  */
59 
60 static struct lto_compression_stream *compression_stream = NULL;
61 
62 /* Begin a new output section named NAME. If COMPRESS is true, zlib compress
63    the section. */
64 
65 void
lto_begin_section(const char * name,bool compress)66 lto_begin_section (const char *name, bool compress)
67 {
68   lang_hooks.lto.begin_section (name);
69 
70   if (streamer_dump_file)
71     {
72       if (flag_dump_unnumbered || flag_dump_noaddr)
73 	  fprintf (streamer_dump_file, "Creating %ssection\n",
74 		   compress ? "compressed " : "");
75 	else
76 	  fprintf (streamer_dump_file, "Creating %ssection %s\n",
77 		   compress ? "compressed " : "", name);
78     }
79   gcc_assert (compression_stream == NULL);
80   if (compress)
81     compression_stream = lto_start_compression (lto_append_data, NULL);
82 }
83 
84 
85 /* End the current output section.  */
86 
87 void
lto_end_section(void)88 lto_end_section (void)
89 {
90   if (compression_stream)
91     {
92       lto_end_compression (compression_stream);
93       compression_stream = NULL;
94     }
95   lang_hooks.lto.end_section ();
96 }
97 
98 /* Write SIZE bytes starting at DATA to the assembler.  */
99 
100 void
lto_write_data(const void * data,unsigned int size)101 lto_write_data (const void *data, unsigned int size)
102 {
103   if (compression_stream)
104     lto_compress_block (compression_stream, (const char *)data, size);
105   else
106     lang_hooks.lto.append_data ((const char *)data, size, NULL);
107 }
108 
109 /* Write SIZE bytes starting at DATA to the assembler.  */
110 
111 void
lto_write_raw_data(const void * data,unsigned int size)112 lto_write_raw_data (const void *data, unsigned int size)
113 {
114   lang_hooks.lto.append_data ((const char *)data, size, NULL);
115 }
116 
117 /* Write all of the chars in OBS to the assembler.  Recycle the blocks
118    in obs as this is being done.  */
119 
120 void
lto_write_stream(struct lto_output_stream * obs)121 lto_write_stream (struct lto_output_stream *obs)
122 {
123   unsigned int block_size = 1024;
124   struct lto_char_ptr_base *block;
125   struct lto_char_ptr_base *next_block;
126   if (!obs->first_block)
127     return;
128 
129   for (block = obs->first_block; block; block = next_block)
130     {
131       const char *base = ((char *)block) + sizeof (struct lto_char_ptr_base);
132       unsigned int num_chars = block_size - sizeof (struct lto_char_ptr_base);
133 
134       /* If this is not the last block, it is full.  If it is the last
135 	 block, left_in_block indicates how many chars are unoccupied in
136 	 this block; subtract from num_chars to obtain occupancy.  */
137       next_block = (struct lto_char_ptr_base *) block->ptr;
138       if (!next_block)
139 	num_chars -= obs->left_in_block;
140 
141       if (compression_stream)
142 	lto_compress_block (compression_stream, base, num_chars);
143       else
144 	lang_hooks.lto.append_data (base, num_chars, block);
145       free (block);
146       block_size *= 2;
147     }
148 }
149 
150 
151 /* Lookup NAME in ENCODER.  If NAME is not found, create a new entry in
152    ENCODER for NAME with the next available index of ENCODER,  then
153    print the index to OBS.  True is returned if NAME was added to
154    ENCODER.  The resulting index is stored in THIS_INDEX.
155 
156    If OBS is NULL, the only action is to add NAME to the encoder. */
157 
158 bool
lto_output_decl_index(struct lto_output_stream * obs,struct lto_tree_ref_encoder * encoder,tree name,unsigned int * this_index)159 lto_output_decl_index (struct lto_output_stream *obs,
160 		       struct lto_tree_ref_encoder *encoder,
161 		       tree name, unsigned int *this_index)
162 {
163   bool new_entry_p = FALSE;
164   bool existed_p;
165 
166   unsigned int &index
167     = encoder->tree_hash_table->get_or_insert (name, &existed_p);
168   if (!existed_p)
169     {
170       index = encoder->trees.length ();
171       if (streamer_dump_file)
172 	{
173 	  print_node_brief (streamer_dump_file, "    Encoding indexable ",
174 			    name, 4);
175 	  fprintf (streamer_dump_file, "  as %i \n", index);
176 	}
177       encoder->trees.safe_push (name);
178       new_entry_p = TRUE;
179     }
180 
181   if (obs)
182     streamer_write_uhwi_stream (obs, index);
183   *this_index = index;
184   return new_entry_p;
185 }
186 
187 /* Output a field DECL to OBS.  */
188 
189 void
lto_output_field_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)190 lto_output_field_decl_index (struct lto_out_decl_state *decl_state,
191 			     struct lto_output_stream * obs, tree decl)
192 {
193   unsigned int index;
194   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_FIELD_DECL],
195 			 decl, &index);
196 }
197 
198 /* Output a function DECL to OBS.  */
199 
200 void
lto_output_fn_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)201 lto_output_fn_decl_index (struct lto_out_decl_state *decl_state,
202 			  struct lto_output_stream * obs, tree decl)
203 {
204   unsigned int index;
205   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_FN_DECL],
206 			 decl, &index);
207 }
208 
209 /* Output a namespace DECL to OBS.  */
210 
211 void
lto_output_namespace_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)212 lto_output_namespace_decl_index (struct lto_out_decl_state *decl_state,
213 				 struct lto_output_stream * obs, tree decl)
214 {
215   unsigned int index;
216   lto_output_decl_index (obs,
217 			 &decl_state->streams[LTO_DECL_STREAM_NAMESPACE_DECL],
218 			 decl, &index);
219 }
220 
221 /* Output a static or extern var DECL to OBS.  */
222 
223 void
lto_output_var_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)224 lto_output_var_decl_index (struct lto_out_decl_state *decl_state,
225 			   struct lto_output_stream * obs, tree decl)
226 {
227   unsigned int index;
228   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_VAR_DECL],
229 			 decl, &index);
230 }
231 
232 /* Output a type DECL to OBS.  */
233 
234 void
lto_output_type_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)235 lto_output_type_decl_index (struct lto_out_decl_state *decl_state,
236 			    struct lto_output_stream * obs, tree decl)
237 {
238   unsigned int index;
239   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_TYPE_DECL],
240 			 decl, &index);
241 }
242 
243 /* Output a type REF to OBS.  */
244 
245 void
lto_output_type_ref_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree ref)246 lto_output_type_ref_index (struct lto_out_decl_state *decl_state,
247 			   struct lto_output_stream *obs, tree ref)
248 {
249   unsigned int index;
250   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_TYPE],
251 			 ref, &index);
252 }
253 
254 
255 /* Create the output block and return it.  */
256 
257 struct lto_simple_output_block *
lto_create_simple_output_block(enum lto_section_type section_type)258 lto_create_simple_output_block (enum lto_section_type section_type)
259 {
260   struct lto_simple_output_block *ob
261     = ((struct lto_simple_output_block *)
262        xcalloc (1, sizeof (struct lto_simple_output_block)));
263 
264   ob->section_type = section_type;
265   ob->decl_state = lto_get_out_decl_state ();
266   ob->main_stream = ((struct lto_output_stream *)
267 		     xcalloc (1, sizeof (struct lto_output_stream)));
268 
269   return ob;
270 }
271 
272 
273 /* Produce a simple section for one of the ipa passes.  */
274 
275 void
lto_destroy_simple_output_block(struct lto_simple_output_block * ob)276 lto_destroy_simple_output_block (struct lto_simple_output_block *ob)
277 {
278   char *section_name;
279   struct lto_simple_header header;
280 
281   section_name = lto_get_section_name (ob->section_type, NULL, 0, NULL);
282   lto_begin_section (section_name, !flag_wpa);
283   free (section_name);
284 
285   /* Write the header which says how to decode the pieces of the
286      t.  */
287   memset (&header, 0, sizeof (struct lto_simple_header));
288   header.main_size = ob->main_stream->total_size;
289   lto_write_data (&header, sizeof header);
290 
291   lto_write_stream (ob->main_stream);
292 
293   /* Put back the assembly section that was there before we started
294      writing lto info.  */
295   lto_end_section ();
296 
297   free (ob->main_stream);
298   free (ob);
299 }
300 
301 
302 /* Return a new lto_out_decl_state. */
303 
304 struct lto_out_decl_state *
lto_new_out_decl_state(void)305 lto_new_out_decl_state (void)
306 {
307   struct lto_out_decl_state *state = XCNEW (struct lto_out_decl_state);
308   int i;
309 
310   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
311     lto_init_tree_ref_encoder (&state->streams[i]);
312 
313   /* At WPA time we do not compress sections by default.  */
314   state->compressed = !flag_wpa;
315 
316   return state;
317 }
318 
319 
320 /* Delete STATE and components.  */
321 
322 void
lto_delete_out_decl_state(struct lto_out_decl_state * state)323 lto_delete_out_decl_state (struct lto_out_decl_state *state)
324 {
325   int i;
326 
327   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
328     lto_destroy_tree_ref_encoder (&state->streams[i]);
329 
330   free (state);
331 }
332 
333 
334 /* Get the currently used lto_out_decl_state structure. */
335 
336 struct lto_out_decl_state *
lto_get_out_decl_state(void)337 lto_get_out_decl_state (void)
338 {
339   return decl_state_stack.last ();
340 }
341 
342 /* Push STATE to top of out decl stack. */
343 
344 void
lto_push_out_decl_state(struct lto_out_decl_state * state)345 lto_push_out_decl_state (struct lto_out_decl_state *state)
346 {
347   decl_state_stack.safe_push (state);
348 }
349 
350 /* Pop the currently used out-decl state from top of stack. */
351 
352 struct lto_out_decl_state *
lto_pop_out_decl_state(void)353 lto_pop_out_decl_state (void)
354 {
355   return decl_state_stack.pop ();
356 }
357 
358 /* Record STATE after it has been used in serializing the body of
359    FN_DECL.  STATE should no longer be used by the caller.  The ownership
360    of it is taken over from this point.  */
361 
362 void
lto_record_function_out_decl_state(tree fn_decl,struct lto_out_decl_state * state)363 lto_record_function_out_decl_state (tree fn_decl,
364 				    struct lto_out_decl_state *state)
365 {
366   int i;
367 
368   /* Strip all hash tables to save some memory. */
369   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
370     if (state->streams[i].tree_hash_table)
371       {
372 	delete state->streams[i].tree_hash_table;
373 	state->streams[i].tree_hash_table = NULL;
374       }
375   state->fn_decl = fn_decl;
376   lto_function_decl_states.safe_push (state);
377 }
378