Index: COFF/Driver.cpp =================================================================== --- COFF/Driver.cpp +++ COFF/Driver.cpp @@ -19,6 +19,7 @@ #include "lld/Common/Driver.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" +#include "lld/Common/Summary.h" #include "lld/Common/Threads.h" #include "lld/Common/Timer.h" #include "lld/Common/Version.h" @@ -999,6 +1000,9 @@ if (Args.hasArg(OPT_show_timing)) Config->ShowTiming = true; + if (Args.hasArg(OPT_summary)) + Summary::Enabled = true; + ScopedTimer T(Timer::root()); // Handle --version, which is an lld extension. This option is a bit odd // because it doesn't start with "/", but we deliberately chose "--" to @@ -1714,8 +1718,11 @@ // Stop early so we can print the results. Timer::root().stop(); - if (Config->ShowTiming) + if (Config->ShowTiming) { + if (Summary::Enabled) + message(""); Timer::root().print(); + } } } // namespace coff Index: COFF/Options.td =================================================================== --- COFF/Options.td +++ COFF/Options.td @@ -171,6 +171,7 @@ def lldmap : F<"lldmap">; def lldmap_file : Joined<["/", "-"], "lldmap:">; def show_timing : F<"time">; +def summary : F<"summary">; //============================================================================== // The flags below do nothing. They are defined only for link.exe compatibility. Index: COFF/PDB.cpp =================================================================== --- COFF/PDB.cpp +++ COFF/PDB.cpp @@ -14,6 +14,7 @@ #include "Symbols.h" #include "Writer.h" #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Summary.h" #include "lld/Common/Timer.h" #include "lld/Common/Threads.h" #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" @@ -180,6 +181,9 @@ /// 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(); + private: BumpPtrAllocator Alloc; @@ -222,6 +226,11 @@ /// List of TypeServer PDBs which cannot be loaded. /// Cached to prevent repeated load attempts. std::map MissingTypeServerPDBs; + + // For statistics + uint64_t GlobalSymbols = 0; + uint64_t ModuleSymbols = 0; + uint64_t PublicSymbols = 0; }; class DebugSHandler { @@ -1041,9 +1050,11 @@ // adding the symbol to the module since we may need to get the next // symbol offset, and writing to the module's symbol stream will update // that offset. - if (symbolGoesInGlobalsStream(Sym, Scopes.empty())) + if (symbolGoesInGlobalsStream(Sym, Scopes.empty())) { addGlobalSymbol(Builder.getGsiBuilder(), File->ModuleDBI->getModuleIndex(), CurSymOffset, Sym); + ++GlobalSymbols; + } if (symbolGoesInModuleStream(Sym, Scopes.empty())) { // Add symbols to the module in bulk. If this symbol is contiguous @@ -1057,6 +1068,7 @@ BulkSymbols = RecordBytes; } CurSymOffset += Sym.length(); + ++ModuleSymbols; } return Error::success(); })); @@ -1339,6 +1351,7 @@ }); if (!Publics.empty()) { + PublicSymbols = Publics.size(); // Sort the public symbols and add them to the stream. parallelSort(Publics, [](const PublicSym32 &L, const PublicSym32 &R) { return L.Name < R.Name; @@ -1348,6 +1361,19 @@ } } +void PDBLinker::printStats() { + Summary::print(ObjFile::Instances.size(), + "Input OBJ files (expanded from all cmd-line inputs)"); + Summary::print(TypeServerIndexMappings.size(), "PDB type server dependencies"); + Summary::print(PrecompTypeIndexMappings.size(), "Precomp OBJ dependencies"); + Summary::print(getTypeTable().size() + getIDTable().size(), + "Merged TPI records"); + Summary::print(PDBStrTab.size(), "Output PDB strings"); + Summary::print(GlobalSymbols, "Global symbol records"); + Summary::print(ModuleSymbols, "Module symbol records"); + Summary::print(PublicSymbols, "Public symbol records"); +} + void PDBLinker::addNatvisFiles() { for (StringRef File : Config->NatvisFiles) { ErrorOr> DataOrErr = @@ -1493,6 +1519,10 @@ codeview::GUID Guid; PDB.commit(&Guid); memcpy(&BuildId->PDB70.Signature, &Guid, 16); + + T2.stop(); + T1.stop(); + PDB.printStats(); } void PDBLinker::initialize(llvm::codeview::DebugInfo *BuildId) { Index: Common/CMakeLists.txt =================================================================== --- Common/CMakeLists.txt +++ Common/CMakeLists.txt @@ -33,6 +33,7 @@ Memory.cpp Reproduce.cpp Strings.cpp + Summary.cpp TargetOptionsCommandFlags.cpp Threads.cpp Timer.cpp Index: Common/Summary.cpp =================================================================== --- Common/Summary.cpp +++ Common/Summary.cpp @@ -0,0 +1,33 @@ +//===- Summary.cpp --------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Summary.h" +#include "lld/Common/ErrorHandler.h" +#include "llvm/ADT/SmallString.h" + +using namespace lld; +using namespace llvm; + +bool Summary::Enabled = false; + +void Summary::print(uint64_t Value, llvm::StringRef S) { + if (!Enabled) + return; + if (!Value) + return; + SmallString<256> Buffer; + raw_svector_ostream Stream(Buffer); + static bool Banner = false; + if (!Banner) { + Banner = true; + Stream << center_justify("Summary", 80) << '\n' + << std::string(80, '-') << '\n'; + } + Stream << format_decimal(Value, 15) << " " << S; + message(Buffer); +} Index: include/lld/Common/Summary.h =================================================================== --- include/lld/Common/Summary.h +++ include/lld/Common/Summary.h @@ -0,0 +1,23 @@ +//===- Summary.h --------------------------------------------------*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_COMMON_SUMMARY_H +#define LLD_COMMON_SUMMARY_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Any.h" + +namespace lld { +namespace Summary { +extern bool Enabled; + +void print(uint64_t Value, llvm::StringRef S); +} +} // namespace lld + +#endif Index: test/COFF/pdb-type-server-simple.test =================================================================== --- test/COFF/pdb-type-server-simple.test +++ test/COFF/pdb-type-server-simple.test @@ -20,7 +20,7 @@ RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb -RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib +RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib /summary | FileCheck %s -check-prefix SUMMARY RUN: llvm-pdbutil dump -symbols -types -ids -globals %t/t.pdb | FileCheck %s @@ -95,3 +95,13 @@ CHECK: 196 | S_END [size = 4] CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]` CHECK-LABEL: Mod 0002 | `* Linker *`: + +SUMMARY: Summary +SUMMARY-NEXT: -------------------------------------------------------------------------------- +SUMMARY-NEXT: 2 Input OBJ files (expanded from all cmd-line inputs) +SUMMARY-NEXT: 1 PDB type server dependencies +SUMMARY-NEXT: 25 Merged TPI records +SUMMARY-NEXT: 3 Output PDB strings +SUMMARY-NEXT: 4 Global symbol records +SUMMARY-NEXT: 14 Module symbol records +SUMMARY-NEXT: 2 Public symbol records \ No newline at end of file Index: test/COFF/precomp-link.test =================================================================== --- test/COFF/precomp-link.test +++ test/COFF/precomp-link.test @@ -1,4 +1,4 @@ -RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf +RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug /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.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 @@ -18,6 +18,17 @@ CHECK-NOT: LF_PRECOMP CHECK-NOT: LF_ENDPRECOMP + +SUMMARY: Summary +SUMMARY-NEXT: -------------------------------------------------------------------------------- +SUMMARY-NEXT: 3 Input OBJ files (expanded from all cmd-line inputs) +SUMMARY-NEXT: 1 Precomp OBJ dependencies +SUMMARY-NEXT: 1044 Merged TPI records +SUMMARY-NEXT: 5 Output PDB strings +SUMMARY-NEXT: 167 Global symbol records +SUMMARY-NEXT: 20 Module symbol records +SUMMARY-NEXT: 3 Public symbol records + // precomp.h #pragma once int Function(char A);