Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit c254cb7

Browse files
author
Zachary Turner
committed
[CodeView] Simplify the use of visiting type records & streams.
There is often a lot of boilerplate code required to visit a type record or type stream. The #1 use case is that you have a sequence of bytes that represent one or more records, and you want to deserialize each one, switch on it, and call a callback with the deserialized record that the user can examine. Currently this requires at least 6 lines of code: codeview::TypeVisitorCallbackPipeline Pipeline; Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(MyCallbacks); codeview::CVTypeVisitor Visitor(Pipeline); consumeError(Visitor.visitTypeRecord(Record)); With this patch, it becomes one line of code: consumeError(codeview::visitTypeRecord(Record, MyCallbacks)); This is done by having the deserialization happen internally inside of the visitTypeRecord function. Since this is occasionally not desirable, the function provides a 3rd parameter that can be used to change this behavior. Hopefully this can significantly reduce the barrier to entry to using the visitation infrastructure. Differential Revision: https://reviews.llvm.org/D33245 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303271 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 66b46e1 commit c254cb7

File tree

16 files changed

+198
-168
lines changed

16 files changed

+198
-168
lines changed

include/llvm/DebugInfo/CodeView/CVTypeVisitor.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class CVTypeVisitor {
2828

2929
Error visitTypeRecord(CVType &Record, TypeIndex Index);
3030
Error visitTypeRecord(CVType &Record);
31-
Error visitMemberRecord(CVMemberRecord &Record);
31+
Error visitMemberRecord(CVMemberRecord Record);
3232

3333
/// Visits the type records in Data. Sets the error flag on parse failures.
3434
Error visitTypeStream(const CVTypeArray &Types);
@@ -47,6 +47,36 @@ class CVTypeVisitor {
4747
TinyPtrVector<TypeServerHandler *> Handlers;
4848
};
4949

50+
enum VisitorDataSource {
51+
VDS_BytesPresent, // The record bytes are passed into the the visitation
52+
// function. The algorithm should first deserialize them
53+
// before passing them on through the pipeline.
54+
VDS_BytesExternal // The record bytes are not present, and it is the
55+
// responsibility of the visitor callback interface to
56+
// supply the bytes.
57+
};
58+
59+
Error visitTypeRecord(CVType &Record, TypeIndex Index,
60+
TypeVisitorCallbacks &Callbacks,
61+
VisitorDataSource Source = VDS_BytesPresent,
62+
TypeServerHandler *TS = nullptr);
63+
Error visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks,
64+
VisitorDataSource Source = VDS_BytesPresent,
65+
TypeServerHandler *TS = nullptr);
66+
67+
Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks,
68+
VisitorDataSource Source = VDS_BytesPresent);
69+
Error visitMemberRecord(TypeLeafKind Kind, ArrayRef<uint8_t> Record,
70+
TypeVisitorCallbacks &Callbacks);
71+
72+
Error visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
73+
TypeVisitorCallbacks &Callbacks);
74+
75+
Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks,
76+
TypeServerHandler *TS = nullptr);
77+
Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks,
78+
TypeServerHandler *TS = nullptr);
79+
5080
} // end namespace codeview
5181
} // end namespace llvm
5282

include/llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@
1111
#define LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
1212

1313
#include "llvm/ADT/TinyPtrVector.h"
14-
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1514
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
1615
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
17-
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1816
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
1917
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
20-
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
2118
#include "llvm/Support/Error.h"
2219

