Skip to content

Commit 3cc5a5d

Browse files
committed
[LLD][COFF] Make /summary work when /debug isn't provided
Previously, `/summary` was meant to print some PDB information. Now move handling of `/summary` to `Writer.cpp` so that the flag will have an effect when `/debug` isn't provided. This will also provide grounds for extending with more general information.
1 parent be6f110 commit 3cc5a5d

File tree

7 files changed

+112
-52
lines changed

7 files changed

+112
-52
lines changed

lld/COFF/COFFLinkerContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "DebugTypes.h"
1515
#include "Driver.h"
1616
#include "InputFiles.h"
17+
#include "PDB.h"
1718
#include "SymbolTable.h"
1819
#include "Writer.h"
1920
#include "lld/Common/CommonLinkerContext.h"
@@ -113,6 +114,8 @@ class COFFLinkerContext : public CommonLinkerContext {
113114
Timer tpiStreamLayoutTimer;
114115
Timer diskCommitTimer;
115116

117+
std::optional<PDBStats> pdbStats;
118+
116119
Configuration config;
117120

118121
DynamicRelocsChunk *dynamicRelocs = nullptr;

lld/COFF/PDB.cpp

Lines changed: 26 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
#include "llvm/Object/CVDebugRecord.h"
4545
#include "llvm/Support/CRC.h"
4646
#include "llvm/Support/Endian.h"
47-
#include "llvm/Support/FormatAdapters.h"
4847
#include "llvm/Support/FormatVariadic.h"
4948
#include "llvm/Support/Path.h"
5049
#include "llvm/Support/ScopedPrinter.h"
@@ -133,8 +132,8 @@ class PDBLinker {
133132
/// Write the PDB to disk and store the Guid generated for it in *Guid.
134133
void commit(codeview::GUID *guid);
135134

136-
// Print statistics regarding the final PDB
137-
void printStats();
135+
// Collect some statistics regarding the final PDB
136+
void collectStats();
138137

139138
private:
140139
void pdbMakeAbsolute(SmallVectorImpl<char> &fileName);
@@ -154,13 +153,6 @@ class PDBLinker {
154153
DebugStringTableSubsection pdbStrTab;
155154

156155
llvm::SmallString<128> nativePath;
157-
158-
// For statistics
159-
uint64_t globalSymbols = 0;
160-
uint64_t moduleSymbols = 0;
161-
uint64_t publicSymbols = 0;
162-
uint64_t nbTypeRecords = 0;
163-
uint64_t nbTypeRecordsBytes = 0;
164156
};
165157

166158
/// Represents an unrelocated DEBUG_S_FRAMEDATA subsection.
@@ -610,7 +602,9 @@ void PDBLinker::analyzeSymbolSubsection(
610602
addGlobalSymbol(builder.getGsiBuilder(),
611603
file->moduleDBI->getModuleIndex(), moduleSymOffset,
612604
storage);
613-
++globalSymbols;
605+
606+
if (ctx.pdbStats.has_value())
607+
++ctx.pdbStats->globalSymbols;
614608
}
615609

616610
// Update the module stream offset and record any string table index
@@ -619,7 +613,9 @@ void PDBLinker::analyzeSymbolSubsection(
619613
if (symbolGoesInModuleStream(sym, scopeLevel)) {
620614
recordStringTableReferences(sym, moduleSymOffset, stringTableFixups);
621615
moduleSymOffset += alignedSize;
622-
++moduleSymbols;
616+
617+
if (ctx.pdbStats.has_value())
618+
++ctx.pdbStats->moduleSymbols;
623619
}
624620

625621
return Error::success();
@@ -1192,10 +1188,10 @@ void PDBLinker::addObjectsToPDB() {
11921188
}
11931189
}
11941190

1195-
if (ctx.config.showSummary) {
1191+
if (ctx.pdbStats.has_value()) {
11961192
for (TpiSource *source : ctx.tpiSourceList) {
1197-
nbTypeRecords += source->nbTypeRecords;
1198-
nbTypeRecordsBytes += source->nbTypeRecordsBytes;
1193+
ctx.pdbStats->nbTypeRecords += source->nbTypeRecords;
1194+
ctx.pdbStats->nbTypeRecordsBytes += source->nbTypeRecordsBytes;
11991195
}
12001196
}
12011197
}
@@ -1231,43 +1227,24 @@ void PDBLinker::addPublicsToPDB() {
12311227
}
12321228
});
12331229

