Branch data Line data Source code
1 : : /* Functions for writing LTO sections.
2 : :
3 : : Copyright (C) 2009-2025 Free Software Foundation, Inc.
4 : : Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5 : :
6 : : This file is part of GCC.
7 : :
8 : : GCC is free software; you can redistribute it and/or modify it under
9 : : the terms of the GNU General Public License as published by the Free
10 : : Software Foundation; either version 3, or (at your option) any later
11 : : version.
12 : :
13 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : : for more details.
17 : :
18 : : You should have received a copy of the GNU General Public License
19 : : along with GCC; see the file COPYING3. If not see
20 : : <http://www.gnu.org/licenses/>. */
21 : :
22 : : #include "config.h"
23 : : #include "system.h"
24 : : #include "coretypes.h"
25 : : #include "backend.h"
26 : : #include "rtl.h"
27 : : #include "tree.h"
28 : : #include "gimple.h"
29 : : #include "cgraph.h"
30 : : #include "data-streamer.h"
31 : : #include "langhooks.h"
32 : : #include "lto-compress.h"
33 : : #include "print-tree.h"
34 : :
35 : : static vec<lto_out_decl_state_ptr> decl_state_stack;
36 : :
37 : : /* List of out decl states used by functions. We use this to
38 : : generate the decl directory later. */
39 : :
40 : : vec<lto_out_decl_state_ptr> lto_function_decl_states;
41 : :
42 : :
43 : : /*****************************************************************************
44 : : Output routines shared by all of the serialization passes.
45 : : *****************************************************************************/
46 : :
47 : :
48 : : /* Flush compressed stream data function, sends NUM_CHARS from CHARS
49 : : to the append lang hook, OPAQUE is currently always NULL. */
50 : :
51 : : static void
52 : 331522 : lto_append_data (const char *chars, unsigned int num_chars, void *opaque)
53 : : {
54 : 331522 : gcc_assert (opaque == NULL);
55 : 331522 : lang_hooks.lto.append_data (chars, num_chars, opaque);
56 : 331522 : }
57 : :
58 : : /* Pointer to the current compression stream. */
59 : :
60 : : static struct lto_compression_stream *compression_stream = NULL;
61 : :
62 : : /* Begin a new output section named NAME. If COMPRESS is true, zlib compress
63 : : the section. */
64 : :
65 : : void
66 : 549173 : lto_begin_section (const char *name, bool compress)
67 : : {
68 : 549173 : lang_hooks.lto.begin_section (name);
69 : :
70 : 549173 : if (streamer_dump_file)
71 : : {
72 : 68 : if (flag_dump_unnumbered || flag_dump_noaddr)
73 : 84 : fprintf (streamer_dump_file, "Creating %ssection\n",
74 : : compress ? "compressed " : "");
75 : : else
76 : 0 : fprintf (streamer_dump_file, "Creating %ssection %s\n",
77 : : compress ? "compressed " : "", name);
78 : : }
79 : 549173 : gcc_assert (compression_stream == NULL);
80 : 549173 : if (compress)
81 : 331522 : compression_stream = lto_start_compression (lto_append_data, NULL);
82 : 549173 : }
83 : :
84 : :
85 : : /* End the current output section. */
86 : :
87 : : void
88 : 549173 : lto_end_section (void)
89 : : {
90 : 549173 : if (compression_stream)
91 : : {
92 : 331522 : lto_end_compression (compression_stream);
93 : 331522 : compression_stream = NULL;
94 : : }
95 : 549173 : lang_hooks.lto.end_section ();
96 : 549173 : }
97 : :
98 : : /* Write SIZE bytes starting at DATA to the assembler. */
99 : :
100 : : void
101 : 5211411 : lto_write_data (const void *data, unsigned int size)
102 : : {
103 : 5211411 : if (compression_stream)
104 : 627023 : lto_compress_block (compression_stream, (const char *)data, size);
105 : : else
106 : 4584388 : lang_hooks.lto.append_data ((const char *)data, size, NULL);
107 : 5211411 : }
108 : :
109 : : /* Write SIZE bytes starting at DATA to the assembler. */
110 : :
111 : : void
112 : 34197 : lto_write_raw_data (const void *data, unsigned int size)
113 : : {
114 : 34197 : lang_hooks.lto.append_data ((const char *)data, size, NULL);
115 : 34197 : }
116 : :
117 : : /* Write all of the chars in OBS to the assembler. Recycle the blocks
118 : : in obs as this is being done. */
119 : :
120 : : void
121 : 805673 : lto_write_stream (struct lto_output_stream *obs)
122 : : {
123 : 805673 : unsigned int block_size = 1024;
124 : 805673 : struct lto_char_ptr_base *block;
125 : 805673 : struct lto_char_ptr_base *next_block;
126 : 805673 : if (!obs->first_block)
127 : : return;
128 : :
129 : 1368635 : for (block = obs->first_block; block; block = next_block)
130 : : {
131 : 706170 : const char *base = ((char *)block) + sizeof (struct lto_char_ptr_base);
132 : 706170 : unsigned int num_chars = block_size - sizeof (struct lto_char_ptr_base);
133 : :
134 : : /* If this is not the last block, it is full. If it is the last
135 : : block, left_in_block indicates how many chars are unoccupied in
136 : : this block; subtract from num_chars to obtain occupancy. */
137 : 706170 : next_block = (struct lto_char_ptr_base *) block->ptr;
138 : 706170 : if (!next_block)
139 : 662465 : num_chars -= obs->left_in_block;
140 : :
141 : 706170 : if (compression_stream)
142 : 609310 : lto_compress_block (compression_stream, base, num_chars);
143 : : else
144 : 96860 : lang_hooks.lto.append_data (base, num_chars, block);
145 : 706170 : free (block);
146 : 706170 : block_size *= 2;
147 : : }
148 : : }
149 : :
150 : : /* Create the output block and return it. */
151 : :
152 : : struct lto_simple_output_block *
153 : 113466 : lto_create_simple_output_block (enum lto_section_type section_type)
154 : : {
155 : 113466 : struct lto_simple_output_block *ob
156 : : = ((struct lto_simple_output_block *)
157 : 113466 : xcalloc (1, sizeof (struct lto_simple_output_block)));
158 : :
159 : 113466 : ob->section_type = section_type;
160 : 113466 : ob->decl_state = lto_get_out_decl_state ();
161 : 226932 : ob->main_stream = ((struct lto_output_stream *)
162 : 113466 : xcalloc (1, sizeof (struct lto_output_stream)));
163 : :
164 : 113466 : return ob;
165 : : }
166 : :
167 : :
168 : : /* Produce a simple section for one of the ipa passes. */
169 : :
170 : : void
171 : 113466 : lto_destroy_simple_output_block (struct lto_simple_output_block *ob)
172 : : {
173 : 113466 : char *section_name;
174 : 113466 : struct lto_simple_header header;
175 : :
176 : 113466 : section_name = lto_get_section_name (ob->section_type, NULL, 0, NULL);
177 : 113466 : lto_begin_section (section_name, !flag_wpa);
178 : 113466 : free (section_name);
179 : :
180 : : /* Write the header which says how to decode the pieces of the
181 : : t. */
182 : 113466 : memset (&header, 0, sizeof (struct lto_simple_header));
183 : 113466 : header.main_size = ob->main_stream->total_size;
184 : 113466 : lto_write_data (&header, sizeof header);
185 : :
186 : 113466 : lto_write_stream (ob->main_stream);
187 : :
188 : : /* Put back the assembly section that was there before we started
189 : : writing lto info. */
190 : 113466 : lto_end_section ();
191 : :
192 : 113466 : free (ob->main_stream);
193 : 113466 : free (ob);
194 : 113466 : }
195 : :
196 : :
197 : : /* Return a new lto_out_decl_state. */
198 : :
199 : : struct lto_out_decl_state *
200 : 184476 : lto_new_out_decl_state (void)
201 : : {
202 : 184476 : struct lto_out_decl_state *state = XCNEW (struct lto_out_decl_state);
203 : 184476 : int i;
204 : :
205 : 553428 : for (i = 0; i < LTO_N_DECL_STREAMS; i++)
206 : 184476 : lto_init_tree_ref_encoder (&state->streams[i]);
207 : :
208 : : /* At WPA time we do not compress sections by default. */
209 : 184476 : state->compressed = !flag_wpa;
210 : :
211 : 184476 : return state;
212 : : }
213 : :
214 : :
215 : : /* Delete STATE and components. */
216 : :
217 : : void
218 : 184476 : lto_delete_out_decl_state (struct lto_out_decl_state *state)
219 : : {
220 : 184476 : int i;
221 : :
222 : 368952 : for (i = 0; i < LTO_N_DECL_STREAMS; i++)
223 : 184476 : lto_destroy_tree_ref_encoder (&state->streams[i]);
224 : :
225 : 184476 : free (state);
226 : 184476 : }
227 : :
228 : :
229 : : /* Get the currently used lto_out_decl_state structure. */
230 : :
231 : : struct lto_out_decl_state *
232 : 770998 : lto_get_out_decl_state (void)
233 : : {
234 : 770998 : return decl_state_stack.last ();
235 : : }
236 : :
237 : : /* Push STATE to top of out decl stack. */
238 : :
239 : : void
240 : 184476 : lto_push_out_decl_state (struct lto_out_decl_state *state)
241 : : {
242 : 184476 : decl_state_stack.safe_push (state);
243 : 184476 : }
244 : :
245 : : /* Pop the currently used out-decl state from top of stack. */
246 : :
247 : : struct lto_out_decl_state *
248 : 184476 : lto_pop_out_decl_state (void)
249 : : {
250 : 184476 : return decl_state_stack.pop ();
251 : : }
252 : :
253 : : /* Record STATE after it has been used in serializing the body of
254 : : FN_DECL. STATE should no longer be used by the caller. The ownership
255 : : of it is taken over from this point. */
256 : :
257 : : void
258 : 151412 : lto_record_function_out_decl_state (tree fn_decl,
259 : : struct lto_out_decl_state *state)
260 : : {
261 : 151412 : int i;
262 : :
263 : : /* Strip all hash tables to save some memory. */
264 : 454236 : for (i = 0; i < LTO_N_DECL_STREAMS; i++)
265 : 151412 : if (state->streams[i].tree_hash_table)
266 : : {
267 : 151412 : delete state->streams[i].tree_hash_table;
268 : 151412 : state->streams[i].tree_hash_table = NULL;
269 : : }
270 : 151412 : state->fn_decl = fn_decl;
271 : 151412 : lto_function_decl_states.safe_push (state);
272 : 151412 : }
|