summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo/CodeView
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-06-21 18:33:01 +0000
committerReid Kleckner <rnk@google.com>2016-06-21 18:33:01 +0000
commit5b335b864b4d308d1229afbc2ce322d7c43e4a37 (patch)
tree945be5302833fb5030dd94f49798923f64fddd7b /llvm/lib/DebugInfo/CodeView
parentff5ca8b4cf712a6dc64cc9a378bed8af27e8caf0 (diff)
downloadbcm5719-llvm-5b335b864b4d308d1229afbc2ce322d7c43e4a37.tar.gz
bcm5719-llvm-5b335b864b4d308d1229afbc2ce322d7c43e4a37.zip
[codeview] Add support for splitting field list records over 64KB
The basic structure is that once a list record goes over 64K, the last subrecord of the list is an LF_INDEX record that refers to the next record. Because the type record graph must be toplogically sorted, this means we have to emit them in reverse order. We build the type record in order of declaration, so this means that if we don't want extra copies, we need to detect when we were about to split a record, and leave space for a continuation subrecord that will point to the eventual split top-level record. Also adds dumping support for these records. Next we should make sure that large method overload lists work properly. llvm-svn: 273294
Diffstat (limited to 'llvm/lib/DebugInfo/CodeView')
-rw-r--r--llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp79
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeDumper.cpp11
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecord.cpp12
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp4
4 files changed, 96 insertions, 10 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
index 5bec65a36df..eab5add310e 100644
--- a/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
+++ b/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
@@ -7,27 +7,92 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
using namespace llvm;
using namespace codeview;
-ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind) : Builder(Kind) {}
+ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind)
+ : Kind(Kind), Builder(Kind) {}
-void ListRecordBuilder::finishSubRecord() {
- SubrecordCount++;
+void ListRecordBuilder::writeListContinuation(const ListContinuationRecord &R) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ assert(getLastContinuationSize() < 65535 - 8 && "continuation won't fit");
+
+ Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation);
+ Builder.writeUInt16(0);
+ Builder.writeTypeIndex(R.getContinuationIndex());
+
+ // End the current segment manually so that nothing comes after the
+ // continuation.
+ ContinuationOffsets.push_back(Builder.size());
+ SubrecordStart = Builder.size();
+}
+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);
+ Builder.writeUInt8(LF_PAD0 + 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);
+ // Check if this subrecord makes the current segment not fit in 64K minus the
+ // space for a continuation record (8 bytes). If the segment does not fit,
+ // back up and insert a continuation record, sliding the current subrecord
+ // down.
+ if (getLastContinuationSize() > 65535 - 8) {
+ SmallString<128> SubrecordCopy(Builder.str().slice(SubrecordStart, Builder.size()));
+ Builder.truncate(SubrecordStart);
+
+ // Write a placeholder continuation record.
+ Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation);
+ Builder.writeUInt16(0);
+ Builder.writeUInt32(0);
+ ContinuationOffsets.push_back(Builder.size());
+ assert(Builder.size() == SubrecordStart + 8 && "wrong continuation size");
+ assert(getLastContinuationSize() < 65535 && "segment too big");
+
+ // Start a new list record of the appropriate kind, and copy the previous
+ // subrecord into place.
+ Builder.writeTypeRecordKind(Kind);
+ Builder.writeBytes(SubrecordCopy);
+ }
+
+ SubrecordStart = Builder.size();
+}
+
+TypeIndex ListRecordBuilder::writeListRecord(TypeTableBuilder &Table) {
+ // Get the continuation segments as a reversed vector of StringRefs for
+ // convenience.
+ SmallVector<StringRef, 1> Segments;
+ StringRef Data = str();
+ size_t LastEnd = 0;
+ for (size_t SegEnd : ContinuationOffsets) {
+ Segments.push_back(Data.slice(LastEnd, SegEnd));
+ LastEnd = SegEnd;
+ }
+ Segments.push_back(Data.slice(LastEnd, Builder.size()));
+
+ // Pop the last record off and emit it directly.
+ StringRef LastRec = Segments.pop_back_val();
+ TypeIndex ContinuationIndex = Table.writeRecord(LastRec);
+
+ // Emit each record with a continuation in reverse order, so that each one
+ // references the previous record.
+ for (StringRef Rec : reverse(Segments)) {
+ assert(*reinterpret_cast<const ulittle16_t *>(Rec.data()) ==
+ unsigned(Kind));
+ ulittle32_t *ContinuationPtr =
+ reinterpret_cast<ulittle32_t *>(const_cast<char *>(Rec.end())) - 1;
+ *ContinuationPtr = ContinuationIndex.getIndex();
+ ContinuationIndex = Table.writeRecord(Rec);
+ }
+ return ContinuationIndex;
}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
index 316bbb43a11..2ff91e727ee 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
@@ -195,6 +195,8 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
case ename: \
return #name;
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+ case LF_FIELDLIST:
+ return "FieldList";
default:
break;
}
@@ -214,6 +216,9 @@ Error CVTypeDumper::visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {
}
Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
+ if (Record.Type == LF_FIELDLIST)
+ Name = "<field list>";
+
// Always record some name for every type, even if Name is empty. CVUDTNames
// is indexed by type index, and must have one entry for every type.
recordType(Name);
@@ -612,6 +617,12 @@ Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
return Error::success();
}
+Error CVTypeDumper::visitListContinuation(ListContinuationRecord &Cont) {
+ DictScope S(*W, "ListContinuation");
+ printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
+ return Error::success();
+}
+
StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
if (TI.isNoneType())
return "<no type>";
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
index cc09abcd988..40f963fe25a 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
@@ -365,6 +365,14 @@ VirtualBaseClassRecord::deserialize(TypeRecordKind Kind,
Offset, Index);
}
+ErrorOr<ListContinuationRecord>
+ListContinuationRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ CV_DESERIALIZE(Data, L);
+ return ListContinuationRecord(L->ContinuationIndex);
+}
+
//===----------------------------------------------------------------------===//
// Type index remapping
//===----------------------------------------------------------------------===//
@@ -556,3 +564,7 @@ bool VirtualBaseClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
Success &= remapIndex(IndexMap, VBPtrType);
return Success;
}
+
+bool ListContinuationRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
+ return remapIndex(IndexMap, ContinuationIndex);
+}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
index 7ac9581db3f..647538ee8ce 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
@@ -267,9 +267,7 @@ TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
}
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());
+ return FieldList.writeListRecord(*this);
}
TypeIndex TypeTableBuilder::writeMethodOverloadList(
OpenPOWER on IntegriCloud