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