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" @@ -1314,6 +1315,8 @@ // Add all object files to the PDB. Merge .debug$T sections into IpiData and // TpiData. void PDBLinker::addObjectsToPDB() { + Summary::print(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::print(TypeServerIndexMappings.size(), "Dependent PDB files"); + Summary::print(PrecompTypeIndexMappings.size(), "Dependent PCH OBJ files"); + Summary::print(GlobalTypeTable.size() + GlobalIDTable.size(), + "Output merged type records"); + Summary::print(PDBStrTab.size(), "Output PDB strings"); + // Construct TPI and IPI stream contents. ScopedTimer T2(TpiStreamLayoutTimer); addTypeInfo(Builder.getTpiBuilder(), getTypeTable()); @@ -1345,6 +1354,8 @@ }); for (const PublicSym32 &Pub : Publics) GsiBuilder.addPublicSymbol(Pub); + + Summary::print(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,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,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);