diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -85,7 +85,7 @@ 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; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -496,6 +496,7 @@ } static void compileBitcodeFiles() { + TimeTraceScope timeScope("LTO"); auto *lto = make(); for (InputFile *file : inputFiles) if (auto *bitcodeFile = dyn_cast(file)) @@ -510,6 +511,7 @@ // 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(sym); if (common == nullptr) @@ -772,6 +774,44 @@ } } +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(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 argsArr, bool canExitEarly, raw_ostream &stdoutOS, raw_ostream &stderrOS) { lld::stdoutOS = &stdoutOS; @@ -952,44 +992,10 @@ 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(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 @@ inputFiles.insert(make(*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); + } } } } diff --git a/lld/MachO/MapFile.cpp b/lld/MachO/MapFile.cpp --- a/lld/MachO/MapFile.cpp +++ b/lld/MachO/MapFile.cpp @@ -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 @@ 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); diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -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 @@ -56,6 +57,7 @@ void writeSections(); void writeUuid(); void writeCodeSignature(); + void writeOutputFile(); void run(); @@ -502,6 +504,7 @@ } 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::scanSymbols() { + TimeTraceScope timeScope("Scan symbols"); for (const macho::Symbol *sym : symtab->getSymbols()) { if (const auto *defined = dyn_cast(sym)) { if (defined->overridesWeakDef) @@ -737,6 +741,8 @@ // 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(segmentOrder)); @@ -777,6 +783,7 @@ } void Writer::createOutputSections() { + TimeTraceScope timeScope("Create output sections"); // First, create hidden sections stringTableSection = make(); unwindInfoSection = make(); // TODO(gkm): only when no -r @@ -834,6 +841,7 @@ } 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::finalizeLinkEditSegment() { + TimeTraceScope timeScope("Finalize __LINKEDIT segment"); // Fill __LINKEDIT contents. in.rebase->finalizeContents(); in.binding->finalizeContents(); @@ -904,6 +913,7 @@ } void Writer::writeUuid() { + TimeTraceScope timeScope("Computing UUID"); uint64_t digest = xxHash64({buffer->getBufferStart(), buffer->getBufferEnd()}); uuidCommand->writeUuid(digest); @@ -914,6 +924,19 @@ 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 @@ 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(); }