@@ -170,7 +170,6 @@ Error MCSchema::fillCache() {
170
170
PaddingRef::KindString,
171
171
MCAssemblerRef::KindString,
172
172
DebugInfoSectionRef::KindString,
173
- DIEDataRef::KindString,
174
173
#define CASV1_SIMPLE_DATA_REF (RefName, IdentifierName ) RefName::KindString,
175
174
#define CASV1_SIMPLE_GROUP_REF (RefName, IdentifierName ) RefName::KindString,
176
175
#define MCFRAGMENT_NODE_REF (MCFragmentName, MCEnumName, MCEnumIdentifier ) \
@@ -1881,16 +1880,12 @@ Error MCCASBuilder::createDebugAbbrevSection() {
1881
1880
// / Helper class to create DIEDataRefs by keeping track of references to
1882
1881
// / children blocks.
1883
1882
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 ()); }
1886
1883
1887
1884
// / Saves the main data stream and any children to a new DIEDataRef node.
1888
1885
Expected<DIEDataRef> getCASNode (MCCASBuilder &CASBuilder) {
1889
- return DIEDataRef::create (CASBuilder, Children, Data);
1886
+ auto Ref = DIEDataRef::create (CASBuilder, toStringRef (Data));
1887
+ return Ref;
1890
1888
}
1891
-
1892
- private:
1893
- SmallVector<cas::ObjectRef> Children;
1894
1889
};
1895
1890
1896
1891
// / Helper class to create DIEDistinctDataRefs.
@@ -1966,13 +1961,15 @@ struct DIEToCASConverter {
1966
1961
ArrayRef<char > DebugInfoData;
1967
1962
MCCASBuilder &CASBuilder;
1968
1963
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);
1972
1968
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);
1976
1973
};
1977
1974
1978
1975
Error InMemoryCASDWARFObject::partitionCUData (ArrayRef<char > DebugInfoData,
@@ -2906,14 +2903,13 @@ DIETopLevelRef::create(MCCASBuilder &MB, ArrayRef<cas::ObjectRef> Children) {
2906
2903
return get (B->build ());
2907
2904
}
2908
2905
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 ) {
2912
2909
Expected<Builder> B = Builder::startNode (MB.Schema , KindString);
2913
2910
if (!B)
2914
2911
return B.takeError ();
2915
2912
append_range (B->Refs , Children);
2916
- append_range (B->Data , toStringRef (Contents));
2917
2913
return get (B->build ());
2918
2914
}
2919
2915
@@ -2976,9 +2972,10 @@ static void writeDIEAttrs(DWARFDie &DIE, ArrayRef<char> DebugInfoData,
2976
2972
// / * Otherwise, abbreviation_index is an index into the list of references of a
2977
2973
// / DIEAbbrevSetRef block. In this case, raw_data should be interpreted
2978
2974
// / 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) {
2982
2979
Expected<unsigned > MaybeAbbrevIndex =
2983
2980
AbbrevWriter.createAbbrevEntry (DIE, CASBuilder);
2984
2981
if (!MaybeAbbrevIndex)
@@ -2998,39 +2995,40 @@ Error DIEToCASConverter::convertImpl(DWARFDie &DIE, DIEDataWriter &DIEWriter,
2998
2995
// FIXME: don't use recursion.
2999
2996
if (shouldCreateSeparateBlockFor (Child)) {
3000
2997
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;
3006
3001
continue ;
3007
3002
}
3008
-
3009
- if ( auto E = convertImpl (Child, DIEWriter, DistinctWriter, AbbrevWriter ))
3003
+ if ( auto E = convertImpl (Child, DIEWriter, DistinctWriter, AbbrevWriter,
3004
+ DIEWriters ))
3010
3005
return E;
3011
3006
}
3012
3007
return Error::success ();
3013
3008
}
3014
3009
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 ();
3023
3020
}
3024
3021
3025
3022
Expected<DIETopLevelRef>
3026
3023
DIEToCASConverter::convert (DWARFDie DIE, ArrayRef<char > HeaderData,
3027
3024
AbbrevSetWriter &AbbrevWriter) {
3028
3025
DistinctDataWriter DistinctWriter;
3029
3026
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
+
3034
3032
Expected<DIEAbbrevSetRef> MaybeAbbrevSet =
3035
3033
AbbrevWriter.endAbbrevSet (CASBuilder);
3036
3034
if (!MaybeAbbrevSet)
@@ -3039,8 +3037,21 @@ DIEToCASConverter::convert(DWARFDie DIE, ArrayRef<char> HeaderData,
3039
3037
DistinctWriter.getCASNode (CASBuilder);
3040
3038
if (!MaybeDistinct)
3041
3039
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 ();
3042
3053
SmallVector<cas::ObjectRef, 3 > Refs{
3043
- MaybeDIE ->getRef (), MaybeAbbrevSet->getRef (), MaybeDistinct->getRef ()};
3054
+ TopDIERef ->getRef (), MaybeAbbrevSet->getRef (), MaybeDistinct->getRef ()};
3044
3055
return DIETopLevelRef::create (CASBuilder, Refs);
3045
3056
}
3046
3057
@@ -3052,8 +3063,8 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
3052
3063
" TopLevelRef is expected to have three references" );
3053
3064
3054
3065
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 ));
3057
3068
Expected<DIEAbbrevSetRef> AbbrevSet =
3058
3069
DIEAbbrevSetRef::get (Schema, TopLevelRef.getReference (1 ));
3059
3070
Expected<DIEDistinctDataRef> DistinctData =
@@ -3075,9 +3086,8 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
3075
3086
}
3076
3087
3077
3088
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);
3081
3091
Error visitDIEAttrs (AbbrevEntryReader &AbbrevReader,
3082
3092
BinaryStreamReader &Reader, StringRef DIEData);
3083
3093
@@ -3143,67 +3153,99 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
3143
3153
return AbbrevEntryReader (AbbrevData);
3144
3154
}
3145
3155
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
+ }
3156
3194
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
+ }
3160
3206
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);
3163
3210
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 ();
3168
3215
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 ();
3173
3219
3174
- if (*ChildAbbrevIdx == getEndOfDIESiblingsMarker ( ))
3175
- break ;
3220
+ if (auto E = visitDIEAttrs (AbbrevReader, Reader, Data ))
3221
+ return E ;
3176
3222
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*/ );
3182
3230
}
3183
-
3184
- if (auto E =
3185
- visitDIERef (DataReader, *ChildAbbrevIdx, DIEData, DIEChildrenStack))
3186
- return E;
3187
3231
}
3188
-
3189
- EndTagCallback (true /* HadChildren*/ );
3190
3232
return Error::success ();
3191
3233
}
3192
3234
3193
- Error DIEVisitor::visitDIERef (DIEDataRef StartDIERef) {
3194
- StringRef DIEData = StartDIERef.getData ();
3195
- BinaryStreamReader DataReader (DIEData, support::endianness::little);
3235
+ Error DIEVisitor::visitDIERef (DIEDedupeTopLevelRef StartDIERef) {
3196
3236
3237
+ auto Offset = DistinctReader.getOffset ();
3197
3238
Expected<uint64_t > MaybeAbbrevIdx = readAbbrevIdx (DistinctReader);
3198
3239
if (!MaybeAbbrevIdx)
3199
3240
return MaybeAbbrevIdx.takeError ();
3200
3241
auto AbbrevIdx = *MaybeAbbrevIdx;
3201
-
3202
3242
// The tag of a fresh block must be meaningful, otherwise we wouldn't have
3203
3243
// made a new block.
3204
3244
assert (AbbrevIdx != getEndOfDIESiblingsMarker () &&
3205
3245
AbbrevIdx != getDIEInAnotherBlockMarker ());
3206
3246
3247
+ DistinctReader.setOffset (Offset);
3248
+
3207
3249
NewBlockCallback (StartDIERef.getID ().toString ());
3208
3250
3209
3251
Expected<SmallVector<DIEDataRef>> MaybeChildren =
@@ -3212,7 +3254,7 @@ Error DIEVisitor::visitDIERef(DIEDataRef StartDIERef) {
3212
3254
return MaybeChildren.takeError ();
3213
3255
ArrayRef<DIEDataRef> Children = *MaybeChildren;
3214
3256
3215
- return visitDIERef (DataReader, AbbrevIdx, DIEData, Children);
3257
+ return visitDIERef (Children);
3216
3258
}
3217
3259
3218
3260
Error mccasformats::v1::visitDebugInfo (
0 commit comments