| //===- DTLTODistributionDriver.cpp - DTLTO Distribution Driver ---------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // \file | |
| // This file implements the Integrated Distributed ThinLTO driver that prepares | |
| // the compilation job descriptions and invokes the external distributor. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/DTLTO/DTLTO.h" | |
| #include "llvm/ADT/STLExtras.h" | |
| #include "llvm/ADT/StringExtras.h" | |
| #include "llvm/ADT/StringRef.h" | |
| #include "llvm/Support/JSON.h" | |
| #include "llvm/Support/Path.h" | |
| #include "llvm/Support/Process.h" | |
| #include "llvm/Support/TimeProfiler.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include <string> | |
| using namespace llvm; | |
| // Generates a JSON file describing the backend compilations, for the | |
| // distributor. | |
| Error lto::DistributionDriver::emitJson() { | |
| using json::Array; | |
| std::error_code EC; | |
| raw_fd_ostream OS(DistributorJsonFile, EC); | |
| if (EC) | |
| return createStringError(EC, "Error while creating Json file"); | |
| json::OStream JOS(OS); | |
| JOS.object([&]() { | |
| // Information common to all jobs. | |
| JOS.attributeObject("common", [&]() { | |
| JOS.attribute("linker_output", Params.LinkerOutputFile); | |
| JOS.attributeArray("args", [&]() { | |
| JOS.value(Params.RemoteCompiler); | |
| // Forward any supplied prepend options. | |
| if (!Params.RemoteCompilerPrependArgs.empty()) | |
| for (auto &A : Params.RemoteCompilerPrependArgs) | |
| JOS.value(A); | |
| JOS.value("-c"); | |
| JOS.value(std::string("--target=") + Params.TargetTriple.str()); | |
| for (const auto &A : Params.CodegenOptions) | |
| JOS.value(A); | |
| }); | |
| JOS.attribute("inputs", Array(Params.CommonInputs)); | |
| }); | |
| // Per-compilation-job information. | |
| JOS.attributeArray("jobs", [&]() { | |
| for (const auto &J : Jobs) { | |
| assert(J.Task != 0); | |
| if (J.Cached) { | |
| continue; | |
| } | |
| SmallVector<StringRef, 2> Inputs; | |
| SmallVector<StringRef, 1> Outputs; | |
| JOS.object([&]() { | |
| JOS.attributeArray("args", [&]() { | |
| JOS.value(J.ModuleID); | |
| Inputs.push_back(J.ModuleID); | |
| JOS.value( | |
| std::string("-fthinlto-index=" + J.SummaryIndexPath.str())); | |
| Inputs.push_back(J.SummaryIndexPath); | |
| JOS.value("-o"); | |
| JOS.value(J.NativeObjectPath); | |
| Outputs.push_back(J.NativeObjectPath); | |
| }); | |
| // Add the bitcode files from which imports will be made. These do | |
| // not explicitly appear on the backend compilation command lines | |
| // but are recorded in the summary index shards. | |
| append_range(Inputs, J.ImportsFilesList); | |
| JOS.attribute("inputs", Array(Inputs)); | |
| JOS.attribute("outputs", Array(Outputs)); | |
| }); | |
| } | |
| }); | |
| }); | |
| return Error::success(); | |
| } | |
| // Saves JSON file on a filesystem. | |
| Error lto::DistributionDriver::saveJson() { | |
| DistributorJsonFile = sys::path::parent_path(Params.LinkerOutputFile); | |
| TimeTraceScope TimeScope("Emit DTLTO JSON"); | |
| sys::path::append(DistributorJsonFile, | |
| sys::path::stem(Params.LinkerOutputFile) + "." + | |
| itostr(sys::Process::getProcessId()) + | |
| ".dist-file.json"); | |
| if (Error E = emitJson()) | |
| return make_error<StringError>( | |
| BCError + "failed to generate distributor JSON script: " + | |
| DistributorJsonFile, | |
| errorToErrorCode(std::move(E))); | |
| // Add JSON file to the cleanup files list. | |
| if (!SaveTemps) | |
| AddToCleanup(DistributorJsonFile); | |
| return Error::success(); | |
| } | |
| // Invokes the distributor to compile uncached ThinLTO modules remotely. | |
| Error lto::DistributionDriver::operator()() { | |
| if (Error E = saveJson()) | |
| return E; | |
| TimeTraceScope TimeScope("Execute DTLTO distributor", Params.DistributorPath); | |
| SmallVector<StringRef, 3> Args = {Params.DistributorPath}; | |
| append_range(Args, Params.DistributorArgs); | |
| Args.push_back(DistributorJsonFile); | |
| std::string ErrMsg; | |
| if (sys::ExecuteAndWait(Args[0], Args, | |
| /*Env=*/std::nullopt, /*Redirects=*/{}, | |
| /*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg)) { | |
| return make_error<StringError>( | |
| BCError + "distributor execution failed" + | |
| (!ErrMsg.empty() ? ": " + ErrMsg + Twine(".") : Twine(".")), | |
| inconvertibleErrorCode()); | |
| } | |
| return Error::success(); | |
| } |