Index: llvm/trunk/test/tools/dsymutil/cmdline.test =================================================================== --- llvm/trunk/test/tools/dsymutil/cmdline.test +++ llvm/trunk/test/tools/dsymutil/cmdline.test @@ -0,0 +1,21 @@ +RUN: llvm-dsymutil -help 2>&1 | FileCheck --check-prefix=HELP %s +HELP: OVERVIEW: manipulate archived DWARF debug symbol files. +HELP: USAGE: llvm-dsymutil [options] +HELP-NOT: -reverse-iterate +HELP: Specific Options: +HELP: -arch= +HELP: -dump-debug-map +HELP: -flat +HELP: -no-odr +HELP: -no-output +HELP: -no-swiftmodule-timestamp +HELP: -o= +HELP: -oso-prepend-path= +HELP: -symtab +HELP: -threads= +HELP: -verbose +HELP: -y +HELP-NOT: -reverse-iterate + +RUN: llvm-dsymutil --version 2>&1 | FileCheck --check-prefix=VERSION %s +VERSION: {{ version }} Index: llvm/trunk/tools/dsymutil/DwarfLinker.cpp =================================================================== --- llvm/trunk/tools/dsymutil/DwarfLinker.cpp +++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp @@ -35,6 +35,7 @@ #include "llvm/Object/MachO.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include @@ -479,7 +480,7 @@ /// @} /// The file we stream the linked Dwarf to. - std::unique_ptr OutFile; + std::unique_ptr OutFile; uint32_t RangesSectionSize; uint32_t LocSectionSize; @@ -617,13 +618,13 @@ // Create the output file. std::error_code EC; OutFile = - llvm::make_unique(OutputFilename, EC, sys::fs::F_None); + llvm::make_unique(OutputFilename, EC, sys::fs::F_None); if (EC) return error(Twine(OutputFilename) + ": " + EC.message(), Context); MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags(); MS = TheTarget->createMCObjectStreamer( - TheTriple, *MC, std::unique_ptr(MAB), *OutFile, + TheTriple, *MC, std::unique_ptr(MAB), OutFile->os(), std::unique_ptr(MCE), *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, /*DWARFMustBeAtTheEnd*/ false); @@ -649,11 +650,16 @@ } bool DwarfStreamer::finish(const DebugMap &DM) { + bool Result = true; if (DM.getTriple().isOSDarwin() && !DM.getBinaryPath().empty()) - return MachOUtils::generateDsymCompanion(DM, *MS, *OutFile); + Result = MachOUtils::generateDsymCompanion(DM, *MS, OutFile->os()); + else + MS->Finish(); - MS->Finish(); - return true; + // Declare success. + OutFile->keep(); + + return Result; } /// Set the current output section to debug_info and change Index: llvm/trunk/tools/dsymutil/dsymutil.cpp =================================================================== --- llvm/trunk/tools/dsymutil/dsymutil.cpp +++ llvm/trunk/tools/dsymutil/dsymutil.cpp @@ -12,9 +12,9 @@ // //===----------------------------------------------------------------------===// +#include "dsymutil.h" #include "DebugMap.h" #include "MachOUtils.h" -#include "dsymutil.h" #include "llvm/Object/MachO.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" @@ -22,8 +22,9 @@ #include "llvm/Support/Options.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/ThreadPool.h" +#include "llvm/Support/raw_ostream.h" #include #include @@ -61,6 +62,13 @@ init(false), cat(DsymCategory)); static alias FlatOutA("f", desc("Alias for --flat"), aliasopt(FlatOut)); +static opt Threads( + "threads", + desc("Specifies the maximum number (n) of simultaneous threads to use\n" + "when linking multiple architectures."), + value_desc("n"), init(0), cat(DsymCategory)); +static alias ThreadsA("t", desc("Alias for --threads"), aliasopt(Threads)); + static opt Verbose("verbose", desc("Verbosity level"), init(false), cat(DsymCategory)); @@ -316,6 +324,15 @@ exitDsymutil(1); } + unsigned NumThreads = Threads; + if (!NumThreads) + NumThreads = llvm::thread::hardware_concurrency(); + if (DumpDebugMap || Verbose) + NumThreads = 1; + NumThreads = std::min(NumThreads, (unsigned)DebugMapPtrsOrErr->size()); + + llvm::ThreadPool Threads(NumThreads); + // If there is more than one link to execute, we need to generate // temporary files. bool NeedsTempFiles = !DumpDebugMap && (*DebugMapPtrsOrErr).size() != 1; @@ -333,14 +350,27 @@ << ")\n"; std::string OutputFile = getOutputFileName(InputFile, NeedsTempFiles); - if (OutputFile.empty() || !linkDwarf(OutputFile, *Map, Options)) - exitDsymutil(1); + + auto LinkLambda = [OutputFile, Options, &Map]() { + if (OutputFile.empty() || !linkDwarf(OutputFile, *Map, Options)) + exitDsymutil(1); + }; + + // FIXME: The DwarfLinker can have some very deep recursion that can max + // out the (significantly smaller) stack when using threads. We don't + // want this limitation when we only have a single thread. + if (NumThreads == 1) + LinkLambda(); + else + Threads.async(LinkLambda); if (NeedsTempFiles) TempFiles.emplace_back(Map->getTriple().getArchName().str(), OutputFile); } + Threads.wait(); + if (NeedsTempFiles && !MachOUtils::generateUniversalBinary( TempFiles, getOutputFileName(InputFile), Options, SDKPath))