@@ -510,24 +510,27 @@ static void printTypeIndexOffset(raw_ostream &OS,
510
510
OS << " {" << TIOff.Type .getIndex () << " , " << TIOff.Offset << " }" ;
511
511
}
512
512
513
- static void dumpTpiHash (ScopedPrinter &P, TpiStream &Tpi) {
514
- if (!opts::raw::DumpTpiHash)
515
- return ;
516
- DictScope DD (P, " Hash" );
517
- P.printNumber (" Number of Hash Buckets" , Tpi.NumHashBuckets ());
518
- P.printNumber (" Hash Key Size" , Tpi.getHashKeySize ());
519
- P.printList (" Values" , Tpi.getHashValues ());
520
- P.printList (" Type Index Offsets" , Tpi.getTypeIndexOffsets (),
521
- printTypeIndexOffset);
522
- P.printList (" Hash Adjustments" , Tpi.getHashAdjustments (),
523
- printTypeIndexOffset);
513
+ namespace {
514
+ class RecordBytesVisitor : public TypeVisitorCallbacks {
515
+ public:
516
+ explicit RecordBytesVisitor (ScopedPrinter &P) : P(P) {}
517
+
518
+ Error visitTypeEnd (CVType &Record) override {
519
+ P.printBinaryBlock (" Bytes" , Record.content ());
520
+ return Error::success ();
521
+ }
522
+
523
+ private:
524
+ ScopedPrinter &P;
525
+ };
524
526
}
525
527
526
528
Error LLVMOutputStyle::dumpTpiStream (uint32_t StreamIdx) {
527
529
assert (StreamIdx == StreamTPI || StreamIdx == StreamIPI);
528
530
529
531
bool DumpRecordBytes = false ;
530
532
bool DumpRecords = false ;
533
+ bool DumpTpiHash = false ;
531
534
StringRef Label;
532
535
StringRef VerLabel;
533
536
if (StreamIdx == StreamTPI) {
@@ -537,6 +540,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
537
540
}
538
541
DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
539
542
DumpRecords = opts::raw::DumpTpiRecords;
543
+ DumpTpiHash = opts::raw::DumpTpiHash;
540
544
Label = " Type Info Stream (TPI)" ;
541
545
VerLabel = " TPI Version" ;
542
546
} else if (StreamIdx == StreamIPI) {
@@ -549,80 +553,98 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
549
553
Label = " Type Info Stream (IPI)" ;
550
554
VerLabel = " IPI Version" ;
551
555
}
552
- if (!DumpRecordBytes && !DumpRecords && !opts::raw::DumpModuleSyms)
556
+ if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash &&
557
+ !opts::raw::DumpModuleSyms)
553
558
return Error::success ();
554
559
560
+ bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash;
561
+
555
562
auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream ()
556
563
: File.getPDBIpiStream ();
557
564
if (!Tpi)
558
565
return Tpi.takeError ();
559
566
560
- // Even if the user doesn't want to dump type records, we still need to
561
- // iterate them in order to build the type database. So when they want to
562
- // dump symbols but not types, don't stick a dumper on the end, just build
563
- // the type database.
567
+ std::unique_ptr<DictScope> StreamScope;
568
+ std::unique_ptr<ListScope> RecordScope;
569
+
570
+ if (!IsSilentDatabaseBuild) {
571
+ StreamScope = llvm::make_unique<DictScope>(P, Label);
572
+ P.printNumber (VerLabel, Tpi->getTpiVersion ());
573
+ P.printNumber (" Record count" , Tpi->NumTypeRecords ());
574
+ }
575
+
564
576
TypeDatabaseVisitor DBV (TypeDB);
565
577
CompactTypeDumpVisitor CTDV (TypeDB, &P);
566
578
TypeDumpVisitor TDV (TypeDB, &P, false );
579
+ RecordBytesVisitor RBV (P);
567
580
TypeDeserializer Deserializer;
581
+
582
+ // We always need to deserialize and add it to the type database. This is
583
+ // true if even if we're not dumping anything, because we could need the
584
+ // type database for the purposes of dumping symbols.
568
585
TypeVisitorCallbackPipeline Pipeline;
569
586
Pipeline.addCallbackToPipeline (Deserializer);
570
587
Pipeline.addCallbackToPipeline (DBV);
571
588
572
- CVTypeVisitor Visitor (Pipeline);
573
-
574
- if (DumpRecords || DumpRecordBytes) {
575
- DictScope D (P, Label);
576
-
577
- P.printNumber (VerLabel, Tpi->getTpiVersion ());
578
- P.printNumber (" Record count" , Tpi->NumTypeRecords ());
579
- ListScope L (P, " Records" );
580
-
581
- bool HadError = false ;
589
+ // If we're in dump mode, add a dumper with the appropriate detail level.
590
+ if (DumpRecords) {
582
591
if (opts::raw::CompactRecords)
583
592
Pipeline.addCallbackToPipeline (CTDV);
584
593
else
585
594
Pipeline.addCallbackToPipeline (TDV);
595
+ }
596
+ if (DumpRecordBytes)
597
+ Pipeline.addCallbackToPipeline (RBV);
586
598
587
- for (auto Type : Tpi->types (&HadError)) {
588
- std::unique_ptr<DictScope> Scope;
589
- if (!opts::raw::CompactRecords)
590
- Scope.reset (new DictScope (P, " " ));
599
+ CVTypeVisitor Visitor (Pipeline);
591
600
592
- if (DumpRecords) {
593
- if (auto EC = Visitor.visitTypeRecord (Type))
594
- return EC;
595
- }
601
+ if (DumpRecords || DumpRecordBytes)
602
+ RecordScope = llvm::make_unique<ListScope>(P, " Records" );
596
603
597
- if (DumpRecordBytes)
598
- P.printBinaryBlock (" Bytes" , Type.content ());
599
- }
600
- dumpTpiHash (P, *Tpi);
601
- if (HadError)
602
- return make_error<RawError>(raw_error_code::corrupt_file,
603
- " TPI stream contained corrupt record" );
604
- {
605
- ListScope L (P, " TypeIndexOffsets" );
606
- for (const auto &IO : Tpi->getTypeIndexOffsets ()) {
607
- P.printString (formatv (" Index: {0:x}, Offset: {1:N}" , IO.Type .getIndex (),
608
- (uint32_t )IO.Offset )
609
- .str ());
610
- }
611
- }
604
+ bool HadError = false ;
605
+
606
+ TypeIndex T (TypeIndex::FirstNonSimpleIndex);
607
+ for (auto Type : Tpi->types (&HadError)) {
608
+ std::unique_ptr<DictScope> OneRecordScope;
612
609
613
- } else if (opts::raw::DumpModuleSyms) {
610
+ if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords)
611
+ OneRecordScope = llvm::make_unique<DictScope>(P, " " );
614
612
615
- bool HadError = false ;
616
- for (auto Type : Tpi->types (&HadError)) {
617
- if (auto EC = Visitor.visitTypeRecord (Type))
618
- return EC;
613
+ if (auto EC = Visitor.visitTypeRecord (Type))
614
+ return EC;
615
+ }
616
+ if (HadError)
617
+ return make_error<RawError>(raw_error_code::corrupt_file,
618
+ " TPI stream contained corrupt record" );
619
+
620
+ if (DumpTpiHash) {
621
+ DictScope DD (P, " Hash" );
622
+ P.printNumber (" Number of Hash Buckets" , Tpi->NumHashBuckets ());
623
+ P.printNumber (" Hash Key Size" , Tpi->getHashKeySize ());
624
+ P.printList (" Values" , Tpi->getHashValues ());
625
+
626
+ ListScope LHA (P, " Adjusters" );
627
+ auto ExpectedST = File.getStringTable ();
628
+ if (!ExpectedST)
629
+ return ExpectedST.takeError ();
630
+ const auto &ST = *ExpectedST;
631
+ for (const auto &E : Tpi->getHashAdjusters ()) {
632
+ DictScope DHA (P);
633
+ StringRef Name = ST.getStringForID (E.first );
634
+ P.printString (" Type" , Name);
635
+ P.printHex (" TI" , E.second );
619
636
}
637
+ }
620
638
621
- dumpTpiHash (P, *Tpi);
622
- if (HadError)
623
- return make_error<RawError>(raw_error_code::corrupt_file,
624
- " TPI stream contained corrupt record" );
639
+ if (!IsSilentDatabaseBuild) {
640
+ ListScope L (P, " TypeIndexOffsets" );
641
+ for (const auto &IO : Tpi->getTypeIndexOffsets ()) {
642
+ P.printString (formatv (" Index: {0:x}, Offset: {1:N}" , IO.Type .getIndex (),
643
+ (uint32_t )IO.Offset )
644
+ .str ());
645
+ }
625
646
}
647
+
626
648
P.flush ();
627
649
return Error::success ();
628
650
}
0 commit comments