llvm/llvm/include/llvm/Bitcode/BitcodeConvenience.h

//===- 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