1 /* Functions for writing LTO sections.
2 
3    Copyright (C) 2009-2014 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 "tm.h"
26 #include "tree.h"
27 #include "basic-block.h"
28 #include "tree-ssa-alias.h"
29 #include "internal-fn.h"
30 #include "gimple-expr.h"
31 #include "is-a.h"
32 #include "gimple.h"
33 #include "expr.h"
34 #include "params.h"
35 #include "input.h"
36 #include "hashtab.h"
37 #include "function.h"
38 #include "except.h"
39 #include "langhooks.h"
40 #include "data-streamer.h"
41 #include "lto-streamer.h"
42 #include "lto-compress.h"
43 
44 static vec<lto_out_decl_state_ptr> decl_state_stack;
45 
46 /* List of out decl states used by functions.  We use this to
47    generate the decl directory later. */
48 
49 vec<lto_out_decl_state_ptr> lto_function_decl_states;
50 
51 
52 /*****************************************************************************
53    Output routines shared by all of the serialization passes.
54 *****************************************************************************/
55 
56 
57 /* Flush compressed stream data function, sends NUM_CHARS from CHARS
58    to the append lang hook, OPAQUE is currently always NULL.  */
59 
60 static void
lto_append_data(const char * chars,unsigned int num_chars,void * opaque)61 lto_append_data (const char *chars, unsigned int num_chars, void *opaque)
62 {
63   gcc_assert (opaque == NULL);
64   lang_hooks.lto.append_data (chars, num_chars, opaque);
65 }
66 
67 /* Pointer to the current compression stream.  */
68 
69 static struct lto_compression_stream *compression_stream = NULL;
70 
71 /* Begin a new output section named NAME. If COMPRESS is true, zlib compress
72    the section. */
73 
74 void
lto_begin_section(const char * name,bool compress)75 lto_begin_section (const char *name, bool compress)
76 {
77   lang_hooks.lto.begin_section (name);
78 
79   /* FIXME lto: for now, suppress compression if the lang_hook that appends
80      data is anything other than assembler output.  The effect here is that
81      we get compression of IL only in non-ltrans object files.  */
82   gcc_assert (compression_stream == NULL);
83   if (compress)
84     compression_stream = lto_start_compression (lto_append_data, NULL);
85 }
86 
87 
88 /* End the current output section.  */
89 
90 void
lto_end_section(void)91 lto_end_section (void)
92 {
93   if (compression_stream)
94     {
95       lto_end_compression (compression_stream);
96       compression_stream = NULL;
97     }
98   lang_hooks.lto.end_section ();
99 }
100 
101 
102 /* Write all of the chars in OBS to the assembler.  Recycle the blocks
103    in obs as this is being done.  */
104 
105 void
lto_write_stream(struct lto_output_stream * obs)106 lto_write_stream (struct lto_output_stream *obs)
107 {
108   unsigned int block_size = 1024;
109   struct lto_char_ptr_base *block;
110   struct lto_char_ptr_base *next_block;
111   if (!obs->first_block)
112     return;
113 
114   for (block = obs->first_block; block; block = next_block)
115     {
116       const char *base = ((char *)block) + sizeof (struct lto_char_ptr_base);
117       unsigned int num_chars = block_size - sizeof (struct lto_char_ptr_base);
118 
119       /* If this is not the last block, it is full.  If it is the last
120 	 block, left_in_block indicates how many chars are unoccupied in
121 	 this block; subtract from num_chars to obtain occupancy.  */
122       next_block = (struct lto_char_ptr_base *) block->ptr;
123       if (!next_block)
124 	num_chars -= obs->left_in_block;
125 
126       /* FIXME lto: WPA mode uses an ELF function as a lang_hook to append
127          output data.  This hook is not happy with the way that compression
128          blocks up output differently to the way it's blocked here.  So for
129          now, we don't compress WPA output.  */
130       if (compression_stream)
131 	{
132 	  lto_compress_block (compression_stream, base, num_chars);
133 	  lang_hooks.lto.append_data (NULL, 0, block);
134 	}
135       else
136 	lang_hooks.lto.append_data (base, num_chars, block);
137       block_size *= 2;
138     }
139 }
140 
141 
142 /* Adds a new block to output stream OBS.  */
143 
144 void
lto_append_block(struct lto_output_stream * obs)145 lto_append_block (struct lto_output_stream *obs)
146 {
147   struct lto_char_ptr_base *new_block;
148 
149   gcc_assert (obs->left_in_block == 0);
150 
151   if (obs->first_block == NULL)
152     {
153       /* This is the first time the stream has been written
154 	 into.  */
155       obs->block_size = 1024;
156       new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size);
157       obs->first_block = new_block;
158     }
159   else
160     {
161       struct lto_char_ptr_base *tptr;
162       /* Get a new block that is twice as big as the last block
163 	 and link it into the list.  */
164       obs->block_size *= 2;
165       new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size);
166       /* The first bytes of the block are reserved as a pointer to
167 	 the next block.  Set the chain of the full block to the
168 	 pointer to the new block.  */
169       tptr = obs->current_block;
170       tptr->ptr = (char *) new_block;
171     }
172 
173   /* Set the place for the next char at the first position after the
174      chain to the next block.  */
175   obs->current_pointer
176     = ((char *) new_block) + sizeof (struct lto_char_ptr_base);
177   obs->current_block = new_block;
178   /* Null out the newly allocated block's pointer to the next block.  */
179   new_block->ptr = NULL;
180   obs->left_in_block = obs->block_size - sizeof (struct lto_char_ptr_base);
181 }
182 
183 
184 /* Write raw DATA of length LEN to the output block OB.  */
185 
186 void
lto_output_data_stream(struct lto_output_stream * obs,const void * data,size_t len)187 lto_output_data_stream (struct lto_output_stream *obs, const void *data,
188 			size_t len)
189 {
190   while (len)
191     {
192       size_t copy;
193 
194       /* No space left.  */
195       if (obs->left_in_block == 0)
196 	lto_append_block (obs);
197 
198       /* Determine how many bytes to copy in this loop.  */
199       if (len <= obs->left_in_block)
200 	copy = len;
201       else
202 	copy = obs->left_in_block;
203 
204       /* Copy the data and do bookkeeping.  */
205       memcpy (obs->current_pointer, data, copy);
206       obs->current_pointer += copy;
207       obs->total_size += copy;
208       obs->left_in_block -= copy;
209       data = (const char *) data + copy;
210       len -= copy;
211     }
212 }
213 
214 
215 /* Lookup NAME in ENCODER.  If NAME is not found, create a new entry in
216    ENCODER for NAME with the next available index of ENCODER,  then
217    print the index to OBS.  True is returned if NAME was added to
218    ENCODER.  The resulting index is stored in THIS_INDEX.
219 
220    If OBS is NULL, the only action is to add NAME to the encoder. */
221 
222 bool
lto_output_decl_index(struct lto_output_stream * obs,struct lto_tree_ref_encoder * encoder,tree name,unsigned int * this_index)223 lto_output_decl_index (struct lto_output_stream *obs,
224 		       struct lto_tree_ref_encoder *encoder,
225 		       tree name, unsigned int *this_index)
226 {
227   unsigned *slot;
228   unsigned int index;
229   bool new_entry_p = FALSE;
230   bool existed_p;
231 
232   slot = encoder->tree_hash_table->insert (name, &existed_p);
233   if (!existed_p)
234     {
235       index = encoder->trees.length ();
236       *slot = index;
237       encoder->trees.safe_push (name);
238       new_entry_p = TRUE;
239     }
240   else
241     index = *slot;
242 
243   if (obs)
244     streamer_write_uhwi_stream (obs, index);
245   *this_index = index;
246   return new_entry_p;
247 }
248 
249 /* Output a field DECL to OBS.  */
250 
251 void
lto_output_field_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)252 lto_output_field_decl_index (struct lto_out_decl_state *decl_state,
253 			     struct lto_output_stream * obs, tree decl)
254 {
255   unsigned int index;
256   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_FIELD_DECL],
257 			 decl, &index);
258 }
259 
260 /* Output a function DECL to OBS.  */
261 
262 void
lto_output_fn_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)263 lto_output_fn_decl_index (struct lto_out_decl_state *decl_state,
264 			  struct lto_output_stream * obs, tree decl)
265 {
266   unsigned int index;
267   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_FN_DECL],
268 			 decl, &index);
269 }
270 
271 /* Output a namespace DECL to OBS.  */
272 
273 void
lto_output_namespace_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)274 lto_output_namespace_decl_index (struct lto_out_decl_state *decl_state,
275 				 struct lto_output_stream * obs, tree decl)
276 {
277   unsigned int index;
278   lto_output_decl_index (obs,
279 			 &decl_state->streams[LTO_DECL_STREAM_NAMESPACE_DECL],
280 			 decl, &index);
281 }
282 
283 /* Output a static or extern var DECL to OBS.  */
284 
285 void
lto_output_var_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)286 lto_output_var_decl_index (struct lto_out_decl_state *decl_state,
287 			   struct lto_output_stream * obs, tree decl)
288 {
289   unsigned int index;
290   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_VAR_DECL],
291 			 decl, &index);
292 }
293 
294 /* Output a type DECL to OBS.  */
295 
296 void
lto_output_type_decl_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree decl)297 lto_output_type_decl_index (struct lto_out_decl_state *decl_state,
298 			    struct lto_output_stream * obs, tree decl)
299 {
300   unsigned int index;
301   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_TYPE_DECL],
302 			 decl, &index);
303 }
304 
305 /* Output a type REF to OBS.  */
306 
307 void
lto_output_type_ref_index(struct lto_out_decl_state * decl_state,struct lto_output_stream * obs,tree ref)308 lto_output_type_ref_index (struct lto_out_decl_state *decl_state,
309 			   struct lto_output_stream *obs, tree ref)
310 {
311   unsigned int index;
312   lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_TYPE],
313 			 ref, &index);
314 }
315 
316 
317 /* Create the output block and return it.  */
318 
319 struct lto_simple_output_block *
lto_create_simple_output_block(enum lto_section_type section_type)320 lto_create_simple_output_block (enum lto_section_type section_type)
321 {
322   struct lto_simple_output_block *ob
323     = ((struct lto_simple_output_block *)
324        xcalloc (1, sizeof (struct lto_simple_output_block)));
325 
326   ob->section_type = section_type;
327   ob->decl_state = lto_get_out_decl_state ();
328   ob->main_stream = ((struct lto_output_stream *)
329 		     xcalloc (1, sizeof (struct lto_output_stream)));
330 
331   return ob;
332 }
333 
334 
335 /* Produce a simple section for one of the ipa passes.  */
336 
337 void
lto_destroy_simple_output_block(struct lto_simple_output_block * ob)338 lto_destroy_simple_output_block (struct lto_simple_output_block *ob)
339 {
340   char *section_name;
341   struct lto_simple_header header;
342   struct lto_output_stream *header_stream;
343 
344   section_name = lto_get_section_name (ob->section_type, NULL, NULL);
345   lto_begin_section (section_name, !flag_wpa);
346   free (section_name);
347 
348   /* Write the header which says how to decode the pieces of the
349      t.  */
350   memset (&header, 0, sizeof (struct lto_simple_header));
351   header.lto_header.major_version = LTO_major_version;
352   header.lto_header.minor_version = LTO_minor_version;
353 
354   header.compressed_size = 0;
355 
356   header.main_size = ob->main_stream->total_size;
357 
358   header_stream = XCNEW (struct lto_output_stream);
359   lto_output_data_stream (header_stream, &header, sizeof header);
360   lto_write_stream (header_stream);
361   free (header_stream);
362 
363   lto_write_stream (ob->main_stream);
364 
365   /* Put back the assembly section that was there before we started
366      writing lto info.  */
367   lto_end_section ();
368 
369   free (ob->main_stream);
370   free (ob);
371 }
372 
373 
374 /* Return a new lto_out_decl_state. */
375 
376 struct lto_out_decl_state *
lto_new_out_decl_state(void)377 lto_new_out_decl_state (void)
378 {
379   struct lto_out_decl_state *state = XCNEW (struct lto_out_decl_state);
380   int i;
381 
382   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
383     lto_init_tree_ref_encoder (&state->streams[i]);
384 
385   return state;
386 }
387 
388 
389 /* Delete STATE and components.  */
390 
391 void
lto_delete_out_decl_state(struct lto_out_decl_state * state)392 lto_delete_out_decl_state (struct lto_out_decl_state *state)
393 {
394   int i;
395 
396   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
397     lto_destroy_tree_ref_encoder (&state->streams[i]);
398 
399   free (state);
400 }
401 
402 
403 /* Get the currently used lto_out_decl_state structure. */
404 
405 struct lto_out_decl_state *
lto_get_out_decl_state(void)406 lto_get_out_decl_state (void)
407 {
408   return decl_state_stack.last ();
409 }
410 
411 /* Push STATE to top of out decl stack. */
412 
413 void
lto_push_out_decl_state(struct lto_out_decl_state * state)414 lto_push_out_decl_state (struct lto_out_decl_state *state)
415 {
416   decl_state_stack.safe_push (state);
417 }
418 
419 /* Pop the currently used out-decl state from top of stack. */
420 
421 struct lto_out_decl_state *
lto_pop_out_decl_state(void)422 lto_pop_out_decl_state (void)
423 {
424   return decl_state_stack.pop ();
425 }
426 
427 /* Record STATE after it has been used in serializing the body of
428    FN_DECL.  STATE should no longer be used by the caller.  The ownership
429    of it is taken over from this point.  */
430 
431 void
lto_record_function_out_decl_state(tree fn_decl,struct lto_out_decl_state * state)432 lto_record_function_out_decl_state (tree fn_decl,
433 				    struct lto_out_decl_state *state)
434 {
435   int i;
436 
437   /* Strip all hash tables to save some memory. */
438   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
439     if (state->streams[i].tree_hash_table)
440       {
441 	delete state->streams[i].tree_hash_table;
442 	state->streams[i].tree_hash_table = NULL;
443       }
444   state->fn_decl = fn_decl;
445   lto_function_decl_states.safe_push (state);
446 }
447