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