Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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