Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -13,6 +13,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/Timer.h" #include @@ -118,6 +119,7 @@ bool SaveTemps; bool Shared; bool Static = false; + bool Stats; bool SysvHash = true; bool Target1Rel; bool Threads; @@ -149,6 +151,7 @@ unsigned LtoO; unsigned Optimize; unsigned ThinLtoJobs; + llvm::TimeRecord StartTime; }; // The only instance of Configuration struct. Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -299,6 +299,9 @@ } if (Args.hasArg(OPT_version)) outs() << getLLDVersion() << "\n"; + if (Args.hasArg(OPT_stats)) + Config->StartTime = TimeRecord::getCurrentTime(true); + Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown); if (const char *Path = getReproduceOption(Args)) { @@ -489,6 +492,7 @@ Config->Relocatable = Args.hasArg(OPT_relocatable); Config->SaveTemps = Args.hasArg(OPT_save_temps); Config->Shared = Args.hasArg(OPT_shared); + Config->Stats = Args.hasArg(OPT_stats); Config->Target1Rel = getArg(Args, OPT_target1_rel, OPT_target1_abs, false); Config->Threads = Args.hasArg(OPT_threads); Config->Trace = Args.hasArg(OPT_trace); Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -173,6 +173,8 @@ def start_lib: F<"start-lib">, HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">; +def stats: F<"stats">, HelpText<"Print resource usage statistics">; + def strip_all: F<"strip-all">, HelpText<"Strip all symbols">; def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" #include @@ -194,6 +195,15 @@ return; if (auto EC = Buffer->commit()) error(EC, "failed to write to the output file"); + if (Config->Stats) { + TimeRecord T = TimeRecord::getCurrentTime(true); + outs() << format("Link user time: %7.4f", + T.getUserTime() - Config->StartTime.getUserTime()) + << "\n"; + outs() << format("Memory usage: %9" PRId64 " ", + (int64_t)sys::Process::GetMallocUsage()) + << "\n"; + } if (Config->ExitEarly) { // Flush the output streams and exit immediately. A full shutdown is a good // test that we are keeping track of all allocated memory, but actually Index: test/ELF/stats.s =================================================================== --- test/ELF/stats.s +++ test/ELF/stats.s @@ -0,0 +1,7 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: ld.lld -stats %t -o %t2 2>&1 | FileCheck %s -check-prefix=STATS + +# STATS: Link user time: +# STATS: Memory usage: