| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| add_subdirectory(CodeView) | ||
| add_subdirectory(DWARF) | ||
| add_subdirectory(PDB) | ||
| add_subdirectory(Symbolize) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| add_llvm_library(LLVMCodeView | ||
| FieldListRecordBuilder.cpp | ||
| Line.cpp | ||
| ListRecordBuilder.cpp | ||
| MemoryTypeTableBuilder.cpp | ||
| MethodListRecordBuilder.cpp | ||
| TypeRecordBuilder.cpp | ||
| TypeTableBuilder.cpp | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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()); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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)); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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()); | ||
| } |