Index: llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h @@ -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 + +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(static_cast(a) | + static_cast(b)); +} + +inline ClassOptions operator&(ClassOptions a, ClassOptions b) { + return static_cast(static_cast(a) & + static_cast(b)); +} + +inline ClassOptions operator~(ClassOptions a) { + return static_cast(~static_cast(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(static_cast(a) | + static_cast(b)); +} + +inline FrameProcedureOptions operator&(FrameProcedureOptions a, + FrameProcedureOptions b) { + return static_cast(static_cast(a) & + static_cast(b)); +} + +inline FrameProcedureOptions operator~(FrameProcedureOptions a) { + return static_cast(~static_cast(a)); +} + +enum class FunctionOptions : uint8_t { + None = 0x00, + CxxReturnUdt = 0x01, + Constructor = 0x02, + ConstructorWithVirtualBases = 0x04 +}; + +inline FunctionOptions operator|(FunctionOptions a, FunctionOptions b) { + return static_cast(static_cast(a) | + static_cast(b)); +} + +inline FunctionOptions operator&(FunctionOptions a, FunctionOptions b) { + return static_cast(static_cast(a) & + static_cast(b)); +} + +inline FunctionOptions operator~(FunctionOptions a) { + return static_cast(~static_cast(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(static_cast(a) | + static_cast(b)); +} + +inline MethodOptions operator&(MethodOptions a, MethodOptions b) { + return static_cast(static_cast(a) & + static_cast(b)); +} + +inline MethodOptions operator~(MethodOptions a) { + return static_cast(~static_cast(a)); +} + +enum class ModifierOptions : uint16_t { + None = 0x0000, + Const = 0x0001, + Volatile = 0x0002, + Unaligned = 0x0004 +}; + +inline ModifierOptions operator|(ModifierOptions a, ModifierOptions b) { + return static_cast(static_cast(a) | + static_cast(b)); +} + +inline ModifierOptions operator&(ModifierOptions a, ModifierOptions b) { + return static_cast(static_cast(a) & + static_cast(b)); +} + +inline ModifierOptions operator~(ModifierOptions a) { + return static_cast(~static_cast(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(static_cast(a) | + static_cast(b)); +} + +inline PointerOptions operator&(PointerOptions a, PointerOptions b) { + return static_cast(static_cast(a) & + static_cast(b)); +} + +inline PointerOptions operator~(PointerOptions a) { + return static_cast(~static_cast(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 Index: llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewOStream.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewOStream.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewOStream.h @@ -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 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 Index: llvm/trunk/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h @@ -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 Index: llvm/trunk/include/llvm/DebugInfo/CodeView/FunctionId.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/FunctionId.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/FunctionId.h @@ -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 + +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 Index: llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h @@ -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 + +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(StartColumn) & StartColumnMask) | + ((static_cast(EndColumn) << EndColumnShift) & EndColumnMask); + } + + uint16_t getStartColumn() const { + return static_cast(ColumnData & StartColumnMask); + } + + uint16_t getEndColumn() const { + return static_cast((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 Index: llvm/trunk/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h @@ -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 ContinuationOffsets; +}; +} +} + +#endif Index: llvm/trunk/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h @@ -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 +#include +#include +#include + +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 Data; + }; + +private: + class RecordHash : std::unary_function { + public: + size_t operator()(llvm::StringRef Val) const { + return static_cast(llvm::hash_value(Val)); + } + }; + +public: + MemoryTypeTableBuilder() {} + + template void ForEachRecord(TFunc Func) { + uint32_t Index = TypeIndex::FirstNonSimpleIndex; + + for (const std::unique_ptr &R : Records) { + Func(TypeIndex(Index), R.get()); + ++Index; + } + } + +private: + virtual TypeIndex writeRecord(llvm::StringRef Data) override; + +private: + std::vector> Records; + std::unordered_map HashedRecords; +}; +} +} + +#endif Index: llvm/trunk/include/llvm/DebugInfo/CodeView/MethodListRecordBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/MethodListRecordBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/MethodListRecordBuilder.h @@ -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 Index: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeIndex.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeIndex.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -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 +#include + +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(Kind)) {} + TypeIndex(SimpleTypeKind Kind, SimpleTypeMode Mode) + : Index(static_cast(Kind) | static_cast(Mode)) {} + + uint32_t getIndex() const { return Index; } + bool isSimple() const { return Index < FirstNonSimpleIndex; } + + SimpleTypeKind getSimpleKind() const { + assert(isSimple()); + return static_cast(Index & SimpleKindMask); + } + + SimpleTypeMode getSimpleMode() const { + assert(isSimple()); + return static_cast(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 Index: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -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 + +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 ArgumentTypes) + : TypeRecord(TypeRecordKind::ArgumentList), ArgumentTypes(ArgumentTypes) { + } + + llvm::ArrayRef getArgumentTypes() const { return ArgumentTypes; } + +private: + llvm::ArrayRef 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 Slots) + : TypeRecord(TypeRecordKind::VirtualTableShape), Slots(Slots) {} + + ArrayRef getSlots() const { return Slots; } + +private: + ArrayRef Slots; +}; +} +} + +#endif Index: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h @@ -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 Buffer; + llvm::raw_svector_ostream Stream; + llvm::support::endian::Writer Writer; +}; +} +} + +#endif Index: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h @@ -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 Index: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h @@ -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 Index: llvm/trunk/lib/DebugInfo/CMakeLists.txt =================================================================== --- llvm/trunk/lib/DebugInfo/CMakeLists.txt +++ llvm/trunk/lib/DebugInfo/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(CodeView) add_subdirectory(DWARF) add_subdirectory(PDB) add_subdirectory(Symbolize) Index: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt +++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt @@ -0,0 +1,9 @@ +add_llvm_library(LLVMCodeView + FieldListRecordBuilder.cpp + Line.cpp + ListRecordBuilder.cpp + MemoryTypeTableBuilder.cpp + MethodListRecordBuilder.cpp + TypeRecordBuilder.cpp + TypeTableBuilder.cpp + ) Index: llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp @@ -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(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(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(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(Access); + Flags |= static_cast(Kind) << MethodKindShift; + Flags |= static_cast(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(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(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(); +} \ No newline at end of file Index: llvm/trunk/lib/DebugInfo/CodeView/LLVMBuild.txt =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/LLVMBuild.txt +++ llvm/trunk/lib/DebugInfo/CodeView/LLVMBuild.txt @@ -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 Index: llvm/trunk/lib/DebugInfo/CodeView/Line.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/Line.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/Line.cpp @@ -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; + } +} Index: llvm/trunk/lib/DebugInfo/CodeView/ListRecordBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/ListRecordBuilder.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/ListRecordBuilder.cpp @@ -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); +} Index: llvm/trunk/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp @@ -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 R(new Record(Data)); + + TypeIndex TI(static_cast(Records.size()) + + TypeIndex::FirstNonSimpleIndex); + HashedRecords.insert(std::make_pair(StringRef(R->data(), R->size()), TI)); + Records.push_back(std::move(R)); + + return TI; +} Index: llvm/trunk/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp @@ -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(Access); + Flags |= static_cast(Kind) << MethodKindShift; + Flags |= static_cast(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()); +} Index: llvm/trunk/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp @@ -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(Value)); + } else { + writeEncodedSignedInteger(Value); + } +} + +void TypeRecordBuilder::writeEncodedSignedInteger(int64_t Value) { + if (Value >= std::numeric_limits::min() && + Value <= std::numeric_limits::max()) { + writeUInt16(static_cast(TypeRecordKind::SByte)); + writeInt16(static_cast(Value)); + } else if (Value >= std::numeric_limits::min() && + Value <= std::numeric_limits::max()) { + writeUInt16(static_cast(TypeRecordKind::Int16)); + writeInt16(static_cast(Value)); + } else if (Value >= std::numeric_limits::min() && + Value <= std::numeric_limits::max()) { + writeUInt16(static_cast(TypeRecordKind::Int32)); + writeInt32(static_cast(Value)); + } else { + writeUInt16(static_cast(TypeRecordKind::Int64)); + writeInt64(Value); + } +} + +void TypeRecordBuilder::writeEncodedUnsignedInteger(uint64_t Value) { + if (Value < static_cast(TypeRecordKind::SByte)) { + writeUInt16(static_cast(Value)); + } else if (Value <= std::numeric_limits::max()) { + writeUInt16(static_cast(TypeRecordKind::UInt16)); + writeUInt16(static_cast(Value)); + } else if (Value <= std::numeric_limits::max()) { + writeUInt16(static_cast(TypeRecordKind::UInt32)); + writeUInt32(static_cast(Value)); + } else { + writeUInt16(static_cast(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(Kind)); +} Index: llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp @@ -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(Record.getOptions()) | + (Record.getSize() << PointerSizeShift) | + (static_cast(Record.getMode()) << PointerModeShift) | + (static_cast(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(Record.getOptions())); + + return writeRecord(Builder); +} + +TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) { + TypeRecordBuilder Builder(TypeRecordKind::Procedure); + + Builder.writeTypeIndex(Record.getReturnType()); + Builder.writeUInt8(static_cast(Record.getCallConv())); + Builder.writeUInt8(static_cast(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(Record.getCallConv())); + Builder.writeUInt8(static_cast(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(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(Record.getOptions()) | + (static_cast(Record.getHfa()) << ClassHfaKindShift) | + (static_cast(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(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 Slots = Record.getSlots(); + + Builder.writeUInt16(Slots.size()); + for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) { + uint8_t Byte = static_cast(Slots[SlotIndex]) << 4; + if ((SlotIndex + 1) < Slots.size()) { + Byte |= static_cast(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()); +} Index: llvm/trunk/lib/DebugInfo/LLVMBuild.txt =================================================================== --- llvm/trunk/lib/DebugInfo/LLVMBuild.txt +++ llvm/trunk/lib/DebugInfo/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = DWARF PDB Symbolize +subdirectories = CodeView DWARF PDB Symbolize [component_0] type = Group Index: llvm/trunk/lib/DebugInfo/Makefile =================================================================== --- llvm/trunk/lib/DebugInfo/Makefile +++ llvm/trunk/lib/DebugInfo/Makefile @@ -10,6 +10,6 @@ include $(LEVEL)/Makefile.config -PARALLEL_DIRS := DWARF PDB Symbolize +PARALLEL_DIRS := CodeView DWARF PDB Symbolize include $(LEVEL)/Makefile.common