Skip to content

Commit c3a1207

Browse files
Merge pull request #7908 from rastogishubham/ExperimentMCCASStable
Cherry-pick PR #7811 to stable/20230725
2 parents 8be112b + 43596f4 commit c3a1207

File tree

4 files changed

+132
-121
lines changed

4 files changed

+132
-121
lines changed

llvm/include/llvm/MCCAS/MCCASObjectV1.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ CASV1_SIMPLE_DATA_REF(DebugAbbrevUnoptRef, mc:debug_abbrev_unopt)
2525
CASV1_SIMPLE_DATA_REF(DistinctDebugLineRef, mc:debug_line_distinct_data)
2626
CASV1_SIMPLE_DATA_REF(DIEAbbrevRef, mc:debug_DIE_abbrev)
2727
CASV1_SIMPLE_DATA_REF(DIEDistinctDataRef, mc:debug_DIE_distinct_data)
28+
CASV1_SIMPLE_DATA_REF(DIEDataRef, mc:debug_DIE_data)
2829
CASV1_SIMPLE_DATA_REF(AddendsRef, mc:addends)
2930

3031
#undef CASV1_SIMPLE_DATA_REF
@@ -41,6 +42,7 @@ CASV1_SIMPLE_GROUP_REF(SymbolTableRef, mc:symbol_table)
4142
CASV1_SIMPLE_GROUP_REF(DebugStringSectionRef, mc:debug_string_section)
4243
CASV1_SIMPLE_GROUP_REF(DIEAbbrevSetRef, mc:debug_DIE_abbrev_set)
4344
CASV1_SIMPLE_GROUP_REF(DIETopLevelRef, mc:debug_DIE_top_level)
45+
CASV1_SIMPLE_GROUP_REF(DIEDedupeTopLevelRef, mc:debug_DIE_Dedupe_top_level)
4446

4547
#undef CASV1_SIMPLE_GROUP_REF
4648
#endif /* CASV1_SIMPLE_GPOUP_REF */

llvm/include/llvm/MCCAS/MCCASObjectV1.h

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -681,44 +681,10 @@ class DebugInfoSectionRef : public SpecificRef<DebugInfoSectionRef> {
681681
explicit DebugInfoSectionRef(SpecificRefT Ref) : SpecificRefT(Ref) {}
682682
};
683683

684-
class DIEDataRef : public SpecificRef<DIEDataRef> {
685-
using SpecificRefT = SpecificRef<DIEDataRef>;
686-
friend class SpecificRef<DIEDataRef>;
687-
688-
public:
689-
static constexpr StringLiteral KindString = "mc:debug_DIE_data";
690-
static Expected<DIEDataRef> create(MCCASBuilder &MB,
691-
ArrayRef<cas::ObjectRef> Children,
692-
ArrayRef<char> Contents);
693-
694-
static Expected<DIEDataRef> get(Expected<MCObjectProxy> Ref) {
695-
auto Specific = SpecificRefT::getSpecific(std::move(Ref));
696-
if (!Specific)
697-
return Specific.takeError();
698-
return DIEDataRef(*Specific);
699-
}
700-
static Expected<DIEDataRef> get(const MCSchema &Schema, cas::ObjectRef ID) {
701-
return get(Schema.get(ID));
702-
}
703-
static std::optional<DIEDataRef> Cast(MCObjectProxy Ref) {
704-
auto Specific = SpecificRefT::Cast(Ref);
705-
if (!Specific)
706-
return std::nullopt;
707-
return DIEDataRef(*Specific);
708-
}
709-
Expected<uint64_t> materialize(MCCASReader &Reader,
710-
ArrayRef<char> AbbrevSectionContents,
711-
ArrayRef<uint32_t> SecOffsetVals,
712-
raw_ostream *Stream = nullptr) const;
713-
714-
private:
715-
explicit DIEDataRef(SpecificRefT Ref) : SpecificRefT(Ref) {}
716-
};
717-
718684
struct LoadedDIETopLevel {
719685
SmallVector<StringRef, 0> AbbrevEntries;
720686
DIEDistinctDataRef DistinctData;
721-
DIEDataRef RootDIE;
687+
DIEDedupeTopLevelRef RootDIE;
722688
};
723689

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

llvm/lib/MCCAS/MCCASObjectV1.cpp

