1*e4b17023SJohn Marino /* Write the GIMPLE representation to a file stream.
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino    Copyright 2009, 2010 Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5*e4b17023SJohn Marino    Re-implemented by Diego Novillo <dnovillo@google.com>
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino This file is part of GCC.
8*e4b17023SJohn Marino 
9*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
10*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
11*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
12*e4b17023SJohn Marino version.
13*e4b17023SJohn Marino 
14*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
16*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17*e4b17023SJohn Marino for more details.
18*e4b17023SJohn Marino 
19*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
20*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
21*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
22*e4b17023SJohn Marino 
23*e4b17023SJohn Marino #include "config.h"
24*e4b17023SJohn Marino #include "system.h"
25*e4b17023SJohn Marino #include "coretypes.h"
26*e4b17023SJohn Marino #include "tm.h"
27*e4b17023SJohn Marino #include "tree.h"
28*e4b17023SJohn Marino #include "expr.h"
29*e4b17023SJohn Marino #include "flags.h"
30*e4b17023SJohn Marino #include "params.h"
31*e4b17023SJohn Marino #include "input.h"
32*e4b17023SJohn Marino #include "hashtab.h"
33*e4b17023SJohn Marino #include "basic-block.h"
34*e4b17023SJohn Marino #include "tree-flow.h"
35*e4b17023SJohn Marino #include "tree-pass.h"
36*e4b17023SJohn Marino #include "cgraph.h"
37*e4b17023SJohn Marino #include "function.h"
38*e4b17023SJohn Marino #include "ggc.h"
39*e4b17023SJohn Marino #include "diagnostic-core.h"
40*e4b17023SJohn Marino #include "except.h"
41*e4b17023SJohn Marino #include "vec.h"
42*e4b17023SJohn Marino #include "lto-symtab.h"
43*e4b17023SJohn Marino #include "lto-streamer.h"
44*e4b17023SJohn Marino #include "data-streamer.h"
45*e4b17023SJohn Marino #include "gimple-streamer.h"
46*e4b17023SJohn Marino #include "tree-streamer.h"
47*e4b17023SJohn Marino #include "streamer-hooks.h"
48*e4b17023SJohn Marino 
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino /* Clear the line info stored in DATA_IN.  */
51*e4b17023SJohn Marino 
52*e4b17023SJohn Marino static void
clear_line_info(struct output_block * ob)53*e4b17023SJohn Marino clear_line_info (struct output_block *ob)
54*e4b17023SJohn Marino {
55*e4b17023SJohn Marino   ob->current_file = NULL;
56*e4b17023SJohn Marino   ob->current_line = 0;
57*e4b17023SJohn Marino   ob->current_col = 0;
58*e4b17023SJohn Marino }
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino 
61*e4b17023SJohn Marino /* Create the output block and return it.  SECTION_TYPE is
62*e4b17023SJohn Marino    LTO_section_function_body or LTO_static_initializer.  */
63*e4b17023SJohn Marino 
64*e4b17023SJohn Marino struct output_block *
create_output_block(enum lto_section_type section_type)65*e4b17023SJohn Marino create_output_block (enum lto_section_type section_type)
66*e4b17023SJohn Marino {
67*e4b17023SJohn Marino   struct output_block *ob = XCNEW (struct output_block);
68*e4b17023SJohn Marino 
69*e4b17023SJohn Marino   ob->section_type = section_type;
70*e4b17023SJohn Marino   ob->decl_state = lto_get_out_decl_state ();
71*e4b17023SJohn Marino   ob->main_stream = XCNEW (struct lto_output_stream);
72*e4b17023SJohn Marino   ob->string_stream = XCNEW (struct lto_output_stream);
73*e4b17023SJohn Marino   ob->writer_cache = streamer_tree_cache_create ();
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino   if (section_type == LTO_section_function_body)
76*e4b17023SJohn Marino     ob->cfg_stream = XCNEW (struct lto_output_stream);
77*e4b17023SJohn Marino 
78*e4b17023SJohn Marino   clear_line_info (ob);
79*e4b17023SJohn Marino 
80*e4b17023SJohn Marino   ob->string_hash_table = htab_create (37, hash_string_slot_node,
81*e4b17023SJohn Marino 				       eq_string_slot_node, NULL);
82*e4b17023SJohn Marino   gcc_obstack_init (&ob->obstack);
83*e4b17023SJohn Marino 
84*e4b17023SJohn Marino   return ob;
85*e4b17023SJohn Marino }
86*e4b17023SJohn Marino 
87*e4b17023SJohn Marino 
88*e4b17023SJohn Marino /* Destroy the output block OB.  */
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino void
destroy_output_block(struct output_block * ob)91*e4b17023SJohn Marino destroy_output_block (struct output_block *ob)
92*e4b17023SJohn Marino {
93*e4b17023SJohn Marino   enum lto_section_type section_type = ob->section_type;
94*e4b17023SJohn Marino 
95*e4b17023SJohn Marino   htab_delete (ob->string_hash_table);
96*e4b17023SJohn Marino 
97*e4b17023SJohn Marino   free (ob->main_stream);
98*e4b17023SJohn Marino   free (ob->string_stream);
99*e4b17023SJohn Marino   if (section_type == LTO_section_function_body)
100*e4b17023SJohn Marino     free (ob->cfg_stream);
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino   streamer_tree_cache_delete (ob->writer_cache);
103*e4b17023SJohn Marino   obstack_free (&ob->obstack, NULL);
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino   free (ob);
106*e4b17023SJohn Marino }
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino /* Look up NODE in the type table and write the index for it to OB.  */
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino static void
output_type_ref(struct output_block * ob,tree node)112*e4b17023SJohn Marino output_type_ref (struct output_block *ob, tree node)
113*e4b17023SJohn Marino {
114*e4b17023SJohn Marino   streamer_write_record_start (ob, LTO_type_ref);
115*e4b17023SJohn Marino   lto_output_type_ref_index (ob->decl_state, ob->main_stream, node);
116*e4b17023SJohn Marino }
117*e4b17023SJohn Marino 
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino /* Return true if tree node T is written to various tables.  For these
120*e4b17023SJohn Marino    nodes, we sometimes want to write their phyiscal representation
121*e4b17023SJohn Marino    (via lto_output_tree), and sometimes we need to emit an index
122*e4b17023SJohn Marino    reference into a table (via lto_output_tree_ref).  */
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino static bool
tree_is_indexable(tree t)125*e4b17023SJohn Marino tree_is_indexable (tree t)
126*e4b17023SJohn Marino {
127*e4b17023SJohn Marino   if (TREE_CODE (t) == PARM_DECL)
128*e4b17023SJohn Marino     return false;
129*e4b17023SJohn Marino   else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t)
130*e4b17023SJohn Marino 	   && !TREE_STATIC (t))
131*e4b17023SJohn Marino     return false;
132*e4b17023SJohn Marino   /* Variably modified types need to be streamed alongside function
133*e4b17023SJohn Marino      bodies because they can refer to local entities.  Together with
134*e4b17023SJohn Marino      them we have to localize their members as well.
135*e4b17023SJohn Marino      ???  In theory that includes non-FIELD_DECLs as well.  */
136*e4b17023SJohn Marino   else if (TYPE_P (t)
137*e4b17023SJohn Marino 	   && variably_modified_type_p (t, NULL_TREE))
138*e4b17023SJohn Marino     return false;
139*e4b17023SJohn Marino   else if (TREE_CODE (t) == FIELD_DECL
140*e4b17023SJohn Marino 	   && variably_modified_type_p (DECL_CONTEXT (t), NULL_TREE))
141*e4b17023SJohn Marino     return false;
142*e4b17023SJohn Marino   else
143*e4b17023SJohn Marino     return (TYPE_P (t) || DECL_P (t) || TREE_CODE (t) == SSA_NAME);
144*e4b17023SJohn Marino }
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino 
147*e4b17023SJohn Marino /* Output info about new location into bitpack BP.
148*e4b17023SJohn Marino    After outputting bitpack, lto_output_location_data has
149*e4b17023SJohn Marino    to be done to output actual data.  */
150*e4b17023SJohn Marino 
151*e4b17023SJohn Marino static inline void
lto_output_location_bitpack(struct bitpack_d * bp,struct output_block * ob,location_t loc)152*e4b17023SJohn Marino lto_output_location_bitpack (struct bitpack_d *bp,
153*e4b17023SJohn Marino 			     struct output_block *ob,
154*e4b17023SJohn Marino 			     location_t loc)
155*e4b17023SJohn Marino {
156*e4b17023SJohn Marino   expanded_location xloc;
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino   bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
159*e4b17023SJohn Marino   if (loc == UNKNOWN_LOCATION)
160*e4b17023SJohn Marino     return;
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino   xloc = expand_location (loc);
163*e4b17023SJohn Marino 
164*e4b17023SJohn Marino   bp_pack_value (bp, ob->current_file != xloc.file, 1);
165*e4b17023SJohn Marino   if (ob->current_file != xloc.file)
166*e4b17023SJohn Marino     bp_pack_var_len_unsigned (bp,
167*e4b17023SJohn Marino 	                      streamer_string_index (ob, xloc.file,
168*e4b17023SJohn Marino 						     strlen (xloc.file) + 1,
169*e4b17023SJohn Marino 						     true));
170*e4b17023SJohn Marino   ob->current_file = xloc.file;
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino   bp_pack_value (bp, ob->current_line != xloc.line, 1);
173*e4b17023SJohn Marino   if (ob->current_line != xloc.line)
174*e4b17023SJohn Marino     bp_pack_var_len_unsigned (bp, xloc.line);
175*e4b17023SJohn Marino   ob->current_line = xloc.line;
176*e4b17023SJohn Marino 
177*e4b17023SJohn Marino   bp_pack_value (bp, ob->current_col != xloc.column, 1);
178*e4b17023SJohn Marino   if (ob->current_col != xloc.column)
179*e4b17023SJohn Marino     bp_pack_var_len_unsigned (bp, xloc.column);
180*e4b17023SJohn Marino   ob->current_col = xloc.column;
181*e4b17023SJohn Marino }
182*e4b17023SJohn Marino 
183*e4b17023SJohn Marino 
184*e4b17023SJohn Marino /* Emit location LOC to output block OB.
185*e4b17023SJohn Marino    If the output_location streamer hook exists, call it.
186*e4b17023SJohn Marino    Otherwise, when bitpack is handy, it is more space efficient to call
187*e4b17023SJohn Marino    lto_output_location_bitpack with existing bitpack.  */
188*e4b17023SJohn Marino 
189*e4b17023SJohn Marino void
lto_output_location(struct output_block * ob,location_t loc)190*e4b17023SJohn Marino lto_output_location (struct output_block *ob, location_t loc)
191*e4b17023SJohn Marino {
192*e4b17023SJohn Marino   if (streamer_hooks.output_location)
193*e4b17023SJohn Marino     streamer_hooks.output_location (ob, loc);
194*e4b17023SJohn Marino   else
195*e4b17023SJohn Marino     {
196*e4b17023SJohn Marino       struct bitpack_d bp = bitpack_create (ob->main_stream);
197*e4b17023SJohn Marino       lto_output_location_bitpack (&bp, ob, loc);
198*e4b17023SJohn Marino       streamer_write_bitpack (&bp);
199*e4b17023SJohn Marino     }
200*e4b17023SJohn Marino }
201*e4b17023SJohn Marino 
202*e4b17023SJohn Marino 
203*e4b17023SJohn Marino /* If EXPR is an indexable tree node, output a reference to it to
204*e4b17023SJohn Marino    output block OB.  Otherwise, output the physical representation of
205*e4b17023SJohn Marino    EXPR to OB.  */
206*e4b17023SJohn Marino 
207*e4b17023SJohn Marino static void
lto_output_tree_ref(struct output_block * ob,tree expr)208*e4b17023SJohn Marino lto_output_tree_ref (struct output_block *ob, tree expr)
209*e4b17023SJohn Marino {
210*e4b17023SJohn Marino   enum tree_code code;
211*e4b17023SJohn Marino 
212*e4b17023SJohn Marino   if (TYPE_P (expr))
213*e4b17023SJohn Marino     {
214*e4b17023SJohn Marino       output_type_ref (ob, expr);
215*e4b17023SJohn Marino       return;
216*e4b17023SJohn Marino     }
217*e4b17023SJohn Marino 
218*e4b17023SJohn Marino   code = TREE_CODE (expr);
219*e4b17023SJohn Marino   switch (code)
220*e4b17023SJohn Marino     {
221*e4b17023SJohn Marino     case SSA_NAME:
222*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_ssa_name_ref);
223*e4b17023SJohn Marino       streamer_write_uhwi (ob, SSA_NAME_VERSION (expr));
224*e4b17023SJohn Marino       break;
225*e4b17023SJohn Marino 
226*e4b17023SJohn Marino     case FIELD_DECL:
227*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_field_decl_ref);
228*e4b17023SJohn Marino       lto_output_field_decl_index (ob->decl_state, ob->main_stream, expr);
229*e4b17023SJohn Marino       break;
230*e4b17023SJohn Marino 
231*e4b17023SJohn Marino     case FUNCTION_DECL:
232*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_function_decl_ref);
233*e4b17023SJohn Marino       lto_output_fn_decl_index (ob->decl_state, ob->main_stream, expr);
234*e4b17023SJohn Marino       break;
235*e4b17023SJohn Marino 
236*e4b17023SJohn Marino     case VAR_DECL:
237*e4b17023SJohn Marino     case DEBUG_EXPR_DECL:
238*e4b17023SJohn Marino       gcc_assert (decl_function_context (expr) == NULL || TREE_STATIC (expr));
239*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_global_decl_ref);
240*e4b17023SJohn Marino       lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
241*e4b17023SJohn Marino       break;
242*e4b17023SJohn Marino 
243*e4b17023SJohn Marino     case CONST_DECL:
244*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_const_decl_ref);
245*e4b17023SJohn Marino       lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
246*e4b17023SJohn Marino       break;
247*e4b17023SJohn Marino 
248*e4b17023SJohn Marino     case IMPORTED_DECL:
249*e4b17023SJohn Marino       gcc_assert (decl_function_context (expr) == NULL);
250*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_imported_decl_ref);
251*e4b17023SJohn Marino       lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
252*e4b17023SJohn Marino       break;
253*e4b17023SJohn Marino 
254*e4b17023SJohn Marino     case TYPE_DECL:
255*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_type_decl_ref);
256*e4b17023SJohn Marino       lto_output_type_decl_index (ob->decl_state, ob->main_stream, expr);
257*e4b17023SJohn Marino       break;
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino     case NAMESPACE_DECL:
260*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_namespace_decl_ref);
261*e4b17023SJohn Marino       lto_output_namespace_decl_index (ob->decl_state, ob->main_stream, expr);
262*e4b17023SJohn Marino       break;
263*e4b17023SJohn Marino 
264*e4b17023SJohn Marino     case LABEL_DECL:
265*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_label_decl_ref);
266*e4b17023SJohn Marino       lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
267*e4b17023SJohn Marino       break;
268*e4b17023SJohn Marino 
269*e4b17023SJohn Marino     case RESULT_DECL:
270*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_result_decl_ref);
271*e4b17023SJohn Marino       lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
272*e4b17023SJohn Marino       break;
273*e4b17023SJohn Marino 
274*e4b17023SJohn Marino     case TRANSLATION_UNIT_DECL:
275*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_translation_unit_decl_ref);
276*e4b17023SJohn Marino       lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
277*e4b17023SJohn Marino       break;
278*e4b17023SJohn Marino 
279*e4b17023SJohn Marino     default:
280*e4b17023SJohn Marino       /* No other node is indexable, so it should have been handled by
281*e4b17023SJohn Marino 	 lto_output_tree.  */
282*e4b17023SJohn Marino       gcc_unreachable ();
283*e4b17023SJohn Marino     }
284*e4b17023SJohn Marino }
285*e4b17023SJohn Marino 
286*e4b17023SJohn Marino 
287*e4b17023SJohn Marino /* Return true if EXPR is a tree node that can be written to disk.  */
288*e4b17023SJohn Marino 
289*e4b17023SJohn Marino static inline bool
lto_is_streamable(tree expr)290*e4b17023SJohn Marino lto_is_streamable (tree expr)
291*e4b17023SJohn Marino {
292*e4b17023SJohn Marino   enum tree_code code = TREE_CODE (expr);
293*e4b17023SJohn Marino 
294*e4b17023SJohn Marino   /* Notice that we reject SSA_NAMEs as well.  We only emit the SSA
295*e4b17023SJohn Marino      name version in lto_output_tree_ref (see output_ssa_names).  */
296*e4b17023SJohn Marino   return !is_lang_specific (expr)
297*e4b17023SJohn Marino 	 && code != SSA_NAME
298*e4b17023SJohn Marino 	 && code != CALL_EXPR
299*e4b17023SJohn Marino 	 && code != LANG_TYPE
300*e4b17023SJohn Marino 	 && code != MODIFY_EXPR
301*e4b17023SJohn Marino 	 && code != INIT_EXPR
302*e4b17023SJohn Marino 	 && code != TARGET_EXPR
303*e4b17023SJohn Marino 	 && code != BIND_EXPR
304*e4b17023SJohn Marino 	 && code != WITH_CLEANUP_EXPR
305*e4b17023SJohn Marino 	 && code != STATEMENT_LIST
306*e4b17023SJohn Marino 	 && code != OMP_CLAUSE
307*e4b17023SJohn Marino 	 && (code == CASE_LABEL_EXPR
308*e4b17023SJohn Marino 	     || code == DECL_EXPR
309*e4b17023SJohn Marino 	     || TREE_CODE_CLASS (code) != tcc_statement);
310*e4b17023SJohn Marino }
311*e4b17023SJohn Marino 
312*e4b17023SJohn Marino 
313*e4b17023SJohn Marino /* Write a physical representation of tree node EXPR to output block
314*e4b17023SJohn Marino    OB.  If REF_P is true, the leaves of EXPR are emitted as references
315*e4b17023SJohn Marino    via lto_output_tree_ref.  IX is the index into the streamer cache
316*e4b17023SJohn Marino    where EXPR is stored.  */
317*e4b17023SJohn Marino 
318*e4b17023SJohn Marino static void
lto_write_tree(struct output_block * ob,tree expr,bool ref_p)319*e4b17023SJohn Marino lto_write_tree (struct output_block *ob, tree expr, bool ref_p)
320*e4b17023SJohn Marino {
321*e4b17023SJohn Marino   struct bitpack_d bp;
322*e4b17023SJohn Marino 
323*e4b17023SJohn Marino   if (!lto_is_streamable (expr))
324*e4b17023SJohn Marino     internal_error ("tree code %qs is not supported in LTO streams",
325*e4b17023SJohn Marino 	            tree_code_name[TREE_CODE (expr)]);
326*e4b17023SJohn Marino 
327*e4b17023SJohn Marino   /* Write the header, containing everything needed to materialize
328*e4b17023SJohn Marino      EXPR on the reading side.  */
329*e4b17023SJohn Marino   streamer_write_tree_header (ob, expr);
330*e4b17023SJohn Marino 
331*e4b17023SJohn Marino   /* Pack all the non-pointer fields in EXPR into a bitpack and write
332*e4b17023SJohn Marino      the resulting bitpack.  */
333*e4b17023SJohn Marino   bp = bitpack_create (ob->main_stream);
334*e4b17023SJohn Marino   streamer_pack_tree_bitfields (&bp, expr);
335*e4b17023SJohn Marino   streamer_write_bitpack (&bp);
336*e4b17023SJohn Marino 
337*e4b17023SJohn Marino   /* Write all the pointer fields in EXPR.  */
338*e4b17023SJohn Marino   streamer_write_tree_body (ob, expr, ref_p);
339*e4b17023SJohn Marino 
340*e4b17023SJohn Marino   /* Write any LTO-specific data to OB.  */
341*e4b17023SJohn Marino   if (DECL_P (expr)
342*e4b17023SJohn Marino       && TREE_CODE (expr) != FUNCTION_DECL
343*e4b17023SJohn Marino       && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
344*e4b17023SJohn Marino     {
345*e4b17023SJohn Marino       /* Handle DECL_INITIAL for symbols.  */
346*e4b17023SJohn Marino       tree initial = DECL_INITIAL (expr);
347*e4b17023SJohn Marino       if (TREE_CODE (expr) == VAR_DECL
348*e4b17023SJohn Marino 	  && (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
349*e4b17023SJohn Marino 	  && initial)
350*e4b17023SJohn Marino 	{
351*e4b17023SJohn Marino 	  lto_varpool_encoder_t varpool_encoder;
352*e4b17023SJohn Marino 	  struct varpool_node *vnode;
353*e4b17023SJohn Marino 
354*e4b17023SJohn Marino 	  varpool_encoder = ob->decl_state->varpool_node_encoder;
355*e4b17023SJohn Marino 	  vnode = varpool_get_node (expr);
356*e4b17023SJohn Marino 	  if (!vnode)
357*e4b17023SJohn Marino 	    initial = error_mark_node;
358*e4b17023SJohn Marino 	  else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
359*e4b17023SJohn Marino 							      vnode))
360*e4b17023SJohn Marino 	    initial = NULL;
361*e4b17023SJohn Marino 	}
362*e4b17023SJohn Marino 
363*e4b17023SJohn Marino       stream_write_tree (ob, initial, ref_p);
364*e4b17023SJohn Marino     }
365*e4b17023SJohn Marino 
366*e4b17023SJohn Marino   /* Mark the end of EXPR.  */
367*e4b17023SJohn Marino   streamer_write_zero (ob);
368*e4b17023SJohn Marino }
369*e4b17023SJohn Marino 
370*e4b17023SJohn Marino 
371*e4b17023SJohn Marino /* Emit the physical representation of tree node EXPR to output block
372*e4b17023SJohn Marino    OB.  If THIS_REF_P is true, the leaves of EXPR are emitted as references
373*e4b17023SJohn Marino    via lto_output_tree_ref.  REF_P is used for streaming siblings of EXPR.  */
374*e4b17023SJohn Marino 
375*e4b17023SJohn Marino void
lto_output_tree(struct output_block * ob,tree expr,bool ref_p,bool this_ref_p)376*e4b17023SJohn Marino lto_output_tree (struct output_block *ob, tree expr,
377*e4b17023SJohn Marino 		 bool ref_p, bool this_ref_p)
378*e4b17023SJohn Marino {
379*e4b17023SJohn Marino   unsigned ix;
380*e4b17023SJohn Marino   bool existed_p;
381*e4b17023SJohn Marino 
382*e4b17023SJohn Marino   if (expr == NULL_TREE)
383*e4b17023SJohn Marino     {
384*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_null);
385*e4b17023SJohn Marino       return;
386*e4b17023SJohn Marino     }
387*e4b17023SJohn Marino 
388*e4b17023SJohn Marino   if (this_ref_p && tree_is_indexable (expr))
389*e4b17023SJohn Marino     {
390*e4b17023SJohn Marino       lto_output_tree_ref (ob, expr);
391*e4b17023SJohn Marino       return;
392*e4b17023SJohn Marino     }
393*e4b17023SJohn Marino 
394*e4b17023SJohn Marino   /* INTEGER_CST nodes are special because they need their original type
395*e4b17023SJohn Marino      to be materialized by the reader (to implement TYPE_CACHED_VALUES).  */
396*e4b17023SJohn Marino   if (TREE_CODE (expr) == INTEGER_CST)
397*e4b17023SJohn Marino     {
398*e4b17023SJohn Marino       streamer_write_integer_cst (ob, expr, ref_p);
399*e4b17023SJohn Marino       return;
400*e4b17023SJohn Marino     }
401*e4b17023SJohn Marino 
402*e4b17023SJohn Marino   existed_p = streamer_tree_cache_insert (ob->writer_cache, expr, &ix);
403*e4b17023SJohn Marino   if (existed_p)
404*e4b17023SJohn Marino     {
405*e4b17023SJohn Marino       /* If a node has already been streamed out, make sure that
406*e4b17023SJohn Marino 	 we don't write it more than once.  Otherwise, the reader
407*e4b17023SJohn Marino 	 will instantiate two different nodes for the same object.  */
408*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_tree_pickle_reference);
409*e4b17023SJohn Marino       streamer_write_uhwi (ob, ix);
410*e4b17023SJohn Marino       streamer_write_enum (ob->main_stream, LTO_tags, LTO_NUM_TAGS,
411*e4b17023SJohn Marino 			   lto_tree_code_to_tag (TREE_CODE (expr)));
412*e4b17023SJohn Marino     }
413*e4b17023SJohn Marino   else if (streamer_handle_as_builtin_p (expr))
414*e4b17023SJohn Marino     {
415*e4b17023SJohn Marino       /* MD and NORMAL builtins do not need to be written out
416*e4b17023SJohn Marino 	 completely as they are always instantiated by the
417*e4b17023SJohn Marino 	 compiler on startup.  The only builtins that need to
418*e4b17023SJohn Marino 	 be written out are BUILT_IN_FRONTEND.  For all other
419*e4b17023SJohn Marino 	 builtins, we simply write the class and code.  */
420*e4b17023SJohn Marino       streamer_write_builtin (ob, expr);
421*e4b17023SJohn Marino     }
422*e4b17023SJohn Marino   else
423*e4b17023SJohn Marino     {
424*e4b17023SJohn Marino       /* This is the first time we see EXPR, write its fields
425*e4b17023SJohn Marino 	 to OB.  */
426*e4b17023SJohn Marino       lto_write_tree (ob, expr, ref_p);
427*e4b17023SJohn Marino     }
428*e4b17023SJohn Marino }
429*e4b17023SJohn Marino 
430*e4b17023SJohn Marino 
431*e4b17023SJohn Marino /* Output to OB a list of try/catch handlers starting with FIRST.  */
432*e4b17023SJohn Marino 
433*e4b17023SJohn Marino static void
output_eh_try_list(struct output_block * ob,eh_catch first)434*e4b17023SJohn Marino output_eh_try_list (struct output_block *ob, eh_catch first)
435*e4b17023SJohn Marino {
436*e4b17023SJohn Marino   eh_catch n;
437*e4b17023SJohn Marino 
438*e4b17023SJohn Marino   for (n = first; n; n = n->next_catch)
439*e4b17023SJohn Marino     {
440*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_eh_catch);
441*e4b17023SJohn Marino       stream_write_tree (ob, n->type_list, true);
442*e4b17023SJohn Marino       stream_write_tree (ob, n->filter_list, true);
443*e4b17023SJohn Marino       stream_write_tree (ob, n->label, true);
444*e4b17023SJohn Marino     }
445*e4b17023SJohn Marino 
446*e4b17023SJohn Marino   streamer_write_record_start (ob, LTO_null);
447*e4b17023SJohn Marino }
448*e4b17023SJohn Marino 
449*e4b17023SJohn Marino 
450*e4b17023SJohn Marino /* Output EH region R in function FN to OB.  CURR_RN is the slot index
451*e4b17023SJohn Marino    that is being emitted in FN->EH->REGION_ARRAY.  This is used to
452*e4b17023SJohn Marino    detect EH region sharing.  */
453*e4b17023SJohn Marino 
454*e4b17023SJohn Marino static void
output_eh_region(struct output_block * ob,eh_region r)455*e4b17023SJohn Marino output_eh_region (struct output_block *ob, eh_region r)
456*e4b17023SJohn Marino {
457*e4b17023SJohn Marino   enum LTO_tags tag;
458*e4b17023SJohn Marino 
459*e4b17023SJohn Marino   if (r == NULL)
460*e4b17023SJohn Marino     {
461*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_null);
462*e4b17023SJohn Marino       return;
463*e4b17023SJohn Marino     }
464*e4b17023SJohn Marino 
465*e4b17023SJohn Marino   if (r->type == ERT_CLEANUP)
466*e4b17023SJohn Marino     tag = LTO_ert_cleanup;
467*e4b17023SJohn Marino   else if (r->type == ERT_TRY)
468*e4b17023SJohn Marino     tag = LTO_ert_try;
469*e4b17023SJohn Marino   else if (r->type == ERT_ALLOWED_EXCEPTIONS)
470*e4b17023SJohn Marino     tag = LTO_ert_allowed_exceptions;
471*e4b17023SJohn Marino   else if (r->type == ERT_MUST_NOT_THROW)
472*e4b17023SJohn Marino     tag = LTO_ert_must_not_throw;
473*e4b17023SJohn Marino   else
474*e4b17023SJohn Marino     gcc_unreachable ();
475*e4b17023SJohn Marino 
476*e4b17023SJohn Marino   streamer_write_record_start (ob, tag);
477*e4b17023SJohn Marino   streamer_write_hwi (ob, r->index);
478*e4b17023SJohn Marino 
479*e4b17023SJohn Marino   if (r->outer)
480*e4b17023SJohn Marino     streamer_write_hwi (ob, r->outer->index);
481*e4b17023SJohn Marino   else
482*e4b17023SJohn Marino     streamer_write_zero (ob);
483*e4b17023SJohn Marino 
484*e4b17023SJohn Marino   if (r->inner)
485*e4b17023SJohn Marino     streamer_write_hwi (ob, r->inner->index);
486*e4b17023SJohn Marino   else
487*e4b17023SJohn Marino     streamer_write_zero (ob);
488*e4b17023SJohn Marino 
489*e4b17023SJohn Marino   if (r->next_peer)
490*e4b17023SJohn Marino     streamer_write_hwi (ob, r->next_peer->index);
491*e4b17023SJohn Marino   else
492*e4b17023SJohn Marino     streamer_write_zero (ob);
493*e4b17023SJohn Marino 
494*e4b17023SJohn Marino   if (r->type == ERT_TRY)
495*e4b17023SJohn Marino     {
496*e4b17023SJohn Marino       output_eh_try_list (ob, r->u.eh_try.first_catch);
497*e4b17023SJohn Marino     }
498*e4b17023SJohn Marino   else if (r->type == ERT_ALLOWED_EXCEPTIONS)
499*e4b17023SJohn Marino     {
500*e4b17023SJohn Marino       stream_write_tree (ob, r->u.allowed.type_list, true);
501*e4b17023SJohn Marino       stream_write_tree (ob, r->u.allowed.label, true);
502*e4b17023SJohn Marino       streamer_write_uhwi (ob, r->u.allowed.filter);
503*e4b17023SJohn Marino     }
504*e4b17023SJohn Marino   else if (r->type == ERT_MUST_NOT_THROW)
505*e4b17023SJohn Marino     {
506*e4b17023SJohn Marino       stream_write_tree (ob, r->u.must_not_throw.failure_decl, true);
507*e4b17023SJohn Marino       lto_output_location (ob, r->u.must_not_throw.failure_loc);
508*e4b17023SJohn Marino     }
509*e4b17023SJohn Marino 
510*e4b17023SJohn Marino   if (r->landing_pads)
511*e4b17023SJohn Marino     streamer_write_hwi (ob, r->landing_pads->index);
512*e4b17023SJohn Marino   else
513*e4b17023SJohn Marino     streamer_write_zero (ob);
514*e4b17023SJohn Marino }
515*e4b17023SJohn Marino 
516*e4b17023SJohn Marino 
517*e4b17023SJohn Marino /* Output landing pad LP to OB.  */
518*e4b17023SJohn Marino 
519*e4b17023SJohn Marino static void
output_eh_lp(struct output_block * ob,eh_landing_pad lp)520*e4b17023SJohn Marino output_eh_lp (struct output_block *ob, eh_landing_pad lp)
521*e4b17023SJohn Marino {
522*e4b17023SJohn Marino   if (lp == NULL)
523*e4b17023SJohn Marino     {
524*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_null);
525*e4b17023SJohn Marino       return;
526*e4b17023SJohn Marino     }
527*e4b17023SJohn Marino 
528*e4b17023SJohn Marino   streamer_write_record_start (ob, LTO_eh_landing_pad);
529*e4b17023SJohn Marino   streamer_write_hwi (ob, lp->index);
530*e4b17023SJohn Marino   if (lp->next_lp)
531*e4b17023SJohn Marino     streamer_write_hwi (ob, lp->next_lp->index);
532*e4b17023SJohn Marino   else
533*e4b17023SJohn Marino     streamer_write_zero (ob);
534*e4b17023SJohn Marino 
535*e4b17023SJohn Marino   if (lp->region)
536*e4b17023SJohn Marino     streamer_write_hwi (ob, lp->region->index);
537*e4b17023SJohn Marino   else
538*e4b17023SJohn Marino     streamer_write_zero (ob);
539*e4b17023SJohn Marino 
540*e4b17023SJohn Marino   stream_write_tree (ob, lp->post_landing_pad, true);
541*e4b17023SJohn Marino }
542*e4b17023SJohn Marino 
543*e4b17023SJohn Marino 
544*e4b17023SJohn Marino /* Output the existing eh_table to OB.  */
545*e4b17023SJohn Marino 
546*e4b17023SJohn Marino static void
output_eh_regions(struct output_block * ob,struct function * fn)547*e4b17023SJohn Marino output_eh_regions (struct output_block *ob, struct function *fn)
548*e4b17023SJohn Marino {
549*e4b17023SJohn Marino   if (fn->eh && fn->eh->region_tree)
550*e4b17023SJohn Marino     {
551*e4b17023SJohn Marino       unsigned i;
552*e4b17023SJohn Marino       eh_region eh;
553*e4b17023SJohn Marino       eh_landing_pad lp;
554*e4b17023SJohn Marino       tree ttype;
555*e4b17023SJohn Marino 
556*e4b17023SJohn Marino       streamer_write_record_start (ob, LTO_eh_table);
557*e4b17023SJohn Marino 
558*e4b17023SJohn Marino       /* Emit the index of the root of the EH region tree.  */
559*e4b17023SJohn Marino       streamer_write_hwi (ob, fn->eh->region_tree->index);
560*e4b17023SJohn Marino 
561*e4b17023SJohn Marino       /* Emit all the EH regions in the region array.  */
562*e4b17023SJohn Marino       streamer_write_hwi (ob, VEC_length (eh_region, fn->eh->region_array));
563*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (eh_region, fn->eh->region_array, i, eh)
564*e4b17023SJohn Marino 	output_eh_region (ob, eh);
565*e4b17023SJohn Marino 
566*e4b17023SJohn Marino       /* Emit all landing pads.  */
567*e4b17023SJohn Marino       streamer_write_hwi (ob, VEC_length (eh_landing_pad, fn->eh->lp_array));
568*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (eh_landing_pad, fn->eh->lp_array, i, lp)
569*e4b17023SJohn Marino 	output_eh_lp (ob, lp);
570*e4b17023SJohn Marino 
571*e4b17023SJohn Marino       /* Emit all the runtime type data.  */
572*e4b17023SJohn Marino       streamer_write_hwi (ob, VEC_length (tree, fn->eh->ttype_data));
573*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (tree, fn->eh->ttype_data, i, ttype)
574*e4b17023SJohn Marino 	stream_write_tree (ob, ttype, true);
575*e4b17023SJohn Marino 
576*e4b17023SJohn Marino       /* Emit the table of action chains.  */
577*e4b17023SJohn Marino       if (targetm.arm_eabi_unwinder)
578*e4b17023SJohn Marino 	{
579*e4b17023SJohn Marino 	  tree t;
580*e4b17023SJohn Marino 	  streamer_write_hwi (ob, VEC_length (tree,
581*e4b17023SJohn Marino 				              fn->eh->ehspec_data.arm_eabi));
582*e4b17023SJohn Marino 	  FOR_EACH_VEC_ELT (tree, fn->eh->ehspec_data.arm_eabi, i, t)
583*e4b17023SJohn Marino 	    stream_write_tree (ob, t, true);
584*e4b17023SJohn Marino 	}
585*e4b17023SJohn Marino       else
586*e4b17023SJohn Marino 	{
587*e4b17023SJohn Marino 	  uchar c;
588*e4b17023SJohn Marino 	  streamer_write_hwi (ob, VEC_length (uchar,
589*e4b17023SJohn Marino 				              fn->eh->ehspec_data.other));
590*e4b17023SJohn Marino 	  FOR_EACH_VEC_ELT (uchar, fn->eh->ehspec_data.other, i, c)
591*e4b17023SJohn Marino 	    streamer_write_char_stream (ob->main_stream, c);
592*e4b17023SJohn Marino 	}
593*e4b17023SJohn Marino     }
594*e4b17023SJohn Marino 
595*e4b17023SJohn Marino   /* The LTO_null either terminates the record or indicates that there
596*e4b17023SJohn Marino      are no eh_records at all.  */
597*e4b17023SJohn Marino   streamer_write_record_start (ob, LTO_null);
598*e4b17023SJohn Marino }
599*e4b17023SJohn Marino 
600*e4b17023SJohn Marino 
601*e4b17023SJohn Marino /* Output all of the active ssa names to the ssa_names stream.  */
602*e4b17023SJohn Marino 
603*e4b17023SJohn Marino static void
output_ssa_names(struct output_block * ob,struct function * fn)604*e4b17023SJohn Marino output_ssa_names (struct output_block *ob, struct function *fn)
605*e4b17023SJohn Marino {
606*e4b17023SJohn Marino   unsigned int i, len;
607*e4b17023SJohn Marino 
608*e4b17023SJohn Marino   len = VEC_length (tree, SSANAMES (fn));
609*e4b17023SJohn Marino   streamer_write_uhwi (ob, len);
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino   for (i = 1; i < len; i++)
612*e4b17023SJohn Marino     {
613*e4b17023SJohn Marino       tree ptr = VEC_index (tree, SSANAMES (fn), i);
614*e4b17023SJohn Marino 
615*e4b17023SJohn Marino       if (ptr == NULL_TREE
616*e4b17023SJohn Marino 	  || SSA_NAME_IN_FREE_LIST (ptr)
617*e4b17023SJohn Marino 	  || !is_gimple_reg (ptr))
618*e4b17023SJohn Marino 	continue;
619*e4b17023SJohn Marino 
620*e4b17023SJohn Marino       streamer_write_uhwi (ob, i);
621*e4b17023SJohn Marino       streamer_write_char_stream (ob->main_stream,
622*e4b17023SJohn Marino 				  SSA_NAME_IS_DEFAULT_DEF (ptr));
623*e4b17023SJohn Marino       stream_write_tree (ob, SSA_NAME_VAR (ptr), true);
624*e4b17023SJohn Marino     }
625*e4b17023SJohn Marino 
626*e4b17023SJohn Marino   streamer_write_zero (ob);
627*e4b17023SJohn Marino }
628*e4b17023SJohn Marino 
629*e4b17023SJohn Marino 
630*e4b17023SJohn Marino /* Output the cfg.  */
631*e4b17023SJohn Marino 
632*e4b17023SJohn Marino static void
output_cfg(struct output_block * ob,struct function * fn)633*e4b17023SJohn Marino output_cfg (struct output_block *ob, struct function *fn)
634*e4b17023SJohn Marino {
635*e4b17023SJohn Marino   struct lto_output_stream *tmp_stream = ob->main_stream;
636*e4b17023SJohn Marino   basic_block bb;
637*e4b17023SJohn Marino 
638*e4b17023SJohn Marino   ob->main_stream = ob->cfg_stream;
639*e4b17023SJohn Marino 
640*e4b17023SJohn Marino   streamer_write_enum (ob->main_stream, profile_status_d, PROFILE_LAST,
641*e4b17023SJohn Marino 		       profile_status_for_function (fn));
642*e4b17023SJohn Marino 
643*e4b17023SJohn Marino   /* Output the number of the highest basic block.  */
644*e4b17023SJohn Marino   streamer_write_uhwi (ob, last_basic_block_for_function (fn));
645*e4b17023SJohn Marino 
646*e4b17023SJohn Marino   FOR_ALL_BB_FN (bb, fn)
647*e4b17023SJohn Marino     {
648*e4b17023SJohn Marino       edge_iterator ei;
649*e4b17023SJohn Marino       edge e;
650*e4b17023SJohn Marino 
651*e4b17023SJohn Marino       streamer_write_hwi (ob, bb->index);
652*e4b17023SJohn Marino 
653*e4b17023SJohn Marino       /* Output the successors and the edge flags.  */
654*e4b17023SJohn Marino       streamer_write_uhwi (ob, EDGE_COUNT (bb->succs));
655*e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->succs)
656*e4b17023SJohn Marino 	{
657*e4b17023SJohn Marino 	  streamer_write_uhwi (ob, e->dest->index);
658*e4b17023SJohn Marino 	  streamer_write_hwi (ob, e->probability);
659*e4b17023SJohn Marino 	  streamer_write_hwi (ob, e->count);
660*e4b17023SJohn Marino 	  streamer_write_uhwi (ob, e->flags);
661*e4b17023SJohn Marino 	}
662*e4b17023SJohn Marino     }
663*e4b17023SJohn Marino 
664*e4b17023SJohn Marino   streamer_write_hwi (ob, -1);
665*e4b17023SJohn Marino 
666*e4b17023SJohn Marino   bb = ENTRY_BLOCK_PTR;
667*e4b17023SJohn Marino   while (bb->next_bb)
668*e4b17023SJohn Marino     {
669*e4b17023SJohn Marino       streamer_write_hwi (ob, bb->next_bb->index);
670*e4b17023SJohn Marino       bb = bb->next_bb;
671*e4b17023SJohn Marino     }
672*e4b17023SJohn Marino 
673*e4b17023SJohn Marino   streamer_write_hwi (ob, -1);
674*e4b17023SJohn Marino 
675*e4b17023SJohn Marino   ob->main_stream = tmp_stream;
676*e4b17023SJohn Marino }
677*e4b17023SJohn Marino 
678*e4b17023SJohn Marino 
679*e4b17023SJohn Marino /* Create the header in the file using OB.  If the section type is for
680*e4b17023SJohn Marino    a function, set FN to the decl for that function.  */
681*e4b17023SJohn Marino 
682*e4b17023SJohn Marino void
produce_asm(struct output_block * ob,tree fn)683*e4b17023SJohn Marino produce_asm (struct output_block *ob, tree fn)
684*e4b17023SJohn Marino {
685*e4b17023SJohn Marino   enum lto_section_type section_type = ob->section_type;
686*e4b17023SJohn Marino   struct lto_function_header header;
687*e4b17023SJohn Marino   char *section_name;
688*e4b17023SJohn Marino   struct lto_output_stream *header_stream;
689*e4b17023SJohn Marino 
690*e4b17023SJohn Marino   if (section_type == LTO_section_function_body)
691*e4b17023SJohn Marino     {
692*e4b17023SJohn Marino       const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn));
693*e4b17023SJohn Marino       section_name = lto_get_section_name (section_type, name, NULL);
694*e4b17023SJohn Marino     }
695*e4b17023SJohn Marino   else
696*e4b17023SJohn Marino     section_name = lto_get_section_name (section_type, NULL, NULL);
697*e4b17023SJohn Marino 
698*e4b17023SJohn Marino   lto_begin_section (section_name, !flag_wpa);
699*e4b17023SJohn Marino   free (section_name);
700*e4b17023SJohn Marino 
701*e4b17023SJohn Marino   /* The entire header is stream computed here.  */
702*e4b17023SJohn Marino   memset (&header, 0, sizeof (struct lto_function_header));
703*e4b17023SJohn Marino 
704*e4b17023SJohn Marino   /* Write the header.  */
705*e4b17023SJohn Marino   header.lto_header.major_version = LTO_major_version;
706*e4b17023SJohn Marino   header.lto_header.minor_version = LTO_minor_version;
707*e4b17023SJohn Marino   header.lto_header.section_type = section_type;
708*e4b17023SJohn Marino 
709*e4b17023SJohn Marino   header.compressed_size = 0;
710*e4b17023SJohn Marino 
711*e4b17023SJohn Marino   if (section_type == LTO_section_function_body)
712*e4b17023SJohn Marino     header.cfg_size = ob->cfg_stream->total_size;
713*e4b17023SJohn Marino   header.main_size = ob->main_stream->total_size;
714*e4b17023SJohn Marino   header.string_size = ob->string_stream->total_size;
715*e4b17023SJohn Marino 
716*e4b17023SJohn Marino   header_stream = XCNEW (struct lto_output_stream);
717*e4b17023SJohn Marino   lto_output_data_stream (header_stream, &header, sizeof header);
718*e4b17023SJohn Marino   lto_write_stream (header_stream);
719*e4b17023SJohn Marino   free (header_stream);
720*e4b17023SJohn Marino 
721*e4b17023SJohn Marino   /* Put all of the gimple and the string table out the asm file as a
722*e4b17023SJohn Marino      block of text.  */
723*e4b17023SJohn Marino   if (section_type == LTO_section_function_body)
724*e4b17023SJohn Marino     lto_write_stream (ob->cfg_stream);
725*e4b17023SJohn Marino   lto_write_stream (ob->main_stream);
726*e4b17023SJohn Marino   lto_write_stream (ob->string_stream);
727*e4b17023SJohn Marino 
728*e4b17023SJohn Marino   lto_end_section ();
729*e4b17023SJohn Marino }
730*e4b17023SJohn Marino 
731*e4b17023SJohn Marino 
732*e4b17023SJohn Marino /* Output the base body of struct function FN using output block OB.  */
733*e4b17023SJohn Marino 
734*e4b17023SJohn Marino static void
output_struct_function_base(struct output_block * ob,struct function * fn)735*e4b17023SJohn Marino output_struct_function_base (struct output_block *ob, struct function *fn)
736*e4b17023SJohn Marino {
737*e4b17023SJohn Marino   struct bitpack_d bp;
738*e4b17023SJohn Marino   unsigned i;
739*e4b17023SJohn Marino   tree t;
740*e4b17023SJohn Marino 
741*e4b17023SJohn Marino   /* Output the static chain and non-local goto save area.  */
742*e4b17023SJohn Marino   stream_write_tree (ob, fn->static_chain_decl, true);
743*e4b17023SJohn Marino   stream_write_tree (ob, fn->nonlocal_goto_save_area, true);
744*e4b17023SJohn Marino 
745*e4b17023SJohn Marino   /* Output all the local variables in the function.  */
746*e4b17023SJohn Marino   streamer_write_hwi (ob, VEC_length (tree, fn->local_decls));
747*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
748*e4b17023SJohn Marino     stream_write_tree (ob, t, true);
749*e4b17023SJohn Marino 
750*e4b17023SJohn Marino   /* Output the function start and end loci.  */
751*e4b17023SJohn Marino   lto_output_location (ob, fn->function_start_locus);
752*e4b17023SJohn Marino   lto_output_location (ob, fn->function_end_locus);
753*e4b17023SJohn Marino 
754*e4b17023SJohn Marino   /* Output current IL state of the function.  */
755*e4b17023SJohn Marino   streamer_write_uhwi (ob, fn->curr_properties);
756*e4b17023SJohn Marino 
757*e4b17023SJohn Marino   /* Write all the attributes for FN.  */
758*e4b17023SJohn Marino   bp = bitpack_create (ob->main_stream);
759*e4b17023SJohn Marino   bp_pack_value (&bp, fn->is_thunk, 1);
760*e4b17023SJohn Marino   bp_pack_value (&bp, fn->has_local_explicit_reg_vars, 1);
761*e4b17023SJohn Marino   bp_pack_value (&bp, fn->after_tree_profile, 1);
762*e4b17023SJohn Marino   bp_pack_value (&bp, fn->returns_pcc_struct, 1);
763*e4b17023SJohn Marino   bp_pack_value (&bp, fn->returns_struct, 1);
764*e4b17023SJohn Marino   bp_pack_value (&bp, fn->can_throw_non_call_exceptions, 1);
765*e4b17023SJohn Marino   bp_pack_value (&bp, fn->always_inline_functions_inlined, 1);
766*e4b17023SJohn Marino   bp_pack_value (&bp, fn->after_inlining, 1);
767*e4b17023SJohn Marino   bp_pack_value (&bp, fn->stdarg, 1);
768*e4b17023SJohn Marino   bp_pack_value (&bp, fn->has_nonlocal_label, 1);
769*e4b17023SJohn Marino   bp_pack_value (&bp, fn->calls_alloca, 1);
770*e4b17023SJohn Marino   bp_pack_value (&bp, fn->calls_setjmp, 1);
771*e4b17023SJohn Marino   bp_pack_value (&bp, fn->va_list_fpr_size, 8);
772*e4b17023SJohn Marino   bp_pack_value (&bp, fn->va_list_gpr_size, 8);
773*e4b17023SJohn Marino   streamer_write_bitpack (&bp);
774*e4b17023SJohn Marino }
775*e4b17023SJohn Marino 
776*e4b17023SJohn Marino 
777*e4b17023SJohn Marino /* Output the body of function NODE->DECL.  */
778*e4b17023SJohn Marino 
779*e4b17023SJohn Marino static void
output_function(struct cgraph_node * node)780*e4b17023SJohn Marino output_function (struct cgraph_node *node)
781*e4b17023SJohn Marino {
782*e4b17023SJohn Marino   tree function;
783*e4b17023SJohn Marino   struct function *fn;
784*e4b17023SJohn Marino   basic_block bb;
785*e4b17023SJohn Marino   struct output_block *ob;
786*e4b17023SJohn Marino 
787*e4b17023SJohn Marino   function = node->decl;
788*e4b17023SJohn Marino   fn = DECL_STRUCT_FUNCTION (function);
789*e4b17023SJohn Marino   ob = create_output_block (LTO_section_function_body);
790*e4b17023SJohn Marino 
791*e4b17023SJohn Marino   clear_line_info (ob);
792*e4b17023SJohn Marino   ob->cgraph_node = node;
793*e4b17023SJohn Marino 
794*e4b17023SJohn Marino   gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
795*e4b17023SJohn Marino 
796*e4b17023SJohn Marino   /* Set current_function_decl and cfun.  */
797*e4b17023SJohn Marino   current_function_decl = function;
798*e4b17023SJohn Marino   push_cfun (fn);
799*e4b17023SJohn Marino 
800*e4b17023SJohn Marino   /* Make string 0 be a NULL string.  */
801*e4b17023SJohn Marino   streamer_write_char_stream (ob->string_stream, 0);
802*e4b17023SJohn Marino 
803*e4b17023SJohn Marino   streamer_write_record_start (ob, LTO_function);
804*e4b17023SJohn Marino 
805*e4b17023SJohn Marino   output_struct_function_base (ob, fn);
806*e4b17023SJohn Marino 
807*e4b17023SJohn Marino   /* Output the head of the arguments list.  */
808*e4b17023SJohn Marino   stream_write_tree (ob, DECL_ARGUMENTS (function), true);
809*e4b17023SJohn Marino 
810*e4b17023SJohn Marino   /* Output all the SSA names used in the function.  */
811*e4b17023SJohn Marino   output_ssa_names (ob, fn);
812*e4b17023SJohn Marino 
813*e4b17023SJohn Marino   /* Output any exception handling regions.  */
814*e4b17023SJohn Marino   output_eh_regions (ob, fn);
815*e4b17023SJohn Marino 
816*e4b17023SJohn Marino   /* Output DECL_INITIAL for the function, which contains the tree of
817*e4b17023SJohn Marino      lexical scopes.  */
818*e4b17023SJohn Marino   stream_write_tree (ob, DECL_INITIAL (function), true);
819*e4b17023SJohn Marino 
820*e4b17023SJohn Marino   /* We will renumber the statements.  The code that does this uses
821*e4b17023SJohn Marino      the same ordering that we use for serializing them so we can use
822*e4b17023SJohn Marino      the same code on the other end and not have to write out the
823*e4b17023SJohn Marino      statement numbers.  We do not assign UIDs to PHIs here because
824*e4b17023SJohn Marino      virtual PHIs get re-computed on-the-fly which would make numbers
825*e4b17023SJohn Marino      inconsistent.  */
826*e4b17023SJohn Marino   set_gimple_stmt_max_uid (cfun, 0);
827*e4b17023SJohn Marino   FOR_ALL_BB (bb)
828*e4b17023SJohn Marino     {
829*e4b17023SJohn Marino       gimple_stmt_iterator gsi;
830*e4b17023SJohn Marino       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
831*e4b17023SJohn Marino 	{
832*e4b17023SJohn Marino 	  gimple stmt = gsi_stmt (gsi);
833*e4b17023SJohn Marino 	  gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
834*e4b17023SJohn Marino 	}
835*e4b17023SJohn Marino     }
836*e4b17023SJohn Marino 
837*e4b17023SJohn Marino   /* Output the code for the function.  */
838*e4b17023SJohn Marino   FOR_ALL_BB_FN (bb, fn)
839*e4b17023SJohn Marino     output_bb (ob, bb, fn);
840*e4b17023SJohn Marino 
841*e4b17023SJohn Marino   /* The terminator for this function.  */
842*e4b17023SJohn Marino   streamer_write_record_start (ob, LTO_null);
843*e4b17023SJohn Marino 
844*e4b17023SJohn Marino   output_cfg (ob, fn);
845*e4b17023SJohn Marino 
846*e4b17023SJohn Marino   /* Create a section to hold the pickled output of this function.   */
847*e4b17023SJohn Marino   produce_asm (ob, function);
848*e4b17023SJohn Marino 
849*e4b17023SJohn Marino   destroy_output_block (ob);
850*e4b17023SJohn Marino 
851*e4b17023SJohn Marino   current_function_decl = NULL;
852*e4b17023SJohn Marino   pop_cfun ();
853*e4b17023SJohn Marino }
854*e4b17023SJohn Marino 
855*e4b17023SJohn Marino 
856*e4b17023SJohn Marino /* Used to pass data to trivally_defined_alias callback.  */
857*e4b17023SJohn Marino struct sets {
858*e4b17023SJohn Marino   cgraph_node_set set;
859*e4b17023SJohn Marino   varpool_node_set vset;
860*e4b17023SJohn Marino };
861*e4b17023SJohn Marino 
862*e4b17023SJohn Marino 
863*e4b17023SJohn Marino /* Return true if alias pair P belongs to the set of cgraph nodes in
864*e4b17023SJohn Marino    SET.  If P is a an alias for a VAR_DECL, it can always be emitted.
865*e4b17023SJohn Marino    However, for FUNCTION_DECL aliases, we should only output the pair
866*e4b17023SJohn Marino    if it belongs to a function whose cgraph node is in SET.
867*e4b17023SJohn Marino    Otherwise, the LTRANS phase will get into trouble when finalizing
868*e4b17023SJohn Marino    aliases because the alias will refer to a function not defined in
869*e4b17023SJohn Marino    the file processed by LTRANS.  */
870*e4b17023SJohn Marino 
871*e4b17023SJohn Marino static bool
trivally_defined_alias(tree decl ATTRIBUTE_UNUSED,tree target,void * data)872*e4b17023SJohn Marino trivally_defined_alias (tree decl ATTRIBUTE_UNUSED,
873*e4b17023SJohn Marino 			tree target, void *data)
874*e4b17023SJohn Marino {
875*e4b17023SJohn Marino   struct sets *set = (struct sets *) data;
876*e4b17023SJohn Marino   struct cgraph_node *fnode = NULL;
877*e4b17023SJohn Marino   struct varpool_node *vnode = NULL;
878*e4b17023SJohn Marino 
879*e4b17023SJohn Marino   fnode = cgraph_node_for_asm (target);
880*e4b17023SJohn Marino   if (fnode)
881*e4b17023SJohn Marino     return cgraph_node_in_set_p (fnode, set->set);
882*e4b17023SJohn Marino   vnode = varpool_node_for_asm (target);
883*e4b17023SJohn Marino   return vnode && varpool_node_in_set_p (vnode, set->vset);
884*e4b17023SJohn Marino }
885*e4b17023SJohn Marino 
886*e4b17023SJohn Marino /* Return true if alias pair P should be output in the current
887*e4b17023SJohn Marino    partition contains cgrpah nodes SET and varpool nodes VSET.
888*e4b17023SJohn Marino    DEFINED is set of all aliases whose targets are defined in
889*e4b17023SJohn Marino    the partition.
890*e4b17023SJohn Marino 
891*e4b17023SJohn Marino    Normal aliases are output when they are defined, while WEAKREF
892*e4b17023SJohn Marino    aliases are output when they are used.  */
893*e4b17023SJohn Marino 
894*e4b17023SJohn Marino static bool
output_alias_pair_p(alias_pair * p,symbol_alias_set_t * defined,cgraph_node_set set,varpool_node_set vset)895*e4b17023SJohn Marino output_alias_pair_p (alias_pair *p, symbol_alias_set_t *defined,
896*e4b17023SJohn Marino 		     cgraph_node_set set, varpool_node_set vset)
897*e4b17023SJohn Marino {
898*e4b17023SJohn Marino   struct cgraph_node *node;
899*e4b17023SJohn Marino   struct varpool_node *vnode;
900*e4b17023SJohn Marino 
901*e4b17023SJohn Marino   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
902*e4b17023SJohn Marino     {
903*e4b17023SJohn Marino       if (TREE_CODE (p->decl) == VAR_DECL)
904*e4b17023SJohn Marino 	{
905*e4b17023SJohn Marino 	  vnode = varpool_get_node (p->decl);
906*e4b17023SJohn Marino 	  return (vnode
907*e4b17023SJohn Marino 		  && referenced_from_this_partition_p (&vnode->ref_list, set, vset));
908*e4b17023SJohn Marino 	}
909*e4b17023SJohn Marino       node = cgraph_get_node (p->decl);
910*e4b17023SJohn Marino       return (node
911*e4b17023SJohn Marino 	      && (referenced_from_this_partition_p (&node->ref_list, set, vset)
912*e4b17023SJohn Marino 		  || reachable_from_this_partition_p (node, set)));
913*e4b17023SJohn Marino     }
914*e4b17023SJohn Marino   else
915*e4b17023SJohn Marino     return symbol_alias_set_contains (defined, p->decl);
916*e4b17023SJohn Marino }
917*e4b17023SJohn Marino 
918*e4b17023SJohn Marino /* Output any unreferenced global symbol defined in SET, alias pairs
919*e4b17023SJohn Marino    and labels.  */
920*e4b17023SJohn Marino 
921*e4b17023SJohn Marino static void
output_unreferenced_globals(cgraph_node_set set,varpool_node_set vset)922*e4b17023SJohn Marino output_unreferenced_globals (cgraph_node_set set, varpool_node_set vset)
923*e4b17023SJohn Marino {
924*e4b17023SJohn Marino   struct output_block *ob;
925*e4b17023SJohn Marino   alias_pair *p;
926*e4b17023SJohn Marino   unsigned i;
927*e4b17023SJohn Marino   symbol_alias_set_t *defined;
928*e4b17023SJohn Marino   struct sets setdata;
929*e4b17023SJohn Marino 
930*e4b17023SJohn Marino   setdata.set = set;
931*e4b17023SJohn Marino   setdata.vset = vset;
932*e4b17023SJohn Marino 
933*e4b17023SJohn Marino   ob = create_output_block (LTO_section_static_initializer);
934*e4b17023SJohn Marino   ob->cgraph_node = NULL;
935*e4b17023SJohn Marino 
936*e4b17023SJohn Marino   clear_line_info (ob);
937*e4b17023SJohn Marino 
938*e4b17023SJohn Marino   /* Make string 0 be a NULL string.  */
939*e4b17023SJohn Marino   streamer_write_char_stream (ob->string_stream, 0);
940*e4b17023SJohn Marino 
941*e4b17023SJohn Marino   /* We really need to propagate in both directoins:
942*e4b17023SJohn Marino      for normal aliases we propagate from first defined alias to
943*e4b17023SJohn Marino      all aliases defined based on it.  For weakrefs we propagate in
944*e4b17023SJohn Marino      the oposite direction.  */
945*e4b17023SJohn Marino   defined = propagate_aliases_backward (trivally_defined_alias, &setdata);
946*e4b17023SJohn Marino 
947*e4b17023SJohn Marino   /* Emit the alias pairs for the nodes in SET.  */
948*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
949*e4b17023SJohn Marino     if (output_alias_pair_p (p, defined, set, vset))
950*e4b17023SJohn Marino       {
951*e4b17023SJohn Marino 	stream_write_tree (ob, p->decl, true);
952*e4b17023SJohn Marino 	stream_write_tree (ob, p->target, true);
953*e4b17023SJohn Marino       }
954*e4b17023SJohn Marino   symbol_alias_set_destroy (defined);
955*e4b17023SJohn Marino 
956*e4b17023SJohn Marino   streamer_write_record_start (ob, LTO_null);
957*e4b17023SJohn Marino 
958*e4b17023SJohn Marino   produce_asm (ob, NULL);
959*e4b17023SJohn Marino   destroy_output_block (ob);
960*e4b17023SJohn Marino }
961*e4b17023SJohn Marino 
962*e4b17023SJohn Marino 
963*e4b17023SJohn Marino /* Emit toplevel asms.  */
964*e4b17023SJohn Marino 
965*e4b17023SJohn Marino void
lto_output_toplevel_asms(void)966*e4b17023SJohn Marino lto_output_toplevel_asms (void)
967*e4b17023SJohn Marino {
968*e4b17023SJohn Marino   struct output_block *ob;
969*e4b17023SJohn Marino   struct cgraph_asm_node *can;
970*e4b17023SJohn Marino   char *section_name;
971*e4b17023SJohn Marino   struct lto_output_stream *header_stream;
972*e4b17023SJohn Marino   struct lto_asm_header header;
973*e4b17023SJohn Marino 
974*e4b17023SJohn Marino   if (! cgraph_asm_nodes)
975*e4b17023SJohn Marino     return;
976*e4b17023SJohn Marino 
977*e4b17023SJohn Marino   ob = create_output_block (LTO_section_asm);
978*e4b17023SJohn Marino 
979*e4b17023SJohn Marino   /* Make string 0 be a NULL string.  */
980*e4b17023SJohn Marino   streamer_write_char_stream (ob->string_stream, 0);
981*e4b17023SJohn Marino 
982*e4b17023SJohn Marino   for (can = cgraph_asm_nodes; can; can = can->next)
983*e4b17023SJohn Marino     {
984*e4b17023SJohn Marino       streamer_write_string_cst (ob, ob->main_stream, can->asm_str);
985*e4b17023SJohn Marino       streamer_write_hwi (ob, can->order);
986*e4b17023SJohn Marino     }
987*e4b17023SJohn Marino 
988*e4b17023SJohn Marino   streamer_write_string_cst (ob, ob->main_stream, NULL_TREE);
989*e4b17023SJohn Marino 
990*e4b17023SJohn Marino   section_name = lto_get_section_name (LTO_section_asm, NULL, NULL);
991*e4b17023SJohn Marino   lto_begin_section (section_name, !flag_wpa);
992*e4b17023SJohn Marino   free (section_name);
993*e4b17023SJohn Marino 
994*e4b17023SJohn Marino   /* The entire header stream is computed here.  */
995*e4b17023SJohn Marino   memset (&header, 0, sizeof (header));
996*e4b17023SJohn Marino 
997*e4b17023SJohn Marino   /* Write the header.  */
998*e4b17023SJohn Marino   header.lto_header.major_version = LTO_major_version;
999*e4b17023SJohn Marino   header.lto_header.minor_version = LTO_minor_version;
1000*e4b17023SJohn Marino   header.lto_header.section_type = LTO_section_asm;
1001*e4b17023SJohn Marino 
1002*e4b17023SJohn Marino   header.main_size = ob->main_stream->total_size;
1003*e4b17023SJohn Marino   header.string_size = ob->string_stream->total_size;
1004*e4b17023SJohn Marino 
1005*e4b17023SJohn Marino   header_stream = XCNEW (struct lto_output_stream);
1006*e4b17023SJohn Marino   lto_output_data_stream (header_stream, &header, sizeof (header));
1007*e4b17023SJohn Marino   lto_write_stream (header_stream);
1008*e4b17023SJohn Marino   free (header_stream);
1009*e4b17023SJohn Marino 
1010*e4b17023SJohn Marino   /* Put all of the gimple and the string table out the asm file as a
1011*e4b17023SJohn Marino      block of text.  */
1012*e4b17023SJohn Marino   lto_write_stream (ob->main_stream);
1013*e4b17023SJohn Marino   lto_write_stream (ob->string_stream);
1014*e4b17023SJohn Marino 
1015*e4b17023SJohn Marino   lto_end_section ();
1016*e4b17023SJohn Marino 
1017*e4b17023SJohn Marino   destroy_output_block (ob);
1018*e4b17023SJohn Marino }
1019*e4b17023SJohn Marino 
1020*e4b17023SJohn Marino 
1021*e4b17023SJohn Marino /* Copy the function body of NODE without deserializing. */
1022*e4b17023SJohn Marino 
1023*e4b17023SJohn Marino static void
copy_function(struct cgraph_node * node)1024*e4b17023SJohn Marino copy_function (struct cgraph_node *node)
1025*e4b17023SJohn Marino {
1026*e4b17023SJohn Marino   tree function = node->decl;
1027*e4b17023SJohn Marino   struct lto_file_decl_data *file_data = node->local.lto_file_data;
1028*e4b17023SJohn Marino   struct lto_output_stream *output_stream = XCNEW (struct lto_output_stream);
1029*e4b17023SJohn Marino   const char *data;
1030*e4b17023SJohn Marino   size_t len;
1031*e4b17023SJohn Marino   const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function));
1032*e4b17023SJohn Marino   char *section_name =
1033*e4b17023SJohn Marino     lto_get_section_name (LTO_section_function_body, name, NULL);
1034*e4b17023SJohn Marino   size_t i, j;
1035*e4b17023SJohn Marino   struct lto_in_decl_state *in_state;
1036*e4b17023SJohn Marino   struct lto_out_decl_state *out_state = lto_get_out_decl_state ();
1037*e4b17023SJohn Marino 
1038*e4b17023SJohn Marino   lto_begin_section (section_name, !flag_wpa);
1039*e4b17023SJohn Marino   free (section_name);
1040*e4b17023SJohn Marino 
1041*e4b17023SJohn Marino   /* We may have renamed the declaration, e.g., a static function.  */
1042*e4b17023SJohn Marino   name = lto_get_decl_name_mapping (file_data, name);
1043*e4b17023SJohn Marino 
1044*e4b17023SJohn Marino   data = lto_get_section_data (file_data, LTO_section_function_body,
1045*e4b17023SJohn Marino                                name, &len);
1046*e4b17023SJohn Marino   gcc_assert (data);
1047*e4b17023SJohn Marino 
1048*e4b17023SJohn Marino   /* Do a bit copy of the function body.  */
1049*e4b17023SJohn Marino   lto_output_data_stream (output_stream, data, len);
1050*e4b17023SJohn Marino   lto_write_stream (output_stream);
1051*e4b17023SJohn Marino 
1052*e4b17023SJohn Marino   /* Copy decls. */
1053*e4b17023SJohn Marino   in_state =
1054*e4b17023SJohn Marino     lto_get_function_in_decl_state (node->local.lto_file_data, function);
1055*e4b17023SJohn Marino   gcc_assert (in_state);
1056*e4b17023SJohn Marino 
1057*e4b17023SJohn Marino   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
1058*e4b17023SJohn Marino     {
1059*e4b17023SJohn Marino       size_t n = in_state->streams[i].size;
1060*e4b17023SJohn Marino       tree *trees = in_state->streams[i].trees;
1061*e4b17023SJohn Marino       struct lto_tree_ref_encoder *encoder = &(out_state->streams[i]);
1062*e4b17023SJohn Marino 
1063*e4b17023SJohn Marino       /* The out state must have the same indices and the in state.
1064*e4b17023SJohn Marino 	 So just copy the vector.  All the encoders in the in state
1065*e4b17023SJohn Marino 	 must be empty where we reach here. */
1066*e4b17023SJohn Marino       gcc_assert (lto_tree_ref_encoder_size (encoder) == 0);
1067*e4b17023SJohn Marino       for (j = 0; j < n; j++)
1068*e4b17023SJohn Marino 	VEC_safe_push (tree, heap, encoder->trees, trees[j]);
1069*e4b17023SJohn Marino       encoder->next_index = n;
1070*e4b17023SJohn Marino     }
1071*e4b17023SJohn Marino 
1072*e4b17023SJohn Marino   lto_free_section_data (file_data, LTO_section_function_body, name,
1073*e4b17023SJohn Marino 			 data, len);
1074*e4b17023SJohn Marino   free (output_stream);
1075*e4b17023SJohn Marino   lto_end_section ();
1076*e4b17023SJohn Marino }
1077*e4b17023SJohn Marino 
1078*e4b17023SJohn Marino 
1079*e4b17023SJohn Marino /* Main entry point from the pass manager.  */
1080*e4b17023SJohn Marino 
1081*e4b17023SJohn Marino static void
lto_output(cgraph_node_set set,varpool_node_set vset)1082*e4b17023SJohn Marino lto_output (cgraph_node_set set, varpool_node_set vset)
1083*e4b17023SJohn Marino {
1084*e4b17023SJohn Marino   struct cgraph_node *node;
1085*e4b17023SJohn Marino   struct lto_out_decl_state *decl_state;
1086*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1087*e4b17023SJohn Marino   bitmap output = lto_bitmap_alloc ();
1088*e4b17023SJohn Marino #endif
1089*e4b17023SJohn Marino   int i, n_nodes;
1090*e4b17023SJohn Marino   lto_cgraph_encoder_t encoder = lto_get_out_decl_state ()->cgraph_node_encoder;
1091*e4b17023SJohn Marino 
1092*e4b17023SJohn Marino   /* Initialize the streamer.  */
1093*e4b17023SJohn Marino   lto_streamer_init ();
1094*e4b17023SJohn Marino 
1095*e4b17023SJohn Marino   n_nodes = lto_cgraph_encoder_size (encoder);
1096*e4b17023SJohn Marino   /* Process only the functions with bodies.  */
1097*e4b17023SJohn Marino   for (i = 0; i < n_nodes; i++)
1098*e4b17023SJohn Marino     {
1099*e4b17023SJohn Marino       node = lto_cgraph_encoder_deref (encoder, i);
1100*e4b17023SJohn Marino       if (lto_cgraph_encoder_encode_body_p (encoder, node)
1101*e4b17023SJohn Marino 	  && !node->alias
1102*e4b17023SJohn Marino 	  && !node->thunk.thunk_p)
1103*e4b17023SJohn Marino 	{
1104*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1105*e4b17023SJohn Marino 	  gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
1106*e4b17023SJohn Marino 	  bitmap_set_bit (output, DECL_UID (node->decl));
1107*e4b17023SJohn Marino #endif
1108*e4b17023SJohn Marino 	  decl_state = lto_new_out_decl_state ();
1109*e4b17023SJohn Marino 	  lto_push_out_decl_state (decl_state);
1110*e4b17023SJohn Marino 	  if (gimple_has_body_p (node->decl))
1111*e4b17023SJohn Marino 	    output_function (node);
1112*e4b17023SJohn Marino 	  else
1113*e4b17023SJohn Marino 	    copy_function (node);
1114*e4b17023SJohn Marino 	  gcc_assert (lto_get_out_decl_state () == decl_state);
1115*e4b17023SJohn Marino 	  lto_pop_out_decl_state ();
1116*e4b17023SJohn Marino 	  lto_record_function_out_decl_state (node->decl, decl_state);
1117*e4b17023SJohn Marino 	}
1118*e4b17023SJohn Marino     }
1119*e4b17023SJohn Marino 
1120*e4b17023SJohn Marino   /* Emit the callgraph after emitting function bodies.  This needs to
1121*e4b17023SJohn Marino      be done now to make sure that all the statements in every function
1122*e4b17023SJohn Marino      have been renumbered so that edges can be associated with call
1123*e4b17023SJohn Marino      statements using the statement UIDs.  */
1124*e4b17023SJohn Marino   output_cgraph (set, vset);
1125*e4b17023SJohn Marino 
1126*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1127*e4b17023SJohn Marino   lto_bitmap_free (output);
1128*e4b17023SJohn Marino #endif
1129*e4b17023SJohn Marino }
1130*e4b17023SJohn Marino 
1131*e4b17023SJohn Marino struct ipa_opt_pass_d pass_ipa_lto_gimple_out =
1132*e4b17023SJohn Marino {
1133*e4b17023SJohn Marino  {
1134*e4b17023SJohn Marino   IPA_PASS,
1135*e4b17023SJohn Marino   "lto_gimple_out",	                /* name */
1136*e4b17023SJohn Marino   gate_lto_out,			        /* gate */
1137*e4b17023SJohn Marino   NULL,		                	/* execute */
1138*e4b17023SJohn Marino   NULL,					/* sub */
1139*e4b17023SJohn Marino   NULL,					/* next */
1140*e4b17023SJohn Marino   0,					/* static_pass_number */
1141*e4b17023SJohn Marino   TV_IPA_LTO_GIMPLE_OUT,		        /* tv_id */
1142*e4b17023SJohn Marino   0,	                                /* properties_required */
1143*e4b17023SJohn Marino   0,					/* properties_provided */
1144*e4b17023SJohn Marino   0,					/* properties_destroyed */
1145*e4b17023SJohn Marino   0,            			/* todo_flags_start */
1146*e4b17023SJohn Marino   0                                     /* todo_flags_finish */
1147*e4b17023SJohn Marino  },
1148*e4b17023SJohn Marino  NULL,		                        /* generate_summary */
1149*e4b17023SJohn Marino  lto_output,           			/* write_summary */
1150*e4b17023SJohn Marino  NULL,		         		/* read_summary */
1151*e4b17023SJohn Marino  lto_output,           			/* write_optimization_summary */
1152*e4b17023SJohn Marino  NULL,					/* read_optimization_summary */
1153*e4b17023SJohn Marino  NULL,					/* stmt_fixup */
1154*e4b17023SJohn Marino  0,					/* TODOs */
1155*e4b17023SJohn Marino  NULL,			                /* function_transform */
1156*e4b17023SJohn Marino  NULL					/* variable_transform */
1157*e4b17023SJohn Marino };
1158*e4b17023SJohn Marino 
1159*e4b17023SJohn Marino 
1160*e4b17023SJohn Marino /* Write each node in encoded by ENCODER to OB, as well as those reachable
1161*e4b17023SJohn Marino    from it and required for correct representation of its semantics.
1162*e4b17023SJohn Marino    Each node in ENCODER must be a global declaration or a type.  A node
1163*e4b17023SJohn Marino    is written only once, even if it appears multiple times in the
1164*e4b17023SJohn Marino    vector.  Certain transitively-reachable nodes, such as those
1165*e4b17023SJohn Marino    representing expressions, may be duplicated, but such nodes
1166*e4b17023SJohn Marino    must not appear in ENCODER itself.  */
1167*e4b17023SJohn Marino 
1168*e4b17023SJohn Marino static void
write_global_stream(struct output_block * ob,struct lto_tree_ref_encoder * encoder)1169*e4b17023SJohn Marino write_global_stream (struct output_block *ob,
1170*e4b17023SJohn Marino 		     struct lto_tree_ref_encoder *encoder)
1171*e4b17023SJohn Marino {
1172*e4b17023SJohn Marino   tree t;
1173*e4b17023SJohn Marino   size_t index;
1174*e4b17023SJohn Marino   const size_t size = lto_tree_ref_encoder_size (encoder);
1175*e4b17023SJohn Marino 
1176*e4b17023SJohn Marino   for (index = 0; index < size; index++)
1177*e4b17023SJohn Marino     {
1178*e4b17023SJohn Marino       t = lto_tree_ref_encoder_get_tree (encoder, index);
1179*e4b17023SJohn Marino       if (!streamer_tree_cache_lookup (ob->writer_cache, t, NULL))
1180*e4b17023SJohn Marino 	stream_write_tree (ob, t, false);
1181*e4b17023SJohn Marino     }
1182*e4b17023SJohn Marino }
1183*e4b17023SJohn Marino 
1184*e4b17023SJohn Marino 
1185*e4b17023SJohn Marino /* Write a sequence of indices into the globals vector corresponding
1186*e4b17023SJohn Marino    to the trees in ENCODER.  These are used by the reader to map the
1187*e4b17023SJohn Marino    indices used to refer to global entities within function bodies to
1188*e4b17023SJohn Marino    their referents.  */
1189*e4b17023SJohn Marino 
1190*e4b17023SJohn Marino static void
write_global_references(struct output_block * ob,struct lto_output_stream * ref_stream,struct lto_tree_ref_encoder * encoder)1191*e4b17023SJohn Marino write_global_references (struct output_block *ob,
1192*e4b17023SJohn Marino 			 struct lto_output_stream *ref_stream,
1193*e4b17023SJohn Marino  			 struct lto_tree_ref_encoder *encoder)
1194*e4b17023SJohn Marino {
1195*e4b17023SJohn Marino   tree t;
1196*e4b17023SJohn Marino   uint32_t index;
1197*e4b17023SJohn Marino   const uint32_t size = lto_tree_ref_encoder_size (encoder);
1198*e4b17023SJohn Marino 
1199*e4b17023SJohn Marino   /* Write size as 32-bit unsigned. */
1200*e4b17023SJohn Marino   lto_output_data_stream (ref_stream, &size, sizeof (int32_t));
1201*e4b17023SJohn Marino 
1202*e4b17023SJohn Marino   for (index = 0; index < size; index++)
1203*e4b17023SJohn Marino     {
1204*e4b17023SJohn Marino       uint32_t slot_num;
1205*e4b17023SJohn Marino 
1206*e4b17023SJohn Marino       t = lto_tree_ref_encoder_get_tree (encoder, index);
1207*e4b17023SJohn Marino       streamer_tree_cache_lookup (ob->writer_cache, t, &slot_num);
1208*e4b17023SJohn Marino       gcc_assert (slot_num != (unsigned)-1);
1209*e4b17023SJohn Marino       lto_output_data_stream (ref_stream, &slot_num, sizeof slot_num);
1210*e4b17023SJohn Marino     }
1211*e4b17023SJohn Marino }
1212*e4b17023SJohn Marino 
1213*e4b17023SJohn Marino 
1214*e4b17023SJohn Marino /* Write all the streams in an lto_out_decl_state STATE using
1215*e4b17023SJohn Marino    output block OB and output stream OUT_STREAM.  */
1216*e4b17023SJohn Marino 
1217*e4b17023SJohn Marino void
lto_output_decl_state_streams(struct output_block * ob,struct lto_out_decl_state * state)1218*e4b17023SJohn Marino lto_output_decl_state_streams (struct output_block *ob,
1219*e4b17023SJohn Marino 			       struct lto_out_decl_state *state)
1220*e4b17023SJohn Marino {
1221*e4b17023SJohn Marino   int i;
1222*e4b17023SJohn Marino 
1223*e4b17023SJohn Marino   for (i = 0;  i < LTO_N_DECL_STREAMS; i++)
1224*e4b17023SJohn Marino     write_global_stream (ob, &state->streams[i]);
1225*e4b17023SJohn Marino }
1226*e4b17023SJohn Marino 
1227*e4b17023SJohn Marino 
1228*e4b17023SJohn Marino /* Write all the references in an lto_out_decl_state STATE using
1229*e4b17023SJohn Marino    output block OB and output stream OUT_STREAM.  */
1230*e4b17023SJohn Marino 
1231*e4b17023SJohn Marino void
lto_output_decl_state_refs(struct output_block * ob,struct lto_output_stream * out_stream,struct lto_out_decl_state * state)1232*e4b17023SJohn Marino lto_output_decl_state_refs (struct output_block *ob,
1233*e4b17023SJohn Marino 			    struct lto_output_stream *out_stream,
1234*e4b17023SJohn Marino 			    struct lto_out_decl_state *state)
1235*e4b17023SJohn Marino {
1236*e4b17023SJohn Marino   unsigned i;
1237*e4b17023SJohn Marino   uint32_t ref;
1238*e4b17023SJohn Marino   tree decl;
1239*e4b17023SJohn Marino 
1240*e4b17023SJohn Marino   /* Write reference to FUNCTION_DECL.  If there is not function,
1241*e4b17023SJohn Marino      write reference to void_type_node. */
1242*e4b17023SJohn Marino   decl = (state->fn_decl) ? state->fn_decl : void_type_node;
1243*e4b17023SJohn Marino   streamer_tree_cache_lookup (ob->writer_cache, decl, &ref);
1244*e4b17023SJohn Marino   gcc_assert (ref != (unsigned)-1);
1245*e4b17023SJohn Marino   lto_output_data_stream (out_stream, &ref, sizeof (uint32_t));
1246*e4b17023SJohn Marino 
1247*e4b17023SJohn Marino   for (i = 0;  i < LTO_N_DECL_STREAMS; i++)
1248*e4b17023SJohn Marino     write_global_references (ob, out_stream, &state->streams[i]);
1249*e4b17023SJohn Marino }
1250*e4b17023SJohn Marino 
1251*e4b17023SJohn Marino 
1252*e4b17023SJohn Marino /* Return the written size of STATE. */
1253*e4b17023SJohn Marino 
1254*e4b17023SJohn Marino static size_t
lto_out_decl_state_written_size(struct lto_out_decl_state * state)1255*e4b17023SJohn Marino lto_out_decl_state_written_size (struct lto_out_decl_state *state)
1256*e4b17023SJohn Marino {
1257*e4b17023SJohn Marino   int i;
1258*e4b17023SJohn Marino   size_t size;
1259*e4b17023SJohn Marino 
1260*e4b17023SJohn Marino   size = sizeof (int32_t);	/* fn_ref. */
1261*e4b17023SJohn Marino   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
1262*e4b17023SJohn Marino     {
1263*e4b17023SJohn Marino       size += sizeof (int32_t); /* vector size. */
1264*e4b17023SJohn Marino       size += (lto_tree_ref_encoder_size (&state->streams[i])
1265*e4b17023SJohn Marino 	       * sizeof (int32_t));
1266*e4b17023SJohn Marino     }
1267*e4b17023SJohn Marino   return size;
1268*e4b17023SJohn Marino }
1269*e4b17023SJohn Marino 
1270*e4b17023SJohn Marino 
1271*e4b17023SJohn Marino /* Write symbol T into STREAM in CACHE. SEEN specifies symbols we wrote
1272*e4b17023SJohn Marino    so far.  */
1273*e4b17023SJohn Marino 
1274*e4b17023SJohn Marino static void
write_symbol(struct streamer_tree_cache_d * cache,struct lto_output_stream * stream,tree t,struct pointer_set_t * seen,bool alias)1275*e4b17023SJohn Marino write_symbol (struct streamer_tree_cache_d *cache,
1276*e4b17023SJohn Marino 	      struct lto_output_stream *stream,
1277*e4b17023SJohn Marino 	      tree t, struct pointer_set_t *seen, bool alias)
1278*e4b17023SJohn Marino {
1279*e4b17023SJohn Marino   const char *name;
1280*e4b17023SJohn Marino   enum gcc_plugin_symbol_kind kind;
1281*e4b17023SJohn Marino   enum gcc_plugin_symbol_visibility visibility;
1282*e4b17023SJohn Marino   unsigned slot_num;
1283*e4b17023SJohn Marino   unsigned HOST_WIDEST_INT size;
1284*e4b17023SJohn Marino   const char *comdat;
1285*e4b17023SJohn Marino   unsigned char c;
1286*e4b17023SJohn Marino 
1287*e4b17023SJohn Marino   /* None of the following kinds of symbols are needed in the
1288*e4b17023SJohn Marino      symbol table.  */
1289*e4b17023SJohn Marino   if (!TREE_PUBLIC (t)
1290*e4b17023SJohn Marino       || is_builtin_fn (t)
1291*e4b17023SJohn Marino       || DECL_ABSTRACT (t)
1292*e4b17023SJohn Marino       || TREE_CODE (t) == RESULT_DECL)
1293*e4b17023SJohn Marino     return;
1294*e4b17023SJohn Marino 
1295*e4b17023SJohn Marino   gcc_assert (TREE_CODE (t) == VAR_DECL
1296*e4b17023SJohn Marino 	      || TREE_CODE (t) == FUNCTION_DECL);
1297*e4b17023SJohn Marino 
1298*e4b17023SJohn Marino   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
1299*e4b17023SJohn Marino 
1300*e4b17023SJohn Marino   /* This behaves like assemble_name_raw in varasm.c, performing the
1301*e4b17023SJohn Marino      same name manipulations that ASM_OUTPUT_LABELREF does. */
1302*e4b17023SJohn Marino   name = IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) (name));
1303*e4b17023SJohn Marino 
1304*e4b17023SJohn Marino   if (pointer_set_contains (seen, name))
1305*e4b17023SJohn Marino     return;
1306*e4b17023SJohn Marino   pointer_set_insert (seen, name);
1307*e4b17023SJohn Marino 
1308*e4b17023SJohn Marino   streamer_tree_cache_lookup (cache, t, &slot_num);
1309*e4b17023SJohn Marino   gcc_assert (slot_num != (unsigned)-1);
1310*e4b17023SJohn Marino 
1311*e4b17023SJohn Marino   if (DECL_EXTERNAL (t))
1312*e4b17023SJohn Marino     {
1313*e4b17023SJohn Marino       if (DECL_WEAK (t))
1314*e4b17023SJohn Marino 	kind = GCCPK_WEAKUNDEF;
1315*e4b17023SJohn Marino       else
1316*e4b17023SJohn Marino 	kind = GCCPK_UNDEF;
1317*e4b17023SJohn Marino     }
1318*e4b17023SJohn Marino   else
1319*e4b17023SJohn Marino     {
1320*e4b17023SJohn Marino       if (DECL_WEAK (t))
1321*e4b17023SJohn Marino 	kind = GCCPK_WEAKDEF;
1322*e4b17023SJohn Marino       else if (DECL_COMMON (t))
1323*e4b17023SJohn Marino 	kind = GCCPK_COMMON;
1324*e4b17023SJohn Marino       else
1325*e4b17023SJohn Marino 	kind = GCCPK_DEF;
1326*e4b17023SJohn Marino 
1327*e4b17023SJohn Marino       /* When something is defined, it should have node attached.  */
1328*e4b17023SJohn Marino       gcc_assert (alias || TREE_CODE (t) != VAR_DECL
1329*e4b17023SJohn Marino 		  || varpool_get_node (t)->finalized);
1330*e4b17023SJohn Marino       gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL
1331*e4b17023SJohn Marino 		  || (cgraph_get_node (t)
1332*e4b17023SJohn Marino 		      && cgraph_get_node (t)->analyzed));
1333*e4b17023SJohn Marino     }
1334*e4b17023SJohn Marino 
1335*e4b17023SJohn Marino   /* Imitate what default_elf_asm_output_external do.
1336*e4b17023SJohn Marino      When symbol is external, we need to output it with DEFAULT visibility
1337*e4b17023SJohn Marino      when compiling with -fvisibility=default, while with HIDDEN visibility
1338*e4b17023SJohn Marino      when symbol has attribute (visibility("hidden")) specified.
1339*e4b17023SJohn Marino      targetm.binds_local_p check DECL_VISIBILITY_SPECIFIED and gets this
1340*e4b17023SJohn Marino      right. */
1341*e4b17023SJohn Marino 
1342*e4b17023SJohn Marino   if (DECL_EXTERNAL (t)
1343*e4b17023SJohn Marino       && !targetm.binds_local_p (t))
1344*e4b17023SJohn Marino     visibility = GCCPV_DEFAULT;
1345*e4b17023SJohn Marino   else
1346*e4b17023SJohn Marino     switch (DECL_VISIBILITY(t))
1347*e4b17023SJohn Marino       {
1348*e4b17023SJohn Marino       case VISIBILITY_DEFAULT:
1349*e4b17023SJohn Marino 	visibility = GCCPV_DEFAULT;
1350*e4b17023SJohn Marino 	break;
1351*e4b17023SJohn Marino       case VISIBILITY_PROTECTED:
1352*e4b17023SJohn Marino 	visibility = GCCPV_PROTECTED;
1353*e4b17023SJohn Marino 	break;
1354*e4b17023SJohn Marino       case VISIBILITY_HIDDEN:
1355*e4b17023SJohn Marino 	visibility = GCCPV_HIDDEN;
1356*e4b17023SJohn Marino 	break;
1357*e4b17023SJohn Marino       case VISIBILITY_INTERNAL:
1358*e4b17023SJohn Marino 	visibility = GCCPV_INTERNAL;
1359*e4b17023SJohn Marino 	break;
1360*e4b17023SJohn Marino       }
1361*e4b17023SJohn Marino 
1362*e4b17023SJohn Marino   if (kind == GCCPK_COMMON
1363*e4b17023SJohn Marino       && DECL_SIZE_UNIT (t)
1364*e4b17023SJohn Marino       && TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST)
1365*e4b17023SJohn Marino     size = TREE_INT_CST_LOW (DECL_SIZE_UNIT (t));
1366*e4b17023SJohn Marino   else
1367*e4b17023SJohn Marino     size = 0;
1368*e4b17023SJohn Marino 
1369*e4b17023SJohn Marino   if (DECL_ONE_ONLY (t))
1370*e4b17023SJohn Marino     comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (t));
1371*e4b17023SJohn Marino   else
1372*e4b17023SJohn Marino     comdat = "";
1373*e4b17023SJohn Marino 
1374*e4b17023SJohn Marino   lto_output_data_stream (stream, name, strlen (name) + 1);
1375*e4b17023SJohn Marino   lto_output_data_stream (stream, comdat, strlen (comdat) + 1);
1376*e4b17023SJohn Marino   c = (unsigned char) kind;
1377*e4b17023SJohn Marino   lto_output_data_stream (stream, &c, 1);
1378*e4b17023SJohn Marino   c = (unsigned char) visibility;
1379*e4b17023SJohn Marino   lto_output_data_stream (stream, &c, 1);
1380*e4b17023SJohn Marino   lto_output_data_stream (stream, &size, 8);
1381*e4b17023SJohn Marino   lto_output_data_stream (stream, &slot_num, 4);
1382*e4b17023SJohn Marino }
1383*e4b17023SJohn Marino 
1384*e4b17023SJohn Marino 
1385*e4b17023SJohn Marino /* Write an IL symbol table to OB.
1386*e4b17023SJohn Marino    SET and VSET are cgraph/varpool node sets we are outputting.  */
1387*e4b17023SJohn Marino 
1388*e4b17023SJohn Marino static void
produce_symtab(struct output_block * ob,cgraph_node_set set,varpool_node_set vset)1389*e4b17023SJohn Marino produce_symtab (struct output_block *ob,
1390*e4b17023SJohn Marino 	        cgraph_node_set set, varpool_node_set vset)
1391*e4b17023SJohn Marino {
1392*e4b17023SJohn Marino   struct streamer_tree_cache_d *cache = ob->writer_cache;
1393*e4b17023SJohn Marino   char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
1394*e4b17023SJohn Marino   struct pointer_set_t *seen;
1395*e4b17023SJohn Marino   struct cgraph_node *node;
1396*e4b17023SJohn Marino   struct varpool_node *vnode;
1397*e4b17023SJohn Marino   struct lto_output_stream stream;
1398*e4b17023SJohn Marino   lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
1399*e4b17023SJohn Marino   lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
1400*e4b17023SJohn Marino   int i;
1401*e4b17023SJohn Marino   alias_pair *p;
1402*e4b17023SJohn Marino   struct sets setdata;
1403*e4b17023SJohn Marino   symbol_alias_set_t *defined;
1404*e4b17023SJohn Marino 
1405*e4b17023SJohn Marino   setdata.set = set;
1406*e4b17023SJohn Marino   setdata.vset = vset;
1407*e4b17023SJohn Marino 
1408*e4b17023SJohn Marino   lto_begin_section (section_name, false);
1409*e4b17023SJohn Marino   free (section_name);
1410*e4b17023SJohn Marino 
1411*e4b17023SJohn Marino   seen = pointer_set_create ();
1412*e4b17023SJohn Marino   memset (&stream, 0, sizeof (stream));
1413*e4b17023SJohn Marino 
1414*e4b17023SJohn Marino   /* Write all functions.
1415*e4b17023SJohn Marino      First write all defined functions and then write all used functions.
1416*e4b17023SJohn Marino      This is done so only to handle duplicated symbols in cgraph.  */
1417*e4b17023SJohn Marino   for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
1418*e4b17023SJohn Marino     {
1419*e4b17023SJohn Marino       node = lto_cgraph_encoder_deref (encoder, i);
1420*e4b17023SJohn Marino       if (DECL_EXTERNAL (node->decl))
1421*e4b17023SJohn Marino 	continue;
1422*e4b17023SJohn Marino       if (DECL_COMDAT (node->decl)
1423*e4b17023SJohn Marino 	  && cgraph_comdat_can_be_unshared_p (node))
1424*e4b17023SJohn Marino 	continue;
1425*e4b17023SJohn Marino       if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
1426*e4b17023SJohn Marino 	continue;
1427*e4b17023SJohn Marino       write_symbol (cache, &stream, node->decl, seen, false);
1428*e4b17023SJohn Marino     }
1429*e4b17023SJohn Marino   for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
1430*e4b17023SJohn Marino     {
1431*e4b17023SJohn Marino       node = lto_cgraph_encoder_deref (encoder, i);
1432*e4b17023SJohn Marino       if (!DECL_EXTERNAL (node->decl))
1433*e4b17023SJohn Marino 	continue;
1434*e4b17023SJohn Marino       /* We keep around unused extern inlines in order to be able to inline
1435*e4b17023SJohn Marino 	 them indirectly or via vtables.  Do not output them to symbol
1436*e4b17023SJohn Marino 	 table: they end up being undefined and just consume space.  */
1437*e4b17023SJohn Marino       if (!node->address_taken && !node->callers)
1438*e4b17023SJohn Marino 	continue;
1439*e4b17023SJohn Marino       if (DECL_COMDAT (node->decl)
1440*e4b17023SJohn Marino 	  && cgraph_comdat_can_be_unshared_p (node))
1441*e4b17023SJohn Marino 	continue;
1442*e4b17023SJohn Marino       if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
1443*e4b17023SJohn Marino 	continue;
1444*e4b17023SJohn Marino       write_symbol (cache, &stream, node->decl, seen, false);
1445*e4b17023SJohn Marino     }
1446*e4b17023SJohn Marino 
1447*e4b17023SJohn Marino   /* Write all variables.  */
1448*e4b17023SJohn Marino   for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
1449*e4b17023SJohn Marino     {
1450*e4b17023SJohn Marino       vnode = lto_varpool_encoder_deref (varpool_encoder, i);
1451*e4b17023SJohn Marino       if (DECL_EXTERNAL (vnode->decl))
1452*e4b17023SJohn Marino 	continue;
1453*e4b17023SJohn Marino       /* COMDAT virtual tables can be unshared.  Do not declare them
1454*e4b17023SJohn Marino 	 in the LTO symbol table to prevent linker from forcing them
1455*e4b17023SJohn Marino 	 into the output. */
1456*e4b17023SJohn Marino       if (DECL_COMDAT (vnode->decl)
1457*e4b17023SJohn Marino 	  && !vnode->force_output
1458*e4b17023SJohn Marino 	  && vnode->finalized
1459*e4b17023SJohn Marino 	  && DECL_VIRTUAL_P (vnode->decl))
1460*e4b17023SJohn Marino 	continue;
1461*e4b17023SJohn Marino       if (vnode->alias && !vnode->alias_of)
1462*e4b17023SJohn Marino 	continue;
1463*e4b17023SJohn Marino       write_symbol (cache, &stream, vnode->decl, seen, false);
1464*e4b17023SJohn Marino     }
1465*e4b17023SJohn Marino   for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
1466*e4b17023SJohn Marino     {
1467*e4b17023SJohn Marino       vnode = lto_varpool_encoder_deref (varpool_encoder, i);
1468*e4b17023SJohn Marino       if (!DECL_EXTERNAL (vnode->decl))
1469*e4b17023SJohn Marino 	continue;
1470*e4b17023SJohn Marino       if (DECL_COMDAT (vnode->decl)
1471*e4b17023SJohn Marino 	  && !vnode->force_output
1472*e4b17023SJohn Marino 	  && vnode->finalized
1473*e4b17023SJohn Marino 	  && DECL_VIRTUAL_P (vnode->decl))
1474*e4b17023SJohn Marino 	continue;
1475*e4b17023SJohn Marino       if (vnode->alias && !vnode->alias_of)
1476*e4b17023SJohn Marino 	continue;
1477*e4b17023SJohn Marino       write_symbol (cache, &stream, vnode->decl, seen, false);
1478*e4b17023SJohn Marino     }
1479*e4b17023SJohn Marino 
1480*e4b17023SJohn Marino   /* Write all aliases.  */
1481*e4b17023SJohn Marino   defined = propagate_aliases_backward (trivally_defined_alias, &setdata);
1482*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
1483*e4b17023SJohn Marino     if (output_alias_pair_p (p, defined, set, vset))
1484*e4b17023SJohn Marino       write_symbol (cache, &stream, p->decl, seen, true);
1485*e4b17023SJohn Marino   symbol_alias_set_destroy (defined);
1486*e4b17023SJohn Marino 
1487*e4b17023SJohn Marino   lto_write_stream (&stream);
1488*e4b17023SJohn Marino   pointer_set_destroy (seen);
1489*e4b17023SJohn Marino 
1490*e4b17023SJohn Marino   lto_end_section ();
1491*e4b17023SJohn Marino }
1492*e4b17023SJohn Marino 
1493*e4b17023SJohn Marino 
1494*e4b17023SJohn Marino /* This pass is run after all of the functions are serialized and all
1495*e4b17023SJohn Marino    of the IPA passes have written their serialized forms.  This pass
1496*e4b17023SJohn Marino    causes the vector of all of the global decls and types used from
1497*e4b17023SJohn Marino    this file to be written in to a section that can then be read in to
1498*e4b17023SJohn Marino    recover these on other side.  */
1499*e4b17023SJohn Marino 
1500*e4b17023SJohn Marino static void
produce_asm_for_decls(cgraph_node_set set,varpool_node_set vset)1501*e4b17023SJohn Marino produce_asm_for_decls (cgraph_node_set set, varpool_node_set vset)
1502*e4b17023SJohn Marino {
1503*e4b17023SJohn Marino   struct lto_out_decl_state *out_state;
1504*e4b17023SJohn Marino   struct lto_out_decl_state *fn_out_state;
1505*e4b17023SJohn Marino   struct lto_decl_header header;
1506*e4b17023SJohn Marino   char *section_name;
1507*e4b17023SJohn Marino   struct output_block *ob;
1508*e4b17023SJohn Marino   struct lto_output_stream *header_stream, *decl_state_stream;
1509*e4b17023SJohn Marino   unsigned idx, num_fns;
1510*e4b17023SJohn Marino   size_t decl_state_size;
1511*e4b17023SJohn Marino   int32_t num_decl_states;
1512*e4b17023SJohn Marino 
1513*e4b17023SJohn Marino   ob = create_output_block (LTO_section_decls);
1514*e4b17023SJohn Marino   ob->global = true;
1515*e4b17023SJohn Marino 
1516*e4b17023SJohn Marino   /* Write out unreferenced globals, alias pairs and labels.  We defer
1517*e4b17023SJohn Marino      doing this until now so that we can write out only what is
1518*e4b17023SJohn Marino      needed.  */
1519*e4b17023SJohn Marino   output_unreferenced_globals (set, vset);
1520*e4b17023SJohn Marino 
1521*e4b17023SJohn Marino   memset (&header, 0, sizeof (struct lto_decl_header));
1522*e4b17023SJohn Marino 
1523*e4b17023SJohn Marino   section_name = lto_get_section_name (LTO_section_decls, NULL, NULL);
1524*e4b17023SJohn Marino   lto_begin_section (section_name, !flag_wpa);
1525*e4b17023SJohn Marino   free (section_name);
1526*e4b17023SJohn Marino 
1527*e4b17023SJohn Marino   /* Make string 0 be a NULL string.  */
1528*e4b17023SJohn Marino   streamer_write_char_stream (ob->string_stream, 0);
1529*e4b17023SJohn Marino 
1530*e4b17023SJohn Marino   /* Write the global symbols.  */
1531*e4b17023SJohn Marino   out_state = lto_get_out_decl_state ();
1532*e4b17023SJohn Marino   num_fns = VEC_length (lto_out_decl_state_ptr, lto_function_decl_states);
1533*e4b17023SJohn Marino   lto_output_decl_state_streams (ob, out_state);
1534*e4b17023SJohn Marino   for (idx = 0; idx < num_fns; idx++)
1535*e4b17023SJohn Marino     {
1536*e4b17023SJohn Marino       fn_out_state =
1537*e4b17023SJohn Marino 	VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
1538*e4b17023SJohn Marino       lto_output_decl_state_streams (ob, fn_out_state);
1539*e4b17023SJohn Marino     }
1540*e4b17023SJohn Marino 
1541*e4b17023SJohn Marino   header.lto_header.major_version = LTO_major_version;
1542*e4b17023SJohn Marino   header.lto_header.minor_version = LTO_minor_version;
1543*e4b17023SJohn Marino   header.lto_header.section_type = LTO_section_decls;
1544*e4b17023SJohn Marino 
1545*e4b17023SJohn Marino   /* Currently not used.  This field would allow us to preallocate
1546*e4b17023SJohn Marino      the globals vector, so that it need not be resized as it is extended.  */
1547*e4b17023SJohn Marino   header.num_nodes = -1;
1548*e4b17023SJohn Marino 
1549*e4b17023SJohn Marino   /* Compute the total size of all decl out states. */
1550*e4b17023SJohn Marino   decl_state_size = sizeof (int32_t);
1551*e4b17023SJohn Marino   decl_state_size += lto_out_decl_state_written_size (out_state);
1552*e4b17023SJohn Marino   for (idx = 0; idx < num_fns; idx++)
1553*e4b17023SJohn Marino     {
1554*e4b17023SJohn Marino       fn_out_state =
1555*e4b17023SJohn Marino 	VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
1556*e4b17023SJohn Marino       decl_state_size += lto_out_decl_state_written_size (fn_out_state);
1557*e4b17023SJohn Marino     }
1558*e4b17023SJohn Marino   header.decl_state_size = decl_state_size;
1559*e4b17023SJohn Marino 
1560*e4b17023SJohn Marino   header.main_size = ob->main_stream->total_size;
1561*e4b17023SJohn Marino   header.string_size = ob->string_stream->total_size;
1562*e4b17023SJohn Marino 
1563*e4b17023SJohn Marino   header_stream = XCNEW (struct lto_output_stream);
1564*e4b17023SJohn Marino   lto_output_data_stream (header_stream, &header, sizeof header);
1565*e4b17023SJohn Marino   lto_write_stream (header_stream);
1566*e4b17023SJohn Marino   free (header_stream);
1567*e4b17023SJohn Marino 
1568*e4b17023SJohn Marino   /* Write the main out-decl state, followed by out-decl states of
1569*e4b17023SJohn Marino      functions. */
1570*e4b17023SJohn Marino   decl_state_stream = ((struct lto_output_stream *)
1571*e4b17023SJohn Marino 		       xcalloc (1, sizeof (struct lto_output_stream)));
1572*e4b17023SJohn Marino   num_decl_states = num_fns + 1;
1573*e4b17023SJohn Marino   lto_output_data_stream (decl_state_stream, &num_decl_states,
1574*e4b17023SJohn Marino 			  sizeof (num_decl_states));
1575*e4b17023SJohn Marino   lto_output_decl_state_refs (ob, decl_state_stream, out_state);
1576*e4b17023SJohn Marino   for (idx = 0; idx < num_fns; idx++)
1577*e4b17023SJohn Marino     {
1578*e4b17023SJohn Marino       fn_out_state =
1579*e4b17023SJohn Marino 	VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
1580*e4b17023SJohn Marino       lto_output_decl_state_refs (ob, decl_state_stream, fn_out_state);
1581*e4b17023SJohn Marino     }
1582*e4b17023SJohn Marino   lto_write_stream (decl_state_stream);
1583*e4b17023SJohn Marino   free(decl_state_stream);
1584*e4b17023SJohn Marino 
1585*e4b17023SJohn Marino   lto_write_stream (ob->main_stream);
1586*e4b17023SJohn Marino   lto_write_stream (ob->string_stream);
1587*e4b17023SJohn Marino 
1588*e4b17023SJohn Marino   lto_end_section ();
1589*e4b17023SJohn Marino 
1590*e4b17023SJohn Marino   /* Write the symbol table.  It is used by linker to determine dependencies
1591*e4b17023SJohn Marino      and thus we can skip it for WPA.  */
1592*e4b17023SJohn Marino   if (!flag_wpa)
1593*e4b17023SJohn Marino     produce_symtab (ob, set, vset);
1594*e4b17023SJohn Marino 
1595*e4b17023SJohn Marino   /* Write command line opts.  */
1596*e4b17023SJohn Marino   lto_write_options ();
1597*e4b17023SJohn Marino 
1598*e4b17023SJohn Marino   /* Deallocate memory and clean up.  */
1599*e4b17023SJohn Marino   for (idx = 0; idx < num_fns; idx++)
1600*e4b17023SJohn Marino     {
1601*e4b17023SJohn Marino       fn_out_state =
1602*e4b17023SJohn Marino 	VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
1603*e4b17023SJohn Marino       lto_delete_out_decl_state (fn_out_state);
1604*e4b17023SJohn Marino     }
1605*e4b17023SJohn Marino   lto_cgraph_encoder_delete (ob->decl_state->cgraph_node_encoder);
1606*e4b17023SJohn Marino   lto_varpool_encoder_delete (ob->decl_state->varpool_node_encoder);
1607*e4b17023SJohn Marino   VEC_free (lto_out_decl_state_ptr, heap, lto_function_decl_states);
1608*e4b17023SJohn Marino   lto_function_decl_states = NULL;
1609*e4b17023SJohn Marino   destroy_output_block (ob);
1610*e4b17023SJohn Marino }
1611*e4b17023SJohn Marino 
1612*e4b17023SJohn Marino 
1613*e4b17023SJohn Marino struct ipa_opt_pass_d pass_ipa_lto_finish_out =
1614*e4b17023SJohn Marino {
1615*e4b17023SJohn Marino  {
1616*e4b17023SJohn Marino   IPA_PASS,
1617*e4b17023SJohn Marino   "lto_decls_out",	                /* name */
1618*e4b17023SJohn Marino   gate_lto_out,			        /* gate */
1619*e4b17023SJohn Marino   NULL,        	                        /* execute */
1620*e4b17023SJohn Marino   NULL,					/* sub */
1621*e4b17023SJohn Marino   NULL,					/* next */
1622*e4b17023SJohn Marino   0,					/* static_pass_number */
1623*e4b17023SJohn Marino   TV_IPA_LTO_DECL_OUT,		        /* tv_id */
1624*e4b17023SJohn Marino   0,	                                /* properties_required */
1625*e4b17023SJohn Marino   0,					/* properties_provided */
1626*e4b17023SJohn Marino   0,					/* properties_destroyed */
1627*e4b17023SJohn Marino   0,            			/* todo_flags_start */
1628*e4b17023SJohn Marino   0                                     /* todo_flags_finish */
1629*e4b17023SJohn Marino  },
1630*e4b17023SJohn Marino  NULL,		                        /* generate_summary */
1631*e4b17023SJohn Marino  produce_asm_for_decls,			/* write_summary */
1632*e4b17023SJohn Marino  NULL,		         		/* read_summary */
1633*e4b17023SJohn Marino  produce_asm_for_decls,			/* write_optimization_summary */
1634*e4b17023SJohn Marino  NULL,					/* read_optimization_summary */
1635*e4b17023SJohn Marino  NULL,					/* stmt_fixup */
1636*e4b17023SJohn Marino  0,					/* TODOs */
1637*e4b17023SJohn Marino  NULL,			                /* function_transform */
1638*e4b17023SJohn Marino  NULL					/* variable_transform */
1639*e4b17023SJohn Marino };
1640