blob: 1069dcd45334939bc86074b608f41dfaf5c23b29 [file] [log] [blame]
//===- TypeTableBuilder.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <type_traits>
namespace llvm {
namespace codeview {
class TypeTableBuilder {
private:
TypeIndex handleError(Error EC) const {
assert(false && "Couldn't write Type!");
consumeError(std::move(EC));
return TypeIndex();
}
BumpPtrAllocator &Allocator;
TypeSerializer Serializer;
public:
explicit TypeTableBuilder(BumpPtrAllocator &Allocator,
bool WriteUnique = true)
: Allocator(Allocator), Serializer(Allocator, WriteUnique) {}
TypeTableBuilder(const TypeTableBuilder &) = delete;
TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;
bool empty() const { return Serializer.records().empty(); }
BumpPtrAllocator &getAllocator() const { return Allocator; }
template <typename T> TypeIndex writeKnownType(T &Record) {
static_assert(!std::is_same<T, FieldListRecord>::value,
"Can't serialize FieldList!");
CVType Type;
Type.Type = static_cast<TypeLeafKind>(Record.getKind());
if (auto EC = Serializer.visitTypeBegin(Type))
return handleError(std::move(EC));
if (auto EC = Serializer.visitKnownRecord(Type, Record))
return handleError(std::move(EC));
auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type);
if (!ExpectedIndex)
return handleError(ExpectedIndex.takeError());
return *ExpectedIndex;
}
TypeIndex writeSerializedRecord(ArrayRef<uint8_t> Record) {
return Serializer.insertRecordBytes(Record);
}
TypeIndex writeSerializedRecord(const RemappedType &Record) {
return Serializer.insertRecord(Record);
}
template <typename TFunc> void ForEachRecord(TFunc Func) {
uint32_t Index = TypeIndex::FirstNonSimpleIndex;
for (auto Record : Serializer.records()) {
Func(TypeIndex(Index), Record);
++Index;
}
}
ArrayRef<ArrayRef<uint8_t>> records() const { return Serializer.records(); }
};
class FieldListRecordBuilder {
TypeTableBuilder &TypeTable;
BumpPtrAllocator Allocator;
TypeSerializer TempSerializer;
CVType Type;
public:
explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable)
: TypeTable(TypeTable), TempSerializer(Allocator, false) {
Type.Type = TypeLeafKind::LF_FIELDLIST;
}
void begin() {
TempSerializer.reset();
if (auto EC = TempSerializer.visitTypeBegin(Type))
consumeError(std::move(EC));
}
template <typename T> void writeMemberType(T &Record) {
CVMemberRecord CVMR;
CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind());
if (auto EC = TempSerializer.visitMemberBegin(CVMR))
consumeError(std::move(EC));
if (auto EC = TempSerializer.visitKnownMember(CVMR, Record))
consumeError(std::move(EC));
if (auto EC = TempSerializer.visitMemberEnd(CVMR))
consumeError(std::move(EC));
}
TypeIndex end(bool Write) {
TypeIndex Index;
if (auto EC = TempSerializer.visitTypeEnd(Type)) {
consumeError(std::move(EC));
return TypeIndex();
}
if (Write) {
for (auto Record : TempSerializer.records())
Index = TypeTable.writeSerializedRecord(Record);
}
return Index;
}
};
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H