//===- llvm/Bitcode/BitcodeConvenience.h - Convenience Wrappers -*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file Convenience wrappers for the LLVM bitcode format and bitstream APIs. /// /// This allows you to use a sort of DSL to declare and use bitcode /// abbreviations and records. Example: /// /// \code /// using Metadata = BCRecordLayout< /// METADATA_ID, // ID /// BCFixed<16>, // Module format major version /// BCFixed<16>, // Module format minor version /// BCBlob // misc. version information /// >; /// Metadata metadata(Out); /// metadata.emit(ScratchRecord, VERSION_MAJOR, VERSION_MINOR, Data); /// \endcode /// /// For details on the bitcode format, see /// http://llvm.org/docs/BitCodeFormat.html /// //===----------------------------------------------------------------------===// #ifndef LLVM_BITCODE_BITCODECONVENIENCE_H #define LLVM_BITCODE_BITCODECONVENIENCE_H #include "llvm/Bitstream/BitCodes.h" #include "llvm/Bitstream/BitstreamWriter.h" #include <cstdint> #include <optional> namespace llvm { namespace detail { /// Convenience base for all kinds of bitcode abbreviation fields. /// /// This just defines common properties queried by the metaprogramming. template <bool Compound = false> class BCField { … }; } // namespace detail /// Represents a literal operand in a bitcode record. /// /// The value of a literal operand is the same for all instances of the record, /// so it is only emitted in the abbreviation definition. /// /// Note that because this uses a compile-time template, you cannot have a /// literal operand that is fixed at run-time without dropping down to the /// raw LLVM APIs. template <uint64_t Value> class BCLiteral : public detail::BCField<> { … }; /// Represents a fixed-width value in a bitcode record. /// /// Note that the LLVM bitcode format only supports unsigned values. template <unsigned Width> class BCFixed : public detail::BCField<> { … }; /// Represents a variable-width value in a bitcode record. /// /// The \p Width parameter should include the continuation bit. /// /// Note that the LLVM bitcode format only supports unsigned values. template <unsigned Width> class BCVBR : public detail::BCField<> { … }; /// Represents a character encoded in LLVM's Char6 encoding. /// /// This format is suitable for encoding decimal numbers (without signs or /// exponents) and C identifiers (without dollar signs), but not much else. /// /// \sa http://llvm.org/docs/BitCodeFormat.html#char6-encoded-value class BCChar6 : public detail::BCField<> { … }; /// Represents an untyped blob of bytes. /// /// If present, this must be the last field in a record. class BCBlob : public detail::BCField<true> { … }; /// Represents an array of some other type. /// /// If present, this must be the last field in a record. template <typename ElementTy> class BCArray : public detail::BCField<true> { … }; namespace detail { /// Attaches the last field to an abbreviation. /// /// This is the base case for \c emitOps. /// /// \sa BCRecordLayout::emitAbbrev template <typename FieldTy> static void emitOps(llvm::BitCodeAbbrev &abbrev) { … } /// Attaches fields to an abbreviation. /// /// This is the recursive case for \c emitOps. /// /// \sa BCRecordLayout::emitAbbrev template <typename FieldTy, typename Next, typename... Rest> static void emitOps(llvm::BitCodeAbbrev &abbrev) { … } /// Helper class for dealing with a scalar element in the middle of a record. /// /// \sa BCRecordLayout template <typename ElementTy, typename... Fields> class BCRecordCoding { … }; /// Helper class for dealing with a scalar element at the end of a record. /// /// This has a separate implementation because up until now we've only been /// \em building the record (into a data buffer), and now we need to hand it /// off to the BitstreamWriter to be emitted. /// /// \sa BCRecordLayout BCRecordCoding<ElementTy>; /// Helper class for dealing with an array at the end of a record. /// /// \sa BCRecordLayout::emitRecord BCRecordCoding<BCArray<ElementTy>>; /// Helper class for dealing with a blob at the end of a record. /// /// \sa BCRecordLayout template <> class BCRecordCoding<BCBlob> { … }; /// A type trait whose \c type field is the last of its template parameters. template <typename Head, typename... Tail> struct last_type { … }; last_type<Head>; /// A type trait whose \c value field is \c true if the last type is BCBlob. has_blob; /// A type trait whose \c value field is \c true if the given type is a /// BCArray (of any element kind). template <typename T> struct is_array { … }; /// A type trait whose \c value field is \c true if the last type is a /// BCArray (of any element kind). has_array; } // namespace detail /// Represents a single bitcode record type. /// /// This class template is meant to be instantiated and then given a name, /// so that from then on that name can be used. template <typename IDField, typename... Fields> class BCGenericRecordLayout { … }; /// A record with a fixed record code. template <unsigned RecordCode, typename... Fields> class BCRecordLayout : public BCGenericRecordLayout<BCLiteral<RecordCode>, Fields...> { … }; /// RAII object to pair entering and exiting a sub-block. class BCBlockRAII { … }; } // namespace llvm #endif