1//===- llvm/Bitcode/BitcodeConvenience.h - Convenience Wrappers -*- C++ -*-===//
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
7//===----------------------------------------------------------------------===//
9/// \file Convenience wrappers for the LLVM bitcode format and bitstream APIs.
11/// This allows you to use a sort of DSL to declare and use bitcode
12/// abbreviations and records. Example:
15/// using Metadata = BCRecordLayout<
17/// BCFixed<16>, // Module format major version
18/// BCFixed<16>, // Module format minor version
19/// BCBlob // misc. version information
21/// Metadata metadata(Out);
22/// metadata.emit(ScratchRecord, VERSION_MAJOR, VERSION_MINOR, Data);
25/// For details on the bitcode format, see
26/// http://llvm.org/docs/BitCodeFormat.html
28//===----------------------------------------------------------------------===//
30#ifndef LLVM_BITCODE_BITCODECONVENIENCE_H
31#define LLVM_BITCODE_BITCODECONVENIENCE_H
40/// Convenience base for all kinds of bitcode abbreviation fields.
42/// This just defines common properties queried by the metaprogramming.
43 template <
bool Compound = false>
class BCField {
47 /// Asserts that the given data is a valid value for this field.
50 /// Converts a raw numeric representation of this value to its preferred
52 template <
typename T>
static T convert(
T rawValue) {
return rawValue; }
56/// Represents a literal operand in a bitcode record.
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.
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
71 assert(
data ==
Value &&
"data value does not match declared literal value");
75/// Represents a fixed-width value in a bitcode record.
77/// Note that the LLVM bitcode format only supports unsigned values.
80 static_assert(Width <= 64,
"fixed-width field is too large");
88 "data value does not fit in the given bit width");
92 assert(
data >= 0 &&
"cannot encode signed integers");
94 "data value does not fit in the given bit width");
98/// Represents a variable-width value in a bitcode record.
100/// The \p Width parameter should include the continuation bit.
102/// Note that the LLVM bitcode format only supports unsigned values.
104 static_assert(Width >= 2,
"width does not have room for continuation bit");
112 assert(
data >= 0 &&
"cannot encode signed integers");
116/// Represents a character encoded in LLVM's Char6 encoding.
118/// This format is suitable for encoding decimal numbers (without signs or
119/// exponents) and C identifiers (without dollar signs), but not much else.
121/// \sa http://llvm.org/docs/BitCodeFormat.html#char6-encoded-value
133 return static_cast<char>(rawValue);
137/// Represents an untyped blob of bytes.
139/// If present, this must be the last field in a record.
147/// Represents an array of some other type.
149/// If present, this must be the last field in a record.
151 static_assert(!ElementTy::IsCompound,
"arrays can only contain scalar types");
156 ElementTy::emitOp(abbrev);
161/// Attaches the last field to an abbreviation.
163/// This is the base case for \c emitOps.
165/// \sa BCRecordLayout::emitAbbrev
167 FieldTy::emitOp(abbrev);
170/// Attaches fields to an abbreviation.
172/// This is the recursive case for \c emitOps.
174/// \sa BCRecordLayout::emitAbbrev
175template <
typename FieldTy,
typename Next,
typename... Rest>
177 static_assert(!FieldTy::IsCompound,
178 "arrays and blobs may not appear in the middle of a record");
179 FieldTy::emitOp(abbrev);
183/// Helper class for dealing with a scalar element in the middle of a record.
185/// \sa BCRecordLayout
188 template <
typename BufferTy,
typename ElementDataTy,
typename... DataTy>
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);
196 std::forward<DataTy>(
data)...);
199 template <
typename T,
typename ElementDataTy,
typename... DataTy>
202 assert(!buffer.
empty() &&
"too few elements in buffer");
203 element = ElementTy::convert(buffer.
front());
205 std::forward<DataTy>(
data)...);
208 template <
typename T,
typename... DataTy>
210 assert(!buffer.
empty() &&
"too few elements in buffer");
212 std::forward<DataTy>(
data)...);
216/// Helper class for dealing with a scalar element at the end of a record.
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.
222/// \sa BCRecordLayout
225 template <
typename BufferTy,
typename DataTy>
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);
235 template <
typename T,
typename DataTy>
237 assert(buffer.
size() == 1 &&
"record data does not match layout");
238 data = ElementTy::convert(buffer.
front());
242 assert(buffer.
size() == 1 &&
"record data does not match layout");
249/// Helper class for dealing with an array at the end of a record.
251/// \sa BCRecordLayout::emitRecord
254 template <
typename BufferTy>
257 // TODO: validate array data.
261 template <
typename BufferTy,
typename ArrayTy>
263 unsigned code,
const ArrayTy &array) {
265 for (
auto &element : array)
266 ElementTy::assertValid(element);
268 buffer.reserve(buffer.size() + std::distance(array.begin(), array.end()));
273 template <
typename BufferTy,
typename ElementDataTy,
typename... DataTy>
275 unsigned code, ElementDataTy element, DataTy...
data) {
276 std::array<ElementDataTy, 1 +
sizeof...(data)> array{{element,
data...}};
277 emit(Stream, buffer, code, array);
280 template <
typename BufferTy>
282 unsigned code, std::nullopt_t) {
286 template <
typename T>
291 template <
typename T,
typename ArrayTy>
304/// Helper class for dealing with a blob at the end of a record.
306/// \sa BCRecordLayout
309 template <
typename BufferTy>
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>
323/// A type trait whose \c type field is the last of its template parameters.
330/// A type trait whose \c value field is \c true if the last type is BCBlob.
331template <
typename... Types>
334/// A type trait whose \c value field is \c true if the given type is a
335/// BCArray (of any element kind).
338 template <
typename E>
static bool check(
BCArray<E> *);
339 static int check(...);
343 static constexpr bool value = !std::is_same<
decltype(check((
T *)
nullptr)),
344 decltype(check(
false))>
::value;
347/// A type trait whose \c value field is \c true if the last type is a
348/// BCArray (of any element kind).
349template <
typename... Types>
353/// Represents a single bitcode record type.
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.
361 /// The abbreviation code used for this record in the current block.
363 /// Note that this is not the same as the semantic record code, which is the
364 /// first field of the record.
367 /// Create a layout and register it with the given bitstream writer.
371 /// Emit a record to the bitstream writer, using the given buffer for scratch
374 /// Note that even fixed arguments must be specified here.
375 template <
typename BufferTy,
typename...
Data>
380 /// Registers this record's layout with the bitstream reader.
382 /// eturns The abbreviation code for the newly-registered record type.
384 auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
386 return Stream.EmitAbbrev(std::move(Abbrev));
389 /// Emit a record identified by \p abbrCode to bitstream reader \p Stream,
390 /// using \p buffer for scratch space.
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>
398 unsigned abbrCode,
unsigned recordID,
Data &&...
data) {
399 static_assert(
sizeof...(data) <=
sizeof...(Fields) ||
401 "Too many record elements");
402 static_assert(
sizeof...(data) >=
sizeof...(Fields),
403 "Too few record elements");
406 Stream, buffer, abbrCode, recordID, std::forward<Data>(
data)...);
409 /// Extract record data from \p buffer into the given data fields.
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>
416 static_assert(
sizeof...(data) <=
sizeof...(Fields),
417 "Too many record elements");
418 static_assert(
sizeof...(Fields) <=
420 "Too few record elements");
422 std::forward<Data>(
data)...);
425 /// Extract record data from \p buffer into the given data fields.
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>
436/// A record with a fixed record code.
437template <
unsigned RecordCode,
typename... Fields>
444 /// The record code associated with this layout.
448 /// Create a layout and register it with the given bitstream writer.
451 /// Emit a record to the bitstream writer, using the given buffer for scratch
454 /// Note that even fixed arguments must be specified here.
455 template <
typename BufferTy,
typename...
Data>
460 /// Emit a record identified by \p abbrCode to bitstream reader \p Stream,
461 /// using \p buffer for scratch space.
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>
467 unsigned abbrCode,
Data &&...
data) {
469 std::forward<Data>(
data)...);
473/// RAII object to pair entering and exiting a sub-block.
480 Stream.EnterSubblock(
block, abbrev);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unify loop Fixup each natural loop to have a single exit block
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
Represents an array of some other type.
static void emitOp(llvm::BitCodeAbbrev &abbrev)
Represents an untyped blob of bytes.
static void emitOp(llvm::BitCodeAbbrev &abbrev)
BCBlockRAII(llvm::BitstreamWriter &Stream, unsigned block, unsigned abbrev)
Represents a character encoded in LLVM's Char6 encoding.
static void assertValid(const T &data)
static void emitOp(llvm::BitCodeAbbrev &abbrev)
Represents a fixed-width value in a bitcode record.
static void emitOp(llvm::BitCodeAbbrev &abbrev)
static void assertValid(const bool &data)
static void assertValid(const T &data)
static void readRecord(BufferTy &buffer, Data &&...data)
Extract record data from buffer into the given data fields.
static unsigned emitAbbrev(llvm::BitstreamWriter &Stream)
BCGenericRecordLayout(llvm::BitstreamWriter &Stream)
Create a layout and register it with the given bitstream writer.
static void readRecord(ArrayRef< ElementTy > buffer, Data &&...data)
Extract record data from buffer into the given data fields.
const unsigned AbbrevCode
static void emitRecord(llvm::BitstreamWriter &Stream, BufferTy &buffer, unsigned abbrCode, unsigned recordID, Data &&...data)
Emit a record identified by abbrCode to bitstream reader Stream, using buffer for scratch space.
void emit(BufferTy &buffer, unsigned id, Data &&...data) const
Emit a record to the bitstream writer, using the given buffer for scratch space.
Represents a literal operand in a bitcode record.
static void emitOp(llvm::BitCodeAbbrev &abbrev)
static void assertValid(const T &data)
@ Code
The record code associated with this layout.
void emit(BufferTy &buffer, Data &&...data) const
Emit a record to the bitstream writer, using the given buffer for scratch space.
BCRecordLayout(llvm::BitstreamWriter &Stream)
Create a layout and register it with the given bitstream writer.
static void emitRecord(llvm::BitstreamWriter &Stream, BufferTy &buffer, unsigned abbrCode, Data &&...data)
Emit a record identified by abbrCode to bitstream reader Stream, using buffer for scratch space.
Represents a variable-width value in a bitcode record.
static void assertValid(const T &data)
static void emitOp(llvm::BitCodeAbbrev &abbrev)
BitCodeAbbrevOp - This describes one or more operands in an abbreviation.
static bool isChar6(char C)
isChar6 - Return true if this character is legal in the Char6 encoding.
BitCodeAbbrev - This class represents an abbreviation record.
void Add(const BitCodeAbbrevOp &OpInfo)
void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals, StringRef Blob)
EmitRecordWithBlob - Emit the specified record to the stream, using an abbrev that includes a blob at...
void EmitRecordWithArray(unsigned Abbrev, const Container &Vals, StringRef Array)
EmitRecordWithArray - Just like EmitRecordWithBlob, works with records that end with an array.
void EmitRecordWithAbbrev(unsigned Abbrev, const Container &Vals)
EmitRecordWithAbbrev - Emit a record with the specified abbreviation.
StringRef - Represent a constant reference to a string, i.e.
LLVM Value Representation.
Convenience base for all kinds of bitcode abbreviation fields.
static const bool IsCompound
static void assertValid(const T &data)
Asserts that the given data is a valid value for this field.
static T convert(T rawValue)
Converts a raw numeric representation of this value to its preferred type.
static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, unsigned code, StringRef data)
static void read(ArrayRef< T > buffer, std::nullopt_t)
static void read(ArrayRef< T > buffer)=delete
static void emit(llvm::BitstreamWriter &Stream, BufferTy &Buffer, unsigned code, std::nullopt_t)
static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, unsigned code, ElementDataTy element, DataTy... data)
static void read(ArrayRef< T > buffer, ArrayTy &array)
static void read(ArrayRef< T > Buffer, ArrayRef< T > &rawData)
static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, unsigned code, const ArrayTy &array)
static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, unsigned code, StringRef data)
static void read(ArrayRef< T > buffer, DataTy &data)=delete
Blob data is not stored in the buffer if you are using the correct accessor; this method should not b...
static void read(ArrayRef< T > buffer)
static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, unsigned code, const DataTy &data)
static void read(ArrayRef< T > buffer, std::nullopt_t)
static void read(ArrayRef< T > buffer)=delete
static void read(ArrayRef< T > buffer, DataTy &data)
Helper class for dealing with a scalar element in the middle of a record.
static void read(ArrayRef< T > buffer, ElementDataTy &element, DataTy &&...data)
static void emit(llvm::BitstreamWriter &Stream, BufferTy &buffer, unsigned code, ElementDataTy element, DataTy &&...data)
static void read(ArrayRef< T > buffer, std::nullopt_t, DataTy &&...data)
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
std::is_same< BCBlob, typename last_type< int, Types... >::type > has_blob
A type trait whose value field is true if the last type is BCBlob.
static void emitOps(llvm::BitCodeAbbrev &abbrev)
Attaches the last field to an abbreviation.
is_array< typename last_type< int, Types... >::type > has_array
A type trait whose value field is true if the last type is a BCArray (of any element kind).
This is an optimization pass for GlobalISel generic memory operations.
mapped_iterator< ItTy, FuncTy > map_iterator(ItTy I, FuncTy F)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
FunctionAddr VTableAddr Next
A type trait whose value field is true if the given type is a BCArray (of any element kind).
static constexpr bool value
A type trait whose type field is the last of its template parameters.
typename last_type< Tail... >::type type