summaryrefslogtreecommitdiff
path: root/include/llvm/DebugInfo/CodeView
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/DebugInfo/CodeView')
-rw-r--r--include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h70
-rw-r--r--include/llvm/DebugInfo/CodeView/CVRecord.h44
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeView.h59
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewRegisters.def268
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewSymbols.def7
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewTypes.def3
-rw-r--r--include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h65
-rw-r--r--include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h87
-rw-r--r--include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h3
-rw-r--r--include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h81
-rw-r--r--include/llvm/DebugInfo/CodeView/RecordName.h (renamed from include/llvm/DebugInfo/CodeView/TypeName.h)10
-rw-r--r--include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h53
-rw-r--r--include/llvm/DebugInfo/CodeView/StringsAndChecksums.h9
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolDeserializer.h6
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolRecord.h13
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolSerializer.h5
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeCollection.h10
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDeserializer.h13
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeHashing.h204
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeIndex.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h10
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecord.h13
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h78
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeSerializer.h159
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeStreamMerger.h28
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeTableBuilder.h137
26 files changed, 973 insertions, 464 deletions
diff --git a/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h
new file mode 100644
index 0000000000000..bd1743511ed4b
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h
@@ -0,0 +1,70 @@
+//===- AppendingTypeTableBuilder.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_APPENDINGTYPETABLEBUILDER_H
+#define LLVM_DEBUGINFO_CODEVIEW_APPENDINGTYPETABLEBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+
+class ContinuationRecordBuilder;
+
+class AppendingTypeTableBuilder : public TypeCollection {
+
+ BumpPtrAllocator &RecordStorage;
+ SimpleTypeSerializer SimpleSerializer;
+
+ /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
+ SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
+
+public:
+ explicit AppendingTypeTableBuilder(BumpPtrAllocator &Storage);
+ ~AppendingTypeTableBuilder();
+
+ // TypeTableCollection overrides
+ Optional<TypeIndex> getFirst() override;
+ Optional<TypeIndex> getNext(TypeIndex Prev) override;
+ CVType getType(TypeIndex Index) override;
+ StringRef getTypeName(TypeIndex Index) override;
+ bool contains(TypeIndex Index) override;
+ uint32_t size() override;
+ uint32_t capacity() override;
+
+ // public interface
+ void reset();
+ TypeIndex nextTypeIndex() const;
+
+ BumpPtrAllocator &getAllocator() { return RecordStorage; }
+
+ ArrayRef<ArrayRef<uint8_t>> records() const;
+ TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
+ TypeIndex insertRecord(ContinuationRecordBuilder &Builder);
+
+ template <typename T> TypeIndex writeLeafType(T &Record) {
+ ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record);
+ return insertRecordBytes(Data);
+ }
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h
index 44040e04388af..9f3a753ad1ae1 100644
--- a/include/llvm/DebugInfo/CodeView/CVRecord.h
+++ b/include/llvm/DebugInfo/CodeView/CVRecord.h
@@ -61,30 +61,38 @@ template <typename Kind> struct RemappedRecord {
SmallVector<std::pair<uint32_t, TypeIndex>, 8> Mappings;
};
+/// Read a complete record from a stream at a random offset.
+template <typename Kind>
+inline Expected<CVRecord<Kind>> readCVRecordFromStream(BinaryStreamRef Stream,
+ uint32_t Offset) {
+ const RecordPrefix *Prefix = nullptr;
+ BinaryStreamReader Reader(Stream);
+ Reader.setOffset(Offset);
+
+ if (auto EC = Reader.readObject(Prefix))
+ return std::move(EC);
+ if (Prefix->RecordLen < 2)
+ return make_error<CodeViewError>(cv_error_code::corrupt_record);
+ Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind));
+
+ Reader.setOffset(Offset);
+ ArrayRef<uint8_t> RawData;
+ if (auto EC = Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
+ return std::move(EC);
+ return codeview::CVRecord<Kind>(K, RawData);
+}
+
} // end namespace codeview
template <typename Kind>
struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
codeview::CVRecord<Kind> &Item) {
- using namespace codeview;
- const RecordPrefix *Prefix = nullptr;
- BinaryStreamReader Reader(Stream);
- uint32_t Offset = Reader.getOffset();
-
- if (auto EC = Reader.readObject(Prefix))
- return EC;
- if (Prefix->RecordLen < 2)
- return make_error<CodeViewError>(cv_error_code::corrupt_record);
- Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind));
-
- Reader.setOffset(Offset);
- ArrayRef<uint8_t> RawData;
- if (auto EC =
- Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
- return EC;
- Item = codeview::CVRecord<Kind>(K, RawData);
- Len = Item.length();
+ auto ExpectedRec = codeview::readCVRecordFromStream<Kind>(Stream, 0);
+ if (!ExpectedRec)
+ return ExpectedRec.takeError();
+ Item = *ExpectedRec;
+ Len = ExpectedRec->length();
return Error::success();
}
};
diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h
index b7a7e33abadf8..1a4f510c24abe 100644
--- a/include/llvm/DebugInfo/CodeView/CodeView.h
+++ b/include/llvm/DebugInfo/CodeView/CodeView.h
@@ -124,6 +124,7 @@ enum class CPUType : uint16_t {
ARM_XMAC = 0x66,
ARM_WMMX = 0x67,
ARM7 = 0x68,
+ ARM64 = 0x69,
Omni = 0x70,
Ia64 = 0x80,
Ia64_2 = 0x81,
@@ -157,7 +158,11 @@ enum SourceLanguage : uint8_t {
Java = 0x0d,
JScript = 0x0e,
MSIL = 0x0f,
- HLSL = 0x10
+ HLSL = 0x10,
+
+ /// The DMD compiler emits 'D' for the CV source language. Microsoft doesn't
+ /// have an enumerator for it yet.
+ D = 'D',
};
/// These values correspond to the CV_call_e enumeration, and are documented
@@ -500,55 +505,9 @@ enum class FrameCookieKind : uint8_t {
// Corresponds to CV_HREG_e enum.
enum class RegisterId : uint16_t {
- Unknown = 0,
- VFrame = 30006,
- AL = 1,
- CL = 2,
- DL = 3,
- BL = 4,
- AH = 5,
- CH = 6,
- DH = 7,
- BH = 8,
- AX = 9,
- CX = 10,
- DX = 11,
- BX = 12,
- SP = 13,
- BP = 14,
- SI = 15,
- DI = 16,
- EAX = 17,
- ECX = 18,
- EDX = 19,
- EBX = 20,
- ESP = 21,
- EBP = 22,
- ESI = 23,
- EDI = 24,
- ES = 25,
- CS = 26,
- SS = 27,
- DS = 28,
- FS = 29,
- GS = 30,
- IP = 31,
- RAX = 328,
- RBX = 329,
- RCX = 330,
- RDX = 331,
- RSI = 332,
- RDI = 333,
- RBP = 334,
- RSP = 335,
- R8 = 336,
- R9 = 337,
- R10 = 338,
- R11 = 339,
- R12 = 340,
- R13 = 341,
- R14 = 342,
- R15 = 343,
+#define CV_REGISTER(name, value) name = value,
+#include "CodeViewRegisters.def"
+#undef CV_REGISTER
};
/// These values correspond to the THUNK_ORDINAL enumeration.
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
new file mode 100644
index 0000000000000..3f06602948668
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
@@ -0,0 +1,268 @@
+//===-- CodeViewRegisters.def - CodeView registers --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// See CV_HREG_e in cvconst.h. This should match the constants there.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CV_REGISTER
+#define CV_REGISTER(name, value)
+#endif
+
+// This currently only contains the "register subset shraed by all processor
+// types" (ERR etc.) and the x86 registers.
+
+CV_REGISTER(ERR, 30000)
+CV_REGISTER(TEB, 30001)
+CV_REGISTER(TIMER, 30002)
+CV_REGISTER(EFAD1, 30003)
+CV_REGISTER(EFAD2, 30004)
+CV_REGISTER(EFAD3, 30005)
+CV_REGISTER(VFRAME, 30006)
+CV_REGISTER(HANDLE, 30007)
+CV_REGISTER(PARAMS, 30008)
+CV_REGISTER(LOCALS, 30009)
+CV_REGISTER(TID, 30010)
+CV_REGISTER(ENV, 30011)
+CV_REGISTER(CMDLN, 30012)
+
+CV_REGISTER(NONE, 0)
+CV_REGISTER(AL, 1)
+CV_REGISTER(CL, 2)
+CV_REGISTER(DL, 3)
+CV_REGISTER(BL, 4)
+CV_REGISTER(AH, 5)
+CV_REGISTER(CH, 6)
+CV_REGISTER(DH, 7)
+CV_REGISTER(BH, 8)
+CV_REGISTER(AX, 9)
+CV_REGISTER(CX, 10)
+CV_REGISTER(DX, 11)
+CV_REGISTER(BX, 12)
+CV_REGISTER(SP, 13)
+CV_REGISTER(BP, 14)
+CV_REGISTER(SI, 15)
+CV_REGISTER(DI, 16)
+CV_REGISTER(EAX, 17)
+CV_REGISTER(ECX, 18)
+CV_REGISTER(EDX, 19)
+CV_REGISTER(EBX, 20)
+CV_REGISTER(ESP, 21)
+CV_REGISTER(EBP, 22)
+CV_REGISTER(ESI, 23)
+CV_REGISTER(EDI, 24)
+CV_REGISTER(ES, 25)
+CV_REGISTER(CS, 26)
+CV_REGISTER(SS, 27)
+CV_REGISTER(DS, 28)
+CV_REGISTER(FS, 29)
+CV_REGISTER(GS, 30)
+CV_REGISTER(IP, 31)
+CV_REGISTER(FLAGS, 32)
+CV_REGISTER(EIP, 33)
+CV_REGISTER(EFLAGS, 34)
+CV_REGISTER(TEMP, 40)
+CV_REGISTER(TEMPH, 41)
+CV_REGISTER(QUOTE, 42)
+CV_REGISTER(PCDR3, 43)
+CV_REGISTER(PCDR4, 44)
+CV_REGISTER(PCDR5, 45)
+CV_REGISTER(PCDR6, 46)
+CV_REGISTER(PCDR7, 47)
+CV_REGISTER(CR0, 80)
+CV_REGISTER(CR1, 81)
+CV_REGISTER(CR2, 82)
+CV_REGISTER(CR3, 83)
+CV_REGISTER(CR4, 84)
+CV_REGISTER(DR0, 90)
+CV_REGISTER(DR1, 91)
+CV_REGISTER(DR2, 92)
+CV_REGISTER(DR3, 93)
+CV_REGISTER(DR4, 94)
+CV_REGISTER(DR5, 95)
+CV_REGISTER(DR6, 96)
+CV_REGISTER(DR7, 97)
+CV_REGISTER(GDTR, 110)
+CV_REGISTER(GDTL, 111)
+CV_REGISTER(IDTR, 112)
+CV_REGISTER(IDTL, 113)
+CV_REGISTER(LDTR, 114)
+CV_REGISTER(TR, 115)
+
+CV_REGISTER(PSEUDO1, 116)
+CV_REGISTER(PSEUDO2, 117)
+CV_REGISTER(PSEUDO3, 118)
+CV_REGISTER(PSEUDO4, 119)
+CV_REGISTER(PSEUDO5, 120)
+CV_REGISTER(PSEUDO6, 121)
+CV_REGISTER(PSEUDO7, 122)
+CV_REGISTER(PSEUDO8, 123)
+CV_REGISTER(PSEUDO9, 124)
+
+CV_REGISTER(ST0, 128)
+CV_REGISTER(ST1, 129)
+CV_REGISTER(ST2, 130)
+CV_REGISTER(ST3, 131)
+CV_REGISTER(ST4, 132)
+CV_REGISTER(ST5, 133)
+CV_REGISTER(ST6, 134)
+CV_REGISTER(ST7, 135)
+CV_REGISTER(CTRL, 136)
+CV_REGISTER(STAT, 137)
+CV_REGISTER(TAG, 138)
+CV_REGISTER(FPIP, 139)
+CV_REGISTER(FPCS, 140)
+CV_REGISTER(FPDO, 141)
+CV_REGISTER(FPDS, 142)
+CV_REGISTER(ISEM, 143)
+CV_REGISTER(FPEIP, 144)
+CV_REGISTER(FPEDO, 145)
+
+CV_REGISTER(MM0, 146)
+CV_REGISTER(MM1, 147)
+CV_REGISTER(MM2, 148)
+CV_REGISTER(MM3, 149)
+CV_REGISTER(MM4, 150)
+CV_REGISTER(MM5, 151)
+CV_REGISTER(MM6, 152)
+CV_REGISTER(MM7, 153)
+
+CV_REGISTER(XMM0, 154)
+CV_REGISTER(XMM1, 155)
+CV_REGISTER(XMM2, 156)
+CV_REGISTER(XMM3, 157)
+CV_REGISTER(XMM4, 158)
+CV_REGISTER(XMM5, 159)
+CV_REGISTER(XMM6, 160)
+CV_REGISTER(XMM7, 161)
+
+CV_REGISTER(MXCSR, 211)
+
+CV_REGISTER(EDXEAX, 212)
+
+CV_REGISTER(EMM0L, 220)
+CV_REGISTER(EMM1L, 221)
+CV_REGISTER(EMM2L, 222)
+CV_REGISTER(EMM3L, 223)
+CV_REGISTER(EMM4L, 224)
+CV_REGISTER(EMM5L, 225)
+CV_REGISTER(EMM6L, 226)
+CV_REGISTER(EMM7L, 227)
+
+CV_REGISTER(EMM0H, 228)
+CV_REGISTER(EMM1H, 229)
+CV_REGISTER(EMM2H, 230)
+CV_REGISTER(EMM3H, 231)
+CV_REGISTER(EMM4H, 232)
+CV_REGISTER(EMM5H, 233)
+CV_REGISTER(EMM6H, 234)
+CV_REGISTER(EMM7H, 235)
+
+CV_REGISTER(MM00, 236)
+CV_REGISTER(MM01, 237)
+CV_REGISTER(MM10, 238)
+CV_REGISTER(MM11, 239)
+CV_REGISTER(MM20, 240)
+CV_REGISTER(MM21, 241)
+CV_REGISTER(MM30, 242)
+CV_REGISTER(MM31, 243)
+CV_REGISTER(MM40, 244)
+CV_REGISTER(MM41, 245)
+CV_REGISTER(MM50, 246)
+CV_REGISTER(MM51, 247)
+CV_REGISTER(MM60, 248)
+CV_REGISTER(MM61, 249)
+CV_REGISTER(MM70, 250)
+CV_REGISTER(MM71, 251)
+
+CV_REGISTER(BND0, 396)
+CV_REGISTER(BND1, 397)
+CV_REGISTER(BND2, 398)
+
+
+CV_REGISTER(XMM8, 252)
+CV_REGISTER(XMM9, 253)
+CV_REGISTER(XMM10, 254)
+CV_REGISTER(XMM11, 255)
+CV_REGISTER(XMM12, 256)
+CV_REGISTER(XMM13, 257)
+CV_REGISTER(XMM14, 258)
+CV_REGISTER(XMM15, 259)
+
+
+CV_REGISTER(SIL, 324)
+CV_REGISTER(DIL, 325)
+CV_REGISTER(BPL, 326)
+CV_REGISTER(SPL, 327)
+
+CV_REGISTER(RAX, 328)
+CV_REGISTER(RBX, 329)
+CV_REGISTER(RCX, 330)
+CV_REGISTER(RDX, 331)
+CV_REGISTER(RSI, 332)
+CV_REGISTER(RDI, 333)
+CV_REGISTER(RBP, 334)
+CV_REGISTER(RSP, 335)
+
+CV_REGISTER(R8, 336)
+CV_REGISTER(R9, 337)
+CV_REGISTER(R10, 338)
+CV_REGISTER(R11, 339)
+CV_REGISTER(R12, 340)
+CV_REGISTER(R13, 341)
+CV_REGISTER(R14, 342)
+CV_REGISTER(R15, 343)
+
+CV_REGISTER(R8B, 344)
+CV_REGISTER(R9B, 345)
+CV_REGISTER(R10B, 346)
+CV_REGISTER(R11B, 347)
+CV_REGISTER(R12B, 348)
+CV_REGISTER(R13B, 349)
+CV_REGISTER(R14B, 350)
+CV_REGISTER(R15B, 351)
+
+CV_REGISTER(R8W, 352)
+CV_REGISTER(R9W, 353)
+CV_REGISTER(R10W, 354)
+CV_REGISTER(R11W, 355)
+CV_REGISTER(R12W, 356)
+CV_REGISTER(R13W, 357)
+CV_REGISTER(R14W, 358)
+CV_REGISTER(R15W, 359)
+
+CV_REGISTER(R8D, 360)
+CV_REGISTER(R9D, 361)
+CV_REGISTER(R10D, 362)
+CV_REGISTER(R11D, 363)
+CV_REGISTER(R12D, 364)
+CV_REGISTER(R13D, 365)
+CV_REGISTER(R14D, 366)
+CV_REGISTER(R15D, 367)
+
+
+// cvconst.h defines both CV_REG_YMM0 (252) and CV_AMD64_YMM0 (368). Keep the
+// original prefix to distinguish them.
+
+CV_REGISTER(AMD64_YMM0, 368)
+CV_REGISTER(AMD64_YMM1, 369)
+CV_REGISTER(AMD64_YMM2, 370)
+CV_REGISTER(AMD64_YMM3, 371)
+CV_REGISTER(AMD64_YMM4, 372)
+CV_REGISTER(AMD64_YMM5, 373)
+CV_REGISTER(AMD64_YMM6, 374)
+CV_REGISTER(AMD64_YMM7, 375)
+CV_REGISTER(AMD64_YMM8, 376)
+CV_REGISTER(AMD64_YMM9, 377)
+CV_REGISTER(AMD64_YMM10, 378)
+CV_REGISTER(AMD64_YMM11, 379)
+CV_REGISTER(AMD64_YMM12, 380)
+CV_REGISTER(AMD64_YMM13, 381)
+CV_REGISTER(AMD64_YMM14, 382)
+CV_REGISTER(AMD64_YMM15, 383)
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def b/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def
index 32813d861d909..41c5380767983 100644
--- a/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def
+++ b/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def
@@ -1,4 +1,4 @@
-//===-- CVLeafTypes.def - All CodeView leaf types ---------------*- C++ -*-===//
+//===-- CodeViewSymbols.def - All CodeView leaf types -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -184,6 +184,9 @@ CV_SYMBOL(S_LDATA_HLSL32 , 0x1163)
CV_SYMBOL(S_GDATA_HLSL32_EX, 0x1164)
CV_SYMBOL(S_LDATA_HLSL32_EX, 0x1165)
+CV_SYMBOL(S_FASTLINK, 0x1167) // Undocumented
+SYMBOL_RECORD_ALIAS(S_INLINEES, 0x1168, InlineesSym, CallerSym) // Undocumented
+
// Known symbol types
SYMBOL_RECORD(S_END , 0x0006, ScopeEndSym)
SYMBOL_RECORD_ALIAS(S_INLINESITE_END , 0x114e, InlineSiteEnd, ScopeEndSym)
@@ -232,7 +235,7 @@ SYMBOL_RECORD(S_HEAPALLOCSITE , 0x115e, HeapAllocationSiteSym)
SYMBOL_RECORD(S_FRAMECOOKIE , 0x113a, FrameCookieSym)
SYMBOL_RECORD(S_CALLEES , 0x115a, CallerSym)
-SYMBOL_RECORD_ALIAS(S_CALLERS , 0x115b, CalleeSym, CallerSym)
+SYMBOL_RECORD_ALIAS(S_CALLERS, 0x115b, CalleeSym, CallerSym)
SYMBOL_RECORD(S_UDT , 0x1108, UDTSym)
SYMBOL_RECORD_ALIAS(S_COBOLUDT , 0x1109, CobolUDT, UDTSym)
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewTypes.def b/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
index 8c193bb13cb7e..69ce9606a670f 100644
--- a/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
+++ b/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
@@ -1,5 +1,4 @@
-
-//===-- CVLeafTypes.def - All CodeView leaf types ---------------*- C++ -*-===//
+//===-- CodeViewTypes.def - All CodeView leaf types -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h b/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h
new file mode 100644
index 0000000000000..7f851a2595dc0
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h
@@ -0,0 +1,65 @@
+//===- ContinuationRecordBuilder.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_CONTINUATIONRECORDBUILDER_H
+#define LLVM_DEBUGINFO_CODEVIEW_CONTINUATIONRECORDBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Error.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+enum class ContinuationRecordKind { FieldList, MethodOverloadList };
+
+class ContinuationRecordBuilder {
+ SmallVector<uint32_t, 4> SegmentOffsets;
+ Optional<ContinuationRecordKind> Kind;
+ AppendingBinaryByteStream Buffer;
+ BinaryStreamWriter SegmentWriter;
+ TypeRecordMapping Mapping;
+ ArrayRef<uint8_t> InjectedSegmentBytes;
+
+ uint32_t getCurrentSegmentLength() const;
+
+ void insertSegmentEnd(uint32_t Offset);
+ CVType createSegmentRecord(uint32_t OffBegin, uint32_t OffEnd,
+ Optional<TypeIndex> RefersTo);
+
+public:
+ ContinuationRecordBuilder();
+ ~ContinuationRecordBuilder();
+
+ void begin(ContinuationRecordKind RecordKind);
+
+ // This template is explicitly instantiated in the implementation file for all
+ // supported types. The method itself is ugly, so inlining it into the header
+ // file clutters an otherwise straightforward interface.
+ template <typename RecordType> void writeMemberType(RecordType &Record);
+
+ std::vector<CVType> end(TypeIndex Index);
+};
+} // namespace codeview
+} // namespace llvm
+
+#endif \ No newline at end of file
diff --git a/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
new file mode 100644
index 0000000000000..d8ac3343c15f9
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
@@ -0,0 +1,87 @@
+//===- GlobalTypeTableBuilder.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_GLOBALTYPETABLEBUILDER_H
+#define LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPETABLEBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeHashing.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+
+class ContinuationRecordBuilder;
+
+class GlobalTypeTableBuilder : public TypeCollection {
+ /// Storage for records. These need to outlive the TypeTableBuilder.
+ BumpPtrAllocator &RecordStorage;
+
+ /// A serializer that can write non-continuation leaf types. Only used as
+ /// a convenience function so that we can provide an interface method to
+ /// write an unserialized record.
+ SimpleTypeSerializer SimpleSerializer;
+
+ /// Hash table.
+ DenseMap<GloballyHashedType, TypeIndex> HashedRecords;
+
+ /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
+ SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
+
+ /// Contains a list of all hash values inexed by TypeIndex.toArrayIndex().
+ SmallVector<GloballyHashedType, 2> SeenHashes;
+
+public:
+ explicit GlobalTypeTableBuilder(BumpPtrAllocator &Storage);
+ ~GlobalTypeTableBuilder();
+
+ // TypeTableCollection overrides
+ Optional<TypeIndex> getFirst() override;
+ Optional<TypeIndex> getNext(TypeIndex Prev) override;
+ CVType getType(TypeIndex Index) override;
+ StringRef getTypeName(TypeIndex Index) override;
+ bool contains(TypeIndex Index) override;
+ uint32_t size() override;
+ uint32_t capacity() override;
+
+ // public interface
+ void reset();
+ TypeIndex nextTypeIndex() const;
+
+ BumpPtrAllocator &getAllocator() { return RecordStorage; }
+
+ ArrayRef<ArrayRef<uint8_t>> records() const;
+ ArrayRef<GloballyHashedType> hashes() const;
+
+ using CreateRecord = llvm::function_ref<ArrayRef<uint8_t>()>;
+
+ TypeIndex insertRecordAs(GloballyHashedType Hash, CreateRecord Create);
+ TypeIndex insertRecordBytes(ArrayRef<uint8_t> Data);
+ TypeIndex insertRecord(ContinuationRecordBuilder &Builder);
+
+ template <typename T> TypeIndex writeLeafType(T &Record) {
+ ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record);
+ return insertRecordBytes(Data);
+ }
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H
diff --git a/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
index cc0c24301d498..16d78692c839a 100644
--- a/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
+++ b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
@@ -67,9 +67,12 @@ public:
void reset(ArrayRef<uint8_t> Data, uint32_t RecordCountHint);
void reset(StringRef Data, uint32_t RecordCountHint);
+ void reset(BinaryStreamReader &Reader, uint32_t RecordCountHint);
uint32_t getOffsetOfType(TypeIndex Index);
+ Optional<CVType> tryGetType(TypeIndex Index);
+
CVType getType(TypeIndex Index) override;
StringRef getTypeName(TypeIndex Index) override;
bool contains(TypeIndex Index) override;
diff --git a/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h
new file mode 100644
index 0000000000000..9030918ebbb32
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h
@@ -0,0 +1,81 @@
+//===- MergingTypeTableBuilder.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_MERGINGTYPETABLEBUILDER_H
+#define LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeHashing.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+
+class ContinuationRecordBuilder;
+
+class MergingTypeTableBuilder : public TypeCollection {
+ /// Storage for records. These need to outlive the TypeTableBuilder.
+ BumpPtrAllocator &RecordStorage;
+
+ /// A serializer that can write non-continuation leaf types. Only used as
+ /// a convenience function so that we can provide an interface method to
+ /// write an unserialized record.
+ SimpleTypeSerializer SimpleSerializer;
+
+ /// Hash table.
+ DenseMap<LocallyHashedType, TypeIndex> HashedRecords;
+
+ /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
+ SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
+
+public:
+ explicit MergingTypeTableBuilder(BumpPtrAllocator &Storage);
+ ~MergingTypeTableBuilder();
+
+ // TypeTableCollection overrides
+ Optional<TypeIndex> getFirst() override;
+ Optional<TypeIndex> getNext(TypeIndex Prev) override;
+ CVType getType(TypeIndex Index) override;
+ StringRef getTypeName(TypeIndex Index) override;
+ bool contains(TypeIndex Index) override;
+ uint32_t size() override;
+ uint32_t capacity() override;
+
+ // public interface
+ void reset();
+ TypeIndex nextTypeIndex() const;
+
+ BumpPtrAllocator &getAllocator() { return RecordStorage; }
+
+ ArrayRef<ArrayRef<uint8_t>> records() const;
+
+ TypeIndex insertRecordAs(hash_code Hash, ArrayRef<uint8_t> &Record);
+ TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
+ TypeIndex insertRecord(ContinuationRecordBuilder &Builder);
+
+ template <typename T> TypeIndex writeLeafType(T &Record) {
+ ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record);
+ return insertRecordBytes(Data);
+ }
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H
diff --git a/include/llvm/DebugInfo/CodeView/TypeName.h b/include/llvm/DebugInfo/CodeView/RecordName.h
index a987b4afd283a..b022108df3d65 100644
--- a/include/llvm/DebugInfo/CodeView/TypeName.h
+++ b/include/llvm/DebugInfo/CodeView/RecordName.h
@@ -1,4 +1,4 @@
-//===- TypeName.h --------------------------------------------- *- C++ --*-===//
+//===- RecordName.h ------------------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,16 +7,18 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPENAME_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPENAME_H
+#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H
+#define LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
namespace llvm {
namespace codeview {
std::string computeTypeName(TypeCollection &Types, TypeIndex Index);
-}
+StringRef getSymbolName(CVSymbol Sym);
+} // namespace codeview
} // namespace llvm
#endif
diff --git a/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h b/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h
new file mode 100644
index 0000000000000..a85d9270186bf
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h
@@ -0,0 +1,53 @@
+//===- SimpleTypeSerializer.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_SIMPLETYPESERIALIZER_H
+#define LLVM_DEBUGINFO_CODEVIEW_SIMPLETYPESERIALIZER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Error.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+
+class SimpleTypeSerializer {
+ std::vector<uint8_t> ScratchBuffer;
+
+public:
+ SimpleTypeSerializer();
+ ~SimpleTypeSerializer();
+
+ // This template is explicitly instantiated in the implementation file for all
+ // supported types. The method itself is ugly, so inlining it into the header
+ // file clutters an otherwise straightforward interface.
+ template <typename T> ArrayRef<uint8_t> serialize(T &Record);
+
+ // Don't allow serialization of field list records using this interface.
+ ArrayRef<uint8_t> serialize(const FieldListRecord &Record) = delete;
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_SIMPLETYPESERIALIZER_H
diff --git a/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h
index 1a83882246652..22a333e631a03 100644
--- a/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h
+++ b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h
@@ -31,8 +31,13 @@ public:
StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings,
const DebugChecksumsSubsectionRef &Checksums);
+ void setStrings(const DebugStringTableSubsectionRef &Strings);
void setChecksums(const DebugChecksumsSubsectionRef &CS);
+ void reset();
+ void resetStrings();
+ void resetChecksums();
+
template <typename T> void initialize(T &&FragmentRange) {
for (const DebugSubsectionRecord &R : FragmentRange) {
if (Strings && Checksums)
@@ -67,8 +72,8 @@ private:
void initializeStrings(const DebugSubsectionRecord &SR);
void initializeChecksums(const DebugSubsectionRecord &FCR);
- std::unique_ptr<DebugStringTableSubsectionRef> OwnedStrings;
- std::unique_ptr<DebugChecksumsSubsectionRef> OwnedChecksums;
+ std::shared_ptr<DebugStringTableSubsectionRef> OwnedStrings;
+ std::shared_ptr<DebugChecksumsSubsectionRef> OwnedChecksums;
const DebugStringTableSubsectionRef *Strings = nullptr;
const DebugChecksumsSubsectionRef *Checksums = nullptr;
diff --git a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
index 5b6599d8c1db0..b5479db97a150 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
@@ -46,6 +46,12 @@ public:
return EC;
return Error::success();
}
+ template <typename T> static Expected<T> deserializeAs(CVSymbol Symbol) {
+ T Record(Symbol.kind());
+ if (auto EC = deserializeAs<T>(Symbol, Record))
+ return std::move(EC);
+ return Record;
+ }
explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate,
CodeViewContainer Container)
diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
index f3086cf3dbb91..cf267f23967bc 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -363,12 +363,12 @@ public:
: SymbolRecord(SymbolRecordKind::PublicSym32),
RecordOffset(RecordOffset) {}
- PublicSymFlags Flags;
- uint32_t Offset;
- uint16_t Segment;
+ PublicSymFlags Flags = PublicSymFlags::None;
+ uint32_t Offset = 0;
+ uint16_t Segment = 0;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_REGISTER
@@ -942,9 +942,14 @@ public:
uint32_t RecordOffset;
};
+// S_ANNOTATION
+
using CVSymbol = CVRecord<SymbolKind>;
using CVSymbolArray = VarStreamArray<CVSymbol>;
+Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
+ uint32_t Offset);
+
} // end namespace codeview
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
index b63ced5217b44..f4d8ab0c3c2ed 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
@@ -28,7 +28,10 @@ namespace codeview {
class SymbolSerializer : public SymbolVisitorCallbacks {
BumpPtrAllocator &Storage;
- std::vector<uint8_t> RecordBuffer;
+ // Since this is a fixed size buffer, use a stack allocated buffer. This
+ // yields measurable performance increase over the repeated heap allocations
+ // when serializing many independent records via writeOneSymbol.
+ std::array<uint8_t, MaxRecordLength> RecordBuffer;
MutableBinaryByteStream Stream;
BinaryStreamWriter Writer;
SymbolRecordMapping Mapping;
diff --git a/include/llvm/DebugInfo/CodeView/TypeCollection.h b/include/llvm/DebugInfo/CodeView/TypeCollection.h
index 0f856f57a7275..e9fc9b0de8efe 100644
--- a/include/llvm/DebugInfo/CodeView/TypeCollection.h
+++ b/include/llvm/DebugInfo/CodeView/TypeCollection.h
@@ -31,6 +31,16 @@ public:
virtual bool contains(TypeIndex Index) = 0;
virtual uint32_t size() = 0;
virtual uint32_t capacity() = 0;
+
+ template <typename TFunc> void ForEachRecord(TFunc Func) {
+ Optional<TypeIndex> Next = getFirst();
+
+ while (Next.hasValue()) {
+ TypeIndex N = *Next;
+ Func(N, getType(N));
+ Next = getNext(N);
+ }
+ }
};
}
}
diff --git a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
index 965cdfd85f489..9887d901773a0 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
@@ -52,6 +52,19 @@ public:
return Error::success();
}
+ template <typename T>
+ static Expected<T> deserializeAs(ArrayRef<uint8_t> Data) {
+ const RecordPrefix *Prefix =
+ reinterpret_cast<const RecordPrefix *>(Data.data());
+ TypeRecordKind K =
+ static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind));
+ T Record(K);
+ CVType CVT(static_cast<TypeLeafKind>(K), Data);
+ if (auto EC = deserializeAs<T>(CVT, Record))
+ return std::move(EC);
+ return Record;
+ }
+
Error visitTypeBegin(CVType &Record) override {
assert(!Mapping && "Already in a type mapping!");
Mapping = llvm::make_unique<MappingInfo>(Record.content());
diff --git a/include/llvm/DebugInfo/CodeView/TypeHashing.h b/include/llvm/DebugInfo/CodeView/TypeHashing.h
new file mode 100644
index 0000000000000..741337533701c
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeHashing.h
@@ -0,0 +1,204 @@
+//===- TypeHashing.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_TYPEHASHING_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEHASHING_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/Hashing.h"
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+
+#include "llvm/Support/FormatProviders.h"
+
+#include <type_traits>
+
+namespace llvm {
+namespace codeview {
+
+/// A locally hashed type represents a straightforward hash code of a serialized
+/// record. The record is simply serialized, and then the bytes are hashed by
+/// a standard algorithm. This is sufficient for the case of de-duplicating
+/// records within a single sequence of types, because if two records both have
+/// a back-reference to the same type in the same stream, they will both have
+/// the same numeric value for the TypeIndex of the back reference.
+struct LocallyHashedType {
+ hash_code Hash;
+ ArrayRef<uint8_t> RecordData;
+
+ /// Given a type, compute its local hash.
+ static LocallyHashedType hashType(ArrayRef<uint8_t> RecordData);
+
+ /// Given a sequence of types, compute all of the local hashes.
+ template <typename Range>
+ static std::vector<LocallyHashedType> hashTypes(Range &&Records) {
+ std::vector<LocallyHashedType> Hashes;
+ Hashes.reserve(std::distance(std::begin(Records), std::end(Records)));
+ for (const auto &R : Records)
+ Hashes.push_back(hashType(R));
+
+ return Hashes;
+ }
+
+ static std::vector<LocallyHashedType>
+ hashTypeCollection(TypeCollection &Types) {
+ std::vector<LocallyHashedType> Hashes;
+ Types.ForEachRecord([&Hashes](TypeIndex TI, const CVType &Type) {
+ Hashes.push_back(hashType(Type.RecordData));
+ });
+ return Hashes;
+ }
+};
+
+enum class GlobalTypeHashAlg : uint16_t { SHA1 = 0 };
+
+/// A globally hashed type represents a hash value that is sufficient to
+/// uniquely identify a record across multiple type streams or type sequences.
+/// This works by, for any given record A which references B, replacing the
+/// TypeIndex that refers to B with a previously-computed global hash for B. As
+/// this is a recursive algorithm (e.g. the global hash of B also depends on the
+/// global hashes of the types that B refers to), a global hash can uniquely
+/// identify identify that A occurs in another stream that has a completely
+/// different graph structure. Although the hash itself is slower to compute,
+/// probing is much faster with a globally hashed type, because the hash itself
+/// is considered "as good as" the original type. Since type records can be
+/// quite large, this makes the equality comparison of the hash much faster than
+/// equality comparison of a full record.
+struct GloballyHashedType {
+ GloballyHashedType() = default;
+ GloballyHashedType(StringRef H)
+ : GloballyHashedType(ArrayRef<uint8_t>(H.bytes_begin(), H.bytes_end())) {}
+ GloballyHashedType(ArrayRef<uint8_t> H) {
+ assert(H.size() == 20);
+ ::memcpy(Hash.data(), H.data(), 20);
+ }
+ std::array<uint8_t, 20> Hash;
+
+ /// Given a sequence of bytes representing a record, compute a global hash for
+ /// this record. Due to the nature of global hashes incorporating the hashes
+ /// of referenced records, this function requires a list of types and ids
+ /// that RecordData might reference, indexable by TypeIndex.
+ static GloballyHashedType hashType(ArrayRef<uint8_t> RecordData,
+ ArrayRef<GloballyHashedType> PreviousTypes,
+ ArrayRef<GloballyHashedType> PreviousIds);
+
+ /// Given a sequence of bytes representing a record, compute a global hash for
+ /// this record. Due to the nature of global hashes incorporating the hashes
+ /// of referenced records, this function requires a list of types and ids
+ /// that RecordData might reference, indexable by TypeIndex.
+ static GloballyHashedType hashType(CVType Type,
+ ArrayRef<GloballyHashedType> PreviousTypes,
+ ArrayRef<GloballyHashedType> PreviousIds) {
+ return hashType(Type.RecordData, PreviousTypes, PreviousIds);
+ }
+
+ /// Given a sequence of combined type and ID records, compute global hashes
+ /// for each of them, returning the results in a vector of hashed types.
+ template <typename Range>
+ static std::vector<GloballyHashedType> hashTypes(Range &&Records) {
+ std::vector<GloballyHashedType> Hashes;
+ for (const auto &R : Records)
+ Hashes.push_back(hashType(R, Hashes, Hashes));
+
+ return Hashes;
+ }
+
+ /// Given a sequence of combined type and ID records, compute global hashes
+ /// for each of them, returning the results in a vector of hashed types.
+ template <typename Range>
+ static std::vector<GloballyHashedType>
+ hashIds(Range &&Records, ArrayRef<GloballyHashedType> TypeHashes) {
+ std::vector<GloballyHashedType> IdHashes;
+ for (const auto &R : Records)
+ IdHashes.push_back(hashType(R, TypeHashes, IdHashes));
+
+ return IdHashes;
+ }
+
+ static std::vector<GloballyHashedType>
+ hashTypeCollection(TypeCollection &Types) {
+ std::vector<GloballyHashedType> Hashes;
+ Types.ForEachRecord([&Hashes](TypeIndex TI, const CVType &Type) {
+ Hashes.push_back(hashType(Type.RecordData, Hashes, Hashes));
+ });
+ return Hashes;
+ }
+};
+#if defined(_MSC_VER)
+// is_trivially_copyable is not available in older versions of libc++, but it is
+// available in all supported versions of MSVC, so at least this gives us some
+// coverage.
+static_assert(std::is_trivially_copyable<GloballyHashedType>::value,
+ "GloballyHashedType must be trivially copyable so that we can "
+ "reinterpret_cast arrays of hash data to arrays of "
+ "GloballyHashedType");
+#endif
+} // namespace codeview
+
+template <> struct DenseMapInfo<codeview::LocallyHashedType> {
+ static codeview::LocallyHashedType Empty;
+ static codeview::LocallyHashedType Tombstone;
+
+ static codeview::LocallyHashedType getEmptyKey() { return Empty; }
+
+ static codeview::LocallyHashedType getTombstoneKey() { return Tombstone; }
+
+ static unsigned getHashValue(codeview::LocallyHashedType Val) {
+ return Val.Hash;
+ }
+
+ static bool isEqual(codeview::LocallyHashedType LHS,
+ codeview::LocallyHashedType RHS) {
+ if (LHS.Hash != RHS.Hash)
+ return false;
+ return LHS.RecordData == RHS.RecordData;
+ }
+};
+
+template <> struct DenseMapInfo<codeview::GloballyHashedType> {
+ static codeview::GloballyHashedType Empty;
+ static codeview::GloballyHashedType Tombstone;
+
+ static codeview::GloballyHashedType getEmptyKey() { return Empty; }
+
+ static codeview::GloballyHashedType getTombstoneKey() { return Tombstone; }
+
+ static unsigned getHashValue(codeview::GloballyHashedType Val) {
+ return *reinterpret_cast<const unsigned *>(Val.Hash.data());
+ }
+
+ static bool isEqual(codeview::GloballyHashedType LHS,
+ codeview::GloballyHashedType RHS) {
+ return LHS.Hash == RHS.Hash;
+ }
+};
+
+template <> struct format_provider<codeview::LocallyHashedType> {
+public:
+ static void format(const codeview::LocallyHashedType &V,
+ llvm::raw_ostream &Stream, StringRef Style) {
+ write_hex(Stream, V.Hash, HexPrintStyle::Upper, 8);
+ }
+};
+
+template <> struct format_provider<codeview::GloballyHashedType> {
+public:
+ static void format(const codeview::GloballyHashedType &V,
+ llvm::raw_ostream &Stream, StringRef Style) {
+ for (uint8_t B : V.Hash) {
+ write_hex(Stream, B, HexPrintStyle::Upper, 2);
+ }
+ }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/TypeIndex.h b/include/llvm/DebugInfo/CodeView/TypeIndex.h
index e0c2226bdbd74..c71281de71455 100644
--- a/include/llvm/DebugInfo/CodeView/TypeIndex.h
+++ b/include/llvm/DebugInfo/CodeView/TypeIndex.h
@@ -98,6 +98,7 @@ public:
static const uint32_t FirstNonSimpleIndex = 0x1000;
static const uint32_t SimpleKindMask = 0x000000ff;
static const uint32_t SimpleModeMask = 0x00000700;
+ static const uint32_t DecoratedItemIdMask = 0x80000000;
public:
TypeIndex() : Index(static_cast<uint32_t>(SimpleTypeKind::None)) {}
@@ -110,6 +111,7 @@ public:
uint32_t getIndex() const { return Index; }
void setIndex(uint32_t I) { Index = I; }
bool isSimple() const { return Index < FirstNonSimpleIndex; }
+ bool isDecoratedItemId() const { return !!(Index & DecoratedItemIdMask); }
bool isNoneType() const { return *this == None(); }
diff --git a/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h b/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
index afe8942159e84..c424a09ece890 100644
--- a/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
+++ b/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
@@ -30,11 +30,17 @@ void discoverTypeIndices(const CVType &Type,
SmallVectorImpl<TiReference> &Refs);
void discoverTypeIndices(const CVType &Type,
SmallVectorImpl<TypeIndex> &Indices);
+void discoverTypeIndices(ArrayRef<uint8_t> RecordData,
+ SmallVectorImpl<TypeIndex> &Indices);
/// Discover type indices in symbol records. Returns false if this is an unknown
/// record.
-bool discoverTypeIndices(const CVSymbol &Symbol,
- SmallVectorImpl<TiReference> &Refs);
+bool discoverTypeIndicesInSymbol(const CVSymbol &Symbol,
+ SmallVectorImpl<TiReference> &Refs);
+bool discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData,
+ SmallVectorImpl<TiReference> &Refs);
+bool discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData,
+ SmallVectorImpl<TypeIndex> &Indices);
}
}
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecord.h b/include/llvm/DebugInfo/CodeView/TypeRecord.h
index 7942c0c0bc215..508bdd395f74e 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecord.h
+++ b/include/llvm/DebugInfo/CodeView/TypeRecord.h
@@ -334,6 +334,11 @@ public:
uint32_t Attrs;
Optional<MemberPointerInfo> MemberInfo;
+ void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
+ uint8_t Size) {
+ Attrs = calcAttrs(PK, PM, PO, Size);
+ }
+
private:
static uint32_t calcAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
uint8_t Size) {
@@ -412,6 +417,14 @@ public:
return (Options & ClassOptions::HasUniqueName) != ClassOptions::None;
}
+ bool isNested() const {
+ return (Options & ClassOptions::Nested) != ClassOptions::None;
+ }
+
+ bool isForwardRef() const {
+ return (Options & ClassOptions::ForwardReference) != ClassOptions::None;
+ }
+
uint16_t getMemberCount() const { return MemberCount; }
ClassOptions getOptions() const { return Options; }
TypeIndex getFieldList() const { return FieldList; }
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h b/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
deleted file mode 100644
index 5a6507ee7f5b4..0000000000000
--- a/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//===- 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/ADT/SmallVector.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.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(StringRef Value);
- void writeGuid(StringRef Guid);
- void writeBytes(StringRef Value) { Stream << Value; }
-
- llvm::StringRef str();
-
- uint64_t size() const { return Stream.tell(); }
- TypeRecordKind kind() const { return Kind; }
-
- /// Returns the number of bytes remaining before this record is larger than
- /// the maximum record length. Accounts for the extra two byte size field in
- /// the header.
- size_t maxBytesRemaining() const { return MaxRecordLength - size() - 2; }
-
- void truncate(uint64_t Size) {
- // This works because raw_svector_ostream is not buffered.
- assert(Size < Buffer.size());
- Buffer.resize(Size);
- }
-
- void reset(TypeRecordKind K) {
- Buffer.clear();
- Kind = K;
- writeTypeRecordKind(K);
- }
-
-private:
- TypeRecordKind Kind;
- llvm::SmallVector<char, 256> Buffer;
- llvm::raw_svector_ostream Stream;
- llvm::support::endian::Writer<llvm::support::endianness::little> Writer;
-};
-}
-}
-
-#endif
diff --git a/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
deleted file mode 100644
index 0e734a8170bdf..0000000000000
--- a/include/llvm/DebugInfo/CodeView/TypeSerializer.h
+++ /dev/null
@@ -1,159 +0,0 @@
-//===- TypeSerializer.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_TYPESERIALIZER_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/BinaryByteStream.h"
-#include "llvm/Support/BinaryStreamWriter.h"
-#include "llvm/Support/Error.h"
-#include <cassert>
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-namespace llvm {
-namespace codeview {
-
-class TypeHasher;
-
-class TypeSerializer : public TypeVisitorCallbacks {
- struct SubRecord {
- SubRecord(TypeLeafKind K, uint32_t S) : Kind(K), Size(S) {}
-
- TypeLeafKind Kind;
- uint32_t Size = 0;
- };
- struct RecordSegment {
- SmallVector<SubRecord, 16> SubRecords;
-
- uint32_t length() const {
- uint32_t L = sizeof(RecordPrefix);
- for (const auto &R : SubRecords) {
- L += R.Size;
- }
- return L;
- }
- };
-
- using MutableRecordList = SmallVector<MutableArrayRef<uint8_t>, 2>;
-
- static constexpr uint8_t ContinuationLength = 8;
- BumpPtrAllocator &RecordStorage;
- RecordSegment CurrentSegment;
- MutableRecordList FieldListSegments;
-
- Optional<TypeLeafKind> TypeKind;
- Optional<TypeLeafKind> MemberKind;
- std::vector<uint8_t> RecordBuffer;
- MutableBinaryByteStream Stream;
- BinaryStreamWriter Writer;
- TypeRecordMapping Mapping;
-
- /// Private type record hashing implementation details are handled here.
- std::unique_ptr<TypeHasher> Hasher;
-
- /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
- SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
-
- /// Temporary storage that we use to copy a record's data while re-writing
- /// its type indices.
- SmallVector<uint8_t, 256> RemapStorage;
-
- TypeIndex nextTypeIndex() const;
-
- bool isInFieldList() const;
- MutableArrayRef<uint8_t> getCurrentSubRecordData();
- MutableArrayRef<uint8_t> getCurrentRecordData();
- Error writeRecordPrefix(TypeLeafKind Kind);
-
- Expected<MutableArrayRef<uint8_t>>
- addPadding(MutableArrayRef<uint8_t> Record);
-
-public:
- explicit TypeSerializer(BumpPtrAllocator &Storage, bool Hash = true);
- ~TypeSerializer() override;
-
- void reset();
-
- BumpPtrAllocator &getAllocator() { return RecordStorage; }
-
- ArrayRef<ArrayRef<uint8_t>> records() const;
- TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
- TypeIndex insertRecord(const RemappedType &Record);
- Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record);
-
- using TypeVisitorCallbacks::visitTypeBegin;
- Error visitTypeBegin(CVType &Record) override;
- Error visitTypeEnd(CVType &Record) override;
- Error visitMemberBegin(CVMemberRecord &Record) override;
- Error visitMemberEnd(CVMemberRecord &Record) override;
-
-#define TYPE_RECORD(EnumName, EnumVal, Name) \
- virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
- return visitKnownRecordImpl(CVR, Record); \
- }
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
- return visitKnownMemberImpl<Name##Record>(CVR, Record); \
- }
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
-
-private:
- template <typename RecordKind>
- Error visitKnownRecordImpl(CVType &CVR, RecordKind &Record) {
- return Mapping.visitKnownRecord(CVR, Record);
- }
-
- template <typename RecordType>
- Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
- assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind()));
-
- if (auto EC = Writer.writeEnum(CVR.Kind))
- return EC;
-
- if (auto EC = Mapping.visitKnownMember(CVR, Record))
- return EC;
-
- // Get all the data that was just written and is yet to be committed to
- // the current segment. Then pad it to 4 bytes.
- MutableArrayRef<uint8_t> ThisRecord = getCurrentSubRecordData();
- auto ExpectedRecord = addPadding(ThisRecord);
- if (!ExpectedRecord)
- return ExpectedRecord.takeError();
- ThisRecord = *ExpectedRecord;
-
- CurrentSegment.SubRecords.emplace_back(CVR.Kind, ThisRecord.size());
- CVR.Data = ThisRecord;
-
- // Both the last subrecord and the total length of this segment should be
- // multiples of 4.
- assert(ThisRecord.size() % 4 == 0);
- assert(CurrentSegment.length() % 4 == 0);
-
- return Error::success();
- }
-};
-
-} // end namespace codeview
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
diff --git a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
index d78fab47db668..59e216abcb11c 100644
--- a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
+++ b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -19,7 +19,9 @@ namespace llvm {
namespace codeview {
class TypeIndex;
-class TypeTableBuilder;
+struct GloballyHashedType;
+class GlobalTypeTableBuilder;
+class MergingTypeTableBuilder;
/// \brief Merge one set of type records into another. This method assumes
/// that all records are type records, and there are no Id records present.
@@ -34,7 +36,7 @@ class TypeTableBuilder;
///
/// \returns Error::success() if the operation succeeded, otherwise an
/// appropriate error code.
-Error mergeTypeRecords(TypeTableBuilder &Dest,
+Error mergeTypeRecords(MergingTypeTableBuilder &Dest,
SmallVectorImpl<TypeIndex> &SourceToDest,
const CVTypeArray &Types);
@@ -59,7 +61,7 @@ Error mergeTypeRecords(TypeTableBuilder &Dest,
///
/// \returns Error::success() if the operation succeeded, otherwise an
/// appropriate error code.
-Error mergeIdRecords(TypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
+Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
SmallVectorImpl<TypeIndex> &SourceToDest,
const CVTypeArray &Ids);
@@ -78,11 +80,27 @@ Error mergeIdRecords(TypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
///
/// \returns Error::success() if the operation succeeded, otherwise an
/// appropriate error code.
-Error mergeTypeAndIdRecords(TypeTableBuilder &DestIds,
- TypeTableBuilder &DestTypes,
+Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds,
+ MergingTypeTableBuilder &DestTypes,
SmallVectorImpl<TypeIndex> &SourceToDest,
const CVTypeArray &IdsAndTypes);
+Error mergeTypeAndIdRecords(GlobalTypeTableBuilder &DestIds,
+ GlobalTypeTableBuilder &DestTypes,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &IdsAndTypes,
+ ArrayRef<GloballyHashedType> Hashes);
+
+Error mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Types,
+ ArrayRef<GloballyHashedType> Hashes);
+
+Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Ids,
+ ArrayRef<GloballyHashedType> Hashes);
+
} // end namespace codeview
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
deleted file mode 100644
index 1069dcd453349..0000000000000
--- a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//===- TypeTableBuilder.h ---------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Error.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <type_traits>
-
-namespace llvm {
-namespace codeview {
-
-class TypeTableBuilder {
-private:
- TypeIndex handleError(Error EC) const {
- assert(false && "Couldn't write Type!");
- consumeError(std::move(EC));
- return TypeIndex();
- }
-
- BumpPtrAllocator &Allocator;
- TypeSerializer Serializer;
-
-public:
- explicit TypeTableBuilder(BumpPtrAllocator &Allocator,
- bool WriteUnique = true)
- : Allocator(Allocator), Serializer(Allocator, WriteUnique) {}
- TypeTableBuilder(const TypeTableBuilder &) = delete;
- TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;
-
- bool empty() const { return Serializer.records().empty(); }
-
- BumpPtrAllocator &getAllocator() const { return Allocator; }
-
- template <typename T> TypeIndex writeKnownType(T &Record) {
- static_assert(!std::is_same<T, FieldListRecord>::value,
- "Can't serialize FieldList!");
-
- CVType Type;
- Type.Type = static_cast<TypeLeafKind>(Record.getKind());
- if (auto EC = Serializer.visitTypeBegin(Type))
- return handleError(std::move(EC));
- if (auto EC = Serializer.visitKnownRecord(Type, Record))
- return handleError(std::move(EC));
-
- auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type);
- if (!ExpectedIndex)
- return handleError(ExpectedIndex.takeError());
-
- return *ExpectedIndex;
- }
-
- TypeIndex writeSerializedRecord(ArrayRef<uint8_t> Record) {
- return Serializer.insertRecordBytes(Record);
- }
-
- TypeIndex writeSerializedRecord(const RemappedType &Record) {
- return Serializer.insertRecord(Record);
- }
-
- template <typename TFunc> void ForEachRecord(TFunc Func) {
- uint32_t Index = TypeIndex::FirstNonSimpleIndex;
-
- for (auto Record : Serializer.records()) {
- Func(TypeIndex(Index), Record);
- ++Index;
- }
- }
-
- ArrayRef<ArrayRef<uint8_t>> records() const { return Serializer.records(); }
-};
-
-class FieldListRecordBuilder {
- TypeTableBuilder &TypeTable;
- BumpPtrAllocator Allocator;
- TypeSerializer TempSerializer;
- CVType Type;
-
-public:
- explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable)
- : TypeTable(TypeTable), TempSerializer(Allocator, false) {
- Type.Type = TypeLeafKind::LF_FIELDLIST;
- }
-
- void begin() {
- TempSerializer.reset();
-
- if (auto EC = TempSerializer.visitTypeBegin(Type))
- consumeError(std::move(EC));
- }
-
- template <typename T> void writeMemberType(T &Record) {
- CVMemberRecord CVMR;
- CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind());
- if (auto EC = TempSerializer.visitMemberBegin(CVMR))
- consumeError(std::move(EC));
- if (auto EC = TempSerializer.visitKnownMember(CVMR, Record))
- consumeError(std::move(EC));
- if (auto EC = TempSerializer.visitMemberEnd(CVMR))
- consumeError(std::move(EC));
- }
-
- TypeIndex end(bool Write) {
- TypeIndex Index;
- if (auto EC = TempSerializer.visitTypeEnd(Type)) {
- consumeError(std::move(EC));
- return TypeIndex();
- }
-
- if (Write) {
- for (auto Record : TempSerializer.records())
- Index = TypeTable.writeSerializedRecord(Record);
- }
-
- return Index;
- }
-};
-
-} // end namespace codeview
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H