forked from OSchip/llvm-project
[lld-macho] Add more TimeTraceScopes
I added just enough to allow us to see a top-level breakdown of time taken. This
is the result of loading the time-trace output into `chrome:://tracing`:
ef5e8234f3/tracing.png
Reviewed By: oontvoo
Differential Revision: https://reviews.llvm.org/D99311
This commit is contained in:
parent
53fd1ada76
commit
4bcaafeb0e
|
@ -85,7 +85,7 @@ struct Configuration {
|
|||
uint32_t headerPad;
|
||||
uint32_t dylibCompatibilityVersion = 0;
|
||||
uint32_t dylibCurrentVersion = 0;
|
||||
uint32_t timeTraceGranularity;
|
||||
uint32_t timeTraceGranularity = 0;
|
||||
std::string progName;
|
||||
llvm::StringRef installName;
|
||||
llvm::StringRef mapFile;
|
||||
|
|
|
@ -496,6 +496,7 @@ static void initLLVM() {
|
|||
}
|
||||
|
||||
static void compileBitcodeFiles() {
|
||||
TimeTraceScope timeScope("LTO");
|
||||
auto *lto = make<BitcodeCompiler>();
|
||||
for (InputFile *file : inputFiles)
|
||||
if (auto *bitcodeFile = dyn_cast<BitcodeFile>(file))
|
||||
|
@ -510,6 +511,7 @@ static void compileBitcodeFiles() {
|
|||
// all InputFiles have been loaded.) As a result, later operations won't see
|
||||
// any CommonSymbols.
|
||||
static void replaceCommonSymbols() {
|
||||
TimeTraceScope timeScope("Replace common symbols");
|
||||
for (macho::Symbol *sym : symtab->getSymbols()) {
|
||||
auto *common = dyn_cast<CommonSymbol>(sym);
|
||||
if (common == nullptr)
|
||||
|
@ -772,6 +774,44 @@ static void handleSymbolPatterns(InputArgList &args,
|
|||
}
|
||||
}
|
||||
|
||||
void createFiles(const InputArgList &args) {
|
||||
TimeTraceScope timeScope("Load input files");
|
||||
// This loop should be reserved for options whose exact ordering matters.
|
||||
// Other options should be handled via filtered() and/or getLastArg().
|
||||
for (const Arg *arg : args) {
|
||||
const Option &opt = arg->getOption();
|
||||
warnIfDeprecatedOption(opt);
|
||||
warnIfUnimplementedOption(opt);
|
||||
|
||||
switch (opt.getID()) {
|
||||
case OPT_INPUT:
|
||||
addFile(arg->getValue(), false);
|
||||
break;
|
||||
case OPT_weak_library:
|
||||
if (auto *dylibFile =
|
||||
dyn_cast_or_null<DylibFile>(addFile(arg->getValue(), false)))
|
||||
dylibFile->forceWeakImport = true;
|
||||
break;
|
||||
case OPT_filelist:
|
||||
addFileList(arg->getValue());
|
||||
break;
|
||||
case OPT_force_load:
|
||||
addFile(arg->getValue(), true);
|
||||
break;
|
||||
case OPT_l:
|
||||
case OPT_weak_l:
|
||||
addLibrary(arg->getValue(), opt.getID() == OPT_weak_l);
|
||||
break;
|
||||
case OPT_framework:
|
||||
case OPT_weak_framework:
|
||||
addFramework(arg->getValue(), opt.getID() == OPT_weak_framework);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
|
||||
raw_ostream &stdoutOS, raw_ostream &stderrOS) {
|
||||
lld::stdoutOS = &stdoutOS;
|
||||
|
@ -952,44 +992,10 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
|
|||
timeTraceProfilerInitialize(config->timeTraceGranularity, config->progName);
|
||||
|
||||
{
|
||||
llvm::TimeTraceScope timeScope("Link", StringRef("ExecuteLinker"));
|
||||
TimeTraceScope timeScope("Link", StringRef("ExecuteLinker"));
|
||||
|
||||
initLLVM(); // must be run before any call to addFile()
|
||||
|
||||
// This loop should be reserved for options whose exact ordering matters.
|
||||
// Other options should be handled via filtered() and/or getLastArg().
|
||||
for (const Arg *arg : args) {
|
||||
const Option &opt = arg->getOption();
|
||||
warnIfDeprecatedOption(opt);
|
||||
warnIfUnimplementedOption(opt);
|
||||
|
||||
switch (opt.getID()) {
|
||||
case OPT_INPUT:
|
||||
addFile(arg->getValue(), false);
|
||||
break;
|
||||
case OPT_weak_library:
|
||||
if (auto *dylibFile =
|
||||
dyn_cast_or_null<DylibFile>(addFile(arg->getValue(), false)))
|
||||
dylibFile->forceWeakImport = true;
|
||||
break;
|
||||
case OPT_filelist:
|
||||
addFileList(arg->getValue());
|
||||
break;
|
||||
case OPT_force_load:
|
||||
addFile(arg->getValue(), true);
|
||||
break;
|
||||
case OPT_l:
|
||||
case OPT_weak_l:
|
||||
addLibrary(arg->getValue(), opt.getID() == OPT_weak_l);
|
||||
break;
|
||||
case OPT_framework:
|
||||
case OPT_weak_framework:
|
||||
addFramework(arg->getValue(), opt.getID() == OPT_weak_framework);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
createFiles(args);
|
||||
|
||||
config->isPic = config->outputType == MH_DYLIB ||
|
||||
config->outputType == MH_BUNDLE || isPie(args);
|
||||
|
@ -1060,12 +1066,15 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
|
|||
inputFiles.insert(make<OpaqueFile>(*buffer, segName, sectName));
|
||||
}
|
||||
|
||||
// Initialize InputSections.
|
||||
for (const InputFile *file : inputFiles) {
|
||||
for (const SubsectionMap &map : file->subsections) {
|
||||
for (const auto &p : map) {
|
||||
InputSection *isec = p.second;
|
||||
inputSections.push_back(isec);
|
||||
{
|
||||
TimeTraceScope timeScope("Gathering input sections");
|
||||
// Gather all InputSections into one vector.
|
||||
for (const InputFile *file : inputFiles) {
|
||||
for (const SubsectionMap &map : file->subsections) {
|
||||
for (const auto &p : map) {
|
||||
InputSection *isec = p.second;
|
||||
inputSections.push_back(isec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "Symbols.h"
|
||||
#include "Target.h"
|
||||
#include "llvm/Support/Parallel.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::sys;
|
||||
|
@ -93,6 +94,8 @@ void macho::writeMapFile() {
|
|||
if (config->mapFile.empty())
|
||||
return;
|
||||
|
||||
TimeTraceScope timeScope("Write map file");
|
||||
|
||||
// Open a map file for writing.
|
||||
std::error_code ec;
|
||||
raw_fd_ostream os(config->mapFile, ec, sys::fs::OF_None);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include "llvm/Support/xxhash.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -56,6 +57,7 @@ public:
|
|||
void writeSections();
|
||||
void writeUuid();
|
||||
void writeCodeSignature();
|
||||
void writeOutputFile();
|
||||
|
||||
void run();
|
||||
|
||||
|
@ -502,6 +504,7 @@ static void prepareSymbolRelocation(lld::macho::Symbol *sym,
|
|||
}
|
||||
|
||||
void Writer::scanRelocations() {
|
||||
TimeTraceScope timeScope("Scan relocations");
|
||||
for (InputSection *isec : inputSections) {
|
||||
if (isec->segname == segment_names::ld) {
|
||||
prepareCompactUnwind(isec);
|
||||
|
@ -534,6 +537,7 @@ void Writer::scanRelocations() {
|
|||
}
|
||||
|
||||
void Writer::scanSymbols() {
|
||||
TimeTraceScope timeScope("Scan symbols");
|
||||
for (const macho::Symbol *sym : symtab->getSymbols()) {
|
||||
if (const auto *defined = dyn_cast<Defined>(sym)) {
|
||||
if (defined->overridesWeakDef)
|
||||
|
@ -737,6 +741,8 @@ static std::function<bool(T, T)> compareByOrder(F ord) {
|
|||
// segments, output sections within each segment, and input sections within each
|
||||
// output segment.
|
||||
static void sortSegmentsAndSections() {
|
||||
TimeTraceScope timeScope("Sort segments and sections");
|
||||
|
||||
llvm::stable_sort(outputSegments,
|
||||
compareByOrder<OutputSegment *>(segmentOrder));
|
||||
|
||||
|
@ -777,6 +783,7 @@ static NamePair maybeRenameSection(NamePair key) {
|
|||
}
|
||||
|
||||
void Writer::createOutputSections() {
|
||||
TimeTraceScope timeScope("Create output sections");
|
||||
// First, create hidden sections
|
||||
stringTableSection = make<StringTableSection>();
|
||||
unwindInfoSection = make<UnwindInfoSection>(); // TODO(gkm): only when no -r
|
||||
|
@ -834,6 +841,7 @@ void Writer::createOutputSections() {
|
|||
}
|
||||
|
||||
void Writer::finalizeAddressses() {
|
||||
TimeTraceScope timeScope("Finalize addresses");
|
||||
// Ensure that segments (and the sections they contain) are allocated
|
||||
// addresses in ascending order, which dyld requires.
|
||||
//
|
||||
|
@ -848,6 +856,7 @@ void Writer::finalizeAddressses() {
|
|||
}
|
||||
|
||||
void Writer::finalizeLinkEditSegment() {
|
||||
TimeTraceScope timeScope("Finalize __LINKEDIT segment");
|
||||
// Fill __LINKEDIT contents.
|
||||
in.rebase->finalizeContents();
|
||||
in.binding->finalizeContents();
|
||||
|
@ -904,6 +913,7 @@ void Writer::writeSections() {
|
|||
}
|
||||
|
||||
void Writer::writeUuid() {
|
||||
TimeTraceScope timeScope("Computing UUID");
|
||||
uint64_t digest =
|
||||
xxHash64({buffer->getBufferStart(), buffer->getBufferEnd()});
|
||||
uuidCommand->writeUuid(digest);
|
||||
|
@ -914,6 +924,19 @@ void Writer::writeCodeSignature() {
|
|||
codeSignatureSection->writeHashes(buffer->getBufferStart());
|
||||
}
|
||||
|
||||
void Writer::writeOutputFile() {
|
||||
TimeTraceScope timeScope("Write output file");
|
||||
openFile();
|
||||
if (errorCount())
|
||||
return;
|
||||
writeSections();
|
||||
writeUuid();
|
||||
writeCodeSignature();
|
||||
|
||||
if (auto e = buffer->commit())
|
||||
error("failed to write to the output file: " + toString(std::move(e)));
|
||||
}
|
||||
|
||||
void Writer::run() {
|
||||
prepareBranchTarget(config->entry);
|
||||
scanRelocations();
|
||||
|
@ -927,15 +950,7 @@ void Writer::run() {
|
|||
finalizeAddressses();
|
||||
finalizeLinkEditSegment();
|
||||
writeMapFile();
|
||||
openFile();
|
||||
if (errorCount())
|
||||
return;
|
||||
writeSections();
|
||||
writeUuid();
|
||||
writeCodeSignature();
|
||||
|
||||
if (auto e = buffer->commit())
|
||||
error("failed to write to the output file: " + toString(std::move(e)));
|
||||
writeOutputFile();
|
||||
}
|
||||
|
||||
void macho::writeResult() { Writer().run(); }
|
||||
|
|
Loading…
Reference in New Issue