data-streamer.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* Generic streaming support for various data types.
  2. Copyright (C) 2011-2020 Free Software Foundation, Inc.
  3. Contributed by Diego Novillo <dnovillo@google.com>
  4. This file is part of GCC.
  5. GCC is free software; you can redistribute it and/or modify it under
  6. the terms of the GNU General Public License as published by the Free
  7. Software Foundation; either version 3, or (at your option) any later
  8. version.
  9. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GCC; see the file COPYING3. If not see
  15. <http://www.gnu.org/licenses/>. */
  16. #ifndef GCC_DATA_STREAMER_H
  17. #define GCC_DATA_STREAMER_H
  18. #include "lto-streamer.h"
  19. /* Data structures used to pack values and bitflags into a vector of
  20. words. Used to stream values of a fixed number of bits in a space
  21. efficient way. */
  22. static unsigned const BITS_PER_BITPACK_WORD = HOST_BITS_PER_WIDE_INT;
  23. typedef unsigned HOST_WIDE_INT bitpack_word_t;
  24. struct bitpack_d
  25. {
  26. /* The position of the first unused or unconsumed bit in the word. */
  27. unsigned pos;
  28. /* The current word we are (un)packing. */
  29. bitpack_word_t word;
  30. /* The lto_output_stream or the lto_input_block we are streaming to/from. */
  31. void *stream;
  32. };
  33. /* In data-streamer.c */
  34. void bp_pack_var_len_unsigned (struct bitpack_d *, unsigned HOST_WIDE_INT);
  35. void bp_pack_var_len_int (struct bitpack_d *, HOST_WIDE_INT);
  36. unsigned HOST_WIDE_INT bp_unpack_var_len_unsigned (struct bitpack_d *);
  37. HOST_WIDE_INT bp_unpack_var_len_int (struct bitpack_d *);
  38. /* In data-streamer-out.c */
  39. void streamer_write_zero (struct output_block *);
  40. void streamer_write_uhwi (struct output_block *, unsigned HOST_WIDE_INT);
  41. void streamer_write_hwi (struct output_block *, HOST_WIDE_INT);
  42. void streamer_write_poly_uint64 (struct output_block *, poly_uint64);
  43. void streamer_write_gcov_count (struct output_block *, gcov_type);
  44. void streamer_write_string (struct output_block *, struct lto_output_stream *,
  45. const char *, bool);
  46. void streamer_write_string_with_length (struct output_block *,
  47. struct lto_output_stream *,
  48. const char *, unsigned int, bool);
  49. void bp_pack_string_with_length (struct output_block *, struct bitpack_d *,
  50. const char *, unsigned int, bool);
  51. void bp_pack_string (struct output_block *, struct bitpack_d *,
  52. const char *, bool);
  53. void streamer_write_uhwi_stream (struct lto_output_stream *,
  54. unsigned HOST_WIDE_INT);
  55. void streamer_write_hwi_stream (struct lto_output_stream *, HOST_WIDE_INT);
  56. void streamer_write_gcov_count_stream (struct lto_output_stream *, gcov_type);
  57. void streamer_write_data_stream (struct lto_output_stream *, const void *,
  58. size_t);
  59. void streamer_write_wide_int (struct output_block *, const wide_int &);
  60. void streamer_write_widest_int (struct output_block *, const widest_int &);
  61. /* In data-streamer-in.c */
  62. const char *streamer_read_string (class data_in *, class lto_input_block *);
  63. const char *streamer_read_indexed_string (class data_in *,
  64. class lto_input_block *,
  65. unsigned int *);
  66. const char *bp_unpack_indexed_string (class data_in *, struct bitpack_d *,
  67. unsigned int *);
  68. const char *bp_unpack_string (class data_in *, struct bitpack_d *);
  69. unsigned HOST_WIDE_INT streamer_read_uhwi (class lto_input_block *);
  70. HOST_WIDE_INT streamer_read_hwi (class lto_input_block *);
  71. poly_uint64 streamer_read_poly_uint64 (class lto_input_block *);
  72. gcov_type streamer_read_gcov_count (class lto_input_block *);
  73. wide_int streamer_read_wide_int (class lto_input_block *);
  74. widest_int streamer_read_widest_int (class lto_input_block *);
  75. /* Returns a new bit-packing context for bit-packing into S. */
  76. static inline struct bitpack_d
  77. bitpack_create (struct lto_output_stream *s)
  78. {
  79. struct bitpack_d bp;
  80. bp.pos = 0;
  81. bp.word = 0;
  82. bp.stream = (void *)s;
  83. return bp;
  84. }
  85. /* Pack the NBITS bit sized value VAL into the bit-packing context BP. */
  86. static inline void
  87. bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits)
  88. {
  89. bitpack_word_t word = bp->word;
  90. int pos = bp->pos;
  91. /* Verify that VAL fits in the NBITS. */
  92. gcc_checking_assert (nbits == BITS_PER_BITPACK_WORD
  93. || !(val & ~(((bitpack_word_t)1<<nbits)-1)));
  94. /* If val does not fit into the current bitpack word switch to the
  95. next one. */
  96. if (pos + nbits > BITS_PER_BITPACK_WORD)
  97. {
  98. streamer_write_uhwi_stream ((struct lto_output_stream *) bp->stream,
  99. word);
  100. word = val;
  101. pos = nbits;
  102. }
  103. else
  104. {
  105. word |= val << pos;
  106. pos += nbits;
  107. }
  108. bp->word = word;
  109. bp->pos = pos;
  110. }
  111. /* Pack VAL into the bit-packing context BP, using NBITS for each
  112. coefficient. */
  113. static inline void
  114. bp_pack_poly_value (struct bitpack_d *bp,
  115. const poly_int<NUM_POLY_INT_COEFFS, bitpack_word_t> &val,
  116. unsigned nbits)
  117. {
  118. for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
  119. bp_pack_value (bp, val.coeffs[i], nbits);
  120. }
  121. /* Finishes bit-packing of BP. */
  122. static inline void
  123. streamer_write_bitpack (struct bitpack_d *bp)
  124. {
  125. streamer_write_uhwi_stream ((struct lto_output_stream *) bp->stream,
  126. bp->word);
  127. bp->word = 0;
  128. bp->pos = 0;
  129. }
  130. /* Returns a new bit-packing context for bit-unpacking from IB. */
  131. static inline struct bitpack_d
  132. streamer_read_bitpack (class lto_input_block *ib)
  133. {
  134. struct bitpack_d bp;
  135. bp.word = streamer_read_uhwi (ib);
  136. bp.pos = 0;
  137. bp.stream = (void *)ib;
  138. return bp;
  139. }
  140. /* Unpacks NBITS bits from the bit-packing context BP and returns them. */
  141. static inline bitpack_word_t
  142. bp_unpack_value (struct bitpack_d *bp, unsigned nbits)
  143. {
  144. bitpack_word_t mask, val;
  145. int pos = bp->pos;
  146. mask = (nbits == BITS_PER_BITPACK_WORD
  147. ? (bitpack_word_t) -1
  148. : ((bitpack_word_t) 1 << nbits) - 1);
  149. /* If there are not continuous nbits in the current bitpack word
  150. switch to the next one. */
  151. if (pos + nbits > BITS_PER_BITPACK_WORD)
  152. {
  153. bp->word = val
  154. = streamer_read_uhwi ((class lto_input_block *)bp->stream);
  155. bp->pos = nbits;
  156. return val & mask;
  157. }
  158. val = bp->word;
  159. val >>= pos;
  160. bp->pos = pos + nbits;
  161. return val & mask;
  162. }
  163. /* Unpacks a polynomial value from the bit-packing context BP in which each
  164. coefficient has NBITS bits. */
  165. static inline poly_int<NUM_POLY_INT_COEFFS, bitpack_word_t>
  166. bp_unpack_poly_value (struct bitpack_d *bp, unsigned nbits)
  167. {
  168. poly_int_pod<NUM_POLY_INT_COEFFS, bitpack_word_t> x;
  169. for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
  170. x.coeffs[i] = bp_unpack_value (bp, nbits);
  171. return x;
  172. }
  173. /* Write a character to the output block. */
  174. static inline void
  175. streamer_write_char_stream (struct lto_output_stream *obs, char c)
  176. {
  177. /* No space left. */
  178. if (obs->left_in_block == 0)
  179. lto_append_block (obs);
  180. /* Write the actual character. */
  181. char *current_pointer = obs->current_pointer;
  182. *(current_pointer++) = c;
  183. obs->current_pointer = current_pointer;
  184. obs->total_size++;
  185. obs->left_in_block--;
  186. }
  187. /* Read byte from the input block. */
  188. static inline unsigned char
  189. streamer_read_uchar (class lto_input_block *ib)
  190. {
  191. if (ib->p >= ib->len)
  192. lto_section_overrun (ib);
  193. return (ib->data[ib->p++]);
  194. }
  195. /* Output VAL into OBS and verify it is in range MIN...MAX that is supposed
  196. to be compile time constant.
  197. Be host independent, limit range to 31bits. */
  198. static inline void
  199. streamer_write_hwi_in_range (struct lto_output_stream *obs,
  200. HOST_WIDE_INT min,
  201. HOST_WIDE_INT max,
  202. HOST_WIDE_INT val)
  203. {
  204. HOST_WIDE_INT range = max - min;
  205. gcc_checking_assert (val >= min && val <= max && range > 0
  206. && range < 0x7fffffff);
  207. val -= min;
  208. streamer_write_uhwi_stream (obs, (unsigned HOST_WIDE_INT) val);
  209. }
  210. /* Input VAL into OBS and verify it is in range MIN...MAX that is supposed
  211. to be compile time constant. PURPOSE is used for error reporting. */
  212. static inline HOST_WIDE_INT
  213. streamer_read_hwi_in_range (class lto_input_block *ib,
  214. const char *purpose,
  215. HOST_WIDE_INT min,
  216. HOST_WIDE_INT max)
  217. {
  218. HOST_WIDE_INT range = max - min;
  219. unsigned HOST_WIDE_INT uval = streamer_read_uhwi (ib);
  220. gcc_checking_assert (range > 0 && range < 0x7fffffff);
  221. HOST_WIDE_INT val = (HOST_WIDE_INT) (uval + (unsigned HOST_WIDE_INT) min);
  222. if (val < min || val > max)
  223. lto_value_range_error (purpose, val, min, max);
  224. return val;
  225. }
  226. /* Output VAL into BP and verify it is in range MIN...MAX that is supposed
  227. to be compile time constant.
  228. Be host independent, limit range to 31bits. */
  229. static inline void
  230. bp_pack_int_in_range (struct bitpack_d *bp,
  231. HOST_WIDE_INT min,
  232. HOST_WIDE_INT max,
  233. HOST_WIDE_INT val)
  234. {
  235. HOST_WIDE_INT range = max - min;
  236. int nbits = floor_log2 (range) + 1;
  237. gcc_checking_assert (val >= min && val <= max && range > 0
  238. && range < 0x7fffffff);
  239. val -= min;
  240. bp_pack_value (bp, val, nbits);
  241. }
  242. /* Input VAL into BP and verify it is in range MIN...MAX that is supposed
  243. to be compile time constant. PURPOSE is used for error reporting. */
  244. static inline HOST_WIDE_INT
  245. bp_unpack_int_in_range (struct bitpack_d *bp,
  246. const char *purpose,
  247. HOST_WIDE_INT min,
  248. HOST_WIDE_INT max)
  249. {
  250. HOST_WIDE_INT range = max - min;
  251. int nbits = floor_log2 (range) + 1;
  252. HOST_WIDE_INT val = bp_unpack_value (bp, nbits);
  253. gcc_checking_assert (range > 0 && range < 0x7fffffff);
  254. if (val < min || val > max)
  255. lto_value_range_error (purpose, val, min, max);
  256. return val;
  257. }
  258. /* Output VAL of type "enum enum_name" into OBS.
  259. Assume range 0...ENUM_LAST - 1. */
  260. #define streamer_write_enum(obs,enum_name,enum_last,val) \
  261. streamer_write_hwi_in_range ((obs), 0, (int)(enum_last) - 1, (int)(val))
  262. /* Input enum of type "enum enum_name" from IB.
  263. Assume range 0...ENUM_LAST - 1. */
  264. #define streamer_read_enum(ib,enum_name,enum_last) \
  265. (enum enum_name)streamer_read_hwi_in_range ((ib), #enum_name, 0, \
  266. (int)(enum_last) - 1)
  267. /* Output VAL of type "enum enum_name" into BP.
  268. Assume range 0...ENUM_LAST - 1. */
  269. #define bp_pack_enum(bp,enum_name,enum_last,val) \
  270. bp_pack_int_in_range ((bp), 0, (int)(enum_last) - 1, (int)(val))
  271. /* Input enum of type "enum enum_name" from BP.
  272. Assume range 0...ENUM_LAST - 1. */
  273. #define bp_unpack_enum(bp,enum_name,enum_last) \
  274. (enum enum_name)bp_unpack_int_in_range ((bp), #enum_name, 0, \
  275. (int)(enum_last) - 1)
  276. /* Output the start of a record with TAG to output block OB. */
  277. static inline void
  278. streamer_write_record_start (struct output_block *ob, enum LTO_tags tag)
  279. {
  280. streamer_write_enum (ob->main_stream, LTO_tags, LTO_NUM_TAGS, tag);
  281. }
  282. /* Return the next tag in the input block IB. */
  283. static inline enum LTO_tags
  284. streamer_read_record_start (class lto_input_block *ib)
  285. {
  286. return streamer_read_enum (ib, LTO_tags, LTO_NUM_TAGS);
  287. }
  288. #endif /* GCC_DATA_STREAMER_H */