Lines changed: 128 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ Error MCSchema::fillCache() {
170170
PaddingRef::KindString,
171171
MCAssemblerRef::KindString,
172172
DebugInfoSectionRef::KindString,
173-
DIEDataRef::KindString,
174173
#define CASV1_SIMPLE_DATA_REF(RefName, IdentifierName) RefName::KindString,
175174
#define CASV1_SIMPLE_GROUP_REF(RefName, IdentifierName) RefName::KindString,
176175
#define MCFRAGMENT_NODE_REF(MCFragmentName, MCEnumName, MCEnumIdentifier) \
@@ -1881,16 +1880,12 @@ Error MCCASBuilder::createDebugAbbrevSection() {
18811880
/// Helper class to create DIEDataRefs by keeping track of references to
18821881
/// children blocks.
18831882
struct DIEDataWriter : public DataWriter {
1884-
/// Add `CASObj` to the list of children of the DIE being created.
1885-
void addRef(DIEDataRef CASObj) { Children.push_back(CASObj.getRef()); }
18861883

18871884
/// Saves the main data stream and any children to a new DIEDataRef node.
18881885
Expected<DIEDataRef> getCASNode(MCCASBuilder &CASBuilder) {
1889-
return DIEDataRef::create(CASBuilder, Children, Data);
1886+
auto Ref = DIEDataRef::create(CASBuilder, toStringRef(Data));
1887+
return Ref;
18901888
}
1891-
1892-
private:
1893-
SmallVector<cas::ObjectRef> Children;
18941889
};
18951890

18961891
/// Helper class to create DIEDistinctDataRefs.
@@ -1966,13 +1961,15 @@ struct DIEToCASConverter {
19661961
ArrayRef<char> DebugInfoData;
19671962
MCCASBuilder &CASBuilder;
19681963

1969-
Expected<DIEDataRef> convertInNewDIEBlock(DWARFDie DIE,
1970-
DistinctDataWriter &DistinctWriter,
1971-
AbbrevSetWriter &AbbrevWriter);
1964+
Error convertInNewDIEBlock(
1965+
DWARFDie DIE, DistinctDataWriter &DistinctWriter,
1966+
AbbrevSetWriter &AbbrevWriter,
1967+
SmallVectorImpl<std::unique_ptr<DIEDataWriter>> &DIEWriters);
19721968

1973-
Error convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
1974-
DistinctDataWriter &DistinctWriter,
1975-
AbbrevSetWriter &AbbrevWriter);
1969+
Error
1970+
convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
1971+
DistinctDataWriter &DistinctWriter, AbbrevSetWriter &AbbrevWriter,
1972+
SmallVectorImpl<std::unique_ptr<DIEDataWriter>> &DIEWriters);
19761973
};
19771974

