Skip to content

Commit 1312409

Browse files
Merge pull request swiftlang#7909 from rastogishubham/CachingMCCASStable
Cherry-pick PR swiftlang#7852 into stable/20230725
2 parents 3b15873 + c2a4ebb commit 1312409

File tree

1 file changed

+161
-33
lines changed

1 file changed

+161
-33
lines changed

llvm/lib/MCCAS/MCCASObjectV1.cpp

Lines changed: 161 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,11 +3086,48 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
30863086
}
30873087

30883088
struct DIEVisitor {
3089+
3090+
struct AbbrevContent {
3091+
dwarf::Attribute Attr;
3092+
dwarf::Form Form;
3093+
bool FormInDistinctData;
3094+
std::optional<uint8_t> FormSize;
3095+
};
3096+
3097+
struct AbbrevEntry {
3098+
dwarf::Tag Tag;
3099+
bool HasChildren;
3100+
SmallVector<AbbrevContent> AbbrevContents;
3101+
};
3102+
3103+
DIEVisitor() = delete;
3104+
3105+
DIEVisitor(ArrayRef<StringRef> AbbrevEntries,
3106+
BinaryStreamReader DistinctReader, StringRef DistinctData,
3107+
std::function<void(StringRef)> HeaderCallback,
3108+
std::function<void(dwarf::Tag, uint64_t)> StartTagCallback,
3109+
std::function<void(dwarf::Attribute, dwarf::Form, StringRef, bool)>
3110+
AttrCallback,
3111+
std::function<void(bool)> EndTagCallback,
3112+
std::function<void(StringRef)> NewBlockCallback)
3113+
: AbbrevEntries(AbbrevEntries), DistinctReader(DistinctReader),
3114+
DistinctData(DistinctData), HeaderCallback(HeaderCallback),
3115+
StartTagCallback(StartTagCallback), AttrCallback(AttrCallback),
3116+
EndTagCallback(EndTagCallback), NewBlockCallback(NewBlockCallback) {
3117+
AbbrevEntryCache.reserve(AbbrevEntries.size());
3118+
for (unsigned I = 0; I < AbbrevEntries.size(); I++) {
3119+
if (Error E = materializeAbbrevDIE(encodeAbbrevIndex(I)))
3120+
report_fatal_error(std::move(E));
3121+
}
3122+
}
3123+
30893124
Error visitDIERef(DIEDedupeTopLevelRef Ref);
30903125
Error visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack);
3091-
Error visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
3092-
BinaryStreamReader &Reader, StringRef DIEData);
3126+
Error visitDIEAttrs(BinaryStreamReader &DataReader, StringRef DIEData,
3127+
ArrayRef<AbbrevContent> DIEContents);
3128+
Error materializeAbbrevDIE(unsigned AbbrevIdx);
30933129

3130+
SmallVector<AbbrevEntry> AbbrevEntryCache;
30943131
ArrayRef<StringRef> AbbrevEntries;
30953132
BinaryStreamReader DistinctReader;
30963133
StringRef DistinctData;
@@ -3103,38 +3140,31 @@ struct DIEVisitor {
31033140
std::function<void(StringRef)> NewBlockCallback;
31043141
};
31053142

3106-
Error DIEVisitor::visitDIEAttrs(AbbrevEntryReader &AbbrevReader,
3107-
BinaryStreamReader &DataReader,
3108-
StringRef DIEData) {
3143+
Error DIEVisitor::visitDIEAttrs(BinaryStreamReader &DataReader,
3144+
StringRef DIEData,
3145+
ArrayRef<AbbrevContent> DIEContents) {
31093146
constexpr auto IsLittleEndian = true;
31103147
constexpr auto AddrSize = 8;
31113148
constexpr auto FormParams =
31123149
dwarf::FormParams{4 /*Version*/, AddrSize, dwarf::DwarfFormat::DWARF32};
31133150

3114-
while (true) {
3115-
Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr();
3116-
if (!Attr)
3117-
return Attr.takeError();
3118-
if (*Attr == getEndOfAttributesMarker())
3119-
break;
3120-
3121-
Expected<dwarf::Form> Form = AbbrevReader.readForm();
3122-
if (!Form)
3123-
return Form.takeError();
3124-
3125-
bool DataInDistinct = doesntDedup(*Form, *Attr);
3151+
for (auto Contents : DIEContents) {
3152+
bool DataInDistinct = Contents.FormInDistinctData;
31263153
auto &ReaderForData = DataInDistinct ? DistinctReader : DataReader;
31273154
StringRef DataToUse = DataInDistinct ? DistinctData : DIEData;
31283155
Expected<uint64_t> FormSize =
3129-
getFormSize(*Form, FormParams, DataToUse, ReaderForData.getOffset(),
3130-
IsLittleEndian, AddrSize);
3156+
Contents.FormSize
3157+
? *Contents.FormSize
3158+
: getFormSize(Contents.Form, FormParams, DataToUse,
3159+
ReaderForData.getOffset(), IsLittleEndian, AddrSize);
31313160
if (!FormSize)
31323161
return FormSize.takeError();
31333162

31343163
ArrayRef<char> RawBytes;
31353164
if (auto E = ReaderForData.readArray(RawBytes, *FormSize))
31363165
return E;
3137-
AttrCallback(*Attr, *Form, toStringRef(RawBytes), DataInDistinct);
3166+
AttrCallback(Contents.Attr, Contents.Form, toStringRef(RawBytes),
3167+
DataInDistinct);
31383168
}
31393169
return Error::success();
31403170
}
@@ -3153,6 +3183,111 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
31533183
return AbbrevEntryReader(AbbrevData);
31543184
}
31553185

3186+
static std::optional<uint8_t> getNonULEBFormSize(dwarf::Form Form,
3187+
dwarf::FormParams FP) {
3188+
switch (Form) {
3189+
case dwarf::DW_FORM_addr:
3190+
return FP.AddrSize;
3191+
case dwarf::DW_FORM_ref_addr:
3192+
return FP.getRefAddrByteSize();
3193+
case dwarf::DW_FORM_exprloc:
3194+
case dwarf::DW_FORM_block:
3195+
case dwarf::DW_FORM_block1:
3196+
case dwarf::DW_FORM_block2:
3197+
case dwarf::DW_FORM_block4:
3198+
case dwarf::DW_FORM_sdata:
3199+
case dwarf::DW_FORM_udata:
3200+
case dwarf::DW_FORM_ref_udata:
3201+
case dwarf::DW_FORM_ref4_cas:
3202+
case dwarf::DW_FORM_strp_cas:
3203+
case dwarf::DW_FORM_rnglistx:
3204+
case dwarf::DW_FORM_loclistx:
3205+
case dwarf::DW_FORM_GNU_addr_index:
3206+
case dwarf::DW_FORM_GNU_str_index:
3207+
case dwarf::DW_FORM_addrx:
3208+
case dwarf::DW_FORM_strx:
3209+
case dwarf::DW_FORM_LLVM_addrx_offset:
3210+
case dwarf::DW_FORM_string:
3211+
case dwarf::DW_FORM_indirect:
3212+
return std::nullopt;
3213+
3214+
case dwarf::DW_FORM_implicit_const:
3215+
case dwarf::DW_FORM_flag_present:
3216+
return 0;
3217+
case dwarf::DW_FORM_data1:
3218+
case dwarf::DW_FORM_ref1:
3219+
case dwarf::DW_FORM_flag:
3220+
case dwarf::DW_FORM_strx1:
3221+
case dwarf::DW_FORM_addrx1:
3222+
return 1;
3223+
case dwarf::DW_FORM_data2:
3224+
case dwarf::DW_FORM_ref2:
3225+
case dwarf::DW_FORM_strx2:
3226+
case dwarf::DW_FORM_addrx2:
3227+
return 2;
3228+
case dwarf::DW_FORM_strx3:
3229+
return 3;
3230+
case dwarf::DW_FORM_data4:
3231+
case dwarf::DW_FORM_ref4:
3232+
case dwarf::DW_FORM_ref_sup4:
3233+
case dwarf::DW_FORM_strx4:
3234+
case dwarf::DW_FORM_addrx4:
3235+
return 4;
3236+
case dwarf::DW_FORM_ref_sig8:
3237+
case dwarf::DW_FORM_data8:
3238+
case dwarf::DW_FORM_ref8:
3239+
case dwarf::DW_FORM_ref_sup8:
3240+
return 8;
3241+
case dwarf::DW_FORM_data16:
3242+
return 16;
3243+
case dwarf::DW_FORM_strp:
3244+
case dwarf::DW_FORM_sec_offset:
3245+
case dwarf::DW_FORM_GNU_ref_alt:
3246+
case dwarf::DW_FORM_GNU_strp_alt:
3247+
case dwarf::DW_FORM_line_strp:
3248+
case dwarf::DW_FORM_strp_sup:
3249+
return FP.getDwarfOffsetByteSize();
3250+
case dwarf::DW_FORM_addrx3:
3251+
case dwarf::DW_FORM_lo_user:
3252+
llvm_unreachable("usupported form");
3253+
break;
3254+
}
3255+
}
3256+
3257+
Error DIEVisitor::materializeAbbrevDIE(unsigned AbbrevIdx) {
3258+
constexpr auto AddrSize = 8;
3259+
constexpr auto FormParams =
3260+
dwarf::FormParams{4 /*Version*/, AddrSize, dwarf::DwarfFormat::DWARF32};
3261+
3262+
AbbrevEntryReader AbbrevReader =
3263+
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
3264+
Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag();
3265+
if (!MaybeTag)
3266+
return MaybeTag.takeError();
3267+
3268+
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3269+
if (!MaybeHasChildren)
3270+
return MaybeHasChildren.takeError();
3271+
3272+
SmallVector<AbbrevContent> AbbrevVector;
3273+
while (true) {
3274+
Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr();
3275+
if (!Attr)
3276+
return Attr.takeError();
3277+
if (*Attr == getEndOfAttributesMarker())
3278+
break;
3279+
3280+
Expected<dwarf::Form> Form = AbbrevReader.readForm();
3281+
if (!Form)
3282+
return Form.takeError();
3283+
AbbrevVector.push_back({*Attr, *Form, doesntDedup(*Form, *Attr),
3284+
getNonULEBFormSize(*Form, FormParams)});
3285+
}
3286+
AbbrevEntryCache.push_back(
3287+
{*MaybeTag, *MaybeHasChildren, std::move(AbbrevVector)});
3288+
return Error::success();
3289+
}
3290+
31563291
/// Restores the state of the \p Reader and \p Data
31573292
/// arguments to a previous state. The algorithm in visitDIERefs is an iterative
31583293
/// implementation of a Depth First Search, and this function is used to
@@ -3205,25 +3340,18 @@ Error DIEVisitor::visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack) {
32053340
}
32063341

32073342
// If we have a legitimate AbbrevIdx, materialize the current DIE.
3208-
AbbrevEntryReader AbbrevReader =
3209-
getAbbrevEntryReader(AbbrevEntries, AbbrevIdx);
3210-
3211-
if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag())
3212-
StartTagCallback(*MaybeTag, AbbrevIdx);
3213-
else
3214-
return MaybeTag.takeError();
3215-
3216-
Expected<bool> MaybeHasChildren = AbbrevReader.readHasChildren();
3217-
if (!MaybeHasChildren)
3218-
return MaybeHasChildren.takeError();
3343+
auto &AbbrevEntryCacheVal =
3344+
AbbrevEntryCache[decodeAbbrevIndexAsAbbrevSetIdx(AbbrevIdx)];
3345+
StartTagCallback(AbbrevEntryCacheVal.Tag, AbbrevIdx);
32193346

3220-
if (auto E = visitDIEAttrs(AbbrevReader, Reader, Data))
3347+
if (auto E =
3348+
visitDIEAttrs(Reader, Data, AbbrevEntryCacheVal.AbbrevContents))
32213349
return E;
32223350

32233351
// If the current DIE doesn't have any children, the current CAS Object will
32243352
// not contain any more data, pop the stack to continue materializing its
32253353
// parent's siblings that may exist.
3226-
if (!*MaybeHasChildren) {
3354+
if (!AbbrevEntryCacheVal.HasChildren) {
32273355
if (!StackOfNodes.empty() && Reader.empty())
32283356
popStack(Reader, Data, StackOfNodes);
32293357
EndTagCallback(false /*HadChildren*/);

0 commit comments

Comments
 (0)