Home | History | Annotate | Line # | Download | only in gcc
data-streamer.h revision 1.1
      1 /* Generic streaming support for various data types.
      2 
      3    Copyright (C) 2011-2013 Free Software Foundation, Inc.
      4    Contributed by Diego Novillo <dnovillo (at) 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