2320
namespace llvm {
@@ -73,18 +70,6 @@ class RandomAccessTypeVisitor {
7370
/// The database visitor which adds new records to the database.
7471
TypeDatabaseVisitor DatabaseVisitor;
7572

76-
/// The deserializer which deserializes new records.
77-
TypeDeserializer Deserializer;
78-
79-
/// The visitation callback pipeline to use. By default this contains a
80-
/// deserializer and a type database visitor. But the callback specified
81-
/// in the constructor is also added.
82-
TypeVisitorCallbackPipeline Pipeline;
83-
84-
/// The visitor used to visit the internal pipeline for deserialization and
85-
/// database maintenance.
86-
CVTypeVisitor InternalVisitor;
87-
8873
/// A vector mapping type indices to type offset. For every record that has
8974
/// been visited, contains the absolute offset of that record in the record
9075
/// array.

include/llvm/DebugInfo/PDB/Native/TpiStream.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class TpiStream {
5151
HashTable &getHashAdjusters();
5252

5353
codeview::CVTypeRange types(bool *HadError) const;
54+
const codeview::CVTypeArray &typeArray() const { return TypeRecords; }
5455

5556
Error commit();
5657

lib/CodeGen/AsmPrinter/CodeViewDebug.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ void CodeViewDebug::emitTypeInformation() {
501501
Error E = Reader.readArray(Types, Reader.getLength());
502502
if (!E) {
503503
TypeVisitorCallbacks C;
504-
E = CVTypeVisitor(C).visitTypeStream(Types);
504+
E = codeview::visitTypeStream(Types, C);
505505
}
506506
if (E) {
507507
logAllUnhandledErrors(std::move(E), errs(), "error: ");

lib/DebugInfo/CodeView/CVTypeDumper.cpp

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1212
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
1313
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
14-
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1514
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
1615
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
1716
#include "llvm/Support/BinaryByteStream.h"
@@ -21,38 +20,23 @@ using namespace llvm::codeview;
2120

2221
Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) {
2322
TypeDatabaseVisitor DBV(TypeDB);
24-
TypeDeserializer Deserializer;
2523
TypeVisitorCallbackPipeline Pipeline;
26-
Pipeline.addCallbackToPipeline(Deserializer);
2724
Pipeline.addCallbackToPipeline(DBV);
2825
Pipeline.addCallbackToPipeline(Dumper);
2926

30-
CVTypeVisitor Visitor(Pipeline);
31-
if (Handler)
32-
Visitor.addTypeServerHandler(*Handler);
33-
3427
CVType RecordCopy = Record;
35-
if (auto EC = Visitor.visitTypeRecord(RecordCopy))
36-
return EC;
37-
return Error::success();
28+
return codeview::visitTypeRecord(RecordCopy, Pipeline, VDS_BytesPresent,
29+
Handler);
3830
}
3931

4032
Error CVTypeDumper::dump(const CVTypeArray &Types,
4133
TypeVisitorCallbacks &Dumper) {
4234
TypeDatabaseVisitor DBV(TypeDB);
43-
TypeDeserializer Deserializer;
4435
TypeVisitorCallbackPipeline Pipeline;
45-
Pipeline.addCallbackToPipeline(Deserializer);
4636
Pipeline.addCallbackToPipeline(DBV);
4737
Pipeline.addCallbackToPipeline(Dumper);
4838

49-
CVTypeVisitor Visitor(Pipeline);
50-
if (Handler)
51-
Visitor.addTypeServerHandler(*Handler);
52-
53-
if (auto EC = Visitor.visitTypeStream(Types))
54-
return EC;
55-
return Error::success();
39+
return codeview::visitTypeStream(Types, Pipeline, Handler);
5640
}
5741

5842
Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) {

lib/DebugInfo/CodeView/CVTypeVisitor.cpp

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,8 @@ static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) {
5959
};
6060

6161
TypeServer2Record R(TypeRecordKind::TypeServer2);
62-
TypeDeserializer Deserializer;
6362
StealTypeServerVisitor Thief(R);
64-
TypeVisitorCallbackPipeline Pipeline;
65-
Pipeline.addCallbackToPipeline(Deserializer);
66-
Pipeline.addCallbackToPipeline(Thief);
67-
CVTypeVisitor Visitor(Pipeline);
68-
if (auto EC = Visitor.visitTypeRecord(Record))
63+
if (auto EC = visitTypeRecord(Record, Thief))
6964
return std::move(EC);
7065

7166
return R;
@@ -178,7 +173,7 @@ static Error visitMemberRecord(CVMemberRecord &Record,
178173
return Error::success();
179174
}
180175

181-
Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) {
176+
Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
182177
return ::visitMemberRecord(Record, Callbacks);
183178
}
184179

@@ -224,3 +219,93 @@ Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
224219
BinaryStreamReader SR(S);
225220
return visitFieldListMemberStream(SR);
226221
}
222+
223+
namespace {
224+
struct FieldListVisitHelper {
225+
FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
226+
VisitorDataSource Source)
227+
: Stream(Data, llvm::support::little), Reader(Stream),
228+
Deserializer(Reader),
229+
Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
230+
if (Source == VDS_BytesPresent) {
231+
Pipeline.addCallbackToPipeline(Deserializer);
232+
Pipeline.addCallbackToPipeline(Callbacks);
233+
}
234+
}
235+
236+
BinaryByteStream Stream;
237+
BinaryStreamReader Reader;
238+
FieldListDeserializer Deserializer;
239+
TypeVisitorCallbackPipeline Pipeline;
240+
CVTypeVisitor Visitor;
241+
};
242+
243+
struct VisitHelper {
244+
VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source,
245+
TypeServerHandler *TS)
246+
: Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
247+
if (TS)
248+
Visitor.addTypeServerHandler(*TS);
249+
if (Source == VDS_BytesPresent) {
250+
Pipeline.addCallbackToPipeline(Deserializer);
251+
Pipeline.addCallbackToPipeline(Callbacks);
252+
}
253+
}
254+
255+
TypeDeserializer Deserializer;
256+
TypeVisitorCallbackPipeline Pipeline;
257+
CVTypeVisitor Visitor;
258+
};
259+
}
260+
261+
Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
262+
TypeVisitorCallbacks &Callbacks,
263+
VisitorDataSource Source,
264+
TypeServerHandler *TS) {
265+
VisitHelper Helper(Callbacks, Source, TS);
266+
return Helper.Visitor.visitTypeRecord(Record, Index);
267+
}
268+
269+
Error llvm::codeview::visitTypeRecord(CVType &Record,
270+
TypeVisitorCallbacks &Callbacks,
271+
VisitorDataSource Source,
272+
TypeServerHandler *TS) {
273+
VisitHelper Helper(Callbacks, Source, TS);
274+
return Helper.Visitor.visitTypeRecord(Record);
275+
}
276+
277+
Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
278+
TypeVisitorCallbacks &Callbacks) {
279+
CVTypeVisitor Visitor(Callbacks);
280+
return Visitor.visitFieldListMemberStream(FieldList);
281+
}
282+
283+
Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
284+
TypeVisitorCallbacks &Callbacks,
285+
VisitorDataSource Source) {
286+
FieldListVisitHelper Helper(Callbacks, Record.Data, Source);
287+
return Helper.Visitor.visitMemberRecord(Record);
288+
}
289+
290+
Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
291+
ArrayRef<uint8_t> Record,
292+
TypeVisitorCallbacks &Callbacks) {
293+
CVMemberRecord R;
294+
R.Data = Record;
295+
R.Kind = Kind;
296+
return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
297+
}
298+
299+
Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
300+
TypeVisitorCallbacks &Callbacks,
301+
TypeServerHandler *TS) {
302+
VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
303+
return Helper.Visitor.visitTypeStream(Types);
304+
}
305+
306+
Error llvm::codeview::visitTypeStream(CVTypeRange Types,
307+
TypeVisitorCallbacks &Callbacks,
308+
TypeServerHandler *TS) {
309+
VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
310+
return Helper.Visitor.visitTypeStream(Types);
311+
}

lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h"
1111

12+
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1213
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
1314
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
1415
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
@@ -20,9 +21,7 @@ RandomAccessTypeVisitor::RandomAccessTypeVisitor(
2021
const CVTypeArray &Types, uint32_t NumRecords,
2122
PartialOffsetArray PartialOffsets)
2223
: Database(NumRecords), Types(Types), DatabaseVisitor(Database),
23-
InternalVisitor(Pipeline), PartialOffsets(PartialOffsets) {
24-
Pipeline.addCallbackToPipeline(Deserializer);
25-
Pipeline.addCallbackToPipeline(DatabaseVisitor);
24+
PartialOffsets(PartialOffsets) {
2625

2726
KnownOffsets.resize(Database.capacity());
2827
}
@@ -38,8 +37,7 @@ Error RandomAccessTypeVisitor::visitTypeIndex(TypeIndex TI,
3837

3938
assert(Database.contains(TI));
4039
auto &Record = Database.getTypeRecord(TI);
41-
CVTypeVisitor V(Callbacks);
42-
return V.visitTypeRecord(Record, TI);
40+
return codeview::visitTypeRecord(Record, TI, Callbacks);
4341
}
4442

4543
Error RandomAccessTypeVisitor::visitRangeForType(TypeIndex TI) {
@@ -78,7 +76,7 @@ Error RandomAccessTypeVisitor::visitRange(TypeIndex Begin, uint32_t BeginOffset,
7876

7977
while (Begin != End) {
8078
assert(!Database.contains(Begin));
81-
if (auto EC = InternalVisitor.visitTypeRecord(*RI, Begin))
79+
if (auto EC = codeview::visitTypeRecord(*RI, Begin, DatabaseVisitor))
8280
return EC;
8381
KnownOffsets[Begin.toArrayIndex()] = BeginOffset;
8482

lib/DebugInfo/CodeView/TypeDumpVisitor.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,7 @@ Error TypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
216216

217217
Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
218218
FieldListRecord &FieldList) {
219-
CVTypeVisitor Visitor(*this);
220-
if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data))
219+
if (auto EC = codeview::visitMemberRecordStream(FieldList.Data, *this))
221220
return EC;
222221

223222
return Error::success();

lib/DebugInfo/CodeView/TypeStreamMerger.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,7 @@ Error TypeStreamMerger::visitKnownRecord(CVType &, FieldListRecord &R) {
361361
// Visit the members inside the field list.
362362
HadUntranslatedMember = false;
363363
FieldListBuilder.begin();
364-
CVTypeVisitor Visitor(*this);
365-
if (auto EC = Visitor.visitFieldListMemberStream(R.Data))
364+
if (auto EC = codeview::visitMemberRecordStream(R.Data, *this))
366365
return EC;
367366

368367
// Write the record if we translated all field list members.
@@ -440,18 +439,9 @@ Error TypeStreamMerger::visitUnknownType(CVType &Rec) {
440439

441440
Error TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
442441
assert(IndexMap.empty());
443-
TypeVisitorCallbackPipeline Pipeline;
444442
LastError = Error::success();
445443

446-
TypeDeserializer Deserializer;
447-
Pipeline.addCallbackToPipeline(Deserializer);
448-
Pipeline.addCallbackToPipeline(*this);
449-
450-
CVTypeVisitor Visitor(Pipeline);
451-
if (Handler)
452-
Visitor.addTypeServerHandler(*Handler);
453-
454-
if (auto EC = Visitor.visitTypeStream(Types))
444+
if (auto EC = codeview::visitTypeStream(Types, *this, Handler))
455445
return EC;
456446

457447
// If we found bad indices but no other errors, try doing another pass and see
@@ -466,7 +456,8 @@ Error TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
466456
IsSecondPass = true;
467457
NumBadIndices = 0;
468458
CurIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex);
469-
if (auto EC = Visitor.visitTypeStream(Types))
459+
460+
if (auto EC = codeview::visitTypeStream(Types, *this, Handler))
470461
return EC;
471462

472463
assert(NumBadIndices <= BadIndicesRemaining &&

lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,8 @@ PDBTypeServerHandler::handleInternal(PDBFile &File,
5555
auto ExpectedTpi = File.getPDBTpiStream();
5656
if (!ExpectedTpi)
5757
return ExpectedTpi.takeError();
58-
CVTypeVisitor Visitor(Callbacks);
5958

60-
if (auto EC = Visitor.visitTypeStream(ExpectedTpi->types(nullptr)))
59+
if (auto EC = codeview::visitTypeStream(ExpectedTpi->typeArray(), Callbacks))
6160
return std::move(EC);
6261

6362
return true;

0 commit comments

Comments
 (0)