19781975
Error InMemoryCASDWARFObject::partitionCUData(ArrayRef<char> DebugInfoData,
@@ -2906,14 +2903,13 @@ DIETopLevelRef::create(MCCASBuilder &MB, ArrayRef<cas::ObjectRef> Children) {
29062903
return get(B->build());
29072904
}
29082905

2909-
Expected<DIEDataRef> DIEDataRef::create(MCCASBuilder &MB,
2910-
ArrayRef<cas::ObjectRef> Children,
2911-
ArrayRef<char> Contents) {
2906+
Expected<DIEDedupeTopLevelRef>
2907+
DIEDedupeTopLevelRef::create(MCCASBuilder &MB,
2908+
ArrayRef<cas::ObjectRef> Children) {
29122909
Expected<Builder> B = Builder::startNode(MB.Schema, KindString);
29132910
if (!B)
29142911
return B.takeError();
29152912
append_range(B->Refs, Children);
2916-
append_range(B->Data, toStringRef(Contents));
29172913
return get(B->build());
29182914
}
29192915

@@ -2976,9 +2972,10 @@ static void writeDIEAttrs(DWARFDie &DIE, ArrayRef<char> DebugInfoData,
29762972
/// * Otherwise, abbreviation_index is an index into the list of references of a
29772973
/// DIEAbbrevSetRef block. In this case, raw_data should be interpreted
29782974
/// according to the corresponding DIEAbbrevRefs block.
2979-
Error DIEToCASConverter::convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
2980-
DistinctDataWriter &DistinctWriter,
2981-
AbbrevSetWriter &AbbrevWriter) {
2975+
Error DIEToCASConverter::convertImpl(
2976+
DWARFDie &DIE, DIEDataWriter &DIEWriter, DistinctDataWriter &DistinctWriter,
2977+
AbbrevSetWriter &AbbrevWriter,
2978+
SmallVectorImpl<std::unique_ptr<DIEDataWriter>> &DIEWriters) {
29822979
Expected<unsigned> MaybeAbbrevIndex =
29832980
AbbrevWriter.createAbbrevEntry(DIE, CASBuilder);
29842981
if (!MaybeAbbrevIndex)
@@ -2998,39 +2995,40 @@ Error DIEToCASConverter::convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
29982995
// FIXME: don't use recursion.
29992996
if (shouldCreateSeparateBlockFor(Child)) {
30002997
DistinctWriter.writeULEB128(getDIEInAnotherBlockMarker());
3001-
auto MaybeNode =
3002-
convertInNewDIEBlock(Child, DistinctWriter, AbbrevWriter);
3003-
if (!MaybeNode)
3004-
return MaybeNode.takeError();
3005-
DIEWriter.addRef(*MaybeNode);
2998+
if (auto E = convertInNewDIEBlock(Child, DistinctWriter, AbbrevWriter,
2999+
DIEWriters))
3000+
return E;
30063001
continue;
30073002
}
3008-
3009-
if (auto E = convertImpl(Child, DIEWriter, DistinctWriter, AbbrevWriter))
3003+
if (auto E = convertImpl(Child, DIEWriter, DistinctWriter, AbbrevWriter,
3004+
DIEWriters))
30103005
return E;
30113006
}
30123007
return Error::success();
30133008
}
30143009

3015-
Expected<DIEDataRef>
3016-
DIEToCASConverter::convertInNewDIEBlock(DWARFDie DIE,
3017-
DistinctDataWriter &DistinctWriter,
3018-
AbbrevSetWriter &AbbrevWriter) {
3019-
DIEDataWriter DIEWriter;
3020-
if (auto E = convertImpl(DIE, DIEWriter, DistinctWriter, AbbrevWriter))
3021-
return std::move(E);
3022-
return DIEWriter.getCASNode(CASBuilder);
3010+
Error DIEToCASConverter::convertInNewDIEBlock(
3011+
DWARFDie DIE, DistinctDataWriter &DistinctWriter,
3012+
AbbrevSetWriter &AbbrevWriter,
3013+
SmallVectorImpl<std::unique_ptr<DIEDataWriter>> &DIEWriters) {
3014+
auto DIEWriter = std::make_unique<DIEDataWriter>();
3015+
DIEWriters.push_back(std::move(DIEWriter));
3016+
if (auto E = convertImpl(DIE, *DIEWriters.back(), DistinctWriter,
3017+
AbbrevWriter, DIEWriters))
3018+
return E;
3019+
return Error::success();
30233020
}
30243021

30253022
Expected<DIETopLevelRef>
30263023
DIEToCASConverter::convert(DWARFDie DIE, ArrayRef<char> HeaderData,
30273024
AbbrevSetWriter &AbbrevWriter) {
30283025
DistinctDataWriter DistinctWriter;
30293026
DistinctWriter.writeData(HeaderData);
3030-
Expected<DIEDataRef> MaybeDIE =
3031-
convertInNewDIEBlock(DIE, DistinctWriter, AbbrevWriter);
3032-
if (!MaybeDIE)
3033-
return MaybeDIE.takeError();
3027+
SmallVector<std::unique_ptr<DIEDataWriter>> DIEWriters;
3028+
if (Error E =
3029+
convertInNewDIEBlock(DIE, DistinctWriter, AbbrevWriter, DIEWriters))
3030+
return std::move(E);
3031+
30343032
Expected<DIEAbbrevSetRef> MaybeAbbrevSet =
30353033
AbbrevWriter.endAbbrevSet(CASBuilder);
30363034
if (!MaybeAbbrevSet)
@@ -3039,8 +3037,21 @@ DIEToCASConverter::convert(DWARFDie DIE, ArrayRef<char> HeaderData,
30393037
DistinctWriter.getCASNode(CASBuilder);
30403038
if (!MaybeDistinct)
30413039
return MaybeDistinct.takeError();
3040+
3041+
SmallVector<cas::ObjectRef> DIERefs;
3042+
DIERefs.reserve(DIEWriters.size());
3043+
for (auto &Writer : DIEWriters) {
3044+
Expected<DIEDataRef> DIERef = Writer->getCASNode(CASBuilder);
3045+
if (!DIERef)
3046+
return DIERef.takeError();
3047+
DIERefs.push_back(DIERef->getRef());
3048+
}
3049+
3050+
auto TopDIERef = DIEDedupeTopLevelRef::create(CASBuilder, DIERefs);
3051+
if (!TopDIERef)
3052+
return TopDIERef.takeError();
30423053
SmallVector<cas::ObjectRef, 3> Refs{
3043-
MaybeDIE->getRef(), MaybeAbbrevSet->getRef(), MaybeDistinct->getRef()};
3054+
TopDIERef->getRef(), MaybeAbbrevSet->getRef(), MaybeDistinct->getRef()};
30443055
return DIETopLevelRef::create(CASBuilder, Refs);
30453056
}
30463057

@@ -3052,8 +3063,8 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
30523063
"TopLevelRef is expected to have three references");
30533064

30543065
const MCSchema &Schema = TopLevelRef.getSchema();
3055-
Expected<DIEDataRef> RootDIE =
3056-
DIEDataRef::get(Schema, TopLevelRef.getReference(0));
3066+
Expected<DIEDedupeTopLevelRef> RootDIE =
3067+
DIEDedupeTopLevelRef::get(Schema, TopLevelRef.getReference(0));
30573068
Expected<DIEAbbrevSetRef> AbbrevSet =
30583069
DIEAbbrevSetRef::get(Schema, TopLevelRef.getReference(1));
30593070
Expected<DIEDistinctDataRef> DistinctData =
@@ -3075,9 +3086,8 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
30753086
}
30763087

30773088
struct DIEVisitor {
3078-
Error visitDIERef(DIEDataRef Ref);
3079-
Error visitDIERef(BinaryStreamReader &DataReader, unsigned AbbrevIdx,
3080-
StringRef DIEData, ArrayRef<DIEDataRef> &DIEChildrenStack);
3089+
Error visitDIERef(DIEDedupeTopLevelRef Ref);
3090+
Error visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack);
30813091
Error visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
30823092
BinaryStreamReader &Reader, StringRef DIEData);
30833093

