re PR c++/58516 (ICE with __transaction_atomic)
[official-gcc.git] / gcc / data-streamer-out.c
blob247ff636e49214edb8da69dea305aa4f7bdd4a15
1 /* Routines for saving various data types to a file stream. This deals
2 with various data types like strings, integers, enums, etc.
4 Copyright (C) 2011-2013 Free Software Foundation, Inc.
5 Contributed by Diego Novillo <dnovillo@google.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "data-streamer.h"
28 /* Return index used to reference STRING of LEN characters in the string table
29 in OB. The string might or might not include a trailing '\0'.
30 Then put the index onto the INDEX_STREAM.
31 When PERSISTENT is set, the string S is supposed to not change during
32 duration of the OB and thus OB can keep pointer into it. */
34 unsigned
35 streamer_string_index (struct output_block *ob, const char *s, unsigned int len,
36 bool persistent)
38 struct string_slot **slot;
39 struct string_slot s_slot;
41 s_slot.s = s;
42 s_slot.len = len;
43 s_slot.slot_num = 0;
45 slot = ob->string_hash_table.find_slot (&s_slot, INSERT);
46 if (*slot == NULL)
48 struct lto_output_stream *string_stream = ob->string_stream;
49 unsigned int start = string_stream->total_size;
50 struct string_slot *new_slot = XOBNEW (&ob->obstack, struct string_slot);
51 const char *string;
53 if (!persistent)
55 char *tmp;
56 string = tmp = XOBNEWVEC (&ob->obstack, char, len);
57 memcpy (tmp, s, len);
59 else
60 string = s;
62 new_slot->s = string;
63 new_slot->len = len;
64 new_slot->slot_num = start;
65 *slot = new_slot;
66 streamer_write_uhwi_stream (string_stream, len);
67 lto_output_data_stream (string_stream, string, len);
68 return start + 1;
70 else
72 struct string_slot *old_slot = *slot;
73 return old_slot->slot_num + 1;
78 /* Output STRING of LEN characters to the string table in OB. The
79 string might or might not include a trailing '\0'. Then put the
80 index onto the INDEX_STREAM.
81 When PERSISTENT is set, the string S is supposed to not change during
82 duration of the OB and thus OB can keep pointer into it. */
84 void
85 streamer_write_string_with_length (struct output_block *ob,
86 struct lto_output_stream *index_stream,
87 const char *s, unsigned int len,
88 bool persistent)
90 if (s)
91 streamer_write_uhwi_stream (index_stream,
92 streamer_string_index (ob, s, len, persistent));
93 else
94 streamer_write_char_stream (index_stream, 0);
98 /* Output the '\0' terminated STRING to the string
99 table in OB. Then put the index onto the INDEX_STREAM.
100 When PERSISTENT is set, the string S is supposed to not change during
101 duration of the OB and thus OB can keep pointer into it. */
103 void
104 streamer_write_string (struct output_block *ob,
105 struct lto_output_stream *index_stream,
106 const char *string, bool persistent)
108 if (string)
109 streamer_write_string_with_length (ob, index_stream, string,
110 strlen (string) + 1,
111 persistent);
112 else
113 streamer_write_char_stream (index_stream, 0);
117 /* Output STRING of LEN characters to the string table in OB. Then
118 put the index into BP.
119 When PERSISTENT is set, the string S is supposed to not change during
120 duration of the OB and thus OB can keep pointer into it. */
122 void
123 bp_pack_string_with_length (struct output_block *ob, struct bitpack_d *bp,
124 const char *s, unsigned int len, bool persistent)
126 unsigned index = 0;
127 if (s)
128 index = streamer_string_index (ob, s, len, persistent);
129 bp_pack_var_len_unsigned (bp, index);
133 /* Output the '\0' terminated STRING to the string
134 table in OB. Then put the index onto the bitpack BP.
135 When PERSISTENT is set, the string S is supposed to not change during
136 duration of the OB and thus OB can keep pointer into it. */
138 void
139 bp_pack_string (struct output_block *ob, struct bitpack_d *bp,
140 const char *s, bool persistent)
142 unsigned index = 0;
143 if (s)
144 index = streamer_string_index (ob, s, strlen (s) + 1, persistent);
145 bp_pack_var_len_unsigned (bp, index);
150 /* Write a zero to the output stream. */
152 void
153 streamer_write_zero (struct output_block *ob)
155 streamer_write_char_stream (ob->main_stream, 0);
159 /* Write an unsigned HOST_WIDE_INT value WORK to OB->main_stream. */
161 void
162 streamer_write_uhwi (struct output_block *ob, unsigned HOST_WIDE_INT work)
164 streamer_write_uhwi_stream (ob->main_stream, work);
168 /* Write a HOST_WIDE_INT value WORK to OB->main_stream. */
170 void
171 streamer_write_hwi (struct output_block *ob, HOST_WIDE_INT work)
173 streamer_write_hwi_stream (ob->main_stream, work);
176 /* Write a gcov counter value WORK to OB->main_stream. */
178 void
179 streamer_write_gcov_count (struct output_block *ob, gcov_type work)
181 streamer_write_gcov_count_stream (ob->main_stream, work);
184 /* Write an unsigned HOST_WIDE_INT value WORK to OBS. */
186 void
187 streamer_write_uhwi_stream (struct lto_output_stream *obs,
188 unsigned HOST_WIDE_INT work)
190 if (obs->left_in_block == 0)
191 lto_append_block (obs);
192 char *current_pointer = obs->current_pointer;
193 unsigned int left_in_block = obs->left_in_block;
194 unsigned int size = 0;
197 unsigned int byte = (work & 0x7f);
198 work >>= 7;
199 if (work != 0)
200 /* More bytes to follow. */
201 byte |= 0x80;
203 *(current_pointer++) = byte;
204 left_in_block--;
205 size++;
207 while (work != 0 && left_in_block > 0);
208 if (work != 0)
210 obs->left_in_block = 0;
211 lto_append_block (obs);
212 current_pointer = obs->current_pointer;
213 left_in_block = obs->left_in_block;
216 unsigned int byte = (work & 0x7f);
217 work >>= 7;
218 if (work != 0)
219 /* More bytes to follow. */
220 byte |= 0x80;
222 *(current_pointer++) = byte;
223 left_in_block--;
224 size++;
226 while (work != 0);
228 obs->current_pointer = current_pointer;
229 obs->left_in_block = left_in_block;
230 obs->total_size += size;
234 /* Write a HOST_WIDE_INT value WORK to OBS. */
236 void
237 streamer_write_hwi_stream (struct lto_output_stream *obs, HOST_WIDE_INT work)
239 if (obs->left_in_block == 0)
240 lto_append_block (obs);
241 char *current_pointer = obs->current_pointer;
242 unsigned int left_in_block = obs->left_in_block;
243 unsigned int size = 0;
244 bool more;
247 unsigned int byte = (work & 0x7f);
248 /* If the lower 7-bits are sign-extended 0 or -1 we are finished. */
249 work >>= 6;
250 more = !(work == 0 || work == -1);
251 if (more)
253 /* More bits to follow. */
254 work >>= 1;
255 byte |= 0x80;
258 *(current_pointer++) = byte;
259 left_in_block--;
260 size++;
262 while (more && left_in_block > 0);
263 if (more)
265 obs->left_in_block = 0;
266 lto_append_block (obs);
267 current_pointer = obs->current_pointer;
268 left_in_block = obs->left_in_block;
271 unsigned int byte = (work & 0x7f);
272 work >>= 6;
273 more = !(work == 0 || work == -1);
274 if (more)
276 work >>= 1;
277 byte |= 0x80;
280 *(current_pointer++) = byte;
281 left_in_block--;
282 size++;
284 while (more);
286 obs->current_pointer = current_pointer;
287 obs->left_in_block = left_in_block;
288 obs->total_size += size;
291 /* Write a GCOV counter value WORK to OBS. */
293 void
294 streamer_write_gcov_count_stream (struct lto_output_stream *obs, gcov_type work)
296 gcc_assert (work >= 0);
297 gcc_assert ((HOST_WIDE_INT) work == work);
298 streamer_write_hwi_stream (obs, work);