Skip to content

Commit 038c057

Browse files
Modify MCCAS debug info section layout.
With this change, the layout of the debug info section in MCCAS has been changed. Now, if there is a DIE that can be split off into it's own CAS block, we do not attach it to its parent CAS block as a reference, it gets added as a neighbor instead. This reduces the dependencies between CAS blocks and increases chances of deduplication if a DIEDataRef doesn't dedupe, by making sure it's parent will still dedupe. This change also re-writes the materialization of the debug info section to be iterative, rather than recursive.
1 parent 2a479c0 commit 038c057

File tree

3 files changed

+128
-77
lines changed

3 files changed

+128
-77
lines changed

llvm/include/llvm/MCCAS/MCCASObjectV1.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ class DIEDataRef : public SpecificRef<DIEDataRef> {
718718
struct LoadedDIETopLevel {
719719
SmallVector<StringRef, 0> AbbrevEntries;
720720
DIEDistinctDataRef DistinctData;
721-
DIEDataRef RootDIE;
721+
DIEDedupeTopLevelRef RootDIE;
722722
};
723723

724724
/// Helper function to load the relevant information from a DIETopLevelRef:

llvm/lib/MCCAS/MCCASObjectV1.cpp

Lines changed: 126 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,7 +1893,9 @@ struct DIEDataWriter : public DataWriter {
18931893

18941894
/// Saves the main data stream and any children to a new DIEDataRef node.
18951895
Expected<DIEDataRef> getCASNode(MCCASBuilder &CASBuilder) {
1896-
return DIEDataRef::create(CASBuilder, Children, Data);
1896+
auto Ref = DIEDataRef::create(CASBuilder, Children, Data);
1897+
Data.clear();
1898+
return Ref;
18971899
}
18981900

18991901
private:
@@ -1973,13 +1975,15 @@ struct DIEToCASConverter {
19731975
ArrayRef<char> DebugInfoData;
19741976
MCCASBuilder &CASBuilder;
19751977

1976-
Expected<DIEDataRef> convertInNewDIEBlock(DWARFDie DIE,
1977-
DistinctDataWriter &DistinctWriter,
1978-
AbbrevSetWriter &AbbrevWriter);
1978+
Error convertInNewDIEBlock(
1979+
DWARFDie DIE, DistinctDataWriter &DistinctWriter,
1980+
AbbrevSetWriter &AbbrevWriter,
1981+
SmallVectorImpl<std::unique_ptr<DIEDataWriter>> &DIEWriters);
19791982

1980-
Error convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
1981-
DistinctDataWriter &DistinctWriter,
1982-
AbbrevSetWriter &AbbrevWriter);
1983+
Error
1984+
convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
1985+
DistinctDataWriter &DistinctWriter, AbbrevSetWriter &AbbrevWriter,
1986+
SmallVectorImpl<std::unique_ptr<DIEDataWriter>> &DIEWriters);
19831987
};
19841988

