[lld] 14f7e5f - [LLD][COFF] Make `/summary` work when `/debug` isn't provided (#157476)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 9 04:28:27 PDT 2025
Author: Alexandre Ganea
Date: 2025-09-09T07:28:24-04:00
New Revision: 14f7e5fa06235dac1a2d82290aa4d69de9d56862
URL: https://github.com/llvm/llvm-project/commit/14f7e5fa06235dac1a2d82290aa4d69de9d56862
DIFF: https://github.com/llvm/llvm-project/commit/14f7e5fa06235dac1a2d82290aa4d69de9d56862.diff
LOG: [LLD][COFF] Make `/summary` work when `/debug` isn't provided (#157476)
Previously, `/summary` was meant to print some PDB information. Now move
handling of `/summary` to `Writer.cpp` so that it can have an effect
when `/debug` isn't provided. This will also provide grounds for
extending with more general information.
Added:
Modified:
lld/COFF/COFFLinkerContext.h
lld/COFF/PDB.cpp
lld/COFF/PDB.h
lld/COFF/Writer.cpp
lld/test/COFF/pdb-type-server-simple.test
lld/test/COFF/precomp-link.test
lld/test/COFF/precomp-summary-fail.test
Removed:
################################################################################
diff --git a/lld/COFF/COFFLinkerContext.h b/lld/COFF/COFFLinkerContext.h
index b44263b5a3390..0f8f2062b9f2e 100644
--- a/lld/COFF/COFFLinkerContext.h
+++ b/lld/COFF/COFFLinkerContext.h
@@ -14,6 +14,7 @@
#include "DebugTypes.h"
#include "Driver.h"
#include "InputFiles.h"
+#include "PDB.h"
#include "SymbolTable.h"
#include "Writer.h"
#include "lld/Common/CommonLinkerContext.h"
@@ -113,6 +114,8 @@ class COFFLinkerContext : public CommonLinkerContext {
Timer tpiStreamLayoutTimer;
Timer diskCommitTimer;
+ std::optional<PDBStats> pdbStats;
+
Configuration config;
DynamicRelocsChunk *dynamicRelocs = nullptr;
diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp
index e5c62af28fdd2..fd54d20da3ccd 100644
--- a/lld/COFF/PDB.cpp
+++ b/lld/COFF/PDB.cpp
@@ -44,7 +44,6 @@
#include "llvm/Object/CVDebugRecord.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -133,8 +132,8 @@ class PDBLinker {
/// Write the PDB to disk and store the Guid generated for it in *Guid.
void commit(codeview::GUID *guid);
- // Print statistics regarding the final PDB
- void printStats();
+ // Collect some statistics regarding the final PDB
+ void collectStats();
private:
void pdbMakeAbsolute(SmallVectorImpl<char> &fileName);
@@ -154,13 +153,6 @@ class PDBLinker {
DebugStringTableSubsection pdbStrTab;
llvm::SmallString<128> nativePath;
-
- // For statistics
- uint64_t globalSymbols = 0;
- uint64_t moduleSymbols = 0;
- uint64_t publicSymbols = 0;
- uint64_t nbTypeRecords = 0;
- uint64_t nbTypeRecordsBytes = 0;
};
/// Represents an unrelocated DEBUG_S_FRAMEDATA subsection.
@@ -610,7 +602,9 @@ void PDBLinker::analyzeSymbolSubsection(
addGlobalSymbol(builder.getGsiBuilder(),
file->moduleDBI->getModuleIndex(), moduleSymOffset,
storage);
- ++globalSymbols;
+
+ if (ctx.pdbStats.has_value())
+ ++ctx.pdbStats->globalSymbols;
}
// Update the module stream offset and record any string table index
@@ -619,7 +613,9 @@ void PDBLinker::analyzeSymbolSubsection(
if (symbolGoesInModuleStream(sym, scopeLevel)) {
recordStringTableReferences(sym, moduleSymOffset, stringTableFixups);
moduleSymOffset += alignedSize;
- ++moduleSymbols;
+
+ if (ctx.pdbStats.has_value())
+ ++ctx.pdbStats->moduleSymbols;
}
return Error::success();
@@ -1192,10 +1188,10 @@ void PDBLinker::addObjectsToPDB() {
}
}
- if (ctx.config.showSummary) {
+ if (ctx.pdbStats.has_value()) {
for (TpiSource *source : ctx.tpiSourceList) {
- nbTypeRecords += source->nbTypeRecords;
- nbTypeRecordsBytes += source->nbTypeRecordsBytes;
+ ctx.pdbStats->nbTypeRecords += source->nbTypeRecords;
+ ctx.pdbStats->nbTypeRecordsBytes += source->nbTypeRecordsBytes;
}
}
}
@@ -1231,43 +1227,24 @@ void PDBLinker::addPublicsToPDB() {
}
});
- if (!publics.empty()) {
- publicSymbols = publics.size();
+ if (ctx.pdbStats.has_value())
+ ctx.pdbStats->publicSymbols = publics.size();
+
+ if (!publics.empty())
gsiBuilder.addPublicSymbols(std::move(publics));
- }
}
-void PDBLinker::printStats() {
+void PDBLinker::collectStats() {
if (!ctx.config.showSummary)
return;
+ ctx.pdbStats->nbTPIrecords = builder.getTpiBuilder().getRecordCount();
+ ctx.pdbStats->nbIPIrecords = builder.getIpiBuilder().getRecordCount();
+ ctx.pdbStats->strTabSize = pdbStrTab.size();
+
SmallString<256> buffer;
raw_svector_ostream stream(buffer);
- stream << center_justify("Summary", 80) << '\n'
- << std::string(80, '-') << '\n';
-
- auto print = [&](uint64_t v, StringRef s) {
- stream << formatv("{0}",
- fmt_align(formatv("{0:N}", v), AlignStyle::Right, 20))
- << " " << s << '\n';
- };
-
- print(ctx.objFileInstances.size(),
- "Input OBJ files (expanded from all cmd-line inputs)");
- print(ctx.consumedInputsSize,
- "Size of all consumed OBJ files (non-lazy), in bytes");
- print(ctx.typeServerSourceMappings.size(), "PDB type server dependencies");
- print(ctx.precompSourceMappings.size(), "Precomp OBJ dependencies");
- print(nbTypeRecords, "Input type records");
- print(nbTypeRecordsBytes, "Size of all input type records, in bytes");
- print(builder.getTpiBuilder().getRecordCount(), "Merged TPI records");
- print(builder.getIpiBuilder().getRecordCount(), "Merged IPI records");
- print(pdbStrTab.size(), "Output PDB strings");
- print(globalSymbols, "Global symbol records");
- print(moduleSymbols, "Module symbol records");
- print(publicSymbols, "Public symbol records");
-
auto printLargeInputTypeRecs = [&](StringRef name,
ArrayRef<uint32_t> recCounts,
TypeCollection &records) {
@@ -1318,9 +1295,9 @@ void PDBLinker::printStats() {
// FIXME: Reimplement for ghash.
printLargeInputTypeRecs("TPI", tMerger.tpiCounts, tMerger.getTypeTable());
printLargeInputTypeRecs("IPI", tMerger.ipiCounts, tMerger.getIDTable());
- }
- Msg(ctx) << buffer;
+ ctx.pdbStats->largeInputTypeRecs = buffer.str();
+ }
}
void PDBLinker::addNatvisFiles() {
@@ -1624,6 +1601,9 @@ void lld::coff::createPDB(COFFLinkerContext &ctx,
{
PDBLinker pdb(ctx);
+ if (ctx.config.showSummary)
+ ctx.pdbStats.emplace();
+
pdb.initialize(buildId);
pdb.addObjectsToPDB();
pdb.addImportFilesToPDB();
@@ -1640,8 +1620,8 @@ void lld::coff::createPDB(COFFLinkerContext &ctx,
memcpy(&buildId->PDB70.Signature, &guid, 16);
}
+ pdb.collectStats();
t1.stop();
- pdb.printStats();
// Manually start this profile point to measure ~PDBLinker().
if (getTimeTraceProfilerInstance() != nullptr)
diff --git a/lld/COFF/PDB.h b/lld/COFF/PDB.h
index 991805cc95b38..4a5df37c0fe6f 100644
--- a/lld/COFF/PDB.h
+++ b/lld/COFF/PDB.h
@@ -30,6 +30,19 @@ void createPDB(COFFLinkerContext &ctx, llvm::ArrayRef<uint8_t> sectionTable,
std::optional<std::pair<llvm::StringRef, uint32_t>>
getFileLineCodeView(const SectionChunk *c, uint32_t addr);
+// For statistics
+struct PDBStats {
+ uint64_t globalSymbols = 0;
+ uint64_t moduleSymbols = 0;
+ uint64_t publicSymbols = 0;
+ uint64_t nbTypeRecords = 0;
+ uint64_t nbTypeRecordsBytes = 0;
+ uint64_t nbTPIrecords = 0;
+ uint64_t nbIPIrecords = 0;
+ uint64_t strTabSize = 0;
+ std::string largeInputTypeRecs;
+};
+
} // namespace coff
} // namespace lld
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 37577e8dd93d9..e0d0ac18ea5d5 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -27,6 +27,8 @@
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/RandomNumberGenerator.h"
#include "llvm/Support/TimeProfiler.h"
@@ -282,6 +284,8 @@ class Writer {
template <typename T>
void prepareLoadConfig(SymbolTable &symtab, T *loadConfig);
+ void printSummary();
+
std::unique_ptr<FileOutputBuffer> &buffer;
std::map<PartialSectionKey, PartialSection *> partialSections;
StringTableBuilder strtab;
@@ -823,6 +827,8 @@ void Writer::run() {
writePEChecksum();
+ printSummary();
+
if (errorCount())
return;
@@ -3046,3 +3052,43 @@ void Writer::prepareLoadConfig(SymbolTable &symtab, T *loadConfig) {
#undef CHECK_VA
#undef CHECK_ABSOLUTE
}
+
+void Writer::printSummary() {
+ if (!ctx.config.showSummary)
+ return;
+
+ SmallString<256> buffer;
+ raw_svector_ostream stream(buffer);
+
+ stream << center_justify("Summary", 80) << '\n'
+ << std::string(80, '-') << '\n';
+
+ auto print = [&](uint64_t v, StringRef s) {
+ stream << formatv("{0}",
+ fmt_align(formatv("{0:N}", v), AlignStyle::Right, 20))
+ << " " << s << '\n';
+ };
+
+ bool hasStats = ctx.pdbStats.has_value();
+
+ print(ctx.objFileInstances.size(),
+ "Input OBJ files (expanded from all cmd-line inputs)");
+ print(ctx.consumedInputsSize,
+ "Size of all consumed OBJ files (non-lazy), in bytes");
+ print(ctx.typeServerSourceMappings.size(), "PDB type server dependencies");
+ print(ctx.precompSourceMappings.size(), "Precomp OBJ dependencies");
+ print(hasStats ? ctx.pdbStats->nbTypeRecords : 0, "Input debug type records");
+ print(hasStats ? ctx.pdbStats->nbTypeRecordsBytes : 0,
+ "Size of all input debug type records, in bytes");
+ print(hasStats ? ctx.pdbStats->nbTPIrecords : 0, "Merged TPI records");
+ print(hasStats ? ctx.pdbStats->nbIPIrecords : 0, "Merged IPI records");
+ print(hasStats ? ctx.pdbStats->strTabSize : 0, "Output PDB strings");
+ print(hasStats ? ctx.pdbStats->globalSymbols : 0, "Global symbol records");
+ print(hasStats ? ctx.pdbStats->moduleSymbols : 0, "Module symbol records");
+ print(hasStats ? ctx.pdbStats->publicSymbols : 0, "Public symbol records");
+
+ if (hasStats)
+ stream << ctx.pdbStats->largeInputTypeRecs;
+
+ Msg(ctx) << buffer;
+}
diff --git a/lld/test/COFF/pdb-type-server-simple.test b/lld/test/COFF/pdb-type-server-simple.test
index 5323a078ac432..693bd9b482dae 100644
--- a/lld/test/COFF/pdb-type-server-simple.test
+++ b/lld/test/COFF/pdb-type-server-simple.test
@@ -110,8 +110,8 @@ SUMMARY-NEXT: 2 Input OBJ files (expanded from all cmd-line i
SUMMARY-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
SUMMARY-NEXT: 1 PDB type server dependencies
SUMMARY-NEXT: 0 Precomp OBJ dependencies
-SUMMARY-NEXT: 25 Input type records
-SUMMARY-NEXT: 868 Size of all input type records, in bytes
+SUMMARY-NEXT: 25 Input debug type records
+SUMMARY-NEXT: 868 Size of all input debug type records, in bytes
SUMMARY-NEXT: 9 Merged TPI records
SUMMARY-NEXT: 16 Merged IPI records
SUMMARY-NEXT: 3 Output PDB strings
diff --git a/lld/test/COFF/precomp-link.test b/lld/test/COFF/precomp-link.test
index 1c26042a44c33..389747920ffcf 100644
--- a/lld/test/COFF/precomp-link.test
+++ b/lld/test/COFF/precomp-link.test
@@ -3,6 +3,9 @@ RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
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
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
+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
+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
+
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
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
@@ -63,8 +66,8 @@ SUMMARY-NEXT: 3 Input OBJ files (expanded from all cmd-line i
SUMMARY-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
SUMMARY-NEXT: 0 PDB type server dependencies
SUMMARY-NEXT: 1 Precomp OBJ dependencies
-SUMMARY-NEXT: 1,066 Input type records
-SUMMARY-NEXT: 55,968 Size of all input type records, in bytes
+SUMMARY-NEXT: 1,066 Input debug type records
+SUMMARY-NEXT: 55,968 Size of all input debug type records, in bytes
SUMMARY-NEXT: 874 Merged TPI records
SUMMARY-NEXT: 170 Merged IPI records
SUMMARY-NEXT: 5 Output PDB strings
@@ -72,6 +75,21 @@ SUMMARY-NEXT: 167 Global symbol records
SUMMARY-NEXT: 20 Module symbol records
SUMMARY-NEXT: 3 Public symbol records
+SUMMARY-NODEBUG: Summary
+SUMMARY-NODEBUG-NEXT: --------------------------------------------------------------------------------
+SUMMARY-NODEBUG-NEXT: 3 Input OBJ files (expanded from all cmd-line inputs)
+SUMMARY-NODEBUG-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
+SUMMARY-NODEBUG-NEXT: 0 PDB type server dependencies
+SUMMARY-NODEBUG-NEXT: 0 Precomp OBJ dependencies
+SUMMARY-NODEBUG-NEXT: 0 Input debug type records
+SUMMARY-NODEBUG-NEXT: 0 Size of all input debug type records, in bytes
+SUMMARY-NODEBUG-NEXT: 0 Merged TPI records
+SUMMARY-NODEBUG-NEXT: 0 Merged IPI records
+SUMMARY-NODEBUG-NEXT: 0 Output PDB strings
+SUMMARY-NODEBUG-NEXT: 0 Global symbol records
+SUMMARY-NODEBUG-NEXT: 0 Module symbol records
+SUMMARY-NODEBUG-NEXT: 0 Public symbol records
+
// precomp.h
#pragma once
int Function(char A);
diff --git a/lld/test/COFF/precomp-summary-fail.test b/lld/test/COFF/precomp-summary-fail.test
index 0d528c76c2180..5568316ff63c6 100644
--- a/lld/test/COFF/precomp-summary-fail.test
+++ b/lld/test/COFF/precomp-summary-fail.test
@@ -15,8 +15,8 @@ SUMMARY-NEXT: 2 Input OBJ files (expanded from all cmd-line i
SUMMARY-NEXT: Size of all consumed OBJ files (non-lazy), in bytes
SUMMARY-NEXT: 0 PDB type server dependencies
SUMMARY-NEXT: 1 Precomp OBJ dependencies
-SUMMARY-NEXT: 8 Input type records
-SUMMARY-NEXT: 232 Size of all input type records, in bytes
+SUMMARY-NEXT: 8 Input debug type records
+SUMMARY-NEXT: 232 Size of all input debug type records, in bytes
SUMMARY-NEXT: 3 Merged TPI records
SUMMARY-NEXT: 2 Merged IPI records
SUMMARY-NEXT: 1 Output PDB strings
More information about the llvm-commits
mailing list