@@ -1893,7 +1893,9 @@ struct DIEDataWriter : public DataWriter {
1893
1893
1894
1894
// / Saves the main data stream and any children to a new DIEDataRef node.
1895
1895
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;
1897
1899
}
1898
1900
1899
1901
private:
@@ -1973,13 +1975,15 @@ struct DIEToCASConverter {
1973
1975
ArrayRef<char > DebugInfoData;
1974
1976
MCCASBuilder &CASBuilder;
1975
1977
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);
1979
1982
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);
1983
1987
};
1984
1988
1985
1989
Error InMemoryCASDWARFObject::partitionCUData (ArrayRef<char > DebugInfoData,
@@ -2998,9 +3002,10 @@ static void writeDIEAttrs(DWARFDie &DIE, ArrayRef<char> DebugInfoData,
2998
3002
// / * Otherwise, abbreviation_index is an index into the list of references of a
2999
3003
// / DIEAbbrevSetRef block. In this case, raw_data should be interpreted
3000
3004
// / 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) {
3004
3009
Expected<unsigned > MaybeAbbrevIndex =
3005
3010
AbbrevWriter.createAbbrevEntry (DIE, CASBuilder);
3006
3011
if (!MaybeAbbrevIndex)
@@ -3020,39 +3025,40 @@ Error DIEToCASConverter::convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
3020
3025
// FIXME: don't use recursion.
3021
3026
if (shouldCreateSeparateBlockFor (Child)) {
3022
3027
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;
3028
3031
continue ;
3029
3032
}
3030
-
3031
- if ( auto E = convertImpl (Child, DIEWriter, DistinctWriter, AbbrevWriter ))
3033
+ if ( auto E = convertImpl (Child, DIEWriter, DistinctWriter, AbbrevWriter,
3034
+ DIEWriters ))
3032
3035
return E;
3033
3036
}
3034
3037
return Error::success ();
3035
3038
}
3036
3039
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 ();
3045
3050
}
3046
3051
3047
3052
Expected<DIETopLevelRef>
3048
3053
DIEToCASConverter::convert (DWARFDie DIE, ArrayRef<char > HeaderData,
3049
3054
AbbrevSetWriter &AbbrevWriter) {
3050
3055
DistinctDataWriter DistinctWriter;
3051
3056
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
+
3056
3062
Expected<DIEAbbrevSetRef> MaybeAbbrevSet =
3057
3063
AbbrevWriter.endAbbrevSet (CASBuilder);
3058
3064
if (!MaybeAbbrevSet)
@@ -3061,8 +3067,21 @@ DIEToCASConverter::convert(DWARFDie DIE, ArrayRef<char> HeaderData,
3061
3067
DistinctWriter.getCASNode (CASBuilder);
3062
3068
if (!MaybeDistinct)
3063
3069
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 ();
3064
3083
SmallVector<cas::ObjectRef, 3 > Refs{
3065
- MaybeDIE ->getRef (), MaybeAbbrevSet->getRef (), MaybeDistinct->getRef ()};
3084
+ TopDIERef ->getRef (), MaybeAbbrevSet->getRef (), MaybeDistinct->getRef ()};
3066
3085
return DIETopLevelRef::create (CASBuilder, Refs);
3067
3086
}
3068
3087
@@ -3074,8 +3093,8 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
3074
3093
" TopLevelRef is expected to have three references" );
3075
3094
3076
3095
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 ));
3079
3098
Expected<DIEAbbrevSetRef> AbbrevSet =
3080
3099
DIEAbbrevSetRef::get (Schema, TopLevelRef.getReference (1 ));
3081
3100
Expected<DIEDistinctDataRef> DistinctData =
@@ -3097,9 +3116,8 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
3097
3116
}
3098
3117
3099
3118
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);
3103
3121
Error visitDIEAttrs (AbbrevEntryReader &AbbrevReader,
3104
3122
BinaryStreamReader &Reader, StringRef DIEData);
3105
3123
@@ -3165,67 +3183,99 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
3165
3183
return AbbrevEntryReader (AbbrevData);
3166
3184
}
3167
3185
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
+ }
3178
3224
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
+ }
3182
3236
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);
3185
3240
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 ();
3190
3245
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 ();
3195
3249
3196
- if (*ChildAbbrevIdx == getEndOfDIESiblingsMarker ( ))
3197
- break ;
3250
+ if (auto E = visitDIEAttrs (AbbrevReader, Reader, Data ))
3251
+ return E ;
3198
3252
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*/ );
3204
3260
}
3205
-
3206
- if (auto E =
3207
- visitDIERef (DataReader, *ChildAbbrevIdx, DIEData, DIEChildrenStack))
3208
- return E;
3209
3261
}
3210
-
3211
- EndTagCallback (true /* HadChildren*/ );
3212
3262
return Error::success ();
3213
3263
}
3214
3264
3215
- Error DIEVisitor::visitDIERef (DIEDataRef StartDIERef) {
3216
- StringRef DIEData = StartDIERef.getData ();
3217
- BinaryStreamReader DataReader (DIEData, endianness::little);
3265
+ Error DIEVisitor::visitDIERef (DIEDedupeTopLevelRef StartDIERef) {
3218
3266
3267
+ auto Offset = DistinctReader.getOffset ();
3219
3268
Expected<uint64_t > MaybeAbbrevIdx = readAbbrevIdx (DistinctReader);
3220
3269
if (!MaybeAbbrevIdx)
3221
3270
return MaybeAbbrevIdx.takeError ();
3222
3271
auto AbbrevIdx = *MaybeAbbrevIdx;
3223
-
3224
3272
// The tag of a fresh block must be meaningful, otherwise we wouldn't have
3225
3273
// made a new block.
3226
3274
assert (AbbrevIdx != getEndOfDIESiblingsMarker () &&
3227
3275
AbbrevIdx != getDIEInAnotherBlockMarker ());
3228
3276
3277
+ DistinctReader.setOffset (Offset);
3278
+
3229
3279
NewBlockCallback (StartDIERef.getID ().toString ());
3230
3280
3231
3281
Expected<SmallVector<DIEDataRef>> MaybeChildren =
@@ -3234,7 +3284,7 @@ Error DIEVisitor::visitDIERef(DIEDataRef StartDIERef) {
3234
3284
return MaybeChildren.takeError ();
3235
3285
ArrayRef<DIEDataRef> Children = *MaybeChildren;
3236
3286
3237
- return visitDIERef (DataReader, AbbrevIdx, DIEData, Children);
3287
+ return visitDIERef (Children);
3238
3288
}
3239
3289
3240
3290
Error mccasformats::v1::visitDebugInfo (
0 commit comments