BitcodeConvenience.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. //===- llvm/Bitcode/BitcodeConvenience.h - Convenience Wrappers -*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file Convenience wrappers for the LLVM bitcode format and bitstream APIs.
  10. ///
  11. /// This allows you to use a sort of DSL to declare and use bitcode
  12. /// abbreviations and records. Example:
  13. ///
  14. /// \code
  15. /// using Metadata = BCRecordLayout<
  16. /// METADATA_ID, // ID
  17. /// BCFixed<16>, // Module format major version
  18. /// BCFixed<16>, // Module format minor version
  19. /// BCBlob // misc. version information
  20. /// >;
  21. /// Metadata metadata(Out);
  22. /// metadata.emit(ScratchRecord, VERSION_MAJOR, VERSION_MINOR, Data);
  23. /// \endcode
  24. ///
  25. /// For details on the bitcode format, see
  26. /// http://llvm.org/docs/BitCodeFormat.html
  27. ///
  28. //===----------------------------------------------------------------------===//
  29. #ifndef LLVM_BITCODE_BITCODECONVENIENCE_H
  30. #define LLVM_BITCODE_BITCODECONVENIENCE_H
  31. #include "llvm/Bitstream/BitCodes.h"
  32. #include "llvm/Bitstream/BitstreamWriter.h"
  33. #include <cstdint>
  34. namespace llvm {
  35. namespace detail {
  36. /// Convenience base for all kinds of bitcode abbreviation fields.
  37. ///
  38. /// This just defines common properties queried by the metaprogramming.
  39. template <bool Compound = false> class BCField {
  40. public:
  41. static const bool IsCompound = Compound;
  42. /// Asserts that the given data is a valid value for this field.
  43. template <typename T> static void assertValid(const T &data) {}
  44. /// Converts a raw numeric representation of this value to its preferred
  45. /// type.
  46. template <typename T> static T convert(T rawValue) { return rawValue; }
  47. };
  48. } // namespace detail
  49. /// Represents a literal operand in a bitcode record.
  50. ///
  51. /// The value of a literal operand is the same for all instances of the record,
  52. /// so it is only emitted in the abbreviation definition.
  53. ///
  54. /// Note that because this uses a compile-time template, you cannot have a
  55. /// literal operand that is fixed at run-time without dropping down to the
  56. /// raw LLVM APIs.
  57. template <uint64_t Value> class BCLiteral : public detail::BCField<> {
  58. public:
  59. static void emitOp(llvm::BitCodeAbbrev &abbrev) {
  60. abbrev.Add(llvm::BitCodeAbbrevOp(Value));
  61. }
  62. template <typename T> static void assertValid(const T &data) {
  63. assert(data == Value && "data value does not match declared literal value");
  64. }
  65. };
  66. /// Represents a fixed-width value in a bitcode record.
  67. ///
  68. /// Note that the LLVM bitcode format only supports unsigned values.
  69. template <unsigned Width> class BCFixed : public detail::BCField<> {
  70. public:
  71. static_assert(Width <= 64, "fixed-width field is too large");
  72. static void emitOp(llvm::BitCodeAbbrev &abbrev) {
  73. abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, Width));
  74. }
  75. static void assertValid(const bool &data) {
  76. assert(llvm::isUInt<Width>(data) &&
  77. "data value does not fit in the given bit width");
  78. }
  79. template <typename T> static void assertValid(const T &data) {
  80. assert(data >= 0 && "cannot encode signed integers");
  81. assert(llvm::isUInt<Width>(data) &&
  82. "data value does not fit in the given bit width");
  83. }
  84. };
  85. /// Represents a variable-width value in a bitcode record.
  86. ///
  87. /// The \p Width parameter should include the continuation bit.
  88. ///
  89. /// Note that the LLVM bitcode format only supports unsigned values.
  90. template <unsigned Width> class BCVBR : public detail::BCField<> {
  91. static_assert(Width >= 2, "width does not have room for continuation bit");
  92. public:
  93. static void emitOp(llvm::BitCodeAbbrev &abbrev) {
  94. abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, Width));
  95. }
  96. template <typename T> static void assertValid(const T &data) {
  97. assert(data >= 0 && "cannot encode signed integers");
  98. }
  99. };
  100. /// Represents a character encoded in LLVM's Char6 encoding.
  101. ///
  102. /// This format is suitable for encoding decimal numbers (without signs or
  103. /// exponents) and C identifiers (without dollar signs), but not much else.
  104. ///
  105. /// \sa http://llvm.org/docs/BitCodeFormat.html#char6-encoded-value
  106. class BCChar6 : public detail::BCField<> {
  107. public:
  108. static void emitOp(llvm::BitCodeAbbrev &abbrev) {
  109. abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Char6));
  110. }
  111. template <typename T> static void assertValid(const T &data) {
  112. assert(llvm::BitCodeAbbrevOp::isChar6(data) && "invalid Char6 data");
  113. }
  114. template <typename T> char convert(T rawValue) {
  115. return static_cast<char>(rawValue);
  116. }
  117. };
  118. /// Represents an untyped blob of bytes.
  119. ///
  120. /// If present, this must be the last field in a record.
  121. class BCBlob : public detail::BCField<true> {
  122. public:
  123. static void emitOp(llvm::BitCodeAbbrev &abbrev) {
  124. abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
  125. }
  126. };
  127. /// Represents an array of some other type.
  128. ///
  129. /// If present, this must be the last field in a record.
  130. template <typename ElementTy> class BCArray : public detail::BCField<true> {
  131. static_assert(!ElementTy::IsCompound, "arrays can only contain scalar types");
  132. public:
  133. static void emitOp(llvm::BitCodeAbbrev &abbrev) {
  134. abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array));
  135. ElementTy::emitOp(abbrev);
  136. }
  137. };
  138. namespace detail {
  139. /// Attaches the last field to an abbreviation.
  140. ///
  141. /// This is the base case for \c emitOps.
  142. ///
  143. /// \sa BCRecordLayout::emitAbbrev
  144. template <typename FieldTy> static void emitOps(llvm::BitCodeAbbrev &abbrev) {
  145. FieldTy::emitOp(abbrev);
  146. }
  147. /// Attaches fields to an abbreviation.
  148. ///
  149. /// This is the recursive case for \c emitOps.
  150. ///
  151. /// \sa BCRecordLayout::emitAbbrev
  152. template <typename FieldTy, typename Next, typename... Rest>
  153. static void emitOps(llvm::BitCodeAbbrev &abbrev) {
  154. static_assert(!FieldTy::IsCompound,
  155. "arrays and blobs may not appear in the middle of a record");
  156. FieldTy::emitOp(abbrev);
  157. emitOps<Next, Rest...>(abbrev);
  158. }
  159. /// Helper class for dealing with a scalar element in the middle of a record.
  160. ///
  161. /// \sa BCRecordLayout
  162. template <typename ElementTy, typename... Fields> class BCRecordCoding {
  163. public:
  164. template <typename BufferTy, typename ElementDataTy, typename... DataTy>
  165. static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
  166. unsigned code, ElementDataTy element, DataTy &&...data) {
  167. static_assert(!ElementTy::IsCompound,
  168. "arrays and blobs may not appear in the middle of a record");
  169. ElementTy::assertValid(element);
  170. buffer.push_back(element);
  171. BCRecordCoding<Fields...>::emit(Stream, buffer, code,
  172. std::forward<DataTy>(data)...);
  173. }
  174. template <typename T, typename ElementDataTy, typename... DataTy>
  175. static void read(ArrayRef<T> buffer, ElementDataTy &element,
  176. DataTy &&...data) {
  177. assert(!buffer.empty() && "too few elements in buffer");
  178. element = ElementTy::convert(buffer.front());
  179. BCRecordCoding<Fields...>::read(buffer.slice(1),
  180. std::forward<DataTy>(data)...);
  181. }
  182. template <typename T, typename... DataTy>
  183. static void read(ArrayRef<T> buffer, NoneType, DataTy &&...data) {
  184. assert(!buffer.empty() && "too few elements in buffer");
  185. BCRecordCoding<Fields...>::read(buffer.slice(1),
  186. std::forward<DataTy>(data)...);
  187. }
  188. };
  189. /// Helper class for dealing with a scalar element at the end of a record.
  190. ///
  191. /// This has a separate implementation because up until now we've only been
  192. /// \em building the record (into a data buffer), and now we need to hand it
  193. /// off to the BitstreamWriter to be emitted.
  194. ///
  195. /// \sa BCRecordLayout
  196. template <typename ElementTy> class BCRecordCoding<ElementTy> {
  197. public:
  198. template <typename BufferTy, typename DataTy>
  199. static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
  200. unsigned code, const DataTy &data) {
  201. static_assert(!ElementTy::IsCompound,
  202. "arrays and blobs need special handling");
  203. ElementTy::assertValid(data);
  204. buffer.push_back(data);
  205. Stream.EmitRecordWithAbbrev(code, buffer);
  206. }
  207. template <typename T, typename DataTy>
  208. static void read(ArrayRef<T> buffer, DataTy &data) {
  209. assert(buffer.size() == 1 && "record data does not match layout");
  210. data = ElementTy::convert(buffer.front());
  211. }
  212. template <typename T> static void read(ArrayRef<T> buffer, NoneType) {
  213. assert(buffer.size() == 1 && "record data does not match layout");
  214. (void)buffer;
  215. }
  216. template <typename T> static void read(ArrayRef<T> buffer) = delete;
  217. };
  218. /// Helper class for dealing with an array at the end of a record.
  219. ///
  220. /// \sa BCRecordLayout::emitRecord
  221. template <typename ElementTy> class BCRecordCoding<BCArray<ElementTy>> {
  222. public:
  223. template <typename BufferTy>
  224. static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
  225. unsigned code, StringRef data) {
  226. // TODO: validate array data.
  227. Stream.EmitRecordWithArray(code, buffer, data);
  228. }
  229. template <typename BufferTy, typename ArrayTy>
  230. static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
  231. unsigned code, const ArrayTy &array) {
  232. #ifndef NDEBUG
  233. for (auto &element : array)
  234. ElementTy::assertValid(element);
  235. #endif
  236. buffer.reserve(buffer.size() + std::distance(array.begin(), array.end()));
  237. std::copy(array.begin(), array.end(), std::back_inserter(buffer));
  238. Stream.EmitRecordWithAbbrev(code, buffer);
  239. }
  240. template <typename BufferTy, typename ElementDataTy, typename... DataTy>
  241. static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
  242. unsigned code, ElementDataTy element, DataTy... data) {
  243. std::array<ElementDataTy, 1 + sizeof...(data)> array{{element, data...}};
  244. emit(Stream, buffer, code, array);
  245. }
  246. template <typename BufferTy>
  247. static void emit(llvm::BitstreamWriter &Stream, BufferTy &Buffer,
  248. unsigned code, NoneType) {
  249. Stream.EmitRecordWithAbbrev(code, Buffer);
  250. }
  251. template <typename T>
  252. static void read(ArrayRef<T> Buffer, ArrayRef<T> &rawData) {
  253. rawData = Buffer;
  254. }
  255. template <typename T, typename ArrayTy>
  256. static void read(ArrayRef<T> buffer, ArrayTy &array) {
  257. array.append(llvm::map_iterator(buffer.begin(), T::convert),
  258. llvm::map_iterator(buffer.end(), T::convert));
  259. }
  260. template <typename T> static void read(ArrayRef<T> buffer, NoneType) {
  261. (void)buffer;
  262. }
  263. template <typename T> static void read(ArrayRef<T> buffer) = delete;
  264. };
  265. /// Helper class for dealing with a blob at the end of a record.
  266. ///
  267. /// \sa BCRecordLayout
  268. template <> class BCRecordCoding<BCBlob> {
  269. public:
  270. template <typename BufferTy>
  271. static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
  272. unsigned code, StringRef data) {
  273. Stream.EmitRecordWithBlob(code, buffer, data);
  274. }
  275. template <typename T> static void read(ArrayRef<T> buffer) { (void)buffer; }
  276. /// Blob data is not stored in the buffer if you are using the correct
  277. /// accessor; this method should not be used.
  278. template <typename T, typename DataTy>
  279. static void read(ArrayRef<T> buffer, DataTy &data) = delete;
  280. };
  281. /// A type trait whose \c type field is the last of its template parameters.
  282. template <typename Head, typename... Tail> struct last_type {
  283. using type = typename last_type<Tail...>::type;
  284. };
  285. template <typename Head> struct last_type<Head> { using type = Head; };
  286. /// A type trait whose \c value field is \c true if the last type is BCBlob.
  287. template <typename... Types>
  288. using has_blob = std::is_same<BCBlob, typename last_type<int, Types...>::type>;
  289. /// A type trait whose \c value field is \c true if the given type is a
  290. /// BCArray (of any element kind).
  291. template <typename T> struct is_array {
  292. private:
  293. template <typename E> static bool check(BCArray<E> *);
  294. static int check(...);
  295. public:
  296. typedef bool value_type;
  297. static constexpr bool value = !std::is_same<decltype(check((T *)nullptr)),
  298. decltype(check(false))>::value;
  299. };
  300. /// A type trait whose \c value field is \c true if the last type is a
  301. /// BCArray (of any element kind).
  302. template <typename... Types>
  303. using has_array = is_array<typename last_type<int, Types...>::type>;
  304. } // namespace detail
  305. /// Represents a single bitcode record type.
  306. ///
  307. /// This class template is meant to be instantiated and then given a name,
  308. /// so that from then on that name can be used.
  309. template <typename IDField, typename... Fields> class BCGenericRecordLayout {
  310. llvm::BitstreamWriter &Stream;
  311. public:
  312. /// The abbreviation code used for this record in the current block.
  313. ///
  314. /// Note that this is not the same as the semantic record code, which is the
  315. /// first field of the record.
  316. const unsigned AbbrevCode;
  317. /// Create a layout and register it with the given bitstream writer.
  318. explicit BCGenericRecordLayout(llvm::BitstreamWriter &Stream)
  319. : Stream(Stream), AbbrevCode(emitAbbrev(Stream)) {}
  320. /// Emit a record to the bitstream writer, using the given buffer for scratch
  321. /// space.
  322. ///
  323. /// Note that even fixed arguments must be specified here.
  324. template <typename BufferTy, typename... Data>
  325. void emit(BufferTy &buffer, unsigned id, Data &&...data) const {
  326. emitRecord(Stream, buffer, AbbrevCode, id, std::forward<Data>(data)...);
  327. }
  328. /// Registers this record's layout with the bitstream reader.
  329. ///
  330. /// eturns The abbreviation code for the newly-registered record type.
  331. static unsigned emitAbbrev(llvm::BitstreamWriter &Stream) {
  332. auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
  333. detail::emitOps<IDField, Fields...>(*Abbrev);
  334. return Stream.EmitAbbrev(std::move(Abbrev));
  335. }
  336. /// Emit a record identified by \p abbrCode to bitstream reader \p Stream,
  337. /// using \p buffer for scratch space.
  338. ///
  339. /// Note that even fixed arguments must be specified here. Blobs are passed
  340. /// as StringRefs, while arrays can be passed inline, as aggregates, or as
  341. /// pre-encoded StringRef data. Skipped values and empty arrays should use
  342. /// the special Nothing value.
  343. template <typename BufferTy, typename... Data>
  344. static void emitRecord(llvm::BitstreamWriter &Stream, BufferTy &buffer,
  345. unsigned abbrCode, unsigned recordID, Data &&...data) {
  346. static_assert(sizeof...(data) <= sizeof...(Fields) ||
  347. detail::has_array<Fields...>::value,
  348. "Too many record elements");
  349. static_assert(sizeof...(data) >= sizeof...(Fields),
  350. "Too few record elements");
  351. buffer.clear();
  352. detail::BCRecordCoding<IDField, Fields...>::emit(
  353. Stream, buffer, abbrCode, recordID, std::forward<Data>(data)...);
  354. }
  355. /// Extract record data from \p buffer into the given data fields.
  356. ///
  357. /// Note that even fixed arguments must be specified here. Pass \c Nothing
  358. /// if you don't care about a particular parameter. Blob data is not included
  359. /// in the buffer and should be handled separately by the caller.
  360. template <typename ElementTy, typename... Data>
  361. static void readRecord(ArrayRef<ElementTy> buffer, Data &&...data) {
  362. static_assert(sizeof...(data) <= sizeof...(Fields),
  363. "Too many record elements");
  364. static_assert(sizeof...(Fields) <=
  365. sizeof...(data) + detail::has_blob<Fields...>::value,
  366. "Too few record elements");
  367. return detail::BCRecordCoding<Fields...>::read(buffer,
  368. std::forward<Data>(data)...);
  369. }
  370. /// Extract record data from \p buffer into the given data fields.
  371. ///
  372. /// Note that even fixed arguments must be specified here. Pass \c Nothing
  373. /// if you don't care about a particular parameter. Blob data is not included
  374. /// in the buffer and should be handled separately by the caller.
  375. template <typename BufferTy, typename... Data>
  376. static void readRecord(BufferTy &buffer, Data &&...data) {
  377. return readRecord(llvm::makeArrayRef(buffer), std::forward<Data>(data)...);
  378. }
  379. };
  380. /// A record with a fixed record code.
  381. template <unsigned RecordCode, typename... Fields>
  382. class BCRecordLayout
  383. : public BCGenericRecordLayout<BCLiteral<RecordCode>, Fields...> {
  384. using Base = BCGenericRecordLayout<BCLiteral<RecordCode>, Fields...>;
  385. public:
  386. enum : unsigned {
  387. /// The record code associated with this layout.
  388. Code = RecordCode
  389. };
  390. /// Create a layout and register it with the given bitstream writer.
  391. explicit BCRecordLayout(llvm::BitstreamWriter &Stream) : Base(Stream) {}
  392. /// Emit a record to the bitstream writer, using the given buffer for scratch
  393. /// space.
  394. ///
  395. /// Note that even fixed arguments must be specified here.
  396. template <typename BufferTy, typename... Data>
  397. void emit(BufferTy &buffer, Data &&...data) const {
  398. Base::emit(buffer, RecordCode, std::forward<Data>(data)...);
  399. }
  400. /// Emit a record identified by \p abbrCode to bitstream reader \p Stream,
  401. /// using \p buffer for scratch space.
  402. ///
  403. /// Note that even fixed arguments must be specified here. Currently, arrays
  404. /// and blobs can only be passed as StringRefs.
  405. template <typename BufferTy, typename... Data>
  406. static void emitRecord(llvm::BitstreamWriter &Stream, BufferTy &buffer,
  407. unsigned abbrCode, Data &&...data) {
  408. Base::emitRecord(Stream, buffer, abbrCode, RecordCode,
  409. std::forward<Data>(data)...);
  410. }
  411. };
  412. /// RAII object to pair entering and exiting a sub-block.
  413. class BCBlockRAII {
  414. llvm::BitstreamWriter &Stream;
  415. public:
  416. BCBlockRAII(llvm::BitstreamWriter &Stream, unsigned block, unsigned abbrev)
  417. : Stream(Stream) {
  418. Stream.EnterSubblock(block, abbrev);
  419. }
  420. ~BCBlockRAII() { Stream.ExitBlock(); }
  421. };
  422. } // namespace llvm
  423. #endif