]>
Commit | Line | Data |
---|---|---|
f0efc7aa DN |
1 | /* Routines for saving various data types to a file stream. This deals |
2 | with various data types like strings, integers, enums, etc. | |
3 | ||
23a5b65a | 4 | Copyright (C) 2011-2014 Free Software Foundation, Inc. |
f0efc7aa DN |
5 | Contributed by Diego Novillo <dnovillo@google.com> |
6 | ||
7 | This file is part of GCC. | |
8 | ||
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. | |
13 | ||
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. | |
18 | ||
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/>. */ | |
22 | ||
23 | #include "config.h" | |
24 | #include "system.h" | |
25 | #include "coretypes.h" | |
4d648807 | 26 | #include "tree.h" |
2fb9a547 AM |
27 | #include "basic-block.h" |
28 | #include "tree-ssa-alias.h" | |
29 | #include "internal-fn.h" | |
30 | #include "gimple-expr.h" | |
31 | #include "is-a.h" | |
8e9055ae | 32 | #include "gimple.h" |
f0efc7aa DN |
33 | #include "data-streamer.h" |
34 | ||
35 | /* Return index used to reference STRING of LEN characters in the string table | |
36 | in OB. The string might or might not include a trailing '\0'. | |
37 | Then put the index onto the INDEX_STREAM. | |
38 | When PERSISTENT is set, the string S is supposed to not change during | |
39 | duration of the OB and thus OB can keep pointer into it. */ | |
40 | ||
41 | unsigned | |
412288f1 DN |
42 | streamer_string_index (struct output_block *ob, const char *s, unsigned int len, |
43 | bool persistent) | |
f0efc7aa DN |
44 | { |
45 | struct string_slot **slot; | |
46 | struct string_slot s_slot; | |
47 | ||
48 | s_slot.s = s; | |
49 | s_slot.len = len; | |
50 | s_slot.slot_num = 0; | |
51 | ||
c203e8a7 | 52 | slot = ob->string_hash_table->find_slot (&s_slot, INSERT); |
f0efc7aa DN |
53 | if (*slot == NULL) |
54 | { | |
55 | struct lto_output_stream *string_stream = ob->string_stream; | |
56 | unsigned int start = string_stream->total_size; | |
57 | struct string_slot *new_slot = XOBNEW (&ob->obstack, struct string_slot); | |
58 | const char *string; | |
59 | ||
60 | if (!persistent) | |
61 | { | |
62 | char *tmp; | |
63 | string = tmp = XOBNEWVEC (&ob->obstack, char, len); | |
64 | memcpy (tmp, s, len); | |
65 | } | |
66 | else | |
67 | string = s; | |
68 | ||
69 | new_slot->s = string; | |
70 | new_slot->len = len; | |
71 | new_slot->slot_num = start; | |
72 | *slot = new_slot; | |
412288f1 | 73 | streamer_write_uhwi_stream (string_stream, len); |
f0efc7aa DN |
74 | lto_output_data_stream (string_stream, string, len); |
75 | return start + 1; | |
76 | } | |
77 | else | |
78 | { | |
79 | struct string_slot *old_slot = *slot; | |
80 | return old_slot->slot_num + 1; | |
81 | } | |
82 | } | |
83 | ||
84 | ||
85 | /* Output STRING of LEN characters to the string table in OB. The | |
86 | string might or might not include a trailing '\0'. Then put the | |
87 | index onto the INDEX_STREAM. | |
88 | When PERSISTENT is set, the string S is supposed to not change during | |
89 | duration of the OB and thus OB can keep pointer into it. */ | |
90 | ||
91 | void | |
412288f1 DN |
92 | streamer_write_string_with_length (struct output_block *ob, |
93 | struct lto_output_stream *index_stream, | |
94 | const char *s, unsigned int len, | |
95 | bool persistent) | |
f0efc7aa DN |
96 | { |
97 | if (s) | |
412288f1 DN |
98 | streamer_write_uhwi_stream (index_stream, |
99 | streamer_string_index (ob, s, len, persistent)); | |
f0efc7aa | 100 | else |
412288f1 | 101 | streamer_write_char_stream (index_stream, 0); |
f0efc7aa DN |
102 | } |
103 | ||
104 | ||
105 | /* Output the '\0' terminated STRING to the string | |
106 | table in OB. Then put the index onto the INDEX_STREAM. | |
107 | When PERSISTENT is set, the string S is supposed to not change during | |
108 | duration of the OB and thus OB can keep pointer into it. */ | |
109 | ||
110 | void | |
412288f1 DN |
111 | streamer_write_string (struct output_block *ob, |
112 | struct lto_output_stream *index_stream, | |
113 | const char *string, bool persistent) | |
f0efc7aa DN |
114 | { |
115 | if (string) | |
412288f1 DN |
116 | streamer_write_string_with_length (ob, index_stream, string, |
117 | strlen (string) + 1, | |
118 | persistent); | |
f0efc7aa | 119 | else |
412288f1 | 120 | streamer_write_char_stream (index_stream, 0); |
f0efc7aa DN |
121 | } |
122 | ||
123 | ||
8135e1e6 RB |
124 | /* Output STRING of LEN characters to the string table in OB. Then |
125 | put the index into BP. | |
126 | When PERSISTENT is set, the string S is supposed to not change during | |
127 | duration of the OB and thus OB can keep pointer into it. */ | |
128 | ||
129 | void | |
130 | bp_pack_string_with_length (struct output_block *ob, struct bitpack_d *bp, | |
131 | const char *s, unsigned int len, bool persistent) | |
132 | { | |
133 | unsigned index = 0; | |
134 | if (s) | |
135 | index = streamer_string_index (ob, s, len, persistent); | |
136 | bp_pack_var_len_unsigned (bp, index); | |
137 | } | |
138 | ||
139 | ||
140 | /* Output the '\0' terminated STRING to the string | |
141 | table in OB. Then put the index onto the bitpack BP. | |
142 | When PERSISTENT is set, the string S is supposed to not change during | |
143 | duration of the OB and thus OB can keep pointer into it. */ | |
144 | ||
145 | void | |
146 | bp_pack_string (struct output_block *ob, struct bitpack_d *bp, | |
147 | const char *s, bool persistent) | |
148 | { | |
149 | unsigned index = 0; | |
150 | if (s) | |
151 | index = streamer_string_index (ob, s, strlen (s) + 1, persistent); | |
152 | bp_pack_var_len_unsigned (bp, index); | |
153 | } | |
154 | ||
155 | ||
156 | ||
f0efc7aa DN |
157 | /* Write a zero to the output stream. */ |
158 | ||
159 | void | |
412288f1 | 160 | streamer_write_zero (struct output_block *ob) |
f0efc7aa | 161 | { |
412288f1 | 162 | streamer_write_char_stream (ob->main_stream, 0); |
f0efc7aa DN |
163 | } |
164 | ||
165 | ||
412288f1 | 166 | /* Write an unsigned HOST_WIDE_INT value WORK to OB->main_stream. */ |
f0efc7aa DN |
167 | |
168 | void | |
412288f1 | 169 | streamer_write_uhwi (struct output_block *ob, unsigned HOST_WIDE_INT work) |
f0efc7aa | 170 | { |
412288f1 | 171 | streamer_write_uhwi_stream (ob->main_stream, work); |
f0efc7aa DN |
172 | } |
173 | ||
174 | ||
412288f1 | 175 | /* Write a HOST_WIDE_INT value WORK to OB->main_stream. */ |
f0efc7aa DN |
176 | |
177 | void | |
412288f1 | 178 | streamer_write_hwi (struct output_block *ob, HOST_WIDE_INT work) |
f0efc7aa | 179 | { |
412288f1 | 180 | streamer_write_hwi_stream (ob->main_stream, work); |
f0efc7aa DN |
181 | } |
182 | ||
89ab31c1 JH |
183 | /* Write a gcov counter value WORK to OB->main_stream. */ |
184 | ||
185 | void | |
186 | streamer_write_gcov_count (struct output_block *ob, gcov_type work) | |
187 | { | |
188 | streamer_write_gcov_count_stream (ob->main_stream, work); | |
189 | } | |
f0efc7aa | 190 | |
412288f1 | 191 | /* Write an unsigned HOST_WIDE_INT value WORK to OBS. */ |
f0efc7aa DN |
192 | |
193 | void | |
412288f1 DN |
194 | streamer_write_uhwi_stream (struct lto_output_stream *obs, |
195 | unsigned HOST_WIDE_INT work) | |
f0efc7aa | 196 | { |
a4fa02d1 RB |
197 | if (obs->left_in_block == 0) |
198 | lto_append_block (obs); | |
199 | char *current_pointer = obs->current_pointer; | |
200 | unsigned int left_in_block = obs->left_in_block; | |
201 | unsigned int size = 0; | |
f0efc7aa DN |
202 | do |
203 | { | |
204 | unsigned int byte = (work & 0x7f); | |
205 | work >>= 7; | |
206 | if (work != 0) | |
207 | /* More bytes to follow. */ | |
208 | byte |= 0x80; | |
209 | ||
a4fa02d1 RB |
210 | *(current_pointer++) = byte; |
211 | left_in_block--; | |
212 | size++; | |
f0efc7aa | 213 | } |
a4fa02d1 RB |
214 | while (work != 0 && left_in_block > 0); |
215 | if (work != 0) | |
216 | { | |
217 | obs->left_in_block = 0; | |
218 | lto_append_block (obs); | |
219 | current_pointer = obs->current_pointer; | |
220 | left_in_block = obs->left_in_block; | |
221 | do | |
222 | { | |
223 | unsigned int byte = (work & 0x7f); | |
224 | work >>= 7; | |
225 | if (work != 0) | |
226 | /* More bytes to follow. */ | |
227 | byte |= 0x80; | |
228 | ||
229 | *(current_pointer++) = byte; | |
230 | left_in_block--; | |
231 | size++; | |
232 | } | |
233 | while (work != 0); | |
234 | } | |
235 | obs->current_pointer = current_pointer; | |
236 | obs->left_in_block = left_in_block; | |
237 | obs->total_size += size; | |
f0efc7aa DN |
238 | } |
239 | ||
240 | ||
412288f1 | 241 | /* Write a HOST_WIDE_INT value WORK to OBS. */ |
f0efc7aa DN |
242 | |
243 | void | |
412288f1 | 244 | streamer_write_hwi_stream (struct lto_output_stream *obs, HOST_WIDE_INT work) |
f0efc7aa | 245 | { |
a4fa02d1 RB |
246 | if (obs->left_in_block == 0) |
247 | lto_append_block (obs); | |
248 | char *current_pointer = obs->current_pointer; | |
249 | unsigned int left_in_block = obs->left_in_block; | |
250 | unsigned int size = 0; | |
251 | bool more; | |
f0efc7aa DN |
252 | do |
253 | { | |
a4fa02d1 RB |
254 | unsigned int byte = (work & 0x7f); |
255 | /* If the lower 7-bits are sign-extended 0 or -1 we are finished. */ | |
256 | work >>= 6; | |
257 | more = !(work == 0 || work == -1); | |
f0efc7aa | 258 | if (more) |
a4fa02d1 RB |
259 | { |
260 | /* More bits to follow. */ | |
261 | work >>= 1; | |
262 | byte |= 0x80; | |
263 | } | |
264 | ||
265 | *(current_pointer++) = byte; | |
266 | left_in_block--; | |
267 | size++; | |
268 | } | |
269 | while (more && left_in_block > 0); | |
270 | if (more) | |
271 | { | |
272 | obs->left_in_block = 0; | |
273 | lto_append_block (obs); | |
274 | current_pointer = obs->current_pointer; | |
275 | left_in_block = obs->left_in_block; | |
276 | do | |
277 | { | |
278 | unsigned int byte = (work & 0x7f); | |
279 | work >>= 6; | |
280 | more = !(work == 0 || work == -1); | |
281 | if (more) | |
282 | { | |
283 | work >>= 1; | |
284 | byte |= 0x80; | |
285 | } | |
286 | ||
287 | *(current_pointer++) = byte; | |
288 | left_in_block--; | |
289 | size++; | |
290 | } | |
291 | while (more); | |
f0efc7aa | 292 | } |
a4fa02d1 RB |
293 | obs->current_pointer = current_pointer; |
294 | obs->left_in_block = left_in_block; | |
295 | obs->total_size += size; | |
f0efc7aa | 296 | } |
89ab31c1 JH |
297 | |
298 | /* Write a GCOV counter value WORK to OBS. */ | |
299 | ||
300 | void | |
301 | streamer_write_gcov_count_stream (struct lto_output_stream *obs, gcov_type work) | |
302 | { | |
303 | gcc_assert (work >= 0); | |
304 | gcc_assert ((HOST_WIDE_INT) work == work); | |
305 | streamer_write_hwi_stream (obs, work); | |
306 | } |