1 /* Generic streaming support for various data types. 2 3 Copyright (C) 2011-2013 Free Software Foundation, Inc. 4 Contributed by Diego Novillo <dnovillo@google.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 #ifndef GCC_DATA_STREAMER_H 23 #define GCC_DATA_STREAMER_H 24 25 #include "vec.h" 26 #include "lto-streamer.h" 27 28 /* Data structures used to pack values and bitflags into a vector of 29 words. Used to stream values of a fixed number of bits in a space 30 efficient way. */ 31 static unsigned const BITS_PER_BITPACK_WORD = HOST_BITS_PER_WIDE_INT; 32 33 typedef unsigned HOST_WIDE_INT bitpack_word_t; 34 35 struct bitpack_d 36 { 37 /* The position of the first unused or unconsumed bit in the word. */ 38 unsigned pos; 39 40 /* The current word we are (un)packing. */ 41 bitpack_word_t word; 42 43 /* The lto_output_stream or the lto_input_block we are streaming to/from. */ 44 void *stream; 45 }; 46 47 48 /* String hashing. */ 49 struct string_slot 50 { 51 const char *s; 52 int len; 53 unsigned int slot_num; 54 }; 55 56 /* In data-streamer.c */ 57 void bp_pack_var_len_unsigned (struct bitpack_d *, unsigned HOST_WIDE_INT); 58 void bp_pack_var_len_int (struct bitpack_d *, HOST_WIDE_INT); 59 unsigned HOST_WIDE_INT bp_unpack_var_len_unsigned (struct bitpack_d *); 60 HOST_WIDE_INT bp_unpack_var_len_int (struct bitpack_d *); 61 62 /* In data-streamer-out.c */ 63 void streamer_write_zero (struct output_block *); 64 void streamer_write_uhwi (struct output_block *, unsigned HOST_WIDE_INT); 65 void streamer_write_hwi (struct output_block *, HOST_WIDE_INT); 66 void streamer_write_string (struct output_block *, struct lto_output_stream *, 67 const char *, bool); 68 unsigned streamer_string_index (struct output_block *, const char *, 69 unsigned int, bool); 70 void streamer_write_string_with_length (struct output_block *, 71 struct lto_output_stream *, 72 const char *, unsigned int, bool); 73 void bp_pack_string_with_length (struct output_block *, struct bitpack_d *, 74 const char *, unsigned int, bool); 75 void bp_pack_string (struct output_block *, struct bitpack_d *, 76 const char *, bool); 77 void streamer_write_uhwi_stream (struct lto_output_stream *, 78 unsigned HOST_WIDE_INT); 79 void streamer_write_hwi_stream (struct lto_output_stream *, HOST_WIDE_INT); 80 81 /* In data-streamer-in.c */ 82 const char *string_for_index (struct data_in *, unsigned int, unsigned int *); 83 const char *streamer_read_string (struct data_in *, struct lto_input_block *); 84 const char *streamer_read_indexed_string (struct data_in *, 85 struct lto_input_block *, 86 unsigned int *); 87 const char *bp_unpack_indexed_string (struct data_in *, struct bitpack_d *, 88 unsigned int *); 89 const char *bp_unpack_string (struct data_in *, struct bitpack_d *); 90 unsigned HOST_WIDE_INT streamer_read_uhwi (struct lto_input_block *); 91 HOST_WIDE_INT streamer_read_hwi (struct lto_input_block *); 92 93 /* Returns a hash code for P. Adapted from libiberty's htab_hash_string 94 to support strings that may not end in '\0'. */ 95 96 static inline hashval_t 97 hash_string_slot_node (const void *p) 98 { 99 const struct string_slot *ds = (const struct string_slot *) p; 100 hashval_t r = ds->len; 101 int i; 102 103 for (i = 0; i < ds->len; i++) 104 r = r * 67 + (unsigned)ds->s[i] - 113; 105 return r; 106 } 107 108 /* Returns nonzero if P1 and P2 are equal. */ 109 110 static inline int 111 eq_string_slot_node (const void *p1, const void *p2) 112 { 113 const struct string_slot *ds1 = (const struct string_slot *) p1; 114 const struct string_slot *ds2 = (const struct string_slot *) p2; 115 116 if (ds1->len == ds2->len) 117 return memcmp (ds1->s, ds2->s, ds1->len) == 0; 118 119 return 0; 120 } 121 122 /* Returns a new bit-packing context for bit-packing into S. */ 123 static inline struct bitpack_d 124 bitpack_create (struct lto_output_stream *s) 125 { 126 struct bitpack_d bp; 127 bp.pos = 0; 128 bp.word = 0; 129 bp.stream = (void *)s; 130 return bp; 131 } 132 133 /* Pack the NBITS bit sized value VAL into the bit-packing context BP. */ 134 static inline void 135 bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits) 136 { 137 bitpack_word_t word = bp->word; 138 int pos = bp->pos; 139 140 /* Verify that VAL fits in the NBITS. */ 141 gcc_checking_assert (nbits == BITS_PER_BITPACK_WORD 142 || !(val & ~(((bitpack_word_t)1<<nbits)-1))); 143 144 /* If val does not fit into the current bitpack word switch to the 145 next one. */ 146 if (pos + nbits > BITS_PER_BITPACK_WORD) 147 { 148 streamer_write_uhwi_stream ((struct lto_output_stream *) bp->stream, 149 word); 150 word = val; 151 pos = nbits; 152 } 153 else 154 { 155 word |= val << pos; 156 pos += nbits; 157 } 158 bp->word = word; 159 bp->pos = pos; 160 } 161 162 /* Finishes bit-packing of BP. */ 163 static inline void 164 streamer_write_bitpack (struct bitpack_d *bp) 165 { 166 streamer_write_uhwi_stream ((struct lto_output_stream *) bp->stream, 167 bp->word); 168 bp->word = 0; 169 bp->pos = 0; 170 } 171 172 /* Returns a new bit-packing context for bit-unpacking from IB. */ 173 static inline struct bitpack_d 174 streamer_read_bitpack (struct lto_input_block *ib) 175 { 176 struct bitpack_d bp; 177 bp.word = streamer_read_uhwi (ib); 178 bp.pos = 0; 179 bp.stream = (void *)ib; 180 return bp; 181 } 182 183 /* Unpacks NBITS bits from the bit-packing context BP and returns them. */ 184 static inline bitpack_word_t 185 bp_unpack_value (struct bitpack_d *bp, unsigned nbits) 186 { 187 bitpack_word_t mask, val; 188 int pos = bp->pos; 189 190 mask = (nbits == BITS_PER_BITPACK_WORD 191 ? (bitpack_word_t) -1 192 : ((bitpack_word_t) 1 << nbits) - 1); 193 194 /* If there are not continuous nbits in the current bitpack word 195 switch to the next one. */ 196 if (pos + nbits > BITS_PER_BITPACK_WORD) 197 { 198 bp->word = val 199 = streamer_read_uhwi ((struct lto_input_block *)bp->stream); 200 bp->pos = nbits; 201 return val & mask; 202 } 203 val = bp->word; 204 val >>= pos; 205 bp->pos = pos + nbits; 206 207 return val & mask; 208 } 209 210 211 /* Write a character to the output block. */ 212 213 static inline void 214 streamer_write_char_stream (struct lto_output_stream *obs, char c) 215 { 216 /* No space left. */ 217 if (obs->left_in_block == 0) 218 lto_append_block (obs); 219 220 /* Write the actual character. */ 221 *obs->current_pointer = c; 222 obs->current_pointer++; 223 obs->total_size++; 224 obs->left_in_block--; 225 } 226 227 228 /* Read byte from the input block. */ 229 230 static inline unsigned char 231 streamer_read_uchar (struct lto_input_block *ib) 232 { 233 if (ib->p >= ib->len) 234 lto_section_overrun (ib); 235 return (ib->data[ib->p++]); 236 } 237 238 /* Output VAL into OBS and verify it is in range MIN...MAX that is supposed 239 to be compile time constant. 240 Be host independent, limit range to 31bits. */ 241 242 static inline void 243 streamer_write_hwi_in_range (struct lto_output_stream *obs, 244 HOST_WIDE_INT min, 245 HOST_WIDE_INT max, 246 HOST_WIDE_INT val) 247 { 248 HOST_WIDE_INT range = max - min; 249 250 gcc_checking_assert (val >= min && val <= max && range > 0 251 && range < 0x7fffffff); 252 253 val -= min; 254 streamer_write_char_stream (obs, val & 255); 255 if (range >= 0xff) 256 streamer_write_char_stream (obs, (val >> 8) & 255); 257 if (range >= 0xffff) 258 streamer_write_char_stream (obs, (val >> 16) & 255); 259 if (range >= 0xffffff) 260 streamer_write_char_stream (obs, (val >> 24) & 255); 261 } 262 263 /* Input VAL into OBS and verify it is in range MIN...MAX that is supposed 264 to be compile time constant. PURPOSE is used for error reporting. */ 265 266 static inline HOST_WIDE_INT 267 streamer_read_hwi_in_range (struct lto_input_block *ib, 268 const char *purpose, 269 HOST_WIDE_INT min, 270 HOST_WIDE_INT max) 271 { 272 HOST_WIDE_INT range = max - min; 273 HOST_WIDE_INT val = streamer_read_uchar (ib); 274 275 gcc_checking_assert (range > 0 && range < 0x7fffffff); 276 277 if (range >= 0xff) 278 val |= ((HOST_WIDE_INT)streamer_read_uchar (ib)) << 8; 279 if (range >= 0xffff) 280 val |= ((HOST_WIDE_INT)streamer_read_uchar (ib)) << 16; 281 if (range >= 0xffffff) 282 val |= ((HOST_WIDE_INT)streamer_read_uchar (ib)) << 24; 283 val += min; 284 if (val < min || val > max) 285 lto_value_range_error (purpose, val, min, max); 286 return val; 287 } 288 289 /* Output VAL into BP and verify it is in range MIN...MAX that is supposed 290 to be compile time constant. 291 Be host independent, limit range to 31bits. */ 292 293 static inline void 294 bp_pack_int_in_range (struct bitpack_d *bp, 295 HOST_WIDE_INT min, 296 HOST_WIDE_INT max, 297 HOST_WIDE_INT val) 298 { 299 HOST_WIDE_INT range = max - min; 300 int nbits = floor_log2 (range) + 1; 301 302 gcc_checking_assert (val >= min && val <= max && range > 0 303 && range < 0x7fffffff); 304 305 val -= min; 306 bp_pack_value (bp, val, nbits); 307 } 308 309 /* Input VAL into BP and verify it is in range MIN...MAX that is supposed 310 to be compile time constant. PURPOSE is used for error reporting. */ 311 312 static inline HOST_WIDE_INT 313 bp_unpack_int_in_range (struct bitpack_d *bp, 314 const char *purpose, 315 HOST_WIDE_INT min, 316 HOST_WIDE_INT max) 317 { 318 HOST_WIDE_INT range = max - min; 319 int nbits = floor_log2 (range) + 1; 320 HOST_WIDE_INT val = bp_unpack_value (bp, nbits); 321 322 gcc_checking_assert (range > 0 && range < 0x7fffffff); 323 324 if (val < min || val > max) 325 lto_value_range_error (purpose, val, min, max); 326 return val; 327 } 328 329 /* Output VAL of type "enum enum_name" into OBS. 330 Assume range 0...ENUM_LAST - 1. */ 331 #define streamer_write_enum(obs,enum_name,enum_last,val) \ 332 streamer_write_hwi_in_range ((obs), 0, (int)(enum_last) - 1, (int)(val)) 333 334 /* Input enum of type "enum enum_name" from IB. 335 Assume range 0...ENUM_LAST - 1. */ 336 #define streamer_read_enum(ib,enum_name,enum_last) \ 337 (enum enum_name)streamer_read_hwi_in_range ((ib), #enum_name, 0, \ 338 (int)(enum_last) - 1) 339 340 /* Output VAL of type "enum enum_name" into BP. 341 Assume range 0...ENUM_LAST - 1. */ 342 #define bp_pack_enum(bp,enum_name,enum_last,val) \ 343 bp_pack_int_in_range ((bp), 0, (int)(enum_last) - 1, (int)(val)) 344 345 /* Input enum of type "enum enum_name" from BP. 346 Assume range 0...ENUM_LAST - 1. */ 347 #define bp_unpack_enum(bp,enum_name,enum_last) \ 348 (enum enum_name)bp_unpack_int_in_range ((bp), #enum_name, 0, \ 349 (int)(enum_last) - 1) 350 351 /* Output the start of a record with TAG to output block OB. */ 352 353 static inline void 354 streamer_write_record_start (struct output_block *ob, enum LTO_tags tag) 355 { 356 streamer_write_enum (ob->main_stream, LTO_tags, LTO_NUM_TAGS, tag); 357 } 358 359 /* Return the next tag in the input block IB. */ 360 361 static inline enum LTO_tags 362 streamer_read_record_start (struct lto_input_block *ib) 363 { 364 return streamer_read_enum (ib, LTO_tags, LTO_NUM_TAGS); 365 } 366 367 #endif /* GCC_DATA_STREAMER_H */ 368