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