19851989
Error InMemoryCASDWARFObject::partitionCUData(ArrayRef<char> DebugInfoData,
@@ -2998,9 +3002,10 @@ static void writeDIEAttrs(DWARFDie &DIE, ArrayRef<char> DebugInfoData,
29983002
/// * Otherwise, abbreviation_index is an index into the list of references of a
29993003
/// DIEAbbrevSetRef block. In this case, raw_data should be interpreted
30003004
/// according to the corresponding DIEAbbrevRefs block.
3001-
Error DIEToCASConverter::convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
3002-
DistinctDataWriter &DistinctWriter,
3003-
AbbrevSetWriter &AbbrevWriter) {
3005+
Error DIEToCASConverter::convertImpl(
3006+
DWARFDie &DIE, DIEDataWriter &DIEWriter, DistinctDataWriter &DistinctWriter,
3007+
AbbrevSetWriter &AbbrevWriter,
3008+
SmallVectorImpl<std::unique_ptr<DIEDataWriter>> &DIEWriters) {
30043009
Expected<unsigned> MaybeAbbrevIndex =
30053010
AbbrevWriter.createAbbrevEntry(DIE, CASBuilder);
30063011
if (!MaybeAbbrevIndex)
@@ -3020,39 +3025,40 @@ Error DIEToCASConverter::convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
30203025
// FIXME: don't use recursion.
30213026
if (shouldCreateSeparateBlockFor(Child)) {
30223027
DistinctWriter.writeULEB128(getDIEInAnotherBlockMarker());
3023-
auto MaybeNode =
3024-
convertInNewDIEBlock(Child, DistinctWriter, AbbrevWriter);
3025-
if (!MaybeNode)
3026-
return MaybeNode.takeError();
3027-
DIEWriter.addRef(*MaybeNode);
3028+
if (auto E = convertInNewDIEBlock(Child, DistinctWriter, AbbrevWriter,
3029+
DIEWriters))
3030+
return E;
30283031
continue;
30293032
}
3030-
3031-
if (auto E = convertImpl(Child, DIEWriter, DistinctWriter, AbbrevWriter))
3033+
if (auto E = convertImpl(Child, DIEWriter, DistinctWriter, AbbrevWriter,
3034+
DIEWriters))
30323035
return E;
30333036
}
30343037
return Error::success();
30353038
}
30363039

3037-
Expected<DIEDataRef>
3038-
DIEToCASConverter::convertInNewDIEBlock(DWARFDie DIE,
3039-
DistinctDataWriter &DistinctWriter,
3040-
AbbrevSetWriter &AbbrevWriter) {
3041-
DIEDataWriter DIEWriter;
3042-
if (auto E = convertImpl(DIE, DIEWriter, DistinctWriter, AbbrevWriter))
3043-
return std::move(E);
3044-
return DIEWriter.getCASNode(CASBuilder);
3040+
Error DIEToCASConverter::convertInNewDIEBlock(
3041+
DWARFDie DIE, DistinctDataWriter &DistinctWriter,
3042+
AbbrevSetWriter &AbbrevWriter,
3043+
SmallVectorImpl<std::unique_ptr<DIEDataWriter>> &DIEWriters) {
3044+
auto DIEWriter = std::make_unique<DIEDataWriter>();
3045+
DIEWriters.push_back(std::move(DIEWriter));
3046+
if (auto E = convertImpl(DIE, *DIEWriters.back(), DistinctWriter,
3047+
AbbrevWriter, DIEWriters))
3048+
return E;
3049+
return Error::success();
30453050
}
30463051

30473052
Expected<DIETopLevelRef>
30483053
DIEToCASConverter::convert(DWARFDie DIE, ArrayRef<char> HeaderData,
30493054
AbbrevSetWriter &AbbrevWriter) {
30503055
DistinctDataWriter DistinctWriter;
30513056
DistinctWriter.writeData(HeaderData);
3052-
Expected<DIEDataRef> MaybeDIE =
3053-
convertInNewDIEBlock(DIE, DistinctWriter, AbbrevWriter);
3054-
if (!MaybeDIE)
3055-
return MaybeDIE.takeError();
3057+
SmallVector<std::unique_ptr<DIEDataWriter>> DIEWriters;
3058+
if (Error E =
3059+
convertInNewDIEBlock(DIE, DistinctWriter, AbbrevWriter, DIEWriters))
3060+
return std::move(E);
3061+
30563062
Expected<DIEAbbrevSetRef> MaybeAbbrevSet =
30573063
AbbrevWriter.endAbbrevSet(CASBuilder);
30583064
if (!MaybeAbbrevSet)
@@ -3061,8 +3067,21 @@ DIEToCASConverter::convert(DWARFDie DIE, ArrayRef<char> HeaderData,
30613067
DistinctWriter.getCASNode(CASBuilder);
30623068
if (!MaybeDistinct)
30633069
return MaybeDistinct.takeError();
3070+
3071+
SmallVector<cas::ObjectRef> DIERefs;
3072+
DIERefs.reserve(DIEWriters.size());
3073+
for (auto &Writer : DIEWriters) {
3074+
Expected<DIEDataRef> DIERef = Writer->getCASNode(CASBuilder);
3075+
if (!DIERef)
3076+
return DIERef.takeError();
3077+
DIERefs.push_back(DIERef->getRef());
3078+
}
3079+
3080+
auto TopDIERef = DIEDedupeTopLevelRef::create(CASBuilder, DIERefs);
3081+
if (!TopDIERef)
3082+
return TopDIERef.takeError();
30643083
SmallVector<cas::ObjectRef, 3> Refs{
3065-
MaybeDIE->getRef(), MaybeAbbrevSet->getRef(), MaybeDistinct->getRef()};
3084+
TopDIERef->getRef(), MaybeAbbrevSet->getRef(), MaybeDistinct->getRef()};
30663085
return DIETopLevelRef::create(CASBuilder, Refs);
30673086
}
30683087

@@ -3074,8 +3093,8 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
30743093
"TopLevelRef is expected to have three references");
30753094

30763095
const MCSchema &Schema = TopLevelRef.getSchema();
3077-
Expected<DIEDataRef> RootDIE =
3078-
DIEDataRef::get(Schema, TopLevelRef.getReference(0));
3096+
Expected<DIEDedupeTopLevelRef> RootDIE =
3097+
DIEDedupeTopLevelRef::get(Schema, TopLevelRef.getReference(0));
30793098
Expected<DIEAbbrevSetRef> AbbrevSet =
30803099
DIEAbbrevSetRef::get(Schema, TopLevelRef.getReference(1));
30813100
Expected<DIEDistinctDataRef> DistinctData =
@@ -3097,9 +3116,8 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
30973116
}
30983117

