Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:22

0001 //===- llvm/Bitcode/BitcodeConvenience.h - Convenience Wrappers -*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file Convenience wrappers for the LLVM bitcode format and bitstream APIs.
0010 ///
0011 /// This allows you to use a sort of DSL to declare and use bitcode
0012 /// abbreviations and records. Example:
0013 ///
0014 /// \code
0015 ///     using Metadata = BCRecordLayout<
0016 ///       METADATA_ID,  // ID
0017 ///       BCFixed<16>,  // Module format major version
0018 ///       BCFixed<16>,  // Module format minor version
0019 ///       BCBlob        // misc. version information
0020 ///     >;
0021 ///     Metadata metadata(Out);
0022 ///     metadata.emit(ScratchRecord, VERSION_MAJOR, VERSION_MINOR, Data);
0023 /// \endcode
0024 ///
0025 /// For details on the bitcode format, see
0026 ///   http://llvm.org/docs/BitCodeFormat.html
0027 ///
0028 //===----------------------------------------------------------------------===//
0029 
0030 #ifndef LLVM_BITCODE_BITCODECONVENIENCE_H
0031 #define LLVM_BITCODE_BITCODECONVENIENCE_H
0032 
0033 #include "llvm/Bitstream/BitCodes.h"
0034 #include "llvm/Bitstream/BitstreamWriter.h"
0035 #include <cstdint>
0036 #include <optional>
0037 
0038 namespace llvm {
0039 namespace detail {
0040 /// Convenience base for all kinds of bitcode abbreviation fields.
0041 ///
0042 /// This just defines common properties queried by the metaprogramming.
0043 template <bool Compound = false> class BCField {
0044 public:
0045   static const bool IsCompound = Compound;
0046 
0047   /// Asserts that the given data is a valid value for this field.
0048   template <typename T> static void assertValid(const T &data) {}
0049 
0050   /// Converts a raw numeric representation of this value to its preferred
0051   /// type.
0052   template <typename T> static T convert(T rawValue) { return rawValue; }
0053 };
0054 } // namespace detail
0055 
0056 /// Represents a literal operand in a bitcode record.
0057 ///
0058 /// The value of a literal operand is the same for all instances of the record,
0059 /// so it is only emitted in the abbreviation definition.
0060 ///
0061 /// Note that because this uses a compile-time template, you cannot have a
0062 /// literal operand that is fixed at run-time without dropping down to the
0063 /// raw LLVM APIs.
0064 template <uint64_t Value> class BCLiteral : public detail::BCField<> {
0065 public:
0066   static void emitOp(llvm::BitCodeAbbrev &abbrev) {
0067     abbrev.Add(llvm::BitCodeAbbrevOp(Value));
0068   }
0069 
0070   template <typename T> static void assertValid(const T &data) {
0071     assert(data == Value && "data value does not match declared literal value");
0072   }
0073 };
0074 
0075 /// Represents a fixed-width value in a bitcode record.
0076 ///
0077 /// Note that the LLVM bitcode format only supports unsigned values.
0078 template <unsigned Width> class BCFixed : public detail::BCField<> {
0079 public:
0080   static_assert(Width <= 64, "fixed-width field is too large");
0081 
0082   static void emitOp(llvm::BitCodeAbbrev &abbrev) {
0083     abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, Width));
0084   }
0085 
0086   static void assertValid(const bool &data) {
0087     assert(llvm::isUInt<Width>(data) &&
0088            "data value does not fit in the given bit width");
0089   }
0090 
0091   template <typename T> static void assertValid(const T &data) {
0092     assert(data >= 0 && "cannot encode signed integers");
0093     assert(llvm::isUInt<Width>(data) &&
0094            "data value does not fit in the given bit width");
0095   }
0096 };
0097 
0098 /// Represents a variable-width value in a bitcode record.
0099 ///
0100 /// The \p Width parameter should include the continuation bit.
0101 ///
0102 /// Note that the LLVM bitcode format only supports unsigned values.
0103 template <unsigned Width> class BCVBR : public detail::BCField<> {
0104   static_assert(Width >= 2, "width does not have room for continuation bit");
0105 
0106 public:
0107   static void emitOp(llvm::BitCodeAbbrev &abbrev) {
0108     abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, Width));
0109   }
0110 
0111   template <typename T> static void assertValid(const T &data) {
0112     assert(data >= 0 && "cannot encode signed integers");
0113   }
0114 };
0115 
0116 /// Represents a character encoded in LLVM's Char6 encoding.
0117 ///
0118 /// This format is suitable for encoding decimal numbers (without signs or
0119 /// exponents) and C identifiers (without dollar signs), but not much else.
0120 ///
0121 /// \sa http://llvm.org/docs/BitCodeFormat.html#char6-encoded-value
0122 class BCChar6 : public detail::BCField<> {
0123 public:
0124   static void emitOp(llvm::BitCodeAbbrev &abbrev) {
0125     abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Char6));
0126   }
0127 
0128   template <typename T> static void assertValid(const T &data) {
0129     assert(llvm::BitCodeAbbrevOp::isChar6(data) && "invalid Char6 data");
0130   }
0131 
0132   template <typename T> char convert(T rawValue) {
0133     return static_cast<char>(rawValue);
0134   }
0135 };
0136 
0137 /// Represents an untyped blob of bytes.
0138 ///
0139 /// If present, this must be the last field in a record.
0140 class BCBlob : public detail::BCField<true> {
0141 public:
0142   static void emitOp(llvm::BitCodeAbbrev &abbrev) {
0143     abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
0144   }
0145 };
0146 
0147 /// Represents an array of some other type.
0148 ///
0149 /// If present, this must be the last field in a record.
0150 template <typename ElementTy> class BCArray : public detail::BCField<true> {
0151   static_assert(!ElementTy::IsCompound, "arrays can only contain scalar types");
0152 
0153 public:
0154   static void emitOp(llvm::BitCodeAbbrev &abbrev) {
0155     abbrev.Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array));
0156     ElementTy::emitOp(abbrev);
0157   }
0158 };
0159 
0160 namespace detail {
0161 /// Attaches the last field to an abbreviation.
0162 ///
0163 /// This is the base case for \c emitOps.
0164 ///
0165 /// \sa BCRecordLayout::emitAbbrev
0166 template <typename FieldTy> static void emitOps(llvm::BitCodeAbbrev &abbrev) {
0167   FieldTy::emitOp(abbrev);
0168 }
0169 
0170 /// Attaches fields to an abbreviation.
0171 ///
0172 /// This is the recursive case for \c emitOps.
0173 ///
0174 /// \sa BCRecordLayout::emitAbbrev
0175 template <typename FieldTy, typename Next, typename... Rest>
0176 static void emitOps(llvm::BitCodeAbbrev &abbrev) {
0177   static_assert(!FieldTy::IsCompound,
0178                 "arrays and blobs may not appear in the middle of a record");
0179   FieldTy::emitOp(abbrev);
0180   emitOps<Next, Rest...>(abbrev);
0181 }
0182 
0183 /// Helper class for dealing with a scalar element in the middle of a record.
0184 ///
0185 /// \sa BCRecordLayout
0186 template <typename ElementTy, typename... Fields> class BCRecordCoding {
0187 public:
0188   template <typename BufferTy, typename ElementDataTy, typename... DataTy>
0189   static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
0190                    unsigned code, ElementDataTy element, DataTy &&...data) {
0191     static_assert(!ElementTy::IsCompound,
0192                   "arrays and blobs may not appear in the middle of a record");
0193     ElementTy::assertValid(element);
0194     buffer.push_back(element);
0195     BCRecordCoding<Fields...>::emit(Stream, buffer, code,
0196                                     std::forward<DataTy>(data)...);
0197   }
0198 
0199   template <typename T, typename ElementDataTy, typename... DataTy>
0200   static void read(ArrayRef<T> buffer, ElementDataTy &element,
0201                    DataTy &&...data) {
0202     assert(!buffer.empty() && "too few elements in buffer");
0203     element = ElementTy::convert(buffer.front());
0204     BCRecordCoding<Fields...>::read(buffer.slice(1),
0205                                     std::forward<DataTy>(data)...);
0206   }
0207 
0208   template <typename T, typename... DataTy>
0209   static void read(ArrayRef<T> buffer, std::nullopt_t, DataTy &&...data) {
0210     assert(!buffer.empty() && "too few elements in buffer");
0211     BCRecordCoding<Fields...>::read(buffer.slice(1),
0212                                     std::forward<DataTy>(data)...);
0213   }
0214 };
0215 
0216 /// Helper class for dealing with a scalar element at the end of a record.
0217 ///
0218 /// This has a separate implementation because up until now we've only been
0219 /// \em building the record (into a data buffer), and now we need to hand it
0220 /// off to the BitstreamWriter to be emitted.
0221 ///
0222 /// \sa BCRecordLayout
0223 template <typename ElementTy> class BCRecordCoding<ElementTy> {
0224 public:
0225   template <typename BufferTy, typename DataTy>
0226   static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
0227                    unsigned code, const DataTy &data) {
0228     static_assert(!ElementTy::IsCompound,
0229                   "arrays and blobs need special handling");
0230     ElementTy::assertValid(data);
0231     buffer.push_back(data);
0232     Stream.EmitRecordWithAbbrev(code, buffer);
0233   }
0234 
0235   template <typename T, typename DataTy>
0236   static void read(ArrayRef<T> buffer, DataTy &data) {
0237     assert(buffer.size() == 1 && "record data does not match layout");
0238     data = ElementTy::convert(buffer.front());
0239   }
0240 
0241   template <typename T> static void read(ArrayRef<T> buffer, std::nullopt_t) {
0242     assert(buffer.size() == 1 && "record data does not match layout");
0243     (void)buffer;
0244   }
0245 
0246   template <typename T> static void read(ArrayRef<T> buffer) = delete;
0247 };
0248 
0249 /// Helper class for dealing with an array at the end of a record.
0250 ///
0251 /// \sa BCRecordLayout::emitRecord
0252 template <typename ElementTy> class BCRecordCoding<BCArray<ElementTy>> {
0253 public:
0254   template <typename BufferTy>
0255   static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
0256                    unsigned code, StringRef data) {
0257     // TODO: validate array data.
0258     Stream.EmitRecordWithArray(code, buffer, data);
0259   }
0260 
0261   template <typename BufferTy, typename ArrayTy>
0262   static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
0263                    unsigned code, const ArrayTy &array) {
0264 #ifndef NDEBUG
0265     for (auto &element : array)
0266       ElementTy::assertValid(element);
0267 #endif
0268     buffer.reserve(buffer.size() + std::distance(array.begin(), array.end()));
0269     std::copy(array.begin(), array.end(), std::back_inserter(buffer));
0270     Stream.EmitRecordWithAbbrev(code, buffer);
0271   }
0272 
0273   template <typename BufferTy, typename ElementDataTy, typename... DataTy>
0274   static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
0275                    unsigned code, ElementDataTy element, DataTy... data) {
0276     std::array<ElementDataTy, 1 + sizeof...(data)> array{{element, data...}};
0277     emit(Stream, buffer, code, array);
0278   }
0279 
0280   template <typename BufferTy>
0281   static void emit(llvm::BitstreamWriter &Stream, BufferTy &Buffer,
0282                    unsigned code, std::nullopt_t) {
0283     Stream.EmitRecordWithAbbrev(code, Buffer);
0284   }
0285 
0286   template <typename T>
0287   static void read(ArrayRef<T> Buffer, ArrayRef<T> &rawData) {
0288     rawData = Buffer;
0289   }
0290 
0291   template <typename T, typename ArrayTy>
0292   static void read(ArrayRef<T> buffer, ArrayTy &array) {
0293     array.append(llvm::map_iterator(buffer.begin(), T::convert),
0294                  llvm::map_iterator(buffer.end(), T::convert));
0295   }
0296 
0297   template <typename T> static void read(ArrayRef<T> buffer, std::nullopt_t) {
0298     (void)buffer;
0299   }
0300 
0301   template <typename T> static void read(ArrayRef<T> buffer) = delete;
0302 };
0303 
0304 /// Helper class for dealing with a blob at the end of a record.
0305 ///
0306 /// \sa BCRecordLayout
0307 template <> class BCRecordCoding<BCBlob> {
0308 public:
0309   template <typename BufferTy>
0310   static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer,
0311                    unsigned code, StringRef data) {
0312     Stream.EmitRecordWithBlob(code, buffer, data);
0313   }
0314 
0315   template <typename T> static void read(ArrayRef<T> buffer) { (void)buffer; }
0316 
0317   /// Blob data is not stored in the buffer if you are using the correct
0318   /// accessor; this method should not be used.
0319   template <typename T, typename DataTy>
0320   static void read(ArrayRef<T> buffer, DataTy &data) = delete;
0321 };
0322 
0323 /// A type trait whose \c type field is the last of its template parameters.
0324 template <typename Head, typename... Tail> struct last_type {
0325   using type = typename last_type<Tail...>::type;
0326 };
0327 
0328 template <typename Head> struct last_type<Head> { using type = Head; };
0329 
0330 /// A type trait whose \c value field is \c true if the last type is BCBlob.
0331 template <typename... Types>
0332 using has_blob = std::is_same<BCBlob, typename last_type<int, Types...>::type>;
0333 
0334 /// A type trait whose \c value field is \c true if the given type is a
0335 /// BCArray (of any element kind).
0336 template <typename T> struct is_array {
0337 private:
0338   template <typename E> static bool check(BCArray<E> *);
0339   static int check(...);
0340 
0341 public:
0342   typedef bool value_type;
0343   static constexpr bool value = !std::is_same<decltype(check((T *)nullptr)),
0344                                               decltype(check(false))>::value;
0345 };
0346 
0347 /// A type trait whose \c value field is \c true if the last type is a
0348 /// BCArray (of any element kind).
0349 template <typename... Types>
0350 using has_array = is_array<typename last_type<int, Types...>::type>;
0351 } // namespace detail
0352 
0353 /// Represents a single bitcode record type.
0354 ///
0355 /// This class template is meant to be instantiated and then given a name,
0356 /// so that from then on that name can be used.
0357 template <typename IDField, typename... Fields> class BCGenericRecordLayout {
0358   llvm::BitstreamWriter &Stream;
0359 
0360 public:
0361   /// The abbreviation code used for this record in the current block.
0362   ///
0363   /// Note that this is not the same as the semantic record code, which is the
0364   /// first field of the record.
0365   const unsigned AbbrevCode;
0366 
0367   /// Create a layout and register it with the given bitstream writer.
0368   explicit BCGenericRecordLayout(llvm::BitstreamWriter &Stream)
0369       : Stream(Stream), AbbrevCode(emitAbbrev(Stream)) {}
0370 
0371   /// Emit a record to the bitstream writer, using the given buffer for scratch
0372   /// space.
0373   ///
0374   /// Note that even fixed arguments must be specified here.
0375   template <typename BufferTy, typename... Data>
0376   void emit(BufferTy &buffer, unsigned id, Data &&...data) const {
0377     emitRecord(Stream, buffer, AbbrevCode, id, std::forward<Data>(data)...);
0378   }
0379 
0380   /// Registers this record's layout with the bitstream reader.
0381   ///
0382   /// eturns The abbreviation code for the newly-registered record type.
0383   static unsigned emitAbbrev(llvm::BitstreamWriter &Stream) {
0384     auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
0385     detail::emitOps<IDField, Fields...>(*Abbrev);
0386     return Stream.EmitAbbrev(std::move(Abbrev));
0387   }
0388 
0389   /// Emit a record identified by \p abbrCode to bitstream reader \p Stream,
0390   /// using \p buffer for scratch space.
0391   ///
0392   /// Note that even fixed arguments must be specified here. Blobs are passed
0393   /// as StringRefs, while arrays can be passed inline, as aggregates, or as
0394   /// pre-encoded StringRef data. Skipped values and empty arrays should use
0395   /// the special Nothing value.
0396   template <typename BufferTy, typename... Data>
0397   static void emitRecord(llvm::BitstreamWriter &Stream, BufferTy &buffer,
0398                          unsigned abbrCode, unsigned recordID, Data &&...data) {
0399     static_assert(sizeof...(data) <= sizeof...(Fields) ||
0400                       detail::has_array<Fields...>::value,
0401                   "Too many record elements");
0402     static_assert(sizeof...(data) >= sizeof...(Fields),
0403                   "Too few record elements");
0404     buffer.clear();
0405     detail::BCRecordCoding<IDField, Fields...>::emit(
0406         Stream, buffer, abbrCode, recordID, std::forward<Data>(data)...);
0407   }
0408 
0409   /// Extract record data from \p buffer into the given data fields.
0410   ///
0411   /// Note that even fixed arguments must be specified here. Pass \c Nothing
0412   /// if you don't care about a particular parameter. Blob data is not included
0413   /// in the buffer and should be handled separately by the caller.
0414   template <typename ElementTy, typename... Data>
0415   static void readRecord(ArrayRef<ElementTy> buffer, Data &&...data) {
0416     static_assert(sizeof...(data) <= sizeof...(Fields),
0417                   "Too many record elements");
0418     static_assert(sizeof...(Fields) <=
0419                       sizeof...(data) + detail::has_blob<Fields...>::value,
0420                   "Too few record elements");
0421     return detail::BCRecordCoding<Fields...>::read(buffer,
0422                                                    std::forward<Data>(data)...);
0423   }
0424 
0425   /// Extract record data from \p buffer into the given data fields.
0426   ///
0427   /// Note that even fixed arguments must be specified here. Pass \c Nothing
0428   /// if you don't care about a particular parameter. Blob data is not included
0429   /// in the buffer and should be handled separately by the caller.
0430   template <typename BufferTy, typename... Data>
0431   static void readRecord(BufferTy &buffer, Data &&...data) {
0432     return readRecord(llvm::ArrayRef(buffer), std::forward<Data>(data)...);
0433   }
0434 };
0435 
0436 /// A record with a fixed record code.
0437 template <unsigned RecordCode, typename... Fields>
0438 class BCRecordLayout
0439     : public BCGenericRecordLayout<BCLiteral<RecordCode>, Fields...> {
0440   using Base = BCGenericRecordLayout<BCLiteral<RecordCode>, Fields...>;
0441 
0442 public:
0443   enum : unsigned {
0444     /// The record code associated with this layout.
0445     Code = RecordCode
0446   };
0447 
0448   /// Create a layout and register it with the given bitstream writer.
0449   explicit BCRecordLayout(llvm::BitstreamWriter &Stream) : Base(Stream) {}
0450 
0451   /// Emit a record to the bitstream writer, using the given buffer for scratch
0452   /// space.
0453   ///
0454   /// Note that even fixed arguments must be specified here.
0455   template <typename BufferTy, typename... Data>
0456   void emit(BufferTy &buffer, Data &&...data) const {
0457     Base::emit(buffer, RecordCode, std::forward<Data>(data)...);
0458   }
0459 
0460   /// Emit a record identified by \p abbrCode to bitstream reader \p Stream,
0461   /// using \p buffer for scratch space.
0462   ///
0463   /// Note that even fixed arguments must be specified here. Currently, arrays
0464   /// and blobs can only be passed as StringRefs.
0465   template <typename BufferTy, typename... Data>
0466   static void emitRecord(llvm::BitstreamWriter &Stream, BufferTy &buffer,
0467                          unsigned abbrCode, Data &&...data) {
0468     Base::emitRecord(Stream, buffer, abbrCode, RecordCode,
0469                      std::forward<Data>(data)...);
0470   }
0471 };
0472 
0473 /// RAII object to pair entering and exiting a sub-block.
0474 class BCBlockRAII {
0475   llvm::BitstreamWriter &Stream;
0476 
0477 public:
0478   BCBlockRAII(llvm::BitstreamWriter &Stream, unsigned block, unsigned abbrev)
0479       : Stream(Stream) {
0480     Stream.EnterSubblock(block, abbrev);
0481   }
0482 
0483   ~BCBlockRAII() { Stream.ExitBlock(); }
0484 };
0485 } // namespace llvm
0486 
0487 #endif