Skip to content

Commit 49237be

Browse files
committed
[DTLTO] DTLTO.cpp had been splitted into three sources: DTLTOInputFiles.cpp, DTLTO.cpp and DTLTODistributionDriver.cpp.
1 parent 57bd7c7 commit 49237be

5 files changed

Lines changed: 371 additions & 310 deletions

File tree

llvm/include/llvm/DTLTO/DTLTO.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ class DTLTO : public LTO {
135135
// Keep temporary files when true.
136136
bool SaveTemps = false;
137137

138+
// Saves the content of Buffer to Path overwriting any existing file.
139+
static Error save(StringRef Buffer, StringRef Path);
140+
138141
public:
139142
struct Job {
140143
// Task index (combines RegularLTO parallel codegen offset with module

llvm/lib/DTLTO/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
add_llvm_component_library(LLVMDTLTO
2+
DTLTOInputFiles.cpp
23
DTLTO.cpp
4+
DTLTODistributionDriver.cpp
35

46
LINK_COMPONENTS
57
BinaryFormat

llvm/lib/DTLTO/DTLTO.cpp

Lines changed: 1 addition & 310 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
8-
//
98
// \file
109
// This file implements support functions for Distributed ThinLTO, focusing on
11-
// preparing input files for distribution.
10+
// preparing complilation jobs for distribution.
1211
//
1312
//===----------------------------------------------------------------------===//
1413

@@ -19,211 +18,18 @@
1918
#include "llvm/ADT/SmallString.h"
2019
#include "llvm/ADT/StringExtras.h"
2120
#include "llvm/ADT/StringRef.h"
22-
#include "llvm/BinaryFormat/Magic.h"
2321
#include "llvm/LTO/LTO.h"
24-
#include "llvm/Object/Archive.h"
2522
#include "llvm/Support/FileSystem.h"
26-
#include "llvm/Support/JSON.h"
2723
#include "llvm/Support/MemoryBufferRef.h"
2824
#include "llvm/Support/Path.h"
2925
#include "llvm/Support/Process.h"
3026
#include "llvm/Support/TimeProfiler.h"
3127
#include "llvm/Support/raw_ostream.h"
32-
#ifdef _WIN32
33-
#include "llvm/Support/Windows/WindowsSupport.h"
34-
#endif
3528

3629
#include <string>
3730

3831
using namespace llvm;
3932

40-
namespace {
41-
42-
// Saves the content of Buffer to Path overwriting any existing file.
43-
Error save(StringRef Buffer, StringRef Path) {
44-
std::error_code EC;
45-
raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::OF_None);
46-
if (EC)
47-
return createStringError(inconvertibleErrorCode(),
48-
"Failed to create file %s: %s", Path.data(),
49-
EC.message().c_str());
50-
OS.write(Buffer.data(), Buffer.size());
51-
if (OS.has_error())
52-
return createStringError(inconvertibleErrorCode(),
53-
"Failed writing to file %s", Path.data());
54-
return Error::success();
55-
}
56-
57-
// Normalize and save a path. Aside from expanding Windows 8.3 short paths,
58-
// no other normalization is currently required here. These paths are
59-
// machine-local and break distribution systems; other normalization is
60-
// handled by the DTLTO distributors.
61-
Expected<StringRef> normalizePath(StringRef Path, StringSaver &Saver) {
62-
#if defined(_WIN32)
63-
if (Path.empty())
64-
return Path;
65-
SmallString<256> Expanded;
66-
if (std::error_code EC = sys::windows::makeLongFormPath(Path, Expanded))
67-
return createStringError(inconvertibleErrorCode(),
68-
"Normalization failed for path %s: %s",
69-
Path.str().c_str(), EC.message().c_str());
70-
return Saver.save(Expanded.str());
71-
#else
72-
return Saver.save(Path);
73-
#endif
74-
}
75-
76-
// Compute the file path for a thin archive member.
77-
//
78-
// For thin archives, an archive member name is typically a file path relative
79-
// to the archive file's directory. This function resolves that path.
80-
SmallString<256> computeThinArchiveMemberPath(StringRef ArchivePath,
81-
StringRef MemberName) {
82-
assert(!ArchivePath.empty() && "An archive file path must be non empty.");
83-
SmallString<256> MemberPath;
84-
if (sys::path::is_relative(MemberName)) {
85-
MemberPath = sys::path::parent_path(ArchivePath);
86-
sys::path::append(MemberPath, MemberName);
87-
} else {
88-
MemberPath = MemberName;
89-
}
90-
sys::path::remove_dots(MemberPath, /*remove_dot_dot=*/true);
91-
return MemberPath;
92-
}
93-
94-
} // namespace
95-
96-
// Determines if a file at the given path is a thin archive file.
97-
Expected<bool> lto::DTLTO::isThinArchive(const StringRef ArchivePath) {
98-
// Return cached result if available.
99-
auto Cached = ArchiveIsThinCache.find(ArchivePath);
100-
if (Cached != ArchiveIsThinCache.end())
101-
return Cached->second;
102-
103-
uint64_t FileSize = -1;
104-
std::error_code EC = sys::fs::file_size(ArchivePath, FileSize);
105-
if (EC)
106-
return createStringError(inconvertibleErrorCode(),
107-
"Failed to get file size from archive %s: %s",
108-
ArchivePath.data(), EC.message().c_str());
109-
if (FileSize < sizeof(object::ThinArchiveMagic))
110-
return createStringError(inconvertibleErrorCode(),
111-
"Archive file size is too small %s",
112-
ArchivePath.data());
113-
114-
// Read only the first few bytes containing the magic signature.
115-
ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFileSlice(
116-
ArchivePath, sizeof(object::ThinArchiveMagic), 0);
117-
if ((EC = MBOrErr.getError()))
118-
return createStringError(inconvertibleErrorCode(),
119-
"Failed to read from archive %s: %s",
120-
ArchivePath.data(), EC.message().c_str());
121-
122-
StringRef Buf = (*MBOrErr)->getBuffer();
123-
if (file_magic::archive != identify_magic(Buf))
124-
return createStringError(inconvertibleErrorCode(),
125-
"Unknown format for archive %s",
126-
ArchivePath.data());
127-
128-
bool IsThin = Buf.starts_with(object::ThinArchiveMagic);
129-
130-
// Cache the result.
131-
ArchiveIsThinCache[ArchivePath] = IsThin;
132-
133-
return IsThin;
134-
}
135-
136-
// Add an input file and prepare it for distribution.
137-
Expected<std::shared_ptr<lto::InputFile>>
138-
lto::DTLTO::addInput(std::unique_ptr<InputFile> InputPtr) {
139-
TimeTraceScope TimeScope("Add input for DTLTO");
140-
141-
// Add the input file to the LTO object.
142-
InputFiles.emplace_back(InputPtr.release());
143-
auto &Input = InputFiles.back();
144-
BitcodeModule &BM = Input->getPrimaryBitcodeModule();
145-
146-
auto setIdFromPath = [&](StringRef Path) -> Error {
147-
auto N = normalizePath(Path, Saver);
148-
if (!N)
149-
return N.takeError();
150-
BM.setModuleIdentifier(*N);
151-
return Error::success();
152-
};
153-
154-
StringRef ArchivePath = Input->getArchivePath();
155-
156-
// In most cases, the module ID already points to an individual bitcode file
157-
// on disk, so no further preparation for distribution is required. However,
158-
// on Windows we overwite the module ID to expand Windows 8.3 short form
159-
// paths. These paths are machine-local and break distribution systems; other
160-
// normalization is handled by the DTLTO distributors.
161-
if (ArchivePath.empty() && !Input->isFatLTOObject()) {
162-
#if defined(_WIN32)
163-
if (Error E = setIdFromPath(Input->getName()))
164-
return std::move(E);
165-
#endif
166-
return Input;
167-
}
168-
169-
// For a member of a thin archive that is not a FatLTO object, there is an
170-
// existing file on disk that can be used, so we can avoid having to
171-
// serialize.
172-
Expected<bool> UseThinMember =
173-
Input->isFatLTOObject() ? false : isThinArchive(ArchivePath);
174-
if (!UseThinMember)
175-
return UseThinMember.takeError();
176-
if (*UseThinMember) {
177-
// For thin archives, use the path to the actual member file on disk.
178-
auto MemberPath =
179-
computeThinArchiveMemberPath(ArchivePath, Input->getMemberName());
180-
if (Error E = setIdFromPath(MemberPath))
181-
return std::move(E);
182-
return Input;
183-
}
184-
185-
// A new file on disk will be needed for archive members and FatLTO objects.
186-
Input->setSerializeForDistribution(true);
187-
188-
// Get the normalized output directory, if we haven't already.
189-
if (LinkerOutputDir.empty()) {
190-
auto N = normalizePath(
191-
sys::path::parent_path(DistributorParams.LinkerOutputFile), Saver);
192-
if (!N)
193-
return N.takeError();
194-
LinkerOutputDir = *N;
195-
}
196-
197-
// Create a unique path by including the process ID and sequence number in the
198-
// filename.
199-
SmallString<256> Id(LinkerOutputDir);
200-
sys::path::append(Id,
201-
Twine(sys::path::filename(Input->getName())) + "." +
202-
std::to_string(InputFiles.size()) /*Sequence number*/ +
203-
"." + utohexstr(sys::Process::getProcessId()) + ".o");
204-
BM.setModuleIdentifier(Saver.save(Id.str()));
205-
return Input;
206-
}
207-
208-
// Save the contents of ThinLTO-enabled input files that must be serialized for
209-
// distribution.
210-
Error lto::DTLTO::handleArchiveInputs() {
211-
for (auto &Input : InputFiles) {
212-
if (!Input->isThinLTO() || !Input->getSerializeForDistribution())
213-
continue;
214-
// Save the content of the input file to a file named after the module ID.
215-
StringRef ModuleId = Input->getName();
216-
TimeTraceScope TimeScope("Serialize bitcode input for DTLTO", ModuleId);
217-
MemoryBufferRef Buf = Input->getFileBuffer();
218-
if (Error Err = save(Buf.getBuffer(), ModuleId))
219-
return Err;
220-
// Cleanup this file on abnormal process exit.
221-
if (!SaveTemps)
222-
addToCleanup(ModuleId);
223-
}
224-
return Error::success();
225-
}
226-
22733
// Remove temporary files created to enable distribution.
22834
void lto::DTLTO::cleanup() {
22935
if (!SaveTemps) {
@@ -503,118 +309,3 @@ Error lto::DTLTO::addObjectFilesToLink() {
503309
}
504310
return Error::success();
505311
}
506-
507-
// Generates a JSON file describing the backend compilations, for the
508-
// distributor.
509-
Error lto::DistributionDriver::emitJson() {
510-
using json::Array;
511-
std::error_code EC;
512-
raw_fd_ostream OS(DistributorJsonFile, EC);
513-
if (EC)
514-
return createStringError(EC, "Error while creating Json file");
515-
516-
json::OStream JOS(OS);
517-
JOS.object([&]() {
518-
// Information common to all jobs.
519-
JOS.attributeObject("common", [&]() {
520-
JOS.attribute("linker_output", Params.LinkerOutputFile);
521-
522-
JOS.attributeArray("args", [&]() {
523-
JOS.value(Params.RemoteCompiler);
524-
525-
// Forward any supplied prepend options.
526-
if (!Params.RemoteCompilerPrependArgs.empty())
527-
for (auto &A : Params.RemoteCompilerPrependArgs)
528-
JOS.value(A);
529-
530-
JOS.value("-c");
531-
532-
JOS.value(std::string("--target=") + Params.TargetTriple.str());
533-
534-
for (const auto &A : Params.CodegenOptions)
535-
JOS.value(A);
536-
});
537-
538-
JOS.attribute("inputs", Array(Params.CommonInputs));
539-
});
540-
541-
// Per-compilation-job information.
542-
JOS.attributeArray("jobs", [&]() {
543-
for (const auto &J : Jobs) {
544-
assert(J.Task != 0);
545-
if (J.Cached) {
546-
continue;
547-
}
548-
549-
SmallVector<StringRef, 2> Inputs;
550-
SmallVector<StringRef, 1> Outputs;
551-
552-
JOS.object([&]() {
553-
JOS.attributeArray("args", [&]() {
554-
JOS.value(J.ModuleID);
555-
Inputs.push_back(J.ModuleID);
556-
557-
JOS.value(
558-
std::string("-fthinlto-index=" + J.SummaryIndexPath.str()));
559-
Inputs.push_back(J.SummaryIndexPath);
560-
561-
JOS.value("-o");
562-
JOS.value(J.NativeObjectPath);
563-
Outputs.push_back(J.NativeObjectPath);
564-
});
565-
566-
// Add the bitcode files from which imports will be made. These do
567-
// not explicitly appear on the backend compilation command lines
568-
// but are recorded in the summary index shards.
569-
append_range(Inputs, J.ImportsFiles);
570-
JOS.attribute("inputs", Array(Inputs));
571-
572-
JOS.attribute("outputs", Array(Outputs));
573-
});
574-
}
575-
});
576-
});
577-
578-
return Error::success();
579-
}
580-
581-
// Saves JSON file on a filesystem.
582-
Error lto::DistributionDriver::saveJson() {
583-
DistributorJsonFile = sys::path::parent_path(Params.LinkerOutputFile);
584-
TimeTraceScope TimeScope("Emit DTLTO JSON");
585-
sys::path::append(DistributorJsonFile,
586-
sys::path::stem(Params.LinkerOutputFile) + "." +
587-
itostr(sys::Process::getProcessId()) +
588-
".dist-file.json");
589-
if (Error E = emitJson())
590-
return make_error<StringError>(
591-
BCError + "failed to generate distributor JSON script: " +
592-
DistributorJsonFile,
593-
errorToErrorCode(std::move(E)));
594-
595-
// Add JSON file to the cleanup files list.
596-
if (!SaveTemps)
597-
AddToCleanup(DistributorJsonFile);
598-
return Error::success();
599-
}
600-
601-
// Invokes the distributor to compile uncached ThinLTO modules remotely.
602-
Error lto::DistributionDriver::operator()() {
603-
if (Error E = saveJson())
604-
return E;
605-
606-
TimeTraceScope TimeScope("Execute DTLTO distributor", Params.DistributorPath);
607-
SmallVector<StringRef, 3> Args = {Params.DistributorPath};
608-
append_range(Args, Params.DistributorArgs);
609-
Args.push_back(DistributorJsonFile);
610-
std::string ErrMsg;
611-
if (sys::ExecuteAndWait(Args[0], Args,
612-
/*Env=*/std::nullopt, /*Redirects=*/{},
613-
/*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg)) {
614-
return make_error<StringError>(
615-
BCError + "distributor execution failed" +
616-
(!ErrMsg.empty() ? ": " + ErrMsg + Twine(".") : Twine(".")),
617-
inconvertibleErrorCode());
618-
}
619-
return Error::success();
620-
}

0 commit comments

Comments
 (0)