forked from OSchip/llvm-project
Delete TypeDatabase.
Merge the functionality into the random access type collection. This class was only being used in 2 places, so getting rid of it simplifies the code. llvm-svn: 305653
This commit is contained in:
parent
c85be52fd8
commit
26dbc5420d
|
@ -27,9 +27,12 @@ namespace codeview {
|
||||||
|
|
||||||
template <typename Kind> class CVRecord {
|
template <typename Kind> class CVRecord {
|
||||||
public:
|
public:
|
||||||
CVRecord() = default;
|
CVRecord() : Type(static_cast<Kind>(0)) {}
|
||||||
|
|
||||||
CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {}
|
CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {}
|
||||||
|
|
||||||
|
bool valid() const { return Type != static_cast<Kind>(0); }
|
||||||
|
|
||||||
uint32_t length() const { return RecordData.size(); }
|
uint32_t length() const { return RecordData.size(); }
|
||||||
Kind kind() const { return Type; }
|
Kind kind() const { return Type; }
|
||||||
ArrayRef<uint8_t> data() const { return RecordData; }
|
ArrayRef<uint8_t> data() const { return RecordData; }
|
||||||
|
|
|
@ -11,18 +11,15 @@
|
||||||
#define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
|
#define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
|
||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||||
|
#include "llvm/Support/Allocator.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
#include "llvm/Support/StringSaver.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace codeview {
|
namespace codeview {
|
||||||
|
|
||||||
class TypeDatabase;
|
|
||||||
class TypeVisitorCallbacks;
|
|
||||||
|
|
||||||
/// \brief Provides amortized O(1) random access to a CodeView type stream.
|
/// \brief Provides amortized O(1) random access to a CodeView type stream.
|
||||||
/// Normally to access a type from a type stream, you must know its byte
|
/// Normally to access a type from a type stream, you must know its byte
|
||||||
/// offset into the type stream, because type records are variable-lengthed.
|
/// offset into the type stream, because type records are variable-lengthed.
|
||||||
|
@ -47,6 +44,11 @@ class TypeVisitorCallbacks;
|
||||||
/// of O(N/M) and an amortized time of O(1).
|
/// of O(N/M) and an amortized time of O(1).
|
||||||
class LazyRandomTypeCollection : public TypeCollection {
|
class LazyRandomTypeCollection : public TypeCollection {
|
||||||
typedef FixedStreamArray<TypeIndexOffset> PartialOffsetArray;
|
typedef FixedStreamArray<TypeIndexOffset> PartialOffsetArray;
|
||||||
|
struct CacheEntry {
|
||||||
|
CVType Type;
|
||||||
|
uint32_t Offset;
|
||||||
|
StringRef Name;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LazyRandomTypeCollection(uint32_t RecordCountHint);
|
explicit LazyRandomTypeCollection(uint32_t RecordCountHint);
|
||||||
|
@ -56,8 +58,8 @@ public:
|
||||||
PartialOffsetArray PartialOffsets);
|
PartialOffsetArray PartialOffsets);
|
||||||
LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint);
|
LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint);
|
||||||
|
|
||||||
void reset(ArrayRef<uint8_t> Data);
|
void reset(ArrayRef<uint8_t> Data, uint32_t RecordCountHint);
|
||||||
void reset(StringRef Data);
|
void reset(StringRef Data, uint32_t RecordCountHint);
|
||||||
|
|
||||||
CVType getType(TypeIndex Index) override;
|
CVType getType(TypeIndex Index) override;
|
||||||
StringRef getTypeName(TypeIndex Index) override;
|
StringRef getTypeName(TypeIndex Index) override;
|
||||||
|
@ -68,32 +70,26 @@ public:
|
||||||
Optional<TypeIndex> getNext(TypeIndex Prev) override;
|
Optional<TypeIndex> getNext(TypeIndex Prev) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const TypeDatabase &database() const { return Database; }
|
|
||||||
Error ensureTypeExists(TypeIndex Index);
|
Error ensureTypeExists(TypeIndex Index);
|
||||||
|
void ensureCapacityFor(TypeIndex Index);
|
||||||
|
|
||||||
Error visitRangeForType(TypeIndex TI);
|
Error visitRangeForType(TypeIndex TI);
|
||||||
Error fullScanForType(TypeIndex TI);
|
Error fullScanForType(TypeIndex TI);
|
||||||
Error visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
|
void visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
|
||||||
Error visitOneRecord(TypeIndex TI, uint32_t Offset, CVType &Record);
|
|
||||||
|
/// Number of actual records.
|
||||||
|
uint32_t Count = 0;
|
||||||
|
|
||||||
|
/// The largest type index which we've visited.
|
||||||
|
TypeIndex LargestTypeIndex = TypeIndex::None();
|
||||||
|
|
||||||
BumpPtrAllocator Allocator;
|
BumpPtrAllocator Allocator;
|
||||||
StringSaver NameStorage;
|
StringSaver NameStorage;
|
||||||
|
|
||||||
SmallVector<StringRef, 10> TypeNames;
|
|
||||||
|
|
||||||
/// Visited records get automatically added to the type database.
|
|
||||||
TypeDatabase Database;
|
|
||||||
|
|
||||||
/// The type array to allow random access visitation of.
|
/// The type array to allow random access visitation of.
|
||||||
CVTypeArray Types;
|
CVTypeArray Types;
|
||||||
|
|
||||||
/// The database visitor which adds new records to the database.
|
std::vector<CacheEntry> Records;
|
||||||
TypeDatabaseVisitor DatabaseVisitor;
|
|
||||||
|
|
||||||
/// A vector mapping type indices to type offset. For every record that has
|
|
||||||
/// been visited, contains the absolute offset of that record in the record
|
|
||||||
/// array.
|
|
||||||
std::vector<uint32_t> KnownOffsets;
|
|
||||||
|
|
||||||
/// An array of index offsets for the given type stream, allowing log(N)
|
/// An array of index offsets for the given type stream, allowing log(N)
|
||||||
/// lookups of a type record by index. Similar to KnownOffsets but only
|
/// lookups of a type record by index. Similar to KnownOffsets but only
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
//===- TypeDatabase.h - A collection of CodeView type records ---*- 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_TYPEDATABASE_H
|
|
||||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASE_H
|
|
||||||
|
|
||||||
#include "llvm/ADT/BitVector.h"
|
|
||||||
#include "llvm/ADT/SmallVector.h"
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
|
||||||
#include "llvm/Support/Allocator.h"
|
|
||||||
#include "llvm/Support/StringSaver.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
namespace codeview {
|
|
||||||
class TypeDatabase : public TypeCollection {
|
|
||||||
friend class RandomAccessTypeVisitor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit TypeDatabase(uint32_t Capacity);
|
|
||||||
|
|
||||||
/// Records the name of a type, and reserves its type index.
|
|
||||||
TypeIndex appendType(StringRef Name, const CVType &Data);
|
|
||||||
|
|
||||||
/// Records the name of a type, and reserves its type index.
|
|
||||||
void recordType(StringRef Name, TypeIndex Index, const CVType &Data);
|
|
||||||
|
|
||||||
/// Saves the name in a StringSet and creates a stable StringRef.
|
|
||||||
StringRef saveTypeName(StringRef TypeName);
|
|
||||||
|
|
||||||
StringRef getTypeName(TypeIndex Index) const;
|
|
||||||
|
|
||||||
const CVType &getTypeRecord(TypeIndex Index) const;
|
|
||||||
CVType &getTypeRecord(TypeIndex Index);
|
|
||||||
|
|
||||||
bool contains(TypeIndex Index) const;
|
|
||||||
uint32_t size() const;
|
|
||||||
uint32_t capacity() const;
|
|
||||||
bool empty() const;
|
|
||||||
|
|
||||||
CVType getType(TypeIndex Index) override;
|
|
||||||
StringRef getTypeName(TypeIndex Index) override;
|
|
||||||
bool contains(TypeIndex Index) override;
|
|
||||||
uint32_t size() override;
|
|
||||||
uint32_t capacity() override;
|
|
||||||
|
|
||||||
Optional<TypeIndex> getFirst() override;
|
|
||||||
Optional<TypeIndex> getNext(TypeIndex Prev) override;
|
|
||||||
|
|
||||||
Optional<TypeIndex> largestTypeIndexLessThan(TypeIndex TI) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
TypeIndex getAppendIndex() const;
|
|
||||||
|
|
||||||
void grow();
|
|
||||||
void grow(TypeIndex Index);
|
|
||||||
|
|
||||||
BumpPtrAllocator Allocator;
|
|
||||||
|
|
||||||
uint32_t Count = 0;
|
|
||||||
TypeIndex LargestTypeIndex;
|
|
||||||
|
|
||||||
/// All user defined type records in .debug$T live in here. Type indices
|
|
||||||
/// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
|
|
||||||
/// index into this vector.
|
|
||||||
SmallVector<StringRef, 10> CVUDTNames;
|
|
||||||
SmallVector<CVType, 10> TypeRecords;
|
|
||||||
|
|
||||||
StringSaver TypeNameStorage;
|
|
||||||
|
|
||||||
BitVector ValidRecords;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,62 +0,0 @@
|
||||||
//===-- TypeDatabaseVisitor.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_TYPEDATABASEVISITOR_H
|
|
||||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASEVISITOR_H
|
|
||||||
|
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
|
||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
namespace codeview {
|
|
||||||
|
|
||||||
/// Dumper for CodeView type streams found in COFF object files and PDB files.
|
|
||||||
class TypeDatabaseVisitor : public TypeVisitorCallbacks {
|
|
||||||
public:
|
|
||||||
explicit TypeDatabaseVisitor(TypeDatabase &TypeDB) : TypeDB(&TypeDB) {}
|
|
||||||
|
|
||||||
/// Paired begin/end actions for all types. Receives all record data,
|
|
||||||
/// including the fixed-length record prefix.
|
|
||||||
Error visitTypeBegin(CVType &Record) override;
|
|
||||||
Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
|
|
||||||
Error visitTypeEnd(CVType &Record) override;
|
|
||||||
Error visitMemberBegin(CVMemberRecord &Record) override;
|
|
||||||
Error visitMemberEnd(CVMemberRecord &Record) override;
|
|
||||||
|
|
||||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
|
||||||
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
|
|
||||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
|
||||||
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
|
|
||||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
|
||||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
|
||||||
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
|
|
||||||
|
|
||||||
private:
|
|
||||||
StringRef getTypeName(TypeIndex Index) const;
|
|
||||||
StringRef saveTypeName(StringRef Name);
|
|
||||||
|
|
||||||
bool IsInFieldList = false;
|
|
||||||
|
|
||||||
/// Name of the current type. Only valid before visitTypeEnd.
|
|
||||||
StringRef Name;
|
|
||||||
/// Current type index. Only valid before visitTypeEnd, and if we are
|
|
||||||
/// visiting a random access type database.
|
|
||||||
Optional<TypeIndex> CurrentTypeIndex;
|
|
||||||
|
|
||||||
TypeDatabase *TypeDB;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace codeview
|
|
||||||
} // end namespace llvm
|
|
||||||
|
|
||||||
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
|
|
|
@ -11,7 +11,9 @@
|
||||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H
|
#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H
|
||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
#include "llvm/Support/StringSaver.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace codeview {
|
namespace codeview {
|
||||||
|
@ -30,11 +32,10 @@ public:
|
||||||
uint32_t capacity() override;
|
uint32_t capacity() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool hasCapacityFor(TypeIndex Index) const;
|
BumpPtrAllocator Allocator;
|
||||||
void ensureTypeExists(TypeIndex Index);
|
StringSaver NameStorage;
|
||||||
|
std::vector<StringRef> Names;
|
||||||
ArrayRef<ArrayRef<uint8_t>> Records;
|
ArrayRef<ArrayRef<uint8_t>> Records;
|
||||||
TypeDatabase Database;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ add_llvm_library(LLVMDebugInfoCodeView
|
||||||
SymbolRecordMapping.cpp
|
SymbolRecordMapping.cpp
|
||||||
SymbolDumper.cpp
|
SymbolDumper.cpp
|
||||||
SymbolSerializer.cpp
|
SymbolSerializer.cpp
|
||||||
TypeDatabase.cpp
|
|
||||||
TypeDatabaseVisitor.cpp
|
|
||||||
TypeDumpVisitor.cpp
|
TypeDumpVisitor.cpp
|
||||||
TypeIndex.cpp
|
TypeIndex.cpp
|
||||||
TypeIndexDiscovery.cpp
|
TypeIndexDiscovery.cpp
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
|
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
|
||||||
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeName.h"
|
#include "llvm/DebugInfo/CodeView/TypeName.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
|
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
|
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
|
||||||
|
@ -32,15 +31,13 @@ LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint)
|
||||||
LazyRandomTypeCollection::LazyRandomTypeCollection(
|
LazyRandomTypeCollection::LazyRandomTypeCollection(
|
||||||
const CVTypeArray &Types, uint32_t RecordCountHint,
|
const CVTypeArray &Types, uint32_t RecordCountHint,
|
||||||
PartialOffsetArray PartialOffsets)
|
PartialOffsetArray PartialOffsets)
|
||||||
: NameStorage(Allocator), Database(RecordCountHint), Types(Types),
|
: NameStorage(Allocator), Types(Types), PartialOffsets(PartialOffsets) {
|
||||||
DatabaseVisitor(Database), PartialOffsets(PartialOffsets) {
|
Records.resize(RecordCountHint);
|
||||||
KnownOffsets.resize(Database.capacity());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef<uint8_t> Data,
|
LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef<uint8_t> Data,
|
||||||
uint32_t RecordCountHint)
|
uint32_t RecordCountHint)
|
||||||
: LazyRandomTypeCollection(RecordCountHint) {
|
: LazyRandomTypeCollection(RecordCountHint) {
|
||||||
reset(Data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data,
|
LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data,
|
||||||
|
@ -53,22 +50,28 @@ LazyRandomTypeCollection::LazyRandomTypeCollection(const CVTypeArray &Types,
|
||||||
uint32_t NumRecords)
|
uint32_t NumRecords)
|
||||||
: LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {}
|
: LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {}
|
||||||
|
|
||||||
void LazyRandomTypeCollection::reset(StringRef Data) {
|
void LazyRandomTypeCollection::reset(StringRef Data, uint32_t RecordCountHint) {
|
||||||
reset(makeArrayRef(Data.bytes_begin(), Data.bytes_end()));
|
Count = 0;
|
||||||
}
|
|
||||||
|
|
||||||
void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data) {
|
|
||||||
PartialOffsets = PartialOffsetArray();
|
PartialOffsets = PartialOffsetArray();
|
||||||
|
|
||||||
BinaryStreamReader Reader(Data, support::little);
|
BinaryStreamReader Reader(Data, support::little);
|
||||||
error(Reader.readArray(Types, Reader.getLength()));
|
error(Reader.readArray(Types, Reader.getLength()));
|
||||||
|
|
||||||
KnownOffsets.resize(Database.capacity());
|
// Clear and then resize, to make sure existing data gets destroyed.
|
||||||
|
Records.clear();
|
||||||
|
Records.resize(RecordCountHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data,
|
||||||
|
uint32_t RecordCountHint) {
|
||||||
|
reset(toStringRef(Data), RecordCountHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
CVType LazyRandomTypeCollection::getType(TypeIndex Index) {
|
CVType LazyRandomTypeCollection::getType(TypeIndex Index) {
|
||||||
error(ensureTypeExists(Index));
|
error(ensureTypeExists(Index));
|
||||||
return Database.getTypeRecord(Index);
|
assert(contains(Index));
|
||||||
|
|
||||||
|
return Records[Index.toArrayIndex()].Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) {
|
StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) {
|
||||||
|
@ -85,30 +88,43 @@ StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t I = Index.toArrayIndex();
|
uint32_t I = Index.toArrayIndex();
|
||||||
if (I >= TypeNames.size())
|
ensureCapacityFor(Index);
|
||||||
TypeNames.resize(I + 1);
|
if (Records[I].Name.data() == nullptr) {
|
||||||
|
|
||||||
if (TypeNames[I].data() == nullptr) {
|
|
||||||
StringRef Result = NameStorage.save(computeTypeName(*this, Index));
|
StringRef Result = NameStorage.save(computeTypeName(*this, Index));
|
||||||
TypeNames[I] = Result;
|
Records[I].Name = Result;
|
||||||
}
|
}
|
||||||
return TypeNames[I];
|
return Records[I].Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LazyRandomTypeCollection::contains(TypeIndex Index) {
|
bool LazyRandomTypeCollection::contains(TypeIndex Index) {
|
||||||
return Database.contains(Index);
|
if (Records.size() <= Index.toArrayIndex())
|
||||||
|
return false;
|
||||||
|
if (!Records[Index.toArrayIndex()].Type.valid())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t LazyRandomTypeCollection::size() { return Database.size(); }
|
uint32_t LazyRandomTypeCollection::size() { return Count; }
|
||||||
|
|
||||||
uint32_t LazyRandomTypeCollection::capacity() { return Database.capacity(); }
|
uint32_t LazyRandomTypeCollection::capacity() { return Records.size(); }
|
||||||
|
|
||||||
Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) {
|
Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) {
|
||||||
if (!Database.contains(TI)) {
|
if (contains(TI))
|
||||||
if (auto EC = visitRangeForType(TI))
|
return Error::success();
|
||||||
return EC;
|
|
||||||
}
|
return visitRangeForType(TI);
|
||||||
return Error::success();
|
}
|
||||||
|
|
||||||
|
void LazyRandomTypeCollection::ensureCapacityFor(TypeIndex Index) {
|
||||||
|
uint32_t MinSize = Index.toArrayIndex() + 1;
|
||||||
|
|
||||||
|
if (MinSize <= capacity())
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t NewCapacity = MinSize * 3 / 2;
|
||||||
|
|
||||||
|
assert(NewCapacity > capacity());
|
||||||
|
Records.resize(NewCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {
|
Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {
|
||||||
|
@ -124,7 +140,7 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {
|
||||||
auto Prev = std::prev(Next);
|
auto Prev = std::prev(Next);
|
||||||
|
|
||||||
TypeIndex TIB = Prev->Type;
|
TypeIndex TIB = Prev->Type;
|
||||||
if (Database.contains(TIB)) {
|
if (contains(TIB)) {
|
||||||
// They've asked us to fetch a type index, but the entry we found in the
|
// They've asked us to fetch a type index, but the entry we found in the
|
||||||
// partial offsets array has already been visited. Since we visit an entire
|
// partial offsets array has already been visited. Since we visit an entire
|
||||||
// block every time, that means this record should have been previously
|
// block every time, that means this record should have been previously
|
||||||
|
@ -135,13 +151,12 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {
|
||||||
|
|
||||||
TypeIndex TIE;
|
TypeIndex TIE;
|
||||||
if (Next == PartialOffsets.end()) {
|
if (Next == PartialOffsets.end()) {
|
||||||
TIE = TypeIndex::fromArrayIndex(Database.capacity());
|
TIE = TypeIndex::fromArrayIndex(capacity());
|
||||||
} else {
|
} else {
|
||||||
TIE = Next->Type;
|
TIE = Next->Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto EC = visitRange(TIB, Prev->Offset, TIE))
|
visitRange(TIB, Prev->Offset, TIE);
|
||||||
return EC;
|
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,34 +185,31 @@ Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {
|
||||||
assert(PartialOffsets.empty());
|
assert(PartialOffsets.empty());
|
||||||
|
|
||||||
TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0);
|
TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0);
|
||||||
uint32_t Offset = 0;
|
|
||||||
auto Begin = Types.begin();
|
auto Begin = Types.begin();
|
||||||
|
|
||||||
if (!Database.empty()) {
|
if (Count > 0) {
|
||||||
// In the case of type streams which we don't know the number of records of,
|
// In the case of type streams which we don't know the number of records of,
|
||||||
// it's possible to search for a type index triggering a full scan, but then
|
// it's possible to search for a type index triggering a full scan, but then
|
||||||
// later additional records are added since we didn't know how many there
|
// later additional records are added since we didn't know how many there
|
||||||
// would be until we did a full visitation, then you try to access the new
|
// would be until we did a full visitation, then you try to access the new
|
||||||
// type triggering another full scan. To avoid this, we assume that if the
|
// type triggering another full scan. To avoid this, we assume that if the
|
||||||
// database has some records, this must be what's going on. So we ask the
|
// database has some records, this must be what's going on. We can also
|
||||||
// database for the largest type index less than the one we're searching for
|
// assume that this index must be larger than the largest type index we've
|
||||||
// and only do the forward scan from there.
|
// visited, so we start from there and scan forward.
|
||||||
auto Prev = Database.largestTypeIndexLessThan(TI);
|
uint32_t Offset = Records[LargestTypeIndex.toArrayIndex()].Offset;
|
||||||
assert(Prev.hasValue() && "Empty database with valid types?");
|
CurrentTI = LargestTypeIndex + 1;
|
||||||
Offset = KnownOffsets[Prev->toArrayIndex()];
|
|
||||||
CurrentTI = *Prev;
|
|
||||||
++CurrentTI;
|
|
||||||
Begin = Types.at(Offset);
|
Begin = Types.at(Offset);
|
||||||
++Begin;
|
++Begin;
|
||||||
Offset = Begin.offset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto End = Types.end();
|
auto End = Types.end();
|
||||||
while (Begin != End) {
|
while (Begin != End) {
|
||||||
if (auto EC = visitOneRecord(CurrentTI, Offset, *Begin))
|
ensureCapacityFor(CurrentTI);
|
||||||
return EC;
|
LargestTypeIndex = std::max(LargestTypeIndex, CurrentTI);
|
||||||
|
auto Idx = CurrentTI.toArrayIndex();
|
||||||
Offset += Begin.getRecordLength();
|
Records[Idx].Type = *Begin;
|
||||||
|
Records[Idx].Offset = Begin.offset();
|
||||||
|
++Count;
|
||||||
++Begin;
|
++Begin;
|
||||||
++CurrentTI;
|
++CurrentTI;
|
||||||
}
|
}
|
||||||
|
@ -207,36 +219,19 @@ Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error LazyRandomTypeCollection::visitRange(TypeIndex Begin,
|
void LazyRandomTypeCollection::visitRange(TypeIndex Begin, uint32_t BeginOffset,
|
||||||
uint32_t BeginOffset,
|
TypeIndex End) {
|
||||||
TypeIndex End) {
|
|
||||||
|
|
||||||
auto RI = Types.at(BeginOffset);
|
auto RI = Types.at(BeginOffset);
|
||||||
assert(RI != Types.end());
|
assert(RI != Types.end());
|
||||||
|
|
||||||
|
ensureCapacityFor(End);
|
||||||
while (Begin != End) {
|
while (Begin != End) {
|
||||||
if (auto EC = visitOneRecord(Begin, BeginOffset, *RI))
|
LargestTypeIndex = std::max(LargestTypeIndex, Begin);
|
||||||
return EC;
|
auto Idx = Begin.toArrayIndex();
|
||||||
|
Records[Idx].Type = *RI;
|
||||||
BeginOffset += RI.getRecordLength();
|
Records[Idx].Offset = RI.offset();
|
||||||
|
++Count;
|
||||||
++Begin;
|
++Begin;
|
||||||
++RI;
|
++RI;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error LazyRandomTypeCollection::visitOneRecord(TypeIndex TI, uint32_t Offset,
|
|
||||||
CVType &Record) {
|
|
||||||
assert(!Database.contains(TI));
|
|
||||||
if (auto EC = codeview::visitTypeRecord(Record, TI, DatabaseVisitor))
|
|
||||||
return EC;
|
|
||||||
// Keep the KnownOffsets array the same size as the Database's capacity. Since
|
|
||||||
// we don't always know how many records are in the type stream, we need to be
|
|
||||||
// prepared for the database growing and receicing a type index that can't fit
|
|
||||||
// in our current buffer.
|
|
||||||
if (KnownOffsets.size() < Database.capacity())
|
|
||||||
KnownOffsets.resize(Database.capacity());
|
|
||||||
KnownOffsets[TI.toArrayIndex()] = Offset;
|
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
//===- TypeDatabase.cpp --------------------------------------- *- C++ --*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
using namespace llvm::codeview;
|
|
||||||
|
|
||||||
TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) {
|
|
||||||
CVUDTNames.resize(Capacity);
|
|
||||||
TypeRecords.resize(Capacity);
|
|
||||||
ValidRecords.resize(Capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) {
|
|
||||||
LargestTypeIndex = getAppendIndex();
|
|
||||||
if (LargestTypeIndex.toArrayIndex() >= capacity())
|
|
||||||
grow();
|
|
||||||
recordType(Name, LargestTypeIndex, Data);
|
|
||||||
return LargestTypeIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TypeDatabase::recordType(StringRef Name, TypeIndex Index,
|
|
||||||
const CVType &Data) {
|
|
||||||
LargestTypeIndex = empty() ? Index : std::max(Index, LargestTypeIndex);
|
|
||||||
|
|
||||||
if (LargestTypeIndex.toArrayIndex() >= capacity())
|
|
||||||
grow(Index);
|
|
||||||
|
|
||||||
uint32_t AI = Index.toArrayIndex();
|
|
||||||
|
|
||||||
assert(!contains(Index));
|
|
||||||
assert(AI < capacity());
|
|
||||||
|
|
||||||
CVUDTNames[AI] = Name;
|
|
||||||
TypeRecords[AI] = Data;
|
|
||||||
ValidRecords.set(AI);
|
|
||||||
++Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Saves the name in a StringSet and creates a stable StringRef.
|
|
||||||
StringRef TypeDatabase::saveTypeName(StringRef TypeName) {
|
|
||||||
return TypeNameStorage.save(TypeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef TypeDatabase::getTypeName(TypeIndex Index) const {
|
|
||||||
if (Index.isNoneType() || Index.isSimple())
|
|
||||||
return TypeIndex::simpleTypeName(Index);
|
|
||||||
|
|
||||||
if (contains(Index))
|
|
||||||
return CVUDTNames[Index.toArrayIndex()];
|
|
||||||
|
|
||||||
return "<unknown UDT>";
|
|
||||||
}
|
|
||||||
|
|
||||||
const CVType &TypeDatabase::getTypeRecord(TypeIndex Index) const {
|
|
||||||
assert(contains(Index));
|
|
||||||
return TypeRecords[Index.toArrayIndex()];
|
|
||||||
}
|
|
||||||
|
|
||||||
CVType &TypeDatabase::getTypeRecord(TypeIndex Index) {
|
|
||||||
assert(contains(Index));
|
|
||||||
return TypeRecords[Index.toArrayIndex()];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TypeDatabase::contains(TypeIndex Index) const {
|
|
||||||
uint32_t AI = Index.toArrayIndex();
|
|
||||||
if (AI >= capacity())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return ValidRecords.test(AI);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t TypeDatabase::size() const { return Count; }
|
|
||||||
|
|
||||||
uint32_t TypeDatabase::capacity() const { return TypeRecords.size(); }
|
|
||||||
|
|
||||||
CVType TypeDatabase::getType(TypeIndex Index) { return getTypeRecord(Index); }
|
|
||||||
|
|
||||||
StringRef TypeDatabase::getTypeName(TypeIndex Index) {
|
|
||||||
return static_cast<const TypeDatabase *>(this)->getTypeName(Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TypeDatabase::contains(TypeIndex Index) {
|
|
||||||
return static_cast<const TypeDatabase *>(this)->contains(Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t TypeDatabase::size() {
|
|
||||||
return static_cast<const TypeDatabase *>(this)->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t TypeDatabase::capacity() {
|
|
||||||
return static_cast<const TypeDatabase *>(this)->capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TypeDatabase::grow() { grow(LargestTypeIndex + 1); }
|
|
||||||
|
|
||||||
void TypeDatabase::grow(TypeIndex NewIndex) {
|
|
||||||
uint32_t NewSize = NewIndex.toArrayIndex() + 1;
|
|
||||||
|
|
||||||
if (NewSize <= capacity())
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32_t NewCapacity = NewSize * 3 / 2;
|
|
||||||
|
|
||||||
TypeRecords.resize(NewCapacity);
|
|
||||||
CVUDTNames.resize(NewCapacity);
|
|
||||||
ValidRecords.resize(NewCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TypeDatabase::empty() const { return size() == 0; }
|
|
||||||
|
|
||||||
Optional<TypeIndex> TypeDatabase::largestTypeIndexLessThan(TypeIndex TI) const {
|
|
||||||
uint32_t AI = TI.toArrayIndex();
|
|
||||||
int N = ValidRecords.find_prev(AI);
|
|
||||||
if (N == -1)
|
|
||||||
return None;
|
|
||||||
return TypeIndex::fromArrayIndex(N);
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeIndex TypeDatabase::getAppendIndex() const {
|
|
||||||
if (empty())
|
|
||||||
return TypeIndex::fromArrayIndex(0);
|
|
||||||
|
|
||||||
return LargestTypeIndex + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<TypeIndex> TypeDatabase::getFirst() {
|
|
||||||
int N = ValidRecords.find_first();
|
|
||||||
if (N == -1)
|
|
||||||
return None;
|
|
||||||
return TypeIndex::fromArrayIndex(N);
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<TypeIndex> TypeDatabase::getNext(TypeIndex Prev) {
|
|
||||||
int N = ValidRecords.find_next(Prev.toArrayIndex());
|
|
||||||
if (N == -1)
|
|
||||||
return None;
|
|
||||||
return TypeIndex::fromArrayIndex(N);
|
|
||||||
}
|
|
|
@ -1,330 +0,0 @@
|
||||||
//===- TypeDatabaseVisitor.cpp -------------------------------- *- C++ --*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
|
|
||||||
|
|
||||||
#include "llvm/ADT/SmallString.h"
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
using namespace llvm::codeview;
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record) {
|
|
||||||
assert(!IsInFieldList);
|
|
||||||
// Reset Name to the empty string. If the visitor sets it, we know it.
|
|
||||||
Name = "";
|
|
||||||
|
|
||||||
if (Record.Type == LF_FIELDLIST) {
|
|
||||||
// Record that we're in a field list so that members do not get assigned
|
|
||||||
// type indices.
|
|
||||||
IsInFieldList = true;
|
|
||||||
}
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
|
|
||||||
if (auto EC = visitTypeBegin(Record))
|
|
||||||
return EC;
|
|
||||||
|
|
||||||
CurrentTypeIndex = Index;
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef TypeDatabaseVisitor::getTypeName(TypeIndex Index) const {
|
|
||||||
return TypeDB->getTypeName(Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef TypeDatabaseVisitor::saveTypeName(StringRef Name) {
|
|
||||||
return TypeDB->saveTypeName(Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitTypeEnd(CVType &CVR) {
|
|
||||||
if (CVR.Type == LF_FIELDLIST) {
|
|
||||||
assert(IsInFieldList);
|
|
||||||
IsInFieldList = false;
|
|
||||||
}
|
|
||||||
assert(!IsInFieldList);
|
|
||||||
|
|
||||||
// Record every type that is not a field list member, even if Name is empty.
|
|
||||||
// CVUDTNames is indexed by type index, and must have one entry for every
|
|
||||||
// type. Field list members are not recorded, and are only referenced by
|
|
||||||
// their containing field list record.
|
|
||||||
if (CurrentTypeIndex)
|
|
||||||
TypeDB->recordType(Name, *CurrentTypeIndex, CVR);
|
|
||||||
else
|
|
||||||
TypeDB->appendType(Name, CVR);
|
|
||||||
|
|
||||||
CurrentTypeIndex.reset();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitMemberBegin(CVMemberRecord &Record) {
|
|
||||||
assert(IsInFieldList);
|
|
||||||
// Reset Name to the empty string. If the visitor sets it, we know it.
|
|
||||||
Name = "";
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitMemberEnd(CVMemberRecord &Record) {
|
|
||||||
assert(IsInFieldList);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
|
|
||||||
FieldListRecord &FieldList) {
|
|
||||||
Name = "<field list>";
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
|
|
||||||
StringIdRecord &String) {
|
|
||||||
// Put this in the database so it gets printed with LF_UDT_SRC_LINE.
|
|
||||||
Name = String.getString();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
|
|
||||||
auto Indices = Args.getIndices();
|
|
||||||
uint32_t Size = Indices.size();
|
|
||||||
SmallString<256> TypeName("(");
|
|
||||||
for (uint32_t I = 0; I < Size; ++I) {
|
|
||||||
StringRef ArgTypeName = getTypeName(Indices[I]);
|
|
||||||
TypeName.append(ArgTypeName);
|
|
||||||
if (I + 1 != Size)
|
|
||||||
TypeName.append(", ");
|
|
||||||
}
|
|
||||||
TypeName.push_back(')');
|
|
||||||
Name = saveTypeName(TypeName);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
|
|
||||||
StringListRecord &Strings) {
|
|
||||||
auto Indices = Strings.getIndices();
|
|
||||||
uint32_t Size = Indices.size();
|
|
||||||
SmallString<256> TypeName("\"");
|
|
||||||
for (uint32_t I = 0; I < Size; ++I) {
|
|
||||||
StringRef ArgTypeName = getTypeName(Indices[I]);
|
|
||||||
TypeName.append(ArgTypeName);
|
|
||||||
if (I + 1 != Size)
|
|
||||||
TypeName.append("\" \"");
|
|
||||||
}
|
|
||||||
TypeName.push_back('\"');
|
|
||||||
Name = saveTypeName(TypeName);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
|
|
||||||
Name = Class.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
|
|
||||||
Name = Union.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
|
|
||||||
Name = Enum.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
|
|
||||||
Name = AT.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
|
|
||||||
Name = VFT.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
|
|
||||||
MemberFuncIdRecord &Id) {
|
|
||||||
Name = Id.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
|
|
||||||
ProcedureRecord &Proc) {
|
|
||||||
StringRef ReturnTypeName = getTypeName(Proc.getReturnType());
|
|
||||||
StringRef ArgListTypeName = getTypeName(Proc.getArgumentList());
|
|
||||||
SmallString<256> TypeName(ReturnTypeName);
|
|
||||||
TypeName.push_back(' ');
|
|
||||||
TypeName.append(ArgListTypeName);
|
|
||||||
Name = saveTypeName(TypeName);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
|
|
||||||
MemberFunctionRecord &MF) {
|
|
||||||
StringRef ReturnTypeName = getTypeName(MF.getReturnType());
|
|
||||||
StringRef ClassTypeName = getTypeName(MF.getClassType());
|
|
||||||
StringRef ArgListTypeName = getTypeName(MF.getArgumentList());
|
|
||||||
SmallString<256> TypeName(ReturnTypeName);
|
|
||||||
TypeName.push_back(' ');
|
|
||||||
TypeName.append(ClassTypeName);
|
|
||||||
TypeName.append("::");
|
|
||||||
TypeName.append(ArgListTypeName);
|
|
||||||
Name = saveTypeName(TypeName);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
|
|
||||||
Name = Func.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
|
|
||||||
TypeServer2Record &TS) {
|
|
||||||
Name = TS.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
|
|
||||||
|
|
||||||
if (Ptr.isPointerToMember()) {
|
|
||||||
const MemberPointerInfo &MI = Ptr.getMemberInfo();
|
|
||||||
|
|
||||||
StringRef PointeeName = getTypeName(Ptr.getReferentType());
|
|
||||||
StringRef ClassName = getTypeName(MI.getContainingType());
|
|
||||||
SmallString<256> TypeName(PointeeName);
|
|
||||||
TypeName.push_back(' ');
|
|
||||||
TypeName.append(ClassName);
|
|
||||||
TypeName.append("::*");
|
|
||||||
Name = saveTypeName(TypeName);
|
|
||||||
} else {
|
|
||||||
SmallString<256> TypeName;
|
|
||||||
if (Ptr.isConst())
|
|
||||||
TypeName.append("const ");
|
|
||||||
if (Ptr.isVolatile())
|
|
||||||
TypeName.append("volatile ");
|
|
||||||
if (Ptr.isUnaligned())
|
|
||||||
TypeName.append("__unaligned ");
|
|
||||||
|
|
||||||
TypeName.append(getTypeName(Ptr.getReferentType()));
|
|
||||||
|
|
||||||
if (Ptr.getMode() == PointerMode::LValueReference)
|
|
||||||
TypeName.append("&");
|
|
||||||
else if (Ptr.getMode() == PointerMode::RValueReference)
|
|
||||||
TypeName.append("&&");
|
|
||||||
else if (Ptr.getMode() == PointerMode::Pointer)
|
|
||||||
TypeName.append("*");
|
|
||||||
|
|
||||||
if (!TypeName.empty())
|
|
||||||
Name = saveTypeName(TypeName);
|
|
||||||
}
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
|
|
||||||
uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
|
|
||||||
|
|
||||||
StringRef ModifiedName = getTypeName(Mod.getModifiedType());
|
|
||||||
SmallString<256> TypeName;
|
|
||||||
if (Mods & uint16_t(ModifierOptions::Const))
|
|
||||||
TypeName.append("const ");
|
|
||||||
if (Mods & uint16_t(ModifierOptions::Volatile))
|
|
||||||
TypeName.append("volatile ");
|
|
||||||
if (Mods & uint16_t(ModifierOptions::Unaligned))
|
|
||||||
TypeName.append("__unaligned ");
|
|
||||||
TypeName.append(ModifiedName);
|
|
||||||
Name = saveTypeName(TypeName);
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
|
|
||||||
VFTableShapeRecord &Shape) {
|
|
||||||
Name =
|
|
||||||
saveTypeName("<vftable " + utostr(Shape.getEntryCount()) + " methods>");
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
NestedTypeRecord &Nested) {
|
|
||||||
Name = Nested.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
OneMethodRecord &Method) {
|
|
||||||
Name = Method.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
OverloadedMethodRecord &Method) {
|
|
||||||
Name = Method.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
DataMemberRecord &Field) {
|
|
||||||
Name = Field.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
StaticDataMemberRecord &Field) {
|
|
||||||
Name = Field.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
EnumeratorRecord &Enum) {
|
|
||||||
Name = Enum.getName();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
BaseClassRecord &Base) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
VirtualBaseClassRecord &VBase) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
ListContinuationRecord &Cont) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(
|
|
||||||
CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
|
|
||||||
UdtSourceLineRecord &SourceLine) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(
|
|
||||||
CVType &CVR, MethodOverloadListRecord &Overloads) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
|
|
||||||
VFPtrRecord &VFP) {
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
|
#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
|
||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
|
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
|
#include "llvm/DebugInfo/CodeView/TypeName.h"
|
||||||
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
|
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
|
||||||
#include "llvm/Support/BinaryByteStream.h"
|
#include "llvm/Support/BinaryByteStream.h"
|
||||||
#include "llvm/Support/BinaryStreamReader.h"
|
#include "llvm/Support/BinaryStreamReader.h"
|
||||||
|
@ -18,14 +18,10 @@
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::codeview;
|
using namespace llvm::codeview;
|
||||||
|
|
||||||
static void error(Error &&EC) {
|
|
||||||
assert(!static_cast<bool>(EC));
|
|
||||||
if (EC)
|
|
||||||
consumeError(std::move(EC));
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeTableCollection::TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records)
|
TypeTableCollection::TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records)
|
||||||
: Records(Records), Database(Records.size()) {}
|
: NameStorage(Allocator), Records(Records) {
|
||||||
|
Names.resize(Records.size());
|
||||||
|
}
|
||||||
|
|
||||||
Optional<TypeIndex> TypeTableCollection::getFirst() {
|
Optional<TypeIndex> TypeTableCollection::getFirst() {
|
||||||
if (empty())
|
if (empty())
|
||||||
|
@ -34,50 +30,38 @@ Optional<TypeIndex> TypeTableCollection::getFirst() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<TypeIndex> TypeTableCollection::getNext(TypeIndex Prev) {
|
Optional<TypeIndex> TypeTableCollection::getNext(TypeIndex Prev) {
|
||||||
|
assert(contains(Prev));
|
||||||
++Prev;
|
++Prev;
|
||||||
assert(Prev.toArrayIndex() <= size());
|
|
||||||
if (Prev.toArrayIndex() == size())
|
if (Prev.toArrayIndex() == size())
|
||||||
return None;
|
return None;
|
||||||
return Prev;
|
return Prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeTableCollection::ensureTypeExists(TypeIndex Index) {
|
|
||||||
assert(hasCapacityFor(Index));
|
|
||||||
|
|
||||||
if (Database.contains(Index))
|
|
||||||
return;
|
|
||||||
|
|
||||||
BinaryByteStream Bytes(Records[Index.toArrayIndex()], support::little);
|
|
||||||
|
|
||||||
CVType Type;
|
|
||||||
uint32_t Len;
|
|
||||||
VarStreamArrayExtractor<CVType> Extract;
|
|
||||||
error(Extract(Bytes, Len, Type));
|
|
||||||
|
|
||||||
TypeDatabaseVisitor DBV(Database);
|
|
||||||
error(codeview::visitTypeRecord(Type, Index, DBV));
|
|
||||||
assert(Database.contains(Index));
|
|
||||||
}
|
|
||||||
|
|
||||||
CVType TypeTableCollection::getType(TypeIndex Index) {
|
CVType TypeTableCollection::getType(TypeIndex Index) {
|
||||||
ensureTypeExists(Index);
|
assert(Index.toArrayIndex() < Records.size());
|
||||||
return Database.getTypeRecord(Index);
|
ArrayRef<uint8_t> Bytes = Records[Index.toArrayIndex()];
|
||||||
|
const RecordPrefix *Prefix =
|
||||||
|
reinterpret_cast<const RecordPrefix *>(Bytes.data());
|
||||||
|
TypeLeafKind Kind = static_cast<TypeLeafKind>(uint16_t(Prefix->RecordKind));
|
||||||
|
return CVType(Kind, Bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef TypeTableCollection::getTypeName(TypeIndex Index) {
|
StringRef TypeTableCollection::getTypeName(TypeIndex Index) {
|
||||||
if (!Index.isSimple())
|
if (Index.isNoneType() || Index.isSimple())
|
||||||
ensureTypeExists(Index);
|
return TypeIndex::simpleTypeName(Index);
|
||||||
return Database.getTypeName(Index);
|
|
||||||
|
uint32_t I = Index.toArrayIndex();
|
||||||
|
if (Names[I].data() == nullptr) {
|
||||||
|
StringRef Result = NameStorage.save(computeTypeName(*this, Index));
|
||||||
|
Names[I] = Result;
|
||||||
|
}
|
||||||
|
return Names[I];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeTableCollection::contains(TypeIndex Index) {
|
bool TypeTableCollection::contains(TypeIndex Index) {
|
||||||
return Database.contains(Index);
|
return Index.toArrayIndex() <= size();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t TypeTableCollection::size() { return Records.size(); }
|
uint32_t TypeTableCollection::size() { return Records.size(); }
|
||||||
|
|
||||||
uint32_t TypeTableCollection::capacity() { return Records.size(); }
|
uint32_t TypeTableCollection::capacity() { return Records.size(); }
|
||||||
|
|
||||||
bool TypeTableCollection::hasCapacityFor(TypeIndex Index) const {
|
|
||||||
return Index.toArrayIndex() < Records.size();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1099,7 +1099,7 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
|
||||||
if (Magic != COFF::DEBUG_SECTION_MAGIC)
|
if (Magic != COFF::DEBUG_SECTION_MAGIC)
|
||||||
return error(object_error::parse_failed);
|
return error(object_error::parse_failed);
|
||||||
|
|
||||||
Types.reset(Data);
|
Types.reset(Data, 100);
|
||||||
|
|
||||||
TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes);
|
TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes);
|
||||||
error(codeview::visitTypeStream(Types, TDV));
|
error(codeview::visitTypeStream(Types, TDV));
|
||||||
|
|
Loading…
Reference in New Issue