Index: COFF/Config.h =================================================================== --- COFF/Config.h +++ COFF/Config.h @@ -101,6 +101,7 @@ bool DebugGHashes = false; bool DebugSymtab = false; bool ShowTiming = false; + bool ShowSummary = false; unsigned DebugTypes = static_cast(DebugType::None); std::vector NatvisFiles; llvm::SmallString<128> PDBAltPath; 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/Timer.h" #include "lld/Common/Version.h" #include "llvm/ADT/Optional.h" @@ -990,6 +991,9 @@ if (Args.hasArg(OPT_show_timing)) Config->ShowTiming = true; + if (Args.hasArg(OPT_summary)) + Config->ShowSummary = 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 @@ -1707,6 +1711,10 @@ Timer::root().stop(); if (Config->ShowTiming) Timer::root().print(); + if (Config->ShowSummary && Config->ShowTiming) + message(""); + if (Config->ShowSummary) + Summary::print(); } } // namespace coff Index: COFF/Options.td =================================================================== --- COFF/Options.td +++ COFF/Options.td @@ -168,6 +168,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 "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" @@ -1314,6 +1315,8 @@ // Add all object files to the PDB. Merge .debug$T sections into IpiData and // TpiData. void PDBLinker::addObjectsToPDB() { + Summary::addLine(ObjFile::Instances.size(), "Input OBJ files (expanded from all cmd-line inputs)"); + ScopedTimer T1(AddObjectsTimer); for (ObjFile *File : ObjFile::Instances) addObjFile(File); @@ -1321,6 +1324,12 @@ Builder.getStringTableBuilder().setStrings(PDBStrTab); T1.stop(); + Summary::addLine(TypeServerIndexMappings.size(), "Dependent PDB files"); + Summary::addLine(PrecompTypeIndexMappings.size(), "Dependent PCH OBJ files"); + Summary::addLine(GlobalTypeTable.size() + GlobalIDTable.size(), + "Output merged type records"); + Summary::addLine(PDBStrTab.size(), "Output PDB strings"); + // Construct TPI and IPI stream contents. ScopedTimer T2(TpiStreamLayoutTimer); addTypeInfo(Builder.getTpiBuilder(), getTypeTable()); @@ -1346,6 +1355,8 @@ }); for (const PublicSym32 &Pub : Publics) GsiBuilder.addPublicSymbol(Pub); + + Summary::addLine(Publics.size(), "Output global symbol records"); } } 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,44 @@ +//===- 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/ErrorHandler.h" +#include "lld/Common/Summary.h" +#include "llvm/ADT/SmallString.h" + +using namespace lld; +using namespace llvm; + +template +static std::string format(T formatter) { + SmallString<80> Buff; + llvm::raw_svector_ostream Stream(Buff); + Stream << formatter; + return Buff.c_str(); +} + +static void printLine(uint64_t Val, StringRef S) { + if (!Val) + return; + std::string Formatted = format(format_decimal(Val, 15)); + message(Formatted + " " + S); +} + +namespace lld { +namespace Summary { +static std::vector> Lines; +void addLine(uint64_t Val, StringRef S) { Lines.push_back({Val, S.str()}); }; +void print() { + message(format(center_justify("Summary", 80))); + message(std::string(80, '-')); + for (auto& L : Lines) + { + printLine(L.first, L.second); + } +} +} // namespace Summary +} // namespace lld 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,10 @@ 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 Dependent PDB files +SUMMARY-NEXT: 3 Output PDB strings +SUMMARY-NEXT: 2 Output global 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,13 @@ 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 Dependent PCH OBJ files +SUMMARY-NEXT: 5 Output PDB strings +SUMMARY-NEXT: 3 Output global symbol records + // precomp.h #pragma once int Function(char A);