blob: 102bee4b0801e1a316b05ef7bd9c46fe2b145af3 [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/TypeSerializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.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)
: Allocator(Allocator), Serializer(Allocator) {}
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(MutableArrayRef<uint8_t> Record) {
return Serializer.insertRecordBytes(Record);
}
template <typename TFunc> void ForEachRecord(TFunc Func) {
uint32_t Index = TypeIndex::FirstNonSimpleIndex;
for (auto Record : Serializer.records()) {
Func(TypeIndex(Index), Record);
++Index;
}
}
ArrayRef<MutableArrayRef<uint8_t>> records() const {
return Serializer.records();
}
};
class FieldListRecordBuilder {
TypeTableBuilder &TypeTable;
TypeSerializer TempSerializer;
CVType Type;
public:
explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable)
: TypeTable(TypeTable), TempSerializer(TypeTable.getAllocator()) {
Type.Type = TypeLeafKind::LF_FIELDLIST;
}
void begin() {
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() {
if (auto EC = TempSerializer.visitTypeEnd(Type)) {
consumeError(std::move(EC));
return TypeIndex();
}
TypeIndex Index;
for (auto Record : TempSerializer.records()) {
Index = TypeTable.writeSerializedRecord(Record);
}
return Index;
}
/// Stop building the record.
void reset() {
if (auto EC = TempSerializer.visitTypeEnd(Type))
consumeError(std::move(EC));
}
};
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H