@@ -3143,67 +3153,99 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
31433153
return AbbrevEntryReader(AbbrevData);
31443154
}
31453155

3146-
Error DIEVisitor::visitDIERef(BinaryStreamReader &DataReader,
3147-
unsigned AbbrevIdx, StringRef DIEData,
3148-
ArrayRef<DIEDataRef> &DIEChildrenStack) {
3149-
AbbrevEntryReader AbbrevReader =
3150-
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
3151-
3152-
if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag())
3153-
StartTagCallback(*MaybeTag, AbbrevIdx);
3154-
else
3155-
return MaybeTag.takeError();
3156+
/// Restores the state of the \p Reader and \p Data
3157+
/// arguments to a previous state. The algorithm in visitDIERefs is an iterative
3158+
/// implementation of a Depth First Search, and this function is used to
3159+
/// simulate a return from a recursive callback, by restoring the locals to a
3160+
/// previous stack frame.
3161+
static void popStack(BinaryStreamReader &Reader, StringRef &Data,
3162+
std::stack<std::pair<StringRef, unsigned>> &StackOfNodes) {
3163+
auto DataAndOffset = StackOfNodes.top();
3164+
Reader = BinaryStreamReader(DataAndOffset.first, support::endianness::little);
3165+
Data = DataAndOffset.first;
3166+
Reader.setOffset(DataAndOffset.second);
3167+
StackOfNodes.pop();
3168+
}
3169+
3170+
// Visit DIERef CAS objects and materialize them.
3171+
Error DIEVisitor::visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack) {
3172+
3173+
std::stack<std::pair<StringRef, unsigned>> StackOfNodes;
3174+
auto Data = DIEChildrenStack.empty() ? StringRef()
3175+
: DIEChildrenStack.front().getData();
3176+
BinaryStreamReader Reader(Data, support::endianness::little);
3177+
3178+
while (!DistinctReader.empty()) {
3179+
3180+
Expected<uint64_t> MaybeAbbrevIdx = readAbbrevIdx(DistinctReader);
3181+
if (!MaybeAbbrevIdx)
3182+
return MaybeAbbrevIdx.takeError();
3183+
auto AbbrevIdx = *MaybeAbbrevIdx;
3184+
3185+
// If we see a EndOfDIESiblingsMarker, we know that this sequence of
3186+
// Children has no more siblings and we need to pop the StackOfNodes and
3187+
// continue materialization of the parent's siblings that may exist.
3188+
if (AbbrevIdx == getEndOfDIESiblingsMarker()) {
3189+
EndTagCallback(true /*HadChildren*/);
3190+
if (!StackOfNodes.empty() && Reader.empty())
3191+
popStack(Reader, Data, StackOfNodes);
3192+
continue;
3193+
}
31563194

3157-
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3158-
if (!MaybeHasChildren)
3159-
return MaybeHasChildren.takeError();
3195+
// If we see a DIEInAnotherBlockMarker, we know that the next DIE is in
3196+
// another CAS Block, we have to push the current CAS Object on the stack,
3197+
// and materialize the next DIE from the DIEChildrenStack.
3198+
if (AbbrevIdx == getDIEInAnotherBlockMarker()) {
3199+
StackOfNodes.push(std::make_pair(Data, Reader.getOffset()));
3200+
DIEChildrenStack = DIEChildrenStack.drop_front();
3201+
Data = DIEChildrenStack.front().getData();
3202+
NewBlockCallback(DIEChildrenStack.front().getID().toString());
3203+
Reader = BinaryStreamReader(Data, support::endianness::little);
3204+
continue;
3205+
}
31603206

3161-
if (auto E = visitDIEAttrs(AbbrevReader, DataReader, DIEData))
3162-
return E;
3207+
// If we have a legitimate AbbrevIdx, materialize the current DIE.
3208+
AbbrevEntryReader AbbrevReader =
3209+
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
31633210

3164-
if (!*MaybeHasChildren) {
3165-
EndTagCallback(false /*HadChildren*/);
3166-
return Error::success();
3167-
}
3211+
if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag())
3212+
StartTagCallback(*MaybeTag, AbbrevIdx);
3213+
else
3214+
return MaybeTag.takeError();
31683215

3169-
while (true) {
3170-
Expected<uint64_t> ChildAbbrevIdx = readAbbrevIdx(DistinctReader);
3171-
if (!ChildAbbrevIdx)
3172-
return ChildAbbrevIdx.takeError();
3216+
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3217+
if (!MaybeHasChildren)
3218+
return MaybeHasChildren.takeError();
31733219

3174-
if (*ChildAbbrevIdx == getEndOfDIESiblingsMarker())
3175-
break;
3220+
if (auto E = visitDIEAttrs(AbbrevReader, Reader, Data))
3221+
return E;
31763222

3177-
if (*ChildAbbrevIdx == getDIEInAnotherBlockMarker()) {
3178-
if (auto E = visitDIERef(DIEChildrenStack.front()))
3179-
return E;
3180-
DIEChildrenStack = DIEChildrenStack.drop_front();
3181-
continue;
3223+
// If the current DIE doesn't have any children, the current CAS Object will
3224+
// not contain any more data, pop the stack to continue materializing its
3225+
// parent's siblings that may exist.
3226+
if (!*MaybeHasChildren) {
3227+
if (!StackOfNodes.empty() && Reader.empty())
3228+
popStack(Reader, Data, StackOfNodes);
3229+
EndTagCallback(false /*HadChildren*/);
31823230
}
3183-
3184-
if (auto E =
3185-
visitDIERef(DataReader, *ChildAbbrevIdx, DIEData, DIEChildrenStack))
3186-
return E;
31873231
}
3188-
3189-
EndTagCallback(true /*HadChildren*/);
31903232
return Error::success();
31913233
}
31923234

3193-
Error DIEVisitor::visitDIERef(DIEDataRef StartDIERef) {
3194-
StringRef DIEData = StartDIERef.getData();
3195-
BinaryStreamReader DataReader(DIEData, support::endianness::little);
3235+
Error DIEVisitor::visitDIERef(DIEDedupeTopLevelRef StartDIERef) {
31963236

3237+
auto Offset = DistinctReader.getOffset();
31973238
Expected<uint64_t> MaybeAbbrevIdx = readAbbrevIdx(DistinctReader);
31983239
if (!MaybeAbbrevIdx)
31993240
return MaybeAbbrevIdx.takeError();
32003241
auto AbbrevIdx = *MaybeAbbrevIdx;
3201-
32023242
// The tag of a fresh block must be meaningful, otherwise we wouldn't have
32033243
// made a new block.
32043244
assert(AbbrevIdx != getEndOfDIESiblingsMarker() &&
32053245
AbbrevIdx != getDIEInAnotherBlockMarker());
32063246

3247+
DistinctReader.setOffset(Offset);
3248+
32073249
NewBlockCallback(StartDIERef.getID().toString());
32083250

32093251
Expected<SmallVector<DIEDataRef>> MaybeChildren =
@@ -3212,7 +3254,7 @@ Error DIEVisitor::visitDIERef(DIEDataRef StartDIERef) {
32123254
return MaybeChildren.takeError();
32133255
ArrayRef<DIEDataRef> Children = *MaybeChildren;
32143256

3215-
return visitDIERef(DataReader, AbbrevIdx, DIEData, Children);
3257+
return visitDIERef(Children);
32163258
}
32173259

32183260
Error mccasformats::v1::visitDebugInfo(

0 commit comments

Comments
 (0)