#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 <memory>
/// @}
/// The file we stream the linked Dwarf to.
- std::unique_ptr<raw_fd_ostream> OutFile;
+ std::unique_ptr<ToolOutputFile> OutFile;
uint32_t RangesSectionSize;
uint32_t LocSectionSize;
// Create the output file.
std::error_code EC;
OutFile =
- llvm::make_unique<raw_fd_ostream>(OutputFilename, EC, sys::fs::F_None);
+ llvm::make_unique<ToolOutputFile>(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<MCAsmBackend>(MAB), *OutFile,
+ TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB), OutFile->os(),
std::unique_ptr<MCCodeEmitter>(MCE), *MSTI, MCOptions.MCRelaxAll,
MCOptions.MCIncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ false);
}
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
//
//===----------------------------------------------------------------------===//
+#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"
#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 <cstdint>
#include <string>
init(false), cat(DsymCategory));
static alias FlatOutA("f", desc("Alias for --flat"), aliasopt(FlatOut));
+static opt<unsigned> 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<bool> Verbose("verbose", desc("Verbosity level"), init(false),
cat(DsymCategory));
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;
<< ")\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))