mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
LLVM CodeView library
Summary: This diff is the initial implementation of the LLVM CodeView library. There is much more work to be done, namely a CodeView dumper and tests. This patch should help others make progress on the LLVM->CodeView debug info emission while I continue with the implementation of the dumper and tests. This library implements support for emitting debug info in the CodeView format. This phase of the implementation only includes support for CodeView type records. Clients that need to emit type records will use a class derived from TypeTableBuilder. TypeTableBuilder provides member functions for writing each kind of type record; each of these functions eventually calls the writeRecord virtual function to emit the actual bits of the record. Derived classes override writeRecord to implement the folding of duplicate records and the actual emission to the appropriate destination. LLVMCodeView provides MemoryTypeTableBuilder, which creates the table in memory. In the future, other classes derived from TypeTableBuilder will write to other destinations, such as the type stream in a PDB. The rest of the types in LLVMCodeView define the actual CodeView type records and all of the supporting enums and other types used in the type records. The TypeIndex class is of particular interest, because it is used by clients as a handle to a type in the type table. The library provides a relatively low-level interface based on the actual on-disk format of CodeView. For example, type records refer to other type records by TypeIndex, rather than by an actual pointer to the referent record. This allows clients to emit type records one at a time, rather than having to keep the entire transitive closure of type records in memory until everything has been emitted. At some point, having a higher-level interface layered on top of this one may be useful for debuggers and other tools that want a more holistic view of the debug info. The lower-level interface should be sufficient for compilers and linkers to do the debug info manipulation that they need to do efficiently. Reviewers: rnk, majnemer Subscribers: silvas, rnk, jevinskie, llvm-commits Differential Revision: http://reviews.llvm.org/D14961 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256385 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20bc430a18
commit
994a189088
367
include/llvm/DebugInfo/CodeView/CodeView.h
Normal file
367
include/llvm/DebugInfo/CodeView/CodeView.h
Normal file
@ -0,0 +1,367 @@
|
||||
//===- CodeView.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_CODEVIEW_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
enum class CallingConvention : uint8_t {
|
||||
NearC = 0x00, // near right to left push, caller pops stack
|
||||
FarC = 0x01, // far right to left push, caller pops stack
|
||||
NearPascal = 0x02, // near left to right push, callee pops stack
|
||||
FarPascal = 0x03, // far left to right push, callee pops stack
|
||||
NearFast = 0x04, // near left to right push with regs, callee pops stack
|
||||
FarFast = 0x05, // far left to right push with regs, callee pops stack
|
||||
NearStdCall = 0x07, // near standard call
|
||||
FarStdCall = 0x08, // far standard call
|
||||
NearSysCall = 0x09, // near sys call
|
||||
FarSysCall = 0x0a, // far sys call
|
||||
ThisCall = 0x0b, // this call (this passed in register)
|
||||
MipsCall = 0x0c, // Mips call
|
||||
Generic = 0x0d, // Generic call sequence
|
||||
AlphaCall = 0x0e, // Alpha call
|
||||
PpcCall = 0x0f, // PPC call
|
||||
SHCall = 0x10, // Hitachi SuperH call
|
||||
ArmCall = 0x11, // ARM call
|
||||
AM33Call = 0x12, // AM33 call
|
||||
TriCall = 0x13, // TriCore Call
|
||||
SH5Call = 0x14, // Hitachi SuperH-5 call
|
||||
M32RCall = 0x15, // M32R Call
|
||||
ClrCall = 0x16, // clr call
|
||||
Inline =
|
||||
0x17, // Marker for routines always inlined and thus lacking a convention
|
||||
NearVector = 0x18 // near left to right push with regs, callee pops stack
|
||||
};
|
||||
|
||||
enum class ClassOptions : uint16_t {
|
||||
None = 0x0000,
|
||||
Packed = 0x0001,
|
||||
HasConstructorOrDestructor = 0x0002,
|
||||
HasOverloadedOperator = 0x0004,
|
||||
Nested = 0x0008,
|
||||
ContainsNestedClass = 0x0010,
|
||||
HasOverloadedAssignmentOperator = 0x0020,
|
||||
HasConversionOperator = 0x0040,
|
||||
ForwardReference = 0x0080,
|
||||
Scoped = 0x0100,
|
||||
HasUniqueName = 0x0200,
|
||||
Sealed = 0x0400,
|
||||
Intrinsic = 0x2000
|
||||
};
|
||||
|
||||
inline ClassOptions operator|(ClassOptions a, ClassOptions b) {
|
||||
return static_cast<ClassOptions>(static_cast<uint16_t>(a) |
|
||||
static_cast<uint16_t>(b));
|
||||
}
|
||||
|
||||
inline ClassOptions operator&(ClassOptions a, ClassOptions b) {
|
||||
return static_cast<ClassOptions>(static_cast<uint16_t>(a) &
|
||||
static_cast<uint16_t>(b));
|
||||
}
|
||||
|
||||
inline ClassOptions operator~(ClassOptions a) {
|
||||
return static_cast<ClassOptions>(~static_cast<uint16_t>(a));
|
||||
}
|
||||
|
||||
enum class FrameProcedureOptions : uint32_t {
|
||||
None = 0x00000000,
|
||||
HasAlloca = 0x00000001,
|
||||
HasSetJmp = 0x00000002,
|
||||
HasLongJmp = 0x00000004,
|
||||
HasInlineAssembly = 0x00000008,
|
||||
HasExceptionHandling = 0x00000010,
|
||||
MarkedInline = 0x00000020,
|
||||
HasStructuredExceptionHandling = 0x00000040,
|
||||
Naked = 0x00000080,
|
||||
SecurityChecks = 0x00000100,
|
||||
AsynchronousExceptionHandling = 0x00000200,
|
||||
NoStackOrderingForSecurityChecks = 0x00000400,
|
||||
Inlined = 0x00000800,
|
||||
StrictSecurityChecks = 0x00001000,
|
||||
SafeBuffers = 0x00002000,
|
||||
ProfileGuidedOptimization = 0x00040000,
|
||||
ValidProfileCounts = 0x00080000,
|
||||
OptimizedForSpeed = 0x00100000,
|
||||
GuardCfg = 0x00200000,
|
||||
GuardCfw = 0x00400000
|
||||
};
|
||||
|
||||
inline FrameProcedureOptions operator|(FrameProcedureOptions a,
|
||||
FrameProcedureOptions b) {
|
||||
return static_cast<FrameProcedureOptions>(static_cast<uint32_t>(a) |
|
||||
static_cast<uint32_t>(b));
|
||||
}
|
||||
|
||||
inline FrameProcedureOptions operator&(FrameProcedureOptions a,
|
||||
FrameProcedureOptions b) {
|
||||
return static_cast<FrameProcedureOptions>(static_cast<uint32_t>(a) &
|
||||
static_cast<uint32_t>(b));
|
||||
}
|
||||
|
||||
inline FrameProcedureOptions operator~(FrameProcedureOptions a) {
|
||||
return static_cast<FrameProcedureOptions>(~static_cast<uint32_t>(a));
|
||||
}
|
||||
|
||||
enum class FunctionOptions : uint8_t {
|
||||
None = 0x00,
|
||||
CxxReturnUdt = 0x01,
|
||||
Constructor = 0x02,
|
||||
ConstructorWithVirtualBases = 0x04
|
||||
};
|
||||
|
||||
inline FunctionOptions operator|(FunctionOptions a, FunctionOptions b) {
|
||||
return static_cast<FunctionOptions>(static_cast<uint8_t>(a) |
|
||||
static_cast<uint8_t>(b));
|
||||
}
|
||||
|
||||
inline FunctionOptions operator&(FunctionOptions a, FunctionOptions b) {
|
||||
return static_cast<FunctionOptions>(static_cast<uint8_t>(a) &
|
||||
static_cast<uint8_t>(b));
|
||||
}
|
||||
|
||||
inline FunctionOptions operator~(FunctionOptions a) {
|
||||
return static_cast<FunctionOptions>(~static_cast<uint8_t>(a));
|
||||
}
|
||||
|
||||
enum class HfaKind : uint8_t {
|
||||
None = 0x00,
|
||||
Float = 0x01,
|
||||
Double = 0x02,
|
||||
Other = 0x03
|
||||
};
|
||||
|
||||
enum class MemberAccess : uint8_t {
|
||||
None = 0,
|
||||
Private = 1,
|
||||
Protected = 2,
|
||||
Public = 3
|
||||
};
|
||||
|
||||
enum class MethodKind : uint8_t {
|
||||
Vanilla = 0x00,
|
||||
Virtual = 0x01,
|
||||
Static = 0x02,
|
||||
Friend = 0x03,
|
||||
IntroducingVirtual = 0x04,
|
||||
PureVirtual = 0x05,
|
||||
PureIntroducingVirtual = 0x06
|
||||
};
|
||||
|
||||
enum class MethodOptions : uint16_t {
|
||||
None = 0x0000,
|
||||
Pseudo = 0x0020,
|
||||
CompilerGenerated = 0x0100,
|
||||
Sealed = 0x0200
|
||||
};
|
||||
|
||||
inline MethodOptions operator|(MethodOptions a, MethodOptions b) {
|
||||
return static_cast<MethodOptions>(static_cast<uint16_t>(a) |
|
||||
static_cast<uint16_t>(b));
|
||||
}
|
||||
|
||||
inline MethodOptions operator&(MethodOptions a, MethodOptions b) {
|
||||
return static_cast<MethodOptions>(static_cast<uint16_t>(a) &
|
||||
static_cast<uint16_t>(b));
|
||||
}
|
||||
|
||||
inline MethodOptions operator~(MethodOptions a) {
|
||||
return static_cast<MethodOptions>(~static_cast<uint16_t>(a));
|
||||
}
|
||||
|
||||
enum class ModifierOptions : uint16_t {
|
||||
None = 0x0000,
|
||||
Const = 0x0001,
|
||||
Volatile = 0x0002,
|
||||
Unaligned = 0x0004
|
||||
};
|
||||
|
||||
inline ModifierOptions operator|(ModifierOptions a, ModifierOptions b) {
|
||||
return static_cast<ModifierOptions>(static_cast<uint16_t>(a) |
|
||||
static_cast<uint16_t>(b));
|
||||
}
|
||||
|
||||
inline ModifierOptions operator&(ModifierOptions a, ModifierOptions b) {
|
||||
return static_cast<ModifierOptions>(static_cast<uint16_t>(a) &
|
||||
static_cast<uint16_t>(b));
|
||||
}
|
||||
|
||||
inline ModifierOptions operator~(ModifierOptions a) {
|
||||
return static_cast<ModifierOptions>(~static_cast<uint16_t>(a));
|
||||
}
|
||||
|
||||
enum class ModuleSubstreamKind : uint32_t {
|
||||
Symbols = 0xf1,
|
||||
Lines = 0xf2,
|
||||
StringTable = 0xf3,
|
||||
FileChecksums = 0xf4,
|
||||
FrameData = 0xf5,
|
||||
InlineeLines = 0xf6,
|
||||
CrossScopeImports = 0xf7,
|
||||
CrossScopeExports = 0xf8
|
||||
};
|
||||
|
||||
enum class PointerKind : uint8_t {
|
||||
Near16 = 0x00, // 16 bit pointer
|
||||
Far16 = 0x01, // 16:16 far pointer
|
||||
Huge16 = 0x02, // 16:16 huge pointer
|
||||
BasedOnSegment = 0x03, // based on segment
|
||||
BasedOnValue = 0x04, // based on value of base
|
||||
BasedOnSegmentValue = 0x05, // based on segment value of base
|
||||
BasedOnAddress = 0x06, // based on address of base
|
||||
BasedOnSegmentAddress = 0x07, // based on segment address of base
|
||||
BasedOnType = 0x08, // based on type
|
||||
BasedOnSelf = 0x09, // based on self
|
||||
Near32 = 0x0a, // 32 bit pointer
|
||||
Far32 = 0x0b, // 16:32 pointer
|
||||
Near64 = 0x0c // 64 bit pointer
|
||||
};
|
||||
|
||||
enum class PointerMode : uint8_t {
|
||||
Pointer = 0x00, // "normal" pointer
|
||||
LValueReference = 0x01, // "old" reference
|
||||
PointerToDataMember = 0x02, // pointer to data member
|
||||
PointerToMemberFunction = 0x03, // pointer to member function
|
||||
RValueReference = 0x04 // r-value reference
|
||||
};
|
||||
|
||||
enum class PointerOptions : uint32_t {
|
||||
None = 0x00000000,
|
||||
Flat32 = 0x00000100,
|
||||
Volatile = 0x00000200,
|
||||
Const = 0x00000400,
|
||||
Unaligned = 0x00000800,
|
||||
Restrict = 0x00001000,
|
||||
WinRTSmartPointer = 0x00080000
|
||||
};
|
||||
|
||||
inline PointerOptions operator|(PointerOptions a, PointerOptions b) {
|
||||
return static_cast<PointerOptions>(static_cast<uint16_t>(a) |
|
||||
static_cast<uint16_t>(b));
|
||||
}
|
||||
|
||||
inline PointerOptions operator&(PointerOptions a, PointerOptions b) {
|
||||
return static_cast<PointerOptions>(static_cast<uint16_t>(a) &
|
||||
static_cast<uint16_t>(b));
|
||||
}
|
||||
|
||||
inline PointerOptions operator~(PointerOptions a) {
|
||||
return static_cast<PointerOptions>(~static_cast<uint16_t>(a));
|
||||
}
|
||||
|
||||
enum class PointerToMemberRepresentation : uint16_t {
|
||||
Unknown = 0x00, // not specified (pre VC8)
|
||||
SingleInheritanceData = 0x01, // member data, single inheritance
|
||||
MultipleInheritanceData = 0x02, // member data, multiple inheritance
|
||||
VirtualInheritanceData = 0x03, // member data, virtual inheritance
|
||||
GeneralData = 0x04, // member data, most general
|
||||
SingleInheritanceFunction = 0x05, // member function, single inheritance
|
||||
MultipleInheritanceFunction = 0x06, // member function, multiple inheritance
|
||||
VirtualInheritanceFunction = 0x07, // member function, virtual inheritance
|
||||
GeneralFunction = 0x08 // member function, most general
|
||||
};
|
||||
|
||||
enum class TypeRecordKind : uint16_t {
|
||||
None = 0,
|
||||
|
||||
VirtualTableShape = 0x000a,
|
||||
Label = 0x000e,
|
||||
EndPrecompiledHeader = 0x0014,
|
||||
|
||||
Modifier = 0x1001,
|
||||
Pointer = 0x1002,
|
||||
Procedure = 0x1008,
|
||||
MemberFunction = 0x1009,
|
||||
|
||||
Oem = 0x100f,
|
||||
Oem2 = 0x1011,
|
||||
|
||||
ArgumentList = 0x1201,
|
||||
FieldList = 0x1203,
|
||||
BitField = 0x1205,
|
||||
MethodList = 0x1206,
|
||||
|
||||
BaseClass = 0x1400,
|
||||
VirtualBaseClass = 0x1401,
|
||||
IndirectVirtualBaseClass = 0x1402,
|
||||
Index = 0x1404,
|
||||
VirtualFunctionTablePointer = 0x1409,
|
||||
|
||||
Enumerate = 0x1502,
|
||||
Array = 0x1503,
|
||||
Class = 0x1504,
|
||||
Structure = 0x1505,
|
||||
Union = 0x1506,
|
||||
Enum = 0x1507,
|
||||
Alias = 0x150a,
|
||||
Member = 0x150d,
|
||||
StaticMember = 0x150e,
|
||||
Method = 0x150f,
|
||||
NestedType = 0x1510,
|
||||
OneMethod = 0x1511,
|
||||
VirtualFunctionTable = 0x151d,
|
||||
|
||||
FunctionId = 0x1601,
|
||||
MemberFunctionId = 0x1602,
|
||||
BuildInfo = 0x1603,
|
||||
SubstringList = 0x1604,
|
||||
StringId = 0x1605,
|
||||
UdtSourceLine = 0x1606,
|
||||
|
||||
SByte = 0x8000,
|
||||
Int16 = 0x8001,
|
||||
UInt16 = 0x8002,
|
||||
Int32 = 0x8003,
|
||||
UInt32 = 0x8004,
|
||||
Single = 0x8005,
|
||||
Double = 0x8006,
|
||||
Float80 = 0x8007,
|
||||
Float128 = 0x8008,
|
||||
Int64 = 0x8009,
|
||||
UInt64 = 0x800a,
|
||||
Float48 = 0x800b,
|
||||
Complex32 = 0x800c,
|
||||
Complex64 = 0x800d,
|
||||
Complex80 = 0x800e,
|
||||
Complex128 = 0x800f,
|
||||
VarString = 0x8010,
|
||||
|
||||
Int128 = 0x8017,
|
||||
UInt128 = 0x8018,
|
||||
|
||||
Decimal = 0x8019,
|
||||
Date = 0x801a,
|
||||
Utf8String = 0x801b,
|
||||
|
||||
Float16 = 0x801c
|
||||
};
|
||||
|
||||
enum class VirtualTableSlotKind : uint8_t {
|
||||
Near16 = 0x00,
|
||||
Far16 = 0x01,
|
||||
This = 0x02,
|
||||
Outer = 0x03,
|
||||
Meta = 0x04,
|
||||
Near = 0x05,
|
||||
Far = 0x06
|
||||
};
|
||||
|
||||
enum class WindowsRTClassKind : uint8_t {
|
||||
None = 0x00,
|
||||
RefClass = 0x01,
|
||||
ValueClass = 0x02,
|
||||
Interface = 0x03
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
39
include/llvm/DebugInfo/CodeView/CodeViewOStream.h
Normal file
39
include/llvm/DebugInfo/CodeView/CodeViewOStream.h
Normal file
@ -0,0 +1,39 @@
|
||||
//===- CodeViewOStream.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_CODEVIEWOSTREAM_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWOSTREAM_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
template <typename Writer> class CodeViewOStream {
|
||||
private:
|
||||
CodeViewOStream(const CodeViewOStream &) = delete;
|
||||
CodeViewOStream &operator=(const CodeViewOStream &) = delete;
|
||||
|
||||
public:
|
||||
typedef typename Writer::LabelType LabelType;
|
||||
|
||||
public:
|
||||
explicit CodeViewOStream(Writer &W);
|
||||
|
||||
private:
|
||||
uint64_t size() const { return W.tell(); }
|
||||
|
||||
private:
|
||||
Writer &W;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
78
include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h
Normal file
78
include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h
Normal file
@ -0,0 +1,78 @@
|
||||
//===- FieldListRecordBuilder.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_FIELDLISTRECORDBUILDER_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_FIELDLISTRECORDBUILDER_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class MethodInfo {
|
||||
public:
|
||||
MethodInfo() : Access(), Kind(), Options(), Type(), VTableSlotOffset(-1) {}
|
||||
|
||||
MethodInfo(MemberAccess Access, MethodKind Kind, MethodOptions Options,
|
||||
TypeIndex Type, int32_t VTableSlotOffset)
|
||||
: Access(Access), Kind(Kind), Options(Options), Type(Type),
|
||||
VTableSlotOffset(VTableSlotOffset) {}
|
||||
|
||||
MemberAccess getAccess() const { return Access; }
|
||||
MethodKind getKind() const { return Kind; }
|
||||
MethodOptions getOptions() const { return Options; }
|
||||
TypeIndex getType() const { return Type; }
|
||||
int32_t getVTableSlotOffset() const { return VTableSlotOffset; }
|
||||
|
||||
private:
|
||||
MemberAccess Access;
|
||||
MethodKind Kind;
|
||||
MethodOptions Options;
|
||||
TypeIndex Type;
|
||||
int32_t VTableSlotOffset;
|
||||
};
|
||||
|
||||
class FieldListRecordBuilder : public ListRecordBuilder {
|
||||
private:
|
||||
FieldListRecordBuilder(const FieldListRecordBuilder &) = delete;
|
||||
void operator=(const FieldListRecordBuilder &) = delete;
|
||||
|
||||
public:
|
||||
FieldListRecordBuilder();
|
||||
|
||||
void writeBaseClass(MemberAccess Access, TypeIndex Type, uint64_t Offset);
|
||||
void writeEnumerate(MemberAccess Access, uint64_t Value, StringRef Name);
|
||||
void writeIndirectVirtualBaseClass(MemberAccess Access, TypeIndex Type,
|
||||
TypeIndex VirtualBasePointerType,
|
||||
int64_t VirtualBasePointerOffset,
|
||||
uint64_t SlotIndex);
|
||||
void writeMember(MemberAccess Access, TypeIndex Type, uint64_t Offset,
|
||||
StringRef Name);
|
||||
void writeOneMethod(MemberAccess Access, MethodKind Kind,
|
||||
MethodOptions Options, TypeIndex Type,
|
||||
int32_t VTableSlotOffset, StringRef Name);
|
||||
void writeOneMethod(const MethodInfo &Method, StringRef Name);
|
||||
void writeMethod(uint16_t OverloadCount, TypeIndex MethodList,
|
||||
StringRef Name);
|
||||
void writeNestedType(TypeIndex Type, StringRef Name);
|
||||
void writeStaticMember(MemberAccess Access, TypeIndex Type, StringRef Name);
|
||||
void writeVirtualBaseClass(MemberAccess Access, TypeIndex Type,
|
||||
TypeIndex VirtualBasePointerType,
|
||||
int64_t VirtualBasePointerOffset,
|
||||
uint64_t SlotIndex);
|
||||
void writeVirtualBaseClass(TypeRecordKind Kind, MemberAccess Access,
|
||||
TypeIndex Type, TypeIndex VirtualBasePointerType,
|
||||
int64_t VirtualBasePointerOffset,
|
||||
uint64_t SlotIndex);
|
||||
void writeVirtualFunctionTablePointer(TypeIndex Type);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
56
include/llvm/DebugInfo/CodeView/FunctionId.h
Normal file
56
include/llvm/DebugInfo/CodeView/FunctionId.h
Normal file
@ -0,0 +1,56 @@
|
||||
//===- FunctionId.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_FUNCTIONID_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_FUNCTIONID_H
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class FunctionId {
|
||||
public:
|
||||
FunctionId() : Index(0) {}
|
||||
|
||||
explicit FunctionId(uint32_t Index) : Index(Index) {}
|
||||
|
||||
uint32_t getIndex() const { return Index; }
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
};
|
||||
|
||||
inline bool operator==(const FunctionId &A, const FunctionId &B) {
|
||||
return A.getIndex() == B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator!=(const FunctionId &A, const FunctionId &B) {
|
||||
return A.getIndex() != B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator<(const FunctionId &A, const FunctionId &B) {
|
||||
return A.getIndex() < B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator<=(const FunctionId &A, const FunctionId &B) {
|
||||
return A.getIndex() <= B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator>(const FunctionId &A, const FunctionId &B) {
|
||||
return A.getIndex() > B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator>=(const FunctionId &A, const FunctionId &B) {
|
||||
return A.getIndex() >= B.getIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
124
include/llvm/DebugInfo/CodeView/Line.h
Normal file
124
include/llvm/DebugInfo/CodeView/Line.h
Normal file
@ -0,0 +1,124 @@
|
||||
//===- Line.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_LINE_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_LINE_H
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class LineInfo {
|
||||
public:
|
||||
static const int32_t AlwaysStepIntoLineNumber = 0xfeefee;
|
||||
static const int32_t NeverStepIntoLineNumber = 0xf00f00;
|
||||
|
||||
private:
|
||||
static const uint32_t StartLineMask = 0x00ffffff;
|
||||
static const uint32_t EndLineDeltaMask = 0x7f000000;
|
||||
static const int EndLineDeltaShift = 24;
|
||||
static const uint32_t StatementFlag = 0x80000000u;
|
||||
|
||||
public:
|
||||
LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement);
|
||||
|
||||
uint32_t getStartLine() const { return LineData & StartLineMask; }
|
||||
|
||||
uint32_t getLineDelta() const {
|
||||
return (LineData & EndLineDeltaMask) >> EndLineDeltaShift;
|
||||
}
|
||||
|
||||
uint32_t getEndLine() const { return getStartLine() + getLineDelta(); }
|
||||
|
||||
bool isStatement() const { return (LineData & StatementFlag) != 0; }
|
||||
|
||||
uint32_t getRawData() const { return LineData; }
|
||||
|
||||
bool isAlwaysStepInto() const {
|
||||
return getStartLine() == AlwaysStepIntoLineNumber;
|
||||
}
|
||||
|
||||
bool isNeverStepInto() const {
|
||||
return getStartLine() == NeverStepIntoLineNumber;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t LineData;
|
||||
};
|
||||
|
||||
class ColumnInfo {
|
||||
private:
|
||||
static const uint32_t StartColumnMask = 0x0000ffffu;
|
||||
static const uint32_t EndColumnMask = 0xffff0000u;
|
||||
static const int EndColumnShift = 16;
|
||||
|
||||
public:
|
||||
ColumnInfo(uint16_t StartColumn, uint16_t EndColumn) {
|
||||
ColumnData =
|
||||
(static_cast<uint32_t>(StartColumn) & StartColumnMask) |
|
||||
((static_cast<uint32_t>(EndColumn) << EndColumnShift) & EndColumnMask);
|
||||
}
|
||||
|
||||
uint16_t getStartColumn() const {
|
||||
return static_cast<uint16_t>(ColumnData & StartColumnMask);
|
||||
}
|
||||
|
||||
uint16_t getEndColumn() const {
|
||||
return static_cast<uint16_t>((ColumnData & EndColumnMask) >>
|
||||
EndColumnShift);
|
||||
}
|
||||
|
||||
uint32_t getRawData() const { return ColumnData; }
|
||||
|
||||
private:
|
||||
uint32_t ColumnData;
|
||||
};
|
||||
|
||||
class Line {
|
||||
private:
|
||||
int32_t CodeOffset;
|
||||
LineInfo LineInf;
|
||||
ColumnInfo ColumnInf;
|
||||
|
||||
public:
|
||||
Line(int32_t CodeOffset, uint32_t StartLine, uint32_t EndLine,
|
||||
uint16_t StartColumn, uint16_t EndColumn, bool IsStatement)
|
||||
: CodeOffset(CodeOffset), LineInf(StartLine, EndLine, IsStatement),
|
||||
ColumnInf(StartColumn, EndColumn) {}
|
||||
|
||||
Line(int32_t CodeOffset, LineInfo LineInf, ColumnInfo ColumnInf)
|
||||
: CodeOffset(CodeOffset), LineInf(LineInf), ColumnInf(ColumnInf) {}
|
||||
|
||||
LineInfo getLineInfo() const { return LineInf; }
|
||||
|
||||
ColumnInfo getColumnInfo() const { return ColumnInf; }
|
||||
|
||||
int32_t getCodeOffset() const { return CodeOffset; }
|
||||
|
||||
uint32_t getStartLine() const { return LineInf.getStartLine(); }
|
||||
|
||||
uint32_t getLineDelta() const { return LineInf.getLineDelta(); }
|
||||
|
||||
uint32_t getEndLine() const { return LineInf.getEndLine(); }
|
||||
|
||||
uint16_t getStartColumn() const { return ColumnInf.getStartColumn(); }
|
||||
|
||||
uint16_t getEndColumn() const { return ColumnInf.getEndColumn(); }
|
||||
|
||||
bool isStatement() const { return LineInf.isStatement(); }
|
||||
|
||||
bool isAlwaysStepInto() const { return LineInf.isAlwaysStepInto(); }
|
||||
|
||||
bool isNeverStepInto() const { return LineInf.isNeverStepInto(); }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
43
include/llvm/DebugInfo/CodeView/ListRecordBuilder.h
Normal file
43
include/llvm/DebugInfo/CodeView/ListRecordBuilder.h
Normal file
@ -0,0 +1,43 @@
|
||||
//===- ListRecordBuilder.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_LISTRECORDBUILDER_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_LISTRECORDBUILDER_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class ListRecordBuilder {
|
||||
private:
|
||||
ListRecordBuilder(const ListRecordBuilder &) = delete;
|
||||
ListRecordBuilder &operator=(const ListRecordBuilder &) = delete;
|
||||
|
||||
protected:
|
||||
const int MethodKindShift = 2;
|
||||
|
||||
explicit ListRecordBuilder(TypeRecordKind Kind);
|
||||
|
||||
public:
|
||||
llvm::StringRef str() { return Builder.str(); }
|
||||
|
||||
protected:
|
||||
void finishSubRecord();
|
||||
|
||||
TypeRecordBuilder &getBuilder() { return Builder; }
|
||||
|
||||
private:
|
||||
TypeRecordBuilder Builder;
|
||||
SmallVector<size_t, 4> ContinuationOffsets;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
68
include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h
Normal file
68
include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h
Normal file
@ -0,0 +1,68 @@
|
||||
//===- MemoryTypeTableBuilder.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_MEMORYTYPETABLEBUILDER_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_MEMORYTYPETABLEBUILDER_H
|
||||
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class MemoryTypeTableBuilder : public TypeTableBuilder {
|
||||
public:
|
||||
class Record {
|
||||
public:
|
||||
explicit Record(llvm::StringRef RData);
|
||||
|
||||
const char *data() const { return Data.get(); }
|
||||
uint16_t size() const { return Size; }
|
||||
|
||||
private:
|
||||
uint16_t Size;
|
||||
std::unique_ptr<char[]> Data;
|
||||
};
|
||||
|
||||
private:
|
||||
class RecordHash : std::unary_function<llvm::StringRef, size_t> {
|
||||
public:
|
||||
size_t operator()(llvm::StringRef Val) const {
|
||||
return static_cast<size_t>(llvm::hash_value(Val));
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
MemoryTypeTableBuilder() {}
|
||||
|
||||
template <typename TFunc> void ForEachRecord(TFunc Func) {
|
||||
uint32_t Index = TypeIndex::FirstNonSimpleIndex;
|
||||
|
||||
for (const std::unique_ptr<Record> &R : Records) {
|
||||
Func(TypeIndex(Index), R.get());
|
||||
++Index;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
virtual TypeIndex writeRecord(llvm::StringRef Data) override;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<Record>> Records;
|
||||
std::unordered_map<llvm::StringRef, TypeIndex, RecordHash> HashedRecords;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
35
include/llvm/DebugInfo/CodeView/MethodListRecordBuilder.h
Normal file
35
include/llvm/DebugInfo/CodeView/MethodListRecordBuilder.h
Normal file
@ -0,0 +1,35 @@
|
||||
//===- MethodListRecordBuilder.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_METHODLISTRECORDBUILDER_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_METHODLISTRECORDBUILDER_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class MethodInfo;
|
||||
|
||||
class MethodListRecordBuilder : public ListRecordBuilder {
|
||||
private:
|
||||
MethodListRecordBuilder(const MethodListRecordBuilder &) = delete;
|
||||
MethodListRecordBuilder &operator=(const MethodListRecordBuilder &) = delete;
|
||||
|
||||
public:
|
||||
MethodListRecordBuilder();
|
||||
|
||||
void writeMethod(MemberAccess Access, MethodKind Kind, MethodOptions Options,
|
||||
TypeIndex Type, int32_t VTableSlotOffset);
|
||||
void writeMethod(const MethodInfo &Method);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
176
include/llvm/DebugInfo/CodeView/TypeIndex.h
Normal file
176
include/llvm/DebugInfo/CodeView/TypeIndex.h
Normal file
@ -0,0 +1,176 @@
|
||||
//===- TypeIndex.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_TYPEINDEX_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
enum class SimpleTypeKind : uint32_t {
|
||||
None = 0x0000, // uncharacterized type (no type)
|
||||
Void = 0x0003, // void
|
||||
NotTranslated = 0x0007, // type not translated by cvpack
|
||||
HResult = 0x0008, // OLE/COM HRESULT
|
||||
|
||||
SignedCharacter = 0x0010, // 8 bit signed
|
||||
UnsignedCharacter = 0x0020, // 8 bit unsigned
|
||||
NarrowCharacter = 0x0070, // really a char
|
||||
WideCharacter = 0x0071, // wide char
|
||||
|
||||
SByte = 0x0068, // 8 bit signed int
|
||||
Byte = 0x0069, // 8 bit unsigned int
|
||||
Int16Short = 0x0011, // 16 bit signed
|
||||
UInt16Short = 0x0021, // 16 bit unsigned
|
||||
Int16 = 0x0072, // 16 bit signed int
|
||||
UInt16 = 0x0073, // 16 bit unsigned int
|
||||
Int32Long = 0x0012, // 32 bit signed
|
||||
UInt32Long = 0x0022, // 32 bit unsigned
|
||||
Int32 = 0x0074, // 32 bit signed int
|
||||
UInt32 = 0x0075, // 32 bit unsigned int
|
||||
Int64Quad = 0x0013, // 64 bit signed
|
||||
UInt64Quad = 0x0023, // 64 bit unsigned
|
||||
Int64 = 0x0076, // 64 bit signed int
|
||||
UInt64 = 0x0077, // 64 bit unsigned int
|
||||
Int128 = 0x0078, // 128 bit signed int
|
||||
UInt128 = 0x0079, // 128 bit unsigned int
|
||||
|
||||
Float16 = 0x0046, // 16 bit real
|
||||
Float32 = 0x0040, // 32 bit real
|
||||
Float32PartialPrecision = 0x0045, // 32 bit PP real
|
||||
Float48 = 0x0044, // 48 bit real
|
||||
Float64 = 0x0041, // 64 bit real
|
||||
Float80 = 0x0042, // 80 bit real
|
||||
Float128 = 0x0043, // 128 bit real
|
||||
|
||||
Complex32 = 0x0050, // 32 bit complex
|
||||
Complex64 = 0x0051, // 64 bit complex
|
||||
Complex80 = 0x0052, // 80 bit complex
|
||||
Complex128 = 0x0053, // 128 bit complex
|
||||
|
||||
Boolean8 = 0x0030, // 8 bit boolean
|
||||
Boolean16 = 0x0031, // 16 bit boolean
|
||||
Boolean32 = 0x0032, // 32 bit boolean
|
||||
Boolean64 = 0x0033 // 64 bit boolean
|
||||
};
|
||||
|
||||
enum class SimpleTypeMode : uint32_t {
|
||||
Direct = 0x00000000, // Not a pointer
|
||||
NearPointer = 0x00000100, // Near pointer
|
||||
FarPointer = 0x00000200, // Far pointer
|
||||
HugePointer = 0x00000300, // Huge pointer
|
||||
NearPointer32 = 0x00000400, // 32 bit near pointer
|
||||
FarPointer32 = 0x00000500, // 32 bit far pointer
|
||||
NearPointer64 = 0x00000600, // 64 bit near pointer
|
||||
NearPointer128 = 0x00000700 // 128 bit near pointer
|
||||
};
|
||||
|
||||
class TypeIndex {
|
||||
public:
|
||||
static const uint32_t FirstNonSimpleIndex = 0x1000;
|
||||
static const uint32_t SimpleKindMask = 0x000000ff;
|
||||
static const uint32_t SimpleModeMask = 0x00000700;
|
||||
|
||||
public:
|
||||
TypeIndex() : Index(0) {}
|
||||
explicit TypeIndex(uint32_t Index) : Index(Index) {}
|
||||
explicit TypeIndex(SimpleTypeKind Kind)
|
||||
: Index(static_cast<uint32_t>(Kind)) {}
|
||||
TypeIndex(SimpleTypeKind Kind, SimpleTypeMode Mode)
|
||||
: Index(static_cast<uint32_t>(Kind) | static_cast<uint32_t>(Mode)) {}
|
||||
|
||||
uint32_t getIndex() const { return Index; }
|
||||
bool isSimple() const { return Index < FirstNonSimpleIndex; }
|
||||
|
||||
SimpleTypeKind getSimpleKind() const {
|
||||
assert(isSimple());
|
||||
return static_cast<SimpleTypeKind>(Index & SimpleKindMask);
|
||||
}
|
||||
|
||||
SimpleTypeMode getSimpleMode() const {
|
||||
assert(isSimple());
|
||||
return static_cast<SimpleTypeMode>(Index & SimpleModeMask);
|
||||
}
|
||||
|
||||
static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); }
|
||||
static TypeIndex VoidPointer32() {
|
||||
return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer32);
|
||||
}
|
||||
static TypeIndex VoidPointer64() {
|
||||
return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer64);
|
||||
}
|
||||
|
||||
static TypeIndex SignedCharacter() {
|
||||
return TypeIndex(SimpleTypeKind::SignedCharacter);
|
||||
}
|
||||
static TypeIndex UnsignedCharacter() {
|
||||
return TypeIndex(SimpleTypeKind::UnsignedCharacter);
|
||||
}
|
||||
static TypeIndex NarrowCharacter() {
|
||||
return TypeIndex(SimpleTypeKind::NarrowCharacter);
|
||||
}
|
||||
static TypeIndex WideCharacter() {
|
||||
return TypeIndex(SimpleTypeKind::WideCharacter);
|
||||
}
|
||||
static TypeIndex Int16Short() {
|
||||
return TypeIndex(SimpleTypeKind::Int16Short);
|
||||
}
|
||||
static TypeIndex UInt16Short() {
|
||||
return TypeIndex(SimpleTypeKind::UInt16Short);
|
||||
}
|
||||
static TypeIndex Int32() { return TypeIndex(SimpleTypeKind::Int32); }
|
||||
static TypeIndex UInt32() { return TypeIndex(SimpleTypeKind::UInt32); }
|
||||
static TypeIndex Int32Long() { return TypeIndex(SimpleTypeKind::Int32Long); }
|
||||
static TypeIndex UInt32Long() {
|
||||
return TypeIndex(SimpleTypeKind::UInt32Long);
|
||||
}
|
||||
static TypeIndex Int64() { return TypeIndex(SimpleTypeKind::Int64); }
|
||||
static TypeIndex UInt64() { return TypeIndex(SimpleTypeKind::UInt64); }
|
||||
static TypeIndex Int64Quad() { return TypeIndex(SimpleTypeKind::Int64Quad); }
|
||||
static TypeIndex UInt64Quad() {
|
||||
return TypeIndex(SimpleTypeKind::UInt64Quad);
|
||||
}
|
||||
|
||||
static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); }
|
||||
static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); }
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
};
|
||||
|
||||
inline bool operator==(const TypeIndex &A, const TypeIndex &B) {
|
||||
return A.getIndex() == B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator!=(const TypeIndex &A, const TypeIndex &B) {
|
||||
return A.getIndex() != B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator<(const TypeIndex &A, const TypeIndex &B) {
|
||||
return A.getIndex() < B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator<=(const TypeIndex &A, const TypeIndex &B) {
|
||||
return A.getIndex() <= B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator>(const TypeIndex &A, const TypeIndex &B) {
|
||||
return A.getIndex() > B.getIndex();
|
||||
}
|
||||
|
||||
inline bool operator>=(const TypeIndex &A, const TypeIndex &B) {
|
||||
return A.getIndex() >= B.getIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
270
include/llvm/DebugInfo/CodeView/TypeRecord.h
Normal file
270
include/llvm/DebugInfo/CodeView/TypeRecord.h
Normal file
@ -0,0 +1,270 @@
|
||||
//===- TypeRecord.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_TYPERECORD_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include <cinttypes>
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class TypeRecord {
|
||||
protected:
|
||||
explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}
|
||||
|
||||
public:
|
||||
TypeRecordKind getKind() const { return Kind; }
|
||||
|
||||
private:
|
||||
TypeRecordKind Kind;
|
||||
};
|
||||
|
||||
class ModifierRecord : public TypeRecord {
|
||||
public:
|
||||
ModifierRecord(TypeIndex ModifiedType, ModifierOptions Options)
|
||||
: TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
|
||||
Options(Options) {}
|
||||
|
||||
TypeIndex getModifiedType() const { return ModifiedType; }
|
||||
ModifierOptions getOptions() const { return Options; }
|
||||
|
||||
private:
|
||||
TypeIndex ModifiedType;
|
||||
ModifierOptions Options;
|
||||
};
|
||||
|
||||
class ProcedureRecord : public TypeRecord {
|
||||
public:
|
||||
ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
|
||||
FunctionOptions Options, uint16_t ParameterCount,
|
||||
TypeIndex ArgumentList)
|
||||
: TypeRecord(TypeRecordKind::Procedure), ReturnType(ReturnType),
|
||||
CallConv(CallConv), Options(Options), ParameterCount(ParameterCount),
|
||||
ArgumentList(ArgumentList) {}
|
||||
|
||||
TypeIndex getReturnType() const { return ReturnType; }
|
||||
CallingConvention getCallConv() const { return CallConv; }
|
||||
FunctionOptions getOptions() const { return Options; }
|
||||
uint16_t getParameterCount() const { return ParameterCount; }
|
||||
TypeIndex getArgumentList() const { return ArgumentList; }
|
||||
|
||||
private:
|
||||
TypeIndex ReturnType;
|
||||
CallingConvention CallConv;
|
||||
FunctionOptions Options;
|
||||
uint16_t ParameterCount;
|
||||
TypeIndex ArgumentList;
|
||||
};
|
||||
|
||||
class MemberFunctionRecord : public TypeRecord {
|
||||
public:
|
||||
MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
|
||||
TypeIndex ThisType, CallingConvention CallConv,
|
||||
FunctionOptions Options, uint16_t ParameterCount,
|
||||
TypeIndex ArgumentList, int32_t ThisPointerAdjustment)
|
||||
: TypeRecord(TypeRecordKind::MemberFunction), ReturnType(ReturnType),
|
||||
ClassType(ClassType), ThisType(ThisType), CallConv(CallConv),
|
||||
Options(Options), ParameterCount(ParameterCount),
|
||||
ArgumentList(ArgumentList),
|
||||
ThisPointerAdjustment(ThisPointerAdjustment) {}
|
||||
|
||||
TypeIndex getReturnType() const { return ReturnType; }
|
||||
TypeIndex getClassType() const { return ClassType; }
|
||||
TypeIndex getThisType() const { return ThisType; }
|
||||
CallingConvention getCallConv() const { return CallConv; }
|
||||
FunctionOptions getOptions() const { return Options; }
|
||||
uint16_t getParameterCount() const { return ParameterCount; }
|
||||
TypeIndex getArgumentList() const { return ArgumentList; }
|
||||
int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; }
|
||||
|
||||
private:
|
||||
TypeIndex ReturnType;
|
||||
TypeIndex ClassType;
|
||||
TypeIndex ThisType;
|
||||
CallingConvention CallConv;
|
||||
FunctionOptions Options;
|
||||
uint16_t ParameterCount;
|
||||
TypeIndex ArgumentList;
|
||||
int32_t ThisPointerAdjustment;
|
||||
};
|
||||
|
||||
class ArgumentListRecord : public TypeRecord {
|
||||
public:
|
||||
explicit ArgumentListRecord(llvm::ArrayRef<TypeIndex> ArgumentTypes)
|
||||
: TypeRecord(TypeRecordKind::ArgumentList), ArgumentTypes(ArgumentTypes) {
|
||||
}
|
||||
|
||||
llvm::ArrayRef<TypeIndex> getArgumentTypes() const { return ArgumentTypes; }
|
||||
|
||||
private:
|
||||
llvm::ArrayRef<TypeIndex> ArgumentTypes;
|
||||
};
|
||||
|
||||
class PointerRecordBase : public TypeRecord {
|
||||
public:
|
||||
PointerRecordBase(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
|
||||
PointerOptions Options, uint8_t Size)
|
||||
: TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
|
||||
PtrKind(Kind), Mode(Mode), Options(Options), Size(Size) {}
|
||||
|
||||
TypeIndex getReferentType() const { return ReferentType; }
|
||||
PointerKind getPointerKind() const { return PtrKind; }
|
||||
PointerMode getMode() const { return Mode; }
|
||||
PointerOptions getOptions() const { return Options; }
|
||||
uint8_t getSize() const { return Size; }
|
||||
|
||||
private:
|
||||
TypeIndex ReferentType;
|
||||
PointerKind PtrKind;
|
||||
PointerMode Mode;
|
||||
PointerOptions Options;
|
||||
uint8_t Size;
|
||||
};
|
||||
|
||||
class PointerRecord : public PointerRecordBase {
|
||||
public:
|
||||
PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
|
||||
PointerOptions Options, uint8_t Size)
|
||||
: PointerRecordBase(ReferentType, Kind, Mode, Options, Size) {}
|
||||
};
|
||||
|
||||
class PointerToMemberRecord : public PointerRecordBase {
|
||||
public:
|
||||
PointerToMemberRecord(TypeIndex ReferentType, PointerKind Kind,
|
||||
PointerMode Mode, PointerOptions Options, uint8_t Size,
|
||||
TypeIndex ContainingType,
|
||||
PointerToMemberRepresentation Representation)
|
||||
: PointerRecordBase(ReferentType, Kind, Mode, Options, Size),
|
||||
ContainingType(ContainingType), Representation(Representation) {}
|
||||
|
||||
TypeIndex getContainingType() const { return ContainingType; }
|
||||
PointerToMemberRepresentation getRepresentation() const {
|
||||
return Representation;
|
||||
}
|
||||
|
||||
private:
|
||||
TypeIndex ContainingType;
|
||||
PointerToMemberRepresentation Representation;
|
||||
};
|
||||
|
||||
class ArrayRecord : public TypeRecord {
|
||||
public:
|
||||
ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
|
||||
llvm::StringRef Name)
|
||||
: TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
|
||||
IndexType(IndexType), Size(Size), Name(Name) {}
|
||||
|
||||
TypeIndex getElementType() const { return ElementType; }
|
||||
TypeIndex getIndexType() const { return IndexType; }
|
||||
uint64_t getSize() const { return Size; }
|
||||
llvm::StringRef getName() const { return Name; }
|
||||
|
||||
private:
|
||||
TypeIndex ElementType;
|
||||
TypeIndex IndexType;
|
||||
uint64_t Size;
|
||||
llvm::StringRef Name;
|
||||
};
|
||||
|
||||
class TagRecord : public TypeRecord {
|
||||
protected:
|
||||
TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
|
||||
TypeIndex FieldList, StringRef Name, StringRef UniqueName)
|
||||
: TypeRecord(Kind), MemberCount(MemberCount), Options(Options),
|
||||
FieldList(FieldList), Name(Name), UniqueName(UniqueName) {}
|
||||
|
||||
public:
|
||||
uint16_t getMemberCount() const { return MemberCount; }
|
||||
ClassOptions getOptions() const { return Options; }
|
||||
TypeIndex getFieldList() const { return FieldList; }
|
||||
StringRef getName() const { return Name; }
|
||||
StringRef getUniqueName() const { return UniqueName; }
|
||||
|
||||
private:
|
||||
uint16_t MemberCount;
|
||||
ClassOptions Options;
|
||||
TypeIndex FieldList;
|
||||
StringRef Name;
|
||||
StringRef UniqueName;
|
||||
};
|
||||
|
||||
class AggregateRecord : public TagRecord {
|
||||
public:
|
||||
AggregateRecord(TypeRecordKind Kind, uint16_t MemberCount,
|
||||
ClassOptions Options, HfaKind Hfa,
|
||||
WindowsRTClassKind WinRTKind, TypeIndex FieldList,
|
||||
TypeIndex DerivationList, TypeIndex VTableShape,
|
||||
uint64_t Size, StringRef Name, StringRef UniqueName)
|
||||
: TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName),
|
||||
Hfa(Hfa), WinRTKind(WinRTKind), DerivationList(DerivationList),
|
||||
VTableShape(VTableShape), Size(Size) {}
|
||||
|
||||
HfaKind getHfa() const { return Hfa; }
|
||||
WindowsRTClassKind getWinRTKind() const { return WinRTKind; }
|
||||
TypeIndex getDerivationList() const { return DerivationList; }
|
||||
TypeIndex getVTableShape() const { return VTableShape; }
|
||||
uint64_t getSize() const { return Size; }
|
||||
|
||||
private:
|
||||
HfaKind Hfa;
|
||||
WindowsRTClassKind WinRTKind;
|
||||
TypeIndex DerivationList;
|
||||
TypeIndex VTableShape;
|
||||
uint64_t Size;
|
||||
};
|
||||
|
||||
class EnumRecord : public TagRecord {
|
||||
public:
|
||||
EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
|
||||
StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
|
||||
: TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name,
|
||||
UniqueName),
|
||||
UnderlyingType(UnderlyingType) {}
|
||||
|
||||
TypeIndex getUnderlyingType() const { return UnderlyingType; }
|
||||
|
||||
private:
|
||||
TypeIndex UnderlyingType;
|
||||
};
|
||||
|
||||
class BitFieldRecord : TypeRecord {
|
||||
public:
|
||||
BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
|
||||
: TypeRecord(TypeRecordKind::BitField), Type(Type), BitOffset(BitOffset),
|
||||
BitSize(BitSize) {}
|
||||
|
||||
TypeIndex getType() const { return Type; }
|
||||
uint8_t getBitOffset() const { return BitOffset; }
|
||||
uint8_t getBitSize() const { return BitSize; }
|
||||
|
||||
private:
|
||||
TypeIndex Type;
|
||||
uint8_t BitSize;
|
||||
uint8_t BitOffset;
|
||||
};
|
||||
|
||||
class VirtualTableShapeRecord : TypeRecord {
|
||||
public:
|
||||
explicit VirtualTableShapeRecord(ArrayRef<VirtualTableSlotKind> Slots)
|
||||
: TypeRecord(TypeRecordKind::VirtualTableShape), Slots(Slots) {}
|
||||
|
||||
ArrayRef<VirtualTableSlotKind> getSlots() const { return Slots; }
|
||||
|
||||
private:
|
||||
ArrayRef<VirtualTableSlotKind> Slots;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
57
include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
Normal file
57
include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
Normal file
@ -0,0 +1,57 @@
|
||||
//===- TypeRecordBuilder.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_TYPERECORDBUILDER_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDBUILDER_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/EndianStream.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class TypeRecordBuilder {
|
||||
private:
|
||||
TypeRecordBuilder(const TypeRecordBuilder &) = delete;
|
||||
TypeRecordBuilder &operator=(const TypeRecordBuilder &) = delete;
|
||||
|
||||
public:
|
||||
explicit TypeRecordBuilder(TypeRecordKind Kind);
|
||||
|
||||
void writeUInt8(uint8_t Value);
|
||||
void writeInt16(int16_t Value);
|
||||
void writeUInt16(uint16_t Value);
|
||||
void writeInt32(int32_t Value);
|
||||
void writeUInt32(uint32_t Value);
|
||||
void writeInt64(int64_t Value);
|
||||
void writeUInt64(uint64_t Value);
|
||||
void writeTypeIndex(TypeIndex TypeInd);
|
||||
void writeTypeRecordKind(TypeRecordKind Kind);
|
||||
void writeEncodedInteger(int64_t Value);
|
||||
void writeEncodedSignedInteger(int64_t Value);
|
||||
void writeEncodedUnsignedInteger(uint64_t Value);
|
||||
void writeNullTerminatedString(const char *Value);
|
||||
void writeNullTerminatedString(StringRef Value);
|
||||
|
||||
llvm::StringRef str();
|
||||
|
||||
uint64_t size() const { return Stream.tell(); }
|
||||
|
||||
private:
|
||||
llvm::SmallVector<char, 256> Buffer;
|
||||
llvm::raw_svector_ostream Stream;
|
||||
llvm::support::endian::Writer<llvm::support::endianness::little> Writer;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
37
include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h
Normal file
37
include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h
Normal file
@ -0,0 +1,37 @@
|
||||
//===- TypeSymbolEmitter.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_TYPESYMBOLEMITTER_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPESYMBOLEMITTER_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class TypeSymbolEmitter {
|
||||
private:
|
||||
TypeSymbolEmitter(const TypeSymbolEmitter &) = delete;
|
||||
TypeSymbolEmitter &operator=(const TypeSymbolEmitter &) = delete;
|
||||
|
||||
protected:
|
||||
TypeSymbolEmitter() {}
|
||||
|
||||
public:
|
||||
virtual ~TypeSymbolEmitter() {}
|
||||
|
||||
public:
|
||||
virtual void writeUserDefinedType(TypeIndex TI, StringRef Name) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
60
include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
Normal file
60
include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
Normal file
@ -0,0 +1,60 @@
|
||||
//===- 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/StringRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class FieldListRecordBuilder;
|
||||
class MethodListRecordBuilder;
|
||||
class TypeRecordBuilder;
|
||||
|
||||
class TypeTableBuilder {
|
||||
private:
|
||||
TypeTableBuilder(const TypeTableBuilder &) = delete;
|
||||
TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;
|
||||
|
||||
protected:
|
||||
TypeTableBuilder();
|
||||
|
||||
public:
|
||||
virtual ~TypeTableBuilder();
|
||||
|
||||
public:
|
||||
TypeIndex writeModifier(const ModifierRecord &Record);
|
||||
TypeIndex writeProcedure(const ProcedureRecord &Record);
|
||||
TypeIndex writeMemberFunction(const MemberFunctionRecord &Record);
|
||||
TypeIndex writeArgumentList(const ArgumentListRecord &Record);
|
||||
TypeIndex writeRecord(TypeRecordBuilder &builder);
|
||||
TypeIndex writePointer(const PointerRecord &Record);
|
||||
TypeIndex writePointerToMember(const PointerToMemberRecord &Record);
|
||||
TypeIndex writeArray(const ArrayRecord &Record);
|
||||
TypeIndex writeAggregate(const AggregateRecord &Record);
|
||||
TypeIndex writeEnum(const EnumRecord &Record);
|
||||
TypeIndex writeBitField(const BitFieldRecord &Record);
|
||||
TypeIndex writeVirtualTableShape(const VirtualTableShapeRecord &Record);
|
||||
|
||||
TypeIndex writeFieldList(FieldListRecordBuilder &FieldList);
|
||||
TypeIndex writeMethodList(MethodListRecordBuilder &MethodList);
|
||||
|
||||
private:
|
||||
virtual TypeIndex writeRecord(llvm::StringRef record) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,3 +1,4 @@
|
||||
add_subdirectory(CodeView)
|
||||
add_subdirectory(DWARF)
|
||||
add_subdirectory(PDB)
|
||||
add_subdirectory(Symbolize)
|
||||
|
9
lib/DebugInfo/CodeView/CMakeLists.txt
Normal file
9
lib/DebugInfo/CodeView/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
||||
add_llvm_library(LLVMCodeView
|
||||
FieldListRecordBuilder.cpp
|
||||
Line.cpp
|
||||
ListRecordBuilder.cpp
|
||||
MemoryTypeTableBuilder.cpp
|
||||
MethodListRecordBuilder.cpp
|
||||
TypeRecordBuilder.cpp
|
||||
TypeTableBuilder.cpp
|
||||
)
|
165
lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
Normal file
165
lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
//===-- FieldListRecordBuilder.cpp ----------------------------------------===//
|
||||
//
|
||||
// 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/FieldListRecordBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace codeview;
|
||||
|
||||
FieldListRecordBuilder::FieldListRecordBuilder()
|
||||
: ListRecordBuilder(TypeRecordKind::FieldList) {}
|
||||
|
||||
void FieldListRecordBuilder::writeBaseClass(MemberAccess Access, TypeIndex Type,
|
||||
uint64_t Offset) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::BaseClass);
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Access));
|
||||
Builder.writeTypeIndex(Type);
|
||||
Builder.writeEncodedUnsignedInteger(Offset);
|
||||
|
||||
finishSubRecord();
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeEnumerate(MemberAccess Access, uint64_t Value,
|
||||
StringRef Name) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::Enumerate);
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Access));
|
||||
Builder.writeEncodedUnsignedInteger(Value);
|
||||
Builder.writeNullTerminatedString(Name);
|
||||
|
||||
finishSubRecord();
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeMember(MemberAccess Access, TypeIndex Type,
|
||||
uint64_t Offset, StringRef Name) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::Member);
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Access));
|
||||
Builder.writeTypeIndex(Type);
|
||||
Builder.writeEncodedUnsignedInteger(Offset);
|
||||
Builder.writeNullTerminatedString(Name);
|
||||
|
||||
finishSubRecord();
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeMethod(uint16_t OverloadCount,
|
||||
TypeIndex MethodList, StringRef Name) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::Method);
|
||||
Builder.writeUInt16(OverloadCount);
|
||||
Builder.writeTypeIndex(MethodList);
|
||||
Builder.writeNullTerminatedString(Name);
|
||||
|
||||
finishSubRecord();
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeOneMethod(
|
||||
MemberAccess Access, MethodKind Kind, MethodOptions Options, TypeIndex Type,
|
||||
int32_t VTableSlotOffset, StringRef Name) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
uint16_t Flags = static_cast<uint16_t>(Access);
|
||||
Flags |= static_cast<uint16_t>(Kind) << MethodKindShift;
|
||||
Flags |= static_cast<uint16_t>(Options);
|
||||
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::OneMethod);
|
||||
Builder.writeUInt16(Flags);
|
||||
Builder.writeTypeIndex(Type);
|
||||
switch (Kind) {
|
||||
case MethodKind::IntroducingVirtual:
|
||||
case MethodKind::PureIntroducingVirtual:
|
||||
assert(VTableSlotOffset >= 0);
|
||||
Builder.writeInt32(VTableSlotOffset);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(VTableSlotOffset == -1);
|
||||
break;
|
||||
}
|
||||
|
||||
Builder.writeNullTerminatedString(Name);
|
||||
|
||||
finishSubRecord();
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeOneMethod(const MethodInfo &Method,
|
||||
StringRef Name) {
|
||||
writeOneMethod(Method.getAccess(), Method.getKind(), Method.getOptions(),
|
||||
Method.getType(), Method.getVTableSlotOffset(), Name);
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeNestedType(TypeIndex Type, StringRef Name) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::NestedType);
|
||||
Builder.writeUInt16(0);
|
||||
Builder.writeTypeIndex(Type);
|
||||
Builder.writeNullTerminatedString(Name);
|
||||
|
||||
finishSubRecord();
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeStaticMember(MemberAccess Access,
|
||||
TypeIndex Type, StringRef Name) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::StaticMember);
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Access));
|
||||
Builder.writeTypeIndex(Type);
|
||||
Builder.writeNullTerminatedString(Name);
|
||||
|
||||
finishSubRecord();
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeIndirectVirtualBaseClass(
|
||||
MemberAccess Access, TypeIndex Type, TypeIndex VirtualBasePointerType,
|
||||
int64_t VirtualBasePointerOffset, uint64_t SlotIndex) {
|
||||
writeVirtualBaseClass(TypeRecordKind::IndirectVirtualBaseClass, Access, Type,
|
||||
VirtualBasePointerType, VirtualBasePointerOffset,
|
||||
SlotIndex);
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeVirtualBaseClass(
|
||||
MemberAccess Access, TypeIndex Type, TypeIndex VirtualBasePointerType,
|
||||
int64_t VirtualBasePointerOffset, uint64_t SlotIndex) {
|
||||
writeVirtualBaseClass(TypeRecordKind::VirtualBaseClass, Access, Type,
|
||||
VirtualBasePointerType, VirtualBasePointerOffset,
|
||||
SlotIndex);
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeVirtualBaseClass(
|
||||
TypeRecordKind Kind, MemberAccess Access, TypeIndex Type,
|
||||
TypeIndex VirtualBasePointerType, int64_t VirtualBasePointerOffset,
|
||||
uint64_t SlotIndex) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
Builder.writeTypeRecordKind(Kind);
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Access));
|
||||
Builder.writeTypeIndex(Type);
|
||||
Builder.writeTypeIndex(VirtualBasePointerType);
|
||||
Builder.writeEncodedInteger(VirtualBasePointerOffset);
|
||||
Builder.writeEncodedUnsignedInteger(SlotIndex);
|
||||
|
||||
finishSubRecord();
|
||||
}
|
||||
|
||||
void FieldListRecordBuilder::writeVirtualFunctionTablePointer(TypeIndex Type) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
Builder.writeTypeRecordKind(TypeRecordKind::VirtualFunctionTablePointer);
|
||||
Builder.writeUInt16(0);
|
||||
Builder.writeTypeIndex(Type);
|
||||
|
||||
finishSubRecord();
|
||||
}
|
22
lib/DebugInfo/CodeView/LLVMBuild.txt
Normal file
22
lib/DebugInfo/CodeView/LLVMBuild.txt
Normal file
@ -0,0 +1,22 @@
|
||||
;===- ./lib/CodeView/LLVMBuild.txt -------------------------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = CodeView
|
||||
parent = Libraries
|
||||
required_libraries = Support
|
22
lib/DebugInfo/CodeView/Line.cpp
Normal file
22
lib/DebugInfo/CodeView/Line.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
//===-- Line.cpp ----------------------------------------------------------===//
|
||||
//
|
||||
// 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/Line.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace codeview;
|
||||
|
||||
LineInfo::LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement) {
|
||||
LineData = StartLine & StartLineMask;
|
||||
uint32_t LineDelta = EndLine - StartLine;
|
||||
LineData |= (LineDelta << EndLineDeltaShift) & EndLineDeltaMask;
|
||||
if (IsStatement) {
|
||||
LineData |= StatementFlag;
|
||||
}
|
||||
}
|
31
lib/DebugInfo/CodeView/ListRecordBuilder.cpp
Normal file
31
lib/DebugInfo/CodeView/ListRecordBuilder.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
//===-- ListRecordBuilder.cpp ---------------------------------------------===//
|
||||
//
|
||||
// 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/ListRecordBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace codeview;
|
||||
|
||||
ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind) : Builder(Kind) {}
|
||||
|
||||
void ListRecordBuilder::finishSubRecord() {
|
||||
// The builder starts at offset 2 in the actual CodeView buffer, so add an
|
||||
// additional offset of 2 before computing the alignment.
|
||||
uint32_t Remainder = (Builder.size() + 2) % 4;
|
||||
if (Remainder != 0) {
|
||||
for (int32_t PaddingBytesLeft = 4 - Remainder; PaddingBytesLeft > 0;
|
||||
--PaddingBytesLeft) {
|
||||
Builder.writeUInt8(0xf0 + PaddingBytesLeft);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Split the list into multiple records if it's longer than 64KB, using
|
||||
// a subrecord of TypeRecordKind::Index to chain the records together.
|
||||
assert(Builder.size() < 65536);
|
||||
}
|
35
lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
Normal file
35
lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
//===-- MemoryTypeTableBuilder.cpp ----------------------------------------===//
|
||||
//
|
||||
// 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/MemoryTypeTableBuilder.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace codeview;
|
||||
|
||||
MemoryTypeTableBuilder::Record::Record(StringRef RData)
|
||||
: Size(RData.size()), Data(new char[RData.size()]) {
|
||||
memcpy(Data.get(), RData.data(), RData.size());
|
||||
}
|
||||
|
||||
TypeIndex MemoryTypeTableBuilder::writeRecord(StringRef Data) {
|
||||
auto I = HashedRecords.find(Data);
|
||||
if (I != HashedRecords.end()) {
|
||||
return I->second;
|
||||
}
|
||||
|
||||
std::unique_ptr<Record> R(new Record(Data));
|
||||
|
||||
TypeIndex TI(static_cast<uint32_t>(Records.size()) +
|
||||
TypeIndex::FirstNonSimpleIndex);
|
||||
HashedRecords.insert(std::make_pair(StringRef(R->data(), R->size()), TI));
|
||||
Records.push_back(std::move(R));
|
||||
|
||||
return TI;
|
||||
}
|
49
lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
Normal file
49
lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
//===-- MethodListRecordBuilder.cpp ---------------------------------------===//
|
||||
//
|
||||
// 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/MethodListRecordBuilder.h"
|
||||
#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace codeview;
|
||||
|
||||
MethodListRecordBuilder::MethodListRecordBuilder()
|
||||
: ListRecordBuilder(TypeRecordKind::MethodList) {}
|
||||
|
||||
void MethodListRecordBuilder::writeMethod(MemberAccess Access, MethodKind Kind,
|
||||
MethodOptions Options, TypeIndex Type,
|
||||
int32_t VTableSlotOffset) {
|
||||
TypeRecordBuilder &Builder = getBuilder();
|
||||
|
||||
uint16_t Flags = static_cast<uint16_t>(Access);
|
||||
Flags |= static_cast<uint16_t>(Kind) << MethodKindShift;
|
||||
Flags |= static_cast<uint16_t>(Options);
|
||||
|
||||
Builder.writeUInt16(Flags);
|
||||
Builder.writeUInt16(0);
|
||||
Builder.writeTypeIndex(Type);
|
||||
switch (Kind) {
|
||||
case MethodKind::IntroducingVirtual:
|
||||
case MethodKind::PureIntroducingVirtual:
|
||||
assert(VTableSlotOffset >= 0);
|
||||
Builder.writeInt32(VTableSlotOffset);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(VTableSlotOffset == -1);
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Fail if too big?
|
||||
}
|
||||
|
||||
void MethodListRecordBuilder::writeMethod(const MethodInfo &Method) {
|
||||
writeMethod(Method.getAccess(), Method.getKind(), Method.getOptions(),
|
||||
Method.getType(), Method.getVTableSlotOffset());
|
||||
}
|
113
lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
Normal file
113
lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
//===-- TypeRecordBuilder.cpp ---------------------------------------------===//
|
||||
//
|
||||
// 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/TypeRecordBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace codeview;
|
||||
|
||||
TypeRecordBuilder::TypeRecordBuilder(TypeRecordKind Kind) : Stream(Buffer),
|
||||
Writer(Stream) {
|
||||
writeTypeRecordKind(Kind);
|
||||
}
|
||||
|
||||
StringRef TypeRecordBuilder::str() {
|
||||
return StringRef(Buffer.data(), Buffer.size());
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeUInt8(uint8_t Value) {
|
||||
Writer.write(Value);
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeInt16(int16_t Value) {
|
||||
Writer.write(Value);
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeUInt16(uint16_t Value) {
|
||||
Writer.write(Value);
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeInt32(int32_t Value) {
|
||||
Writer.write(Value);
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeUInt32(uint32_t Value) {
|
||||
Writer.write(Value);
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeInt64(int64_t Value) {
|
||||
Writer.write(Value);
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeUInt64(uint64_t Value) {
|
||||
Writer.write(Value);
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeEncodedInteger(int64_t Value) {
|
||||
if (Value >= 0) {
|
||||
writeEncodedUnsignedInteger(static_cast<uint64_t>(Value));
|
||||
} else {
|
||||
writeEncodedSignedInteger(Value);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeEncodedSignedInteger(int64_t Value) {
|
||||
if (Value >= std::numeric_limits<int8_t>::min() &&
|
||||
Value <= std::numeric_limits<int8_t>::max()) {
|
||||
writeUInt16(static_cast<uint16_t>(TypeRecordKind::SByte));
|
||||
writeInt16(static_cast<int8_t>(Value));
|
||||
} else if (Value >= std::numeric_limits<int16_t>::min() &&
|
||||
Value <= std::numeric_limits<int16_t>::max()) {
|
||||
writeUInt16(static_cast<uint16_t>(TypeRecordKind::Int16));
|
||||
writeInt16(static_cast<int16_t>(Value));
|
||||
} else if (Value >= std::numeric_limits<int32_t>::min() &&
|
||||
Value <= std::numeric_limits<int32_t>::max()) {
|
||||
writeUInt16(static_cast<uint32_t>(TypeRecordKind::Int32));
|
||||
writeInt32(static_cast<int32_t>(Value));
|
||||
} else {
|
||||
writeUInt16(static_cast<uint16_t>(TypeRecordKind::Int64));
|
||||
writeInt64(Value);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeEncodedUnsignedInteger(uint64_t Value) {
|
||||
if (Value < static_cast<uint16_t>(TypeRecordKind::SByte)) {
|
||||
writeUInt16(static_cast<uint16_t>(Value));
|
||||
} else if (Value <= std::numeric_limits<uint16_t>::max()) {
|
||||
writeUInt16(static_cast<uint16_t>(TypeRecordKind::UInt16));
|
||||
writeUInt16(static_cast<uint16_t>(Value));
|
||||
} else if (Value <= std::numeric_limits<uint32_t>::max()) {
|
||||
writeUInt16(static_cast<uint16_t>(TypeRecordKind::UInt32));
|
||||
writeUInt32(static_cast<uint32_t>(Value));
|
||||
} else {
|
||||
writeUInt16(static_cast<uint16_t>(TypeRecordKind::UInt64));
|
||||
writeUInt64(Value);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeNullTerminatedString(const char *Value) {
|
||||
assert(Value != nullptr);
|
||||
|
||||
size_t Length = strlen(Value);
|
||||
Stream.write(Value, Length);
|
||||
writeUInt8(0);
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeNullTerminatedString(StringRef Value) {
|
||||
Stream.write(Value.data(), Value.size());
|
||||
writeUInt8(0);
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeTypeIndex(TypeIndex TypeInd) {
|
||||
writeUInt32(TypeInd.getIndex());
|
||||
}
|
||||
|
||||
void TypeRecordBuilder::writeTypeRecordKind(TypeRecordKind Kind) {
|
||||
writeUInt16(static_cast<uint16_t>(Kind));
|
||||
}
|
221
lib/DebugInfo/CodeView/TypeTableBuilder.cpp
Normal file
221
lib/DebugInfo/CodeView/TypeTableBuilder.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
//===-- TypeTableBuilder.cpp ----------------------------------------------===//
|
||||
//
|
||||
// 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/TypeTableBuilder.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
|
||||
#include "llvm/DebugInfo/CodeView/MethodListRecordBuilder.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"
|
||||
#include "llvm/support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace codeview;
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t PointerKindMask = 0x0000001f;
|
||||
const int PointerKindShift = 0;
|
||||
const uint32_t PointerModeMask = 0x000000e0;
|
||||
const int PointerModeShift = 5;
|
||||
const uint32_t PointerSizeMask = 0x0007e000;
|
||||
const int PointerSizeShift = 13;
|
||||
const uint32_t PointerOptionsMask = 0x00081f00;
|
||||
|
||||
const int ClassHfaKindShift = 11;
|
||||
const int ClassWindowsRTClassKindShift = 14;
|
||||
|
||||
void writePointerBase(TypeRecordBuilder &Builder,
|
||||
const PointerRecordBase &Record) {
|
||||
Builder.writeTypeIndex(Record.getReferentType());
|
||||
uint32_t flags =
|
||||
static_cast<uint32_t>(Record.getOptions()) |
|
||||
(Record.getSize() << PointerSizeShift) |
|
||||
(static_cast<uint32_t>(Record.getMode()) << PointerModeShift) |
|
||||
(static_cast<uint32_t>(Record.getPointerKind()) << PointerKindShift);
|
||||
Builder.writeUInt32(flags);
|
||||
}
|
||||
}
|
||||
|
||||
TypeTableBuilder::TypeTableBuilder() {}
|
||||
|
||||
TypeTableBuilder::~TypeTableBuilder() {}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::Modifier);
|
||||
|
||||
Builder.writeTypeIndex(Record.getModifiedType());
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::Procedure);
|
||||
|
||||
Builder.writeTypeIndex(Record.getReturnType());
|
||||
Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
|
||||
Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
|
||||
Builder.writeUInt16(Record.getParameterCount());
|
||||
Builder.writeTypeIndex(Record.getArgumentList());
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex
|
||||
TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::MemberFunction);
|
||||
|
||||
Builder.writeTypeIndex(Record.getReturnType());
|
||||
Builder.writeTypeIndex(Record.getClassType());
|
||||
Builder.writeTypeIndex(Record.getThisType());
|
||||
Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
|
||||
Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
|
||||
Builder.writeUInt16(Record.getParameterCount());
|
||||
Builder.writeTypeIndex(Record.getArgumentList());
|
||||
Builder.writeInt32(Record.getThisPointerAdjustment());
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex
|
||||
TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::ArgumentList);
|
||||
|
||||
Builder.writeUInt32(Record.getArgumentTypes().size());
|
||||
for (TypeIndex TI : Record.getArgumentTypes()) {
|
||||
Builder.writeTypeIndex(TI);
|
||||
}
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::Pointer);
|
||||
|
||||
writePointerBase(Builder, Record);
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex
|
||||
TypeTableBuilder::writePointerToMember(const PointerToMemberRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::Pointer);
|
||||
|
||||
writePointerBase(Builder, Record);
|
||||
|
||||
Builder.writeTypeIndex(Record.getContainingType());
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Record.getRepresentation()));
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::Array);
|
||||
|
||||
Builder.writeTypeIndex(Record.getElementType());
|
||||
Builder.writeTypeIndex(Record.getIndexType());
|
||||
Builder.writeEncodedUnsignedInteger(Record.getSize());
|
||||
Builder.writeNullTerminatedString(Record.getName());
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) {
|
||||
assert((Record.getKind() == TypeRecordKind::Structure) ||
|
||||
(Record.getKind() == TypeRecordKind::Class) ||
|
||||
(Record.getKind() == TypeRecordKind::Union));
|
||||
|
||||
TypeRecordBuilder Builder(Record.getKind());
|
||||
|
||||
Builder.writeUInt16(Record.getMemberCount());
|
||||
uint16_t Flags =
|
||||
static_cast<uint16_t>(Record.getOptions()) |
|
||||
(static_cast<uint16_t>(Record.getHfa()) << ClassHfaKindShift) |
|
||||
(static_cast<uint16_t>(Record.getWinRTKind())
|
||||
<< ClassWindowsRTClassKindShift);
|
||||
Builder.writeUInt16(Flags);
|
||||
Builder.writeTypeIndex(Record.getFieldList());
|
||||
if (Record.getKind() != TypeRecordKind::Union) {
|
||||
Builder.writeTypeIndex(Record.getDerivationList());
|
||||
Builder.writeTypeIndex(Record.getVTableShape());
|
||||
} else {
|
||||
assert(Record.getDerivationList() == TypeIndex());
|
||||
assert(Record.getVTableShape() == TypeIndex());
|
||||
}
|
||||
Builder.writeEncodedUnsignedInteger(Record.getSize());
|
||||
Builder.writeNullTerminatedString(Record.getName());
|
||||
if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
|
||||
ClassOptions::None) {
|
||||
Builder.writeNullTerminatedString(Record.getUniqueName());
|
||||
}
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::Enum);
|
||||
|
||||
Builder.writeUInt16(Record.getMemberCount());
|
||||
Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
|
||||
Builder.writeTypeIndex(Record.getUnderlyingType());
|
||||
Builder.writeTypeIndex(Record.getFieldList());
|
||||
Builder.writeNullTerminatedString(Record.getName());
|
||||
if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
|
||||
ClassOptions::None) {
|
||||
Builder.writeNullTerminatedString(Record.getUniqueName());
|
||||
}
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::BitField);
|
||||
|
||||
Builder.writeTypeIndex(Record.getType());
|
||||
Builder.writeUInt8(Record.getBitSize());
|
||||
Builder.writeUInt8(Record.getBitOffset());
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeVirtualTableShape(
|
||||
const VirtualTableShapeRecord &Record) {
|
||||
TypeRecordBuilder Builder(TypeRecordKind::VirtualTableShape);
|
||||
|
||||
ArrayRef<VirtualTableSlotKind> Slots = Record.getSlots();
|
||||
|
||||
Builder.writeUInt16(Slots.size());
|
||||
for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
|
||||
uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
|
||||
if ((SlotIndex + 1) < Slots.size()) {
|
||||
Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
|
||||
}
|
||||
Builder.writeUInt8(Byte);
|
||||
}
|
||||
|
||||
return writeRecord(Builder);
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
|
||||
return writeRecord(Builder.str());
|
||||
}
|
||||
|
||||
TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
|
||||
// TODO: Split the list into multiple records if it's longer than 64KB, using
|
||||
// a subrecord of TypeRecordKind::Index to chain the records together.
|
||||
return writeRecord(FieldList.str());
|
||||
}
|
||||
|
||||
TypeIndex
|
||||
TypeTableBuilder::writeMethodList(MethodListRecordBuilder &MethodList) {
|
||||
// TODO: Split the list into multiple records if it's longer than 64KB, using
|
||||
// a subrecord of TypeRecordKind::Index to chain the records together.
|
||||
return writeRecord(MethodList.str());
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[common]
|
||||
subdirectories = DWARF PDB Symbolize
|
||||
subdirectories = CodeView DWARF PDB Symbolize
|
||||
|
||||
[component_0]
|
||||
type = Group
|
||||
|
@ -10,6 +10,6 @@ LEVEL = ../..
|
||||
|
||||
include $(LEVEL)/Makefile.config
|
||||
|
||||
PARALLEL_DIRS := DWARF PDB Symbolize
|
||||
PARALLEL_DIRS := CodeView DWARF PDB Symbolize
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
Loading…
Reference in New Issue
Block a user