1234-
if (!publics.empty()) {
1235-
publicSymbols = publics.size();
1230+
if (ctx.pdbStats.has_value())
1231+
ctx.pdbStats->publicSymbols = publics.size();
1232+
1233+
if (!publics.empty())
12361234
gsiBuilder.addPublicSymbols(std::move(publics));
1237-
}
12381235
}
12391236

1240-
void PDBLinker::printStats() {
1237+
void PDBLinker::collectStats() {
12411238
if (!ctx.config.showSummary)
12421239
return;
12431240

1241+
ctx.pdbStats->nbTPIrecords = builder.getTpiBuilder().getRecordCount();
1242+
ctx.pdbStats->nbIPIrecords = builder.getIpiBuilder().getRecordCount();
1243+
ctx.pdbStats->strTabSize = pdbStrTab.size();
1244+
12441245
SmallString<256> buffer;
12451246
raw_svector_ostream stream(buffer);
12461247

1247-
stream << center_justify("Summary", 80) << '\n'
1248-
<< std::string(80, '-') << '\n';
1249-
1250-
auto print = [&](uint64_t v, StringRef s) {
1251-
stream << formatv("{0}",
1252-
fmt_align(formatv("{0:N}", v), AlignStyle::Right, 20))
1253-
<< " " << s << '\n';
1254-
};
1255-
1256-
print(ctx.objFileInstances.size(),
1257-
"Input OBJ files (expanded from all cmd-line inputs)");
1258-
print(ctx.consumedInputsSize,
1259-
"Size of all consumed OBJ files (non-lazy), in bytes");
1260-
print(ctx.typeServerSourceMappings.size(), "PDB type server dependencies");
1261-
print(ctx.precompSourceMappings.size(), "Precomp OBJ dependencies");
1262-
print(nbTypeRecords, "Input type records");
1263-
print(nbTypeRecordsBytes, "Size of all input type records, in bytes");
1264-
print(builder.getTpiBuilder().getRecordCount(), "Merged TPI records");
1265-
print(builder.getIpiBuilder().getRecordCount(), "Merged IPI records");
1266-
print(pdbStrTab.size(), "Output PDB strings");
1267-
print(globalSymbols, "Global symbol records");
1268-
print(moduleSymbols, "Module symbol records");
1269-
print(publicSymbols, "Public symbol records");
1270-
12711248
auto printLargeInputTypeRecs = [&](StringRef name,
12721249
ArrayRef<uint32_t> recCounts,
12731250
TypeCollection &records) {
@@ -1318,9 +1295,9 @@ void PDBLinker::printStats() {
13181295
// FIXME: Reimplement for ghash.
13191296
printLargeInputTypeRecs("TPI", tMerger.tpiCounts, tMerger.getTypeTable());
13201297
printLargeInputTypeRecs("IPI", tMerger.ipiCounts, tMerger.getIDTable());
1321-
}
13221298

1323-
Msg(ctx) << buffer;
1299+
ctx.pdbStats->largeInputTypeRecs = buffer.str();
1300+
}
13241301
}
13251302

13261303
void PDBLinker::addNatvisFiles() {
@@ -1624,6 +1601,9 @@ void lld::coff::createPDB(COFFLinkerContext &ctx,
16241601
{
16251602
PDBLinker pdb(ctx);
16261603

1604+
if (ctx.config.showSummary)
1605+
ctx.pdbStats.emplace();
1606+
16271607
pdb.initialize(buildId);
16281608
pdb.addObjectsToPDB();
16291609
pdb.addImportFilesToPDB();
@@ -1640,8 +1620,8 @@ void lld::coff::createPDB(COFFLinkerContext &ctx,
16401620
memcpy(&buildId->PDB70.Signature, &guid, 16);
16411621
}
16421622

1623+
pdb.collectStats();
16431624
t1.stop();
1644-
pdb.printStats();
16451625

16461626
// Manually start this profile point to measure ~PDBLinker().
16471627
if (getTimeTraceProfilerInstance() != nullptr)

lld/COFF/PDB.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ void createPDB(COFFLinkerContext &ctx, llvm::ArrayRef<uint8_t> sectionTable,
3030
std::optional<std::pair<llvm::StringRef, uint32_t>>
3131
getFileLineCodeView(const SectionChunk *c, uint32_t addr);
3232

33+
// For statistics
34+
struct PDBStats {
35+
uint64_t globalSymbols = 0;
36+
uint64_t moduleSymbols = 0;
37+
uint64_t publicSymbols = 0;
38+
uint64_t nbTypeRecords = 0;
39+
uint64_t nbTypeRecordsBytes = 0;
40+
uint64_t nbTPIrecords = 0;
41+
uint64_t nbIPIrecords = 0;
42+
uint64_t strTabSize = 0;
43+
std::string largeInputTypeRecs;
44+
};
45+
3346
} // namespace coff
3447
} // namespace lld
3548

lld/COFF/Writer.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "llvm/MC/StringTableBuilder.h"
2828
#include "llvm/Support/Endian.h"
2929
#include "llvm/Support/FileOutputBuffer.h"
30+
#include "llvm/Support/FormatAdapters.h"
31+
#include "llvm/Support/FormatVariadic.h"
3032
#include "llvm/Support/Parallel.h"
3133
#include "llvm/Support/RandomNumberGenerator.h"
3234
#include "llvm/Support/TimeProfiler.h"
@@ -282,6 +284,8 @@ class Writer {
282284
template <typename T>
283285
void prepareLoadConfig(SymbolTable &symtab, T *loadConfig);
284286

287+
void printSummary();
288+
285289
std::unique_ptr<FileOutputBuffer> &buffer;
286290
std::map<PartialSectionKey, PartialSection *> partialSections;
287291
StringTableBuilder strtab;
@@ -823,6 +827,8 @@ void Writer::run() {
823827

824828
writePEChecksum();
825829

830+
printSummary();
831+
826832
if (errorCount())
827833
return;
828834

@@ -3046,3 +3052,43 @@ void Writer::prepareLoadConfig(SymbolTable &symtab, T *loadConfig) {
30463052
#undef CHECK_VA
30473053
#undef CHECK_ABSOLUTE
30483054
}
3055+
3056+
void Writer::printSummary() {
3057+
if (!ctx.config.showSummary)
3058+
return;
3059+
3060+
SmallString<256> buffer;
3061+
raw_svector_ostream stream(buffer);
3062+
3063+
stream << center_justify("Summary", 80) << '\n'
3064+
<< std::string(80, '-') << '\n';
3065+
3066+
auto print = [&](uint64_t v, StringRef s) {
3067+
stream << formatv("{0}",
3068+
fmt_align(formatv("{0:N}", v), AlignStyle::Right, 20))
3069+
<< " " << s << '\n';
3070+
};
3071+
3072+
bool hasStats = ctx.pdbStats.has_value();
3073+
3074+
print(ctx.objFileInstances.size(),
3075+
"Input OBJ files (expanded from all cmd-line inputs)");
3076+
print(ctx.consumedInputsSize,
3077+
"Size of all consumed OBJ files (non-lazy), in bytes");
3078+
print(ctx.typeServerSourceMappings.size(), "PDB type server dependencies");
3079+
print(ctx.precompSourceMappings.size(), "Precomp OBJ dependencies");
3080+
print(hasStats ? ctx.pdbStats->nbTypeRecords : 0, "Input debug type records");
3081+
print(hasStats ? ctx.pdbStats->nbTypeRecordsBytes : 0,
3082+
"Size of all input debug type records, in bytes");
3083+
print(hasStats ? ctx.pdbStats->nbTPIrecords : 0, "Merged TPI records");
3084+
print(hasStats ? ctx.pdbStats->nbIPIrecords : 0, "Merged IPI records");
3085+
print(hasStats ? ctx.pdbStats->strTabSize : 0, "Output PDB strings");
3086+
print(hasStats ? ctx.pdbStats->globalSymbols : 0, "Global symbol records");
3087+
print(hasStats ? ctx.pdbStats->moduleSymbols : 0, "Module symbol records");
3088+
print(hasStats ? ctx.pdbStats->publicSymbols : 0, "Public symbol records");
3089+
3090+
if (hasStats)
3091+
stream << ctx.pdbStats->largeInputTypeRecs;
3092+
3093+
Msg(ctx) << buffer;
3094+
}

lld/test/COFF/pdb-type-server-simple.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ SUMMARY-NEXT: 2 Input OBJ files (expanded from all cmd-line i
110110
SUMMARY-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
111111
SUMMARY-NEXT: 1 PDB type server dependencies
112112
SUMMARY-NEXT: 0 Precomp OBJ dependencies
113-
SUMMARY-NEXT: 25 Input type records
114-
SUMMARY-NEXT: 868 Size of all input type records, in bytes
113+
SUMMARY-NEXT: 25 Input debug type records
114+
SUMMARY-NEXT: 868 Size of all input debug type records, in bytes
115115
SUMMARY-NEXT: 9 Merged TPI records
116116
SUMMARY-NEXT: 16 Merged IPI records
117117
SUMMARY-NEXT: 3 Output PDB strings

lld/test/COFF/precomp-link.test

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
33
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug:ghash /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY
44
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
55

6+
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY-NODEBUG
7+
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY-NODEBUG
8+
69
RUN: lld-link %S/Inputs/precomp.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf
710
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
811

@@ -63,15 +66,30 @@ SUMMARY-NEXT: 3 Input OBJ files (expanded from all cmd-line i
6366
SUMMARY-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
6467
SUMMARY-NEXT: 0 PDB type server dependencies
6568
SUMMARY-NEXT: 1 Precomp OBJ dependencies
66-
SUMMARY-NEXT: 1,066 Input type records
67-
SUMMARY-NEXT: 55,968 Size of all input type records, in bytes
69+
SUMMARY-NEXT: 1,066 Input debug type records
70+
SUMMARY-NEXT: 55,968 Size of all input debug type records, in bytes
6871
SUMMARY-NEXT: 874 Merged TPI records
6972
SUMMARY-NEXT: 170 Merged IPI records
7073
SUMMARY-NEXT: 5 Output PDB strings
7174
SUMMARY-NEXT: 167 Global symbol records
7275
SUMMARY-NEXT: 20 Module symbol records
7376
SUMMARY-NEXT: 3 Public symbol records
7477

78+
SUMMARY-NODEBUG: Summary
79+
SUMMARY-NODEBUG-NEXT: --------------------------------------------------------------------------------
80+
SUMMARY-NODEBUG-NEXT: 3 Input OBJ files (expanded from all cmd-line inputs)
81+
SUMMARY-NODEBUG-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
82+
SUMMARY-NODEBUG-NEXT: 0 PDB type server dependencies
83+
SUMMARY-NODEBUG-NEXT: 0 Precomp OBJ dependencies
84+
SUMMARY-NODEBUG-NEXT: 0 Input debug type records
85+
SUMMARY-NODEBUG-NEXT: 0 Size of all input debug type records, in bytes
86+
SUMMARY-NODEBUG-NEXT: 0 Merged TPI records
87+
SUMMARY-NODEBUG-NEXT: 0 Merged IPI records
88+
SUMMARY-NODEBUG-NEXT: 0 Output PDB strings
89+
SUMMARY-NODEBUG-NEXT: 0 Global symbol records
90+
SUMMARY-NODEBUG-NEXT: 0 Module symbol records
91+
SUMMARY-NODEBUG-NEXT: 0 Public symbol records
92+
7593
// precomp.h
7694
#pragma once
7795
int Function(char A);

lld/test/COFF/precomp-summary-fail.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ SUMMARY-NEXT: 2 Input OBJ files (expanded from all cmd-line i
1515
SUMMARY-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
1616
SUMMARY-NEXT: 0 PDB type server dependencies
1717
SUMMARY-NEXT: 1 Precomp OBJ dependencies
18-
SUMMARY-NEXT: 8 Input type records
19-
SUMMARY-NEXT: 232 Size of all input type records, in bytes
18+
SUMMARY-NEXT: 8 Input debug type records
19+
SUMMARY-NEXT: 232 Size of all input debug type records, in bytes
2020
SUMMARY-NEXT: 3 Merged TPI records
2121
SUMMARY-NEXT: 2 Merged IPI records
2222
SUMMARY-NEXT: 1 Output PDB strings

0 commit comments

Comments
 (0)