30993118
struct DIEVisitor {
3100-
Error visitDIERef(DIEDataRef Ref);
3101-
Error visitDIERef(BinaryStreamReader &DataReader, unsigned AbbrevIdx,
3102-
StringRef DIEData, ArrayRef<DIEDataRef> &DIEChildrenStack);
3119+
Error visitDIERef(DIEDedupeTopLevelRef Ref);
3120+
Error visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack);
31033121
Error visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
31043122
BinaryStreamReader &Reader, StringRef DIEData);
31053123

@@ -3165,67 +3183,99 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
31653183
return AbbrevEntryReader(AbbrevData);
31663184
}
31673185

3168-
Error DIEVisitor::visitDIERef(BinaryStreamReader &DataReader,
3169-
unsigned AbbrevIdx, StringRef DIEData,
3170-
ArrayRef<DIEDataRef> &DIEChildrenStack) {
3171-
AbbrevEntryReader AbbrevReader =
3172-
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
3173-
3174-
if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag())
3175-
StartTagCallback(*MaybeTag, AbbrevIdx);
3176-
else
3177-
return MaybeTag.takeError();
3186+
/// Restores the state of the \p Reader and \p Data
3187+
/// arguments to a previous state. The algorithm in visitDIERefs is an iterative
3188+
/// implementation of a Depth First Search, and this function is used to
3189+
/// simulate a return from a recursive callback, by restoring the locals to a
3190+
/// previous stack frame.
3191+
static void popStack(BinaryStreamReader &Reader, StringRef &Data,
3192+
std::stack<std::pair<StringRef, unsigned>> &StackOfNodes) {
3193+
auto DataAndOffset = StackOfNodes.top();
3194+
Reader = BinaryStreamReader(DataAndOffset.first, llvm::endianness::little);
3195+
Data = DataAndOffset.first;
3196+
Reader.setOffset(DataAndOffset.second);
3197+
StackOfNodes.pop();
3198+
}
3199+
3200+
// Visit DIERef CAS objects and materialize them.
3201+
Error DIEVisitor::visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack) {
3202+
3203+
std::stack<std::pair<StringRef, unsigned>> StackOfNodes;
3204+
auto Data = DIEChildrenStack.empty() ? StringRef()
3205+
: DIEChildrenStack.front().getData();
3206+
BinaryStreamReader Reader(Data, llvm::endianness::little);
3207+
3208+
while (!DistinctReader.empty()) {
3209+
3210+
Expected<uint64_t> MaybeAbbrevIdx = readAbbrevIdx(DistinctReader);
3211+
if (!MaybeAbbrevIdx)
3212+
return MaybeAbbrevIdx.takeError();
3213+
auto AbbrevIdx = *MaybeAbbrevIdx;
3214+
3215+
// If we see a EndOfDIESiblingsMarker, we know that this sequence of
3216+
// Children has no more siblings and we need to pop the StackOfNodes and
3217+
// continue materialization of the parent's siblings that may exist.
3218+
if (AbbrevIdx == getEndOfDIESiblingsMarker()) {
3219+
EndTagCallback(true /*HadChildren*/);
3220+
if (!StackOfNodes.empty() && Reader.empty())
3221+
popStack(Reader, Data, StackOfNodes);
3222+
continue;
3223+
}
31783224

3179-
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3180-
if (!MaybeHasChildren)
3181-
return MaybeHasChildren.takeError();
3225+
// If we see a DIEInAnotherBlockMarker, we know that the next DIE is in
3226+
// another CAS Block, we have to push the current CAS Object on the stack,
3227+
// and materialize the next DIE from the DIEChildrenStack.
3228+
if (AbbrevIdx == getDIEInAnotherBlockMarker()) {
3229+
StackOfNodes.push(std::make_pair(Data, Reader.getOffset()));
3230+
DIEChildrenStack = DIEChildrenStack.drop_front();
3231+
Data = DIEChildrenStack.front().getData();
3232+
NewBlockCallback(DIEChildrenStack.front().getID().toString());
3233+
Reader = BinaryStreamReader(Data, llvm::endianness::little);
3234+
continue;
3235+
}
31823236

3183-
if (auto E = visitDIEAttrs(AbbrevReader, DataReader, DIEData))
3184-
return E;
3237+
// If we have a legitimate AbbrevIdx, materialize the current DIE.
3238+
AbbrevEntryReader AbbrevReader =
3239+
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
31853240

3186-
if (!*MaybeHasChildren) {
3187-
EndTagCallback(false /*HadChildren*/);
3188-
return Error::success();
3189-
}
3241+
if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag())
3242+
StartTagCallback(*MaybeTag, AbbrevIdx);
3243+
else
3244+
return MaybeTag.takeError();
31903245

3191-
while (true) {
3192-
Expected<uint64_t> ChildAbbrevIdx = readAbbrevIdx(DistinctReader);
3193-
if (!ChildAbbrevIdx)
3194-
return ChildAbbrevIdx.takeError();
3246+
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3247+
if (!MaybeHasChildren)
3248+
return MaybeHasChildren.takeError();
31953249

3196-
if (*ChildAbbrevIdx == getEndOfDIESiblingsMarker())
3197-
break;
3250+
if (auto E = visitDIEAttrs(AbbrevReader, Reader, Data))
3251+
return E;
31983252

3199-
if (*ChildAbbrevIdx == getDIEInAnotherBlockMarker()) {
3200-
if (auto E = visitDIERef(DIEChildrenStack.front()))
3201-
return E;
3202-
DIEChildrenStack = DIEChildrenStack.drop_front();
3203-
continue;
3253+
// If the current DIE doesn't have any children, the current CAS Object will
3254+
// not contain any more data, pop the stack to continue materializing its
3255+
// parent's siblings that may exist.
3256+
if (!*MaybeHasChildren) {
3257+
if (!StackOfNodes.empty() && Reader.empty())
3258+
popStack(Reader, Data, StackOfNodes);
3259+
EndTagCallback(false /*HadChildren*/);
32043260
}
3205-
3206-
if (auto E =
3207-
visitDIERef(DataReader, *ChildAbbrevIdx, DIEData, DIEChildrenStack))
3208-
return E;
32093261
}
3210-
3211-
EndTagCallback(true /*HadChildren*/);
32123262
return Error::success();
32133263
}
32143264

3215-
Error DIEVisitor::visitDIERef(DIEDataRef StartDIERef) {
3216-
StringRef DIEData = StartDIERef.getData();
3217-
BinaryStreamReader DataReader(DIEData, endianness::little);
3265+
Error DIEVisitor::visitDIERef(DIEDedupeTopLevelRef StartDIERef) {
32183266

3267+
auto Offset = DistinctReader.getOffset();
32193268
Expected<uint64_t> MaybeAbbrevIdx = readAbbrevIdx(DistinctReader);
32203269
if (!MaybeAbbrevIdx)
32213270
return MaybeAbbrevIdx.takeError();
32223271
auto AbbrevIdx = *MaybeAbbrevIdx;
3223-
32243272
// The tag of a fresh block must be meaningful, otherwise we wouldn't have
32253273
// made a new block.
32263274
assert(AbbrevIdx != getEndOfDIESiblingsMarker() &&
32273275
AbbrevIdx != getDIEInAnotherBlockMarker());
32283276

3277+
DistinctReader.setOffset(Offset);
3278+
32293279
NewBlockCallback(StartDIERef.getID().toString());
32303280

32313281
Expected<SmallVector<DIEDataRef>> MaybeChildren =
@@ -3234,7 +3284,7 @@ Error DIEVisitor::visitDIERef(DIEDataRef StartDIERef) {
32343284
return MaybeChildren.takeError();
32353285
ArrayRef<DIEDataRef> Children = *MaybeChildren;
32363286

3237-
return visitDIERef(DataReader, AbbrevIdx, DIEData, Children);
3287+
return visitDIERef(Children);
32383288
}
32393289

32403290
Error mccasformats::v1::visitDebugInfo(

llvm/test/tools/llvm-cas-dump/basic_debug_test.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
; CHECK-NEXT: mc:padding llvmcas://{{.*}}
2929
; CHECK-NEXT: mc:debug_info_section llvmcas://{{.*}}
3030
; CHECK-NEXT: mc:debug_DIE_top_level llvmcas://{{.*}}
31+
; CHECK-NEXT: mc:debug_DIE_Dedupe_top_level llvmcas://{{.*}}
3132
; CHECK-NEXT: mc:debug_DIE_data llvmcas://{{.*}}
3233
; CHECK-NEXT: mc:debug_DIE_data llvmcas://{{.*}}
3334
; CHECK-NEXT: mc:debug_DIE_abbrev_set llvmcas://{{.*}}

0 commit comments

Comments
 (0)