@@ -3098,11 +3098,48 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
3098
3098
}
3099
3099
3100
3100
struct DIEVisitor {
3101
+
3102
+ struct AbbrevContent {
3103
+ dwarf::Attribute Attr;
3104
+ dwarf::Form Form;
3105
+ bool FormInDistinctData;
3106
+ std::optional<uint8_t > FormSize;
3107
+ };
3108
+
3109
+ struct AbbrevEntry {
3110
+ dwarf::Tag Tag;
3111
+ bool HasChildren;
3112
+ SmallVector<AbbrevContent> AbbrevContents;
3113
+ };
3114
+
3115
+ DIEVisitor () = delete ;
3116
+
3117
+ DIEVisitor (ArrayRef<StringRef> AbbrevEntries,
3118
+ BinaryStreamReader DistinctReader, StringRef DistinctData,
3119
+ std::function<void (StringRef)> HeaderCallback,
3120
+ std::function<void (dwarf::Tag, uint64_t )> StartTagCallback,
3121
+ std::function<void (dwarf::Attribute, dwarf::Form, StringRef, bool )>
3122
+ AttrCallback,
3123
+ std::function<void (bool )> EndTagCallback,
3124
+ std::function<void (StringRef)> NewBlockCallback)
3125
+ : AbbrevEntries(AbbrevEntries), DistinctReader(DistinctReader),
3126
+ DistinctData (DistinctData), HeaderCallback(HeaderCallback),
3127
+ StartTagCallback(StartTagCallback), AttrCallback(AttrCallback),
3128
+ EndTagCallback(EndTagCallback), NewBlockCallback(NewBlockCallback) {
3129
+ AbbrevEntryCache.reserve (AbbrevEntries.size ());
3130
+ for (unsigned I = 0 ; I < AbbrevEntries.size (); I++) {
3131
+ if (Error E = materializeAbbrevDIE (encodeAbbrevIndex (I)))
3132
+ report_fatal_error (std::move (E));
3133
+ }
3134
+ }
3135
+
3101
3136
Error visitDIERef (DIEDedupeTopLevelRef Ref);
3102
3137
Error visitDIERef (ArrayRef<DIEDataRef> &DIEChildrenStack);
3103
- Error visitDIEAttrs (AbbrevEntryReader &AbbrevReader,
3104
- BinaryStreamReader &Reader, StringRef DIEData);
3138
+ Error visitDIEAttrs (BinaryStreamReader &DataReader, StringRef DIEData,
3139
+ ArrayRef<AbbrevContent> DIEContents);
3140
+ Error materializeAbbrevDIE (unsigned AbbrevIdx);
3105
3141
3142
+ SmallVector<AbbrevEntry> AbbrevEntryCache;
3106
3143
ArrayRef<StringRef> AbbrevEntries;
3107
3144
BinaryStreamReader DistinctReader;
3108
3145
StringRef DistinctData;
@@ -3115,38 +3152,31 @@ struct DIEVisitor {
3115
3152
std::function<void (StringRef)> NewBlockCallback;
3116
3153
};
3117
3154
3118
- Error DIEVisitor::visitDIEAttrs (AbbrevEntryReader &AbbrevReader ,
3119
- BinaryStreamReader &DataReader ,
3120
- StringRef DIEData ) {
3155
+ Error DIEVisitor::visitDIEAttrs (BinaryStreamReader &DataReader ,
3156
+ StringRef DIEData ,
3157
+ ArrayRef<AbbrevContent> DIEContents ) {
3121
3158
constexpr auto IsLittleEndian = true ;
3122
3159
constexpr auto AddrSize = 8 ;
3123
3160
constexpr auto FormParams =
3124
3161
dwarf::FormParams{4 /* Version*/ , AddrSize, dwarf::DwarfFormat::DWARF32};
3125
3162
3126
- while (true ) {
3127
- Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr ();
3128
- if (!Attr)
3129
- return Attr.takeError ();
3130
- if (*Attr == getEndOfAttributesMarker ())
3131
- break ;
3132
-
3133
- Expected<dwarf::Form> Form = AbbrevReader.readForm ();
3134
- if (!Form)
3135
- return Form.takeError ();
3136
-
3137
- bool DataInDistinct = doesntDedup (*Form, *Attr);
3163
+ for (auto Contents : DIEContents) {
3164
+ bool DataInDistinct = Contents.FormInDistinctData ;
3138
3165
auto &ReaderForData = DataInDistinct ? DistinctReader : DataReader;
3139
3166
StringRef DataToUse = DataInDistinct ? DistinctData : DIEData;
3140
3167
Expected<uint64_t > FormSize =
3141
- getFormSize (*Form, FormParams, DataToUse, ReaderForData.getOffset (),
3142
- IsLittleEndian, AddrSize);
3168
+ Contents.FormSize
3169
+ ? *Contents.FormSize
3170
+ : getFormSize (Contents.Form , FormParams, DataToUse,
3171
+ ReaderForData.getOffset (), IsLittleEndian, AddrSize);
3143
3172
if (!FormSize)
3144
3173
return FormSize.takeError ();
3145
3174
3146
3175
ArrayRef<char > RawBytes;
3147
3176
if (auto E = ReaderForData.readArray (RawBytes, *FormSize))
3148
3177
return E;
3149
- AttrCallback (*Attr, *Form, toStringRef (RawBytes), DataInDistinct);
3178
+ AttrCallback (Contents.Attr , Contents.Form , toStringRef (RawBytes),
3179
+ DataInDistinct);
3150
3180
}
3151
3181
return Error::success ();
3152
3182
}
@@ -3165,6 +3195,111 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
3165
3195
return AbbrevEntryReader (AbbrevData);
3166
3196
}
3167
3197
3198
+ static std::optional<uint8_t > getNonULEBFormSize (dwarf::Form Form,
3199
+ dwarf::FormParams FP) {
3200
+ switch (Form) {
3201
+ case dwarf::DW_FORM_addr:
3202
+ return FP.AddrSize ;
3203
+ case dwarf::DW_FORM_ref_addr:
3204
+ return FP.getRefAddrByteSize ();
3205
+ case dwarf::DW_FORM_exprloc:
3206
+ case dwarf::DW_FORM_block:
3207
+ case dwarf::DW_FORM_block1:
3208
+ case dwarf::DW_FORM_block2:
3209
+ case dwarf::DW_FORM_block4:
3210
+ case dwarf::DW_FORM_sdata:
3211
+ case dwarf::DW_FORM_udata:
3212
+ case dwarf::DW_FORM_ref_udata:
3213
+ case dwarf::DW_FORM_ref4_cas:
3214
+ case dwarf::DW_FORM_strp_cas:
3215
+ case dwarf::DW_FORM_rnglistx:
3216
+ case dwarf::DW_FORM_loclistx:
3217
+ case dwarf::DW_FORM_GNU_addr_index:
3218
+ case dwarf::DW_FORM_GNU_str_index:
3219
+ case dwarf::DW_FORM_addrx:
3220
+ case dwarf::DW_FORM_strx:
3221
+ case dwarf::DW_FORM_LLVM_addrx_offset:
3222
+ case dwarf::DW_FORM_string:
3223
+ case dwarf::DW_FORM_indirect:
3224
+ return std::nullopt;
3225
+
3226
+ case dwarf::DW_FORM_implicit_const:
3227
+ case dwarf::DW_FORM_flag_present:
3228
+ return 0 ;
3229
+ case dwarf::DW_FORM_data1:
3230
+ case dwarf::DW_FORM_ref1:
3231
+ case dwarf::DW_FORM_flag:
3232
+ case dwarf::DW_FORM_strx1:
3233
+ case dwarf::DW_FORM_addrx1:
3234
+ return 1 ;
3235
+ case dwarf::DW_FORM_data2:
3236
+ case dwarf::DW_FORM_ref2:
3237
+ case dwarf::DW_FORM_strx2:
3238
+ case dwarf::DW_FORM_addrx2:
3239
+ return 2 ;
3240
+ case dwarf::DW_FORM_strx3:
3241
+ return 3 ;
3242
+ case dwarf::DW_FORM_data4:
3243
+ case dwarf::DW_FORM_ref4:
3244
+ case dwarf::DW_FORM_ref_sup4:
3245
+ case dwarf::DW_FORM_strx4:
3246
+ case dwarf::DW_FORM_addrx4:
3247
+ return 4 ;
3248
+ case dwarf::DW_FORM_ref_sig8:
3249
+ case dwarf::DW_FORM_data8:
3250
+ case dwarf::DW_FORM_ref8:
3251
+ case dwarf::DW_FORM_ref_sup8:
3252
+ return 8 ;
3253
+ case dwarf::DW_FORM_data16:
3254
+ return 16 ;
3255
+ case dwarf::DW_FORM_strp:
3256
+ case dwarf::DW_FORM_sec_offset:
3257
+ case dwarf::DW_FORM_GNU_ref_alt:
3258
+ case dwarf::DW_FORM_GNU_strp_alt:
3259
+ case dwarf::DW_FORM_line_strp:
3260
+ case dwarf::DW_FORM_strp_sup:
3261
+ return FP.getDwarfOffsetByteSize ();
3262
+ case dwarf::DW_FORM_addrx3:
3263
+ case dwarf::DW_FORM_lo_user:
3264
+ llvm_unreachable (" usupported form" );
3265
+ break ;
3266
+ }
3267
+ }
3268
+
3269
+ Error DIEVisitor::materializeAbbrevDIE (unsigned AbbrevIdx) {
3270
+ constexpr auto AddrSize = 8 ;
3271
+ constexpr auto FormParams =
3272
+ dwarf::FormParams{4 /* Version*/ , AddrSize, dwarf::DwarfFormat::DWARF32};
3273
+
3274
+ AbbrevEntryReader AbbrevReader =
3275
+ getAbbrevEntryReader (AbbrevEntries, AbbrevIdx);
3276
+ Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag ();
3277
+ if (!MaybeTag)
3278
+ return MaybeTag.takeError ();
3279
+
3280
+ Expected<bool > MaybeHasChildren = AbbrevReader.readHasChildren ();
3281
+ if (!MaybeHasChildren)
3282
+ return MaybeHasChildren.takeError ();
3283
+
3284
+ SmallVector<AbbrevContent> AbbrevVector;
3285
+ while (true ) {
3286
+ Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr ();
3287
+ if (!Attr)
3288
+ return Attr.takeError ();
3289
+ if (*Attr == getEndOfAttributesMarker ())
3290
+ break ;
3291
+
3292
+ Expected<dwarf::Form> Form = AbbrevReader.readForm ();
3293
+ if (!Form)
3294
+ return Form.takeError ();
3295
+ AbbrevVector.push_back ({*Attr, *Form, doesntDedup (*Form, *Attr),
3296
+ getNonULEBFormSize (*Form, FormParams)});
3297
+ }
3298
+ AbbrevEntryCache.push_back (
3299
+ {*MaybeTag, *MaybeHasChildren, std::move (AbbrevVector)});
3300
+ return Error::success ();
3301
+ }
3302
+
3168
3303
// / Restores the state of the \p Reader and \p Data
3169
3304
// / arguments to a previous state. The algorithm in visitDIERefs is an iterative
3170
3305
// / implementation of a Depth First Search, and this function is used to
@@ -3217,25 +3352,18 @@ Error DIEVisitor::visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack) {
3217
3352
}
3218
3353
3219
3354
// If we have a legitimate AbbrevIdx, materialize the current DIE.
3220
- AbbrevEntryReader AbbrevReader =
3221
- getAbbrevEntryReader (AbbrevEntries, AbbrevIdx);
3222
-
3223
- if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag ())
3224
- StartTagCallback (*MaybeTag, AbbrevIdx);
3225
- else
3226
- return MaybeTag.takeError ();
3227
-
3228
- Expected<bool > MaybeHasChildren = AbbrevReader.readHasChildren ();
3229
- if (!MaybeHasChildren)
3230
- return MaybeHasChildren.takeError ();
3355
+ auto &AbbrevEntryCacheVal =
3356
+ AbbrevEntryCache[decodeAbbrevIndexAsAbbrevSetIdx (AbbrevIdx)];
3357
+ StartTagCallback (AbbrevEntryCacheVal.Tag , AbbrevIdx);
3231
3358
3232
- if (auto E = visitDIEAttrs (AbbrevReader, Reader, Data))
3359
+ if (auto E =
3360
+ visitDIEAttrs (Reader, Data, AbbrevEntryCacheVal.AbbrevContents ))
3233
3361
return E;
3234
3362
3235
3363
// If the current DIE doesn't have any children, the current CAS Object will
3236
3364
// not contain any more data, pop the stack to continue materializing its
3237
3365
// parent's siblings that may exist.
3238
- if (!*MaybeHasChildren ) {
3366
+ if (!AbbrevEntryCacheVal. HasChildren ) {
3239
3367
if (!StackOfNodes.empty () && Reader.empty ())
3240
3368
popStack (Reader, Data, StackOfNodes);
3241
3369
EndTagCallback (false /* HadChildren*/ );
0 commit comments