//===- DTLTO.cpp - Integrated Distributed ThinLTO implementation ----------===//
//
// 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 support functions for Integrated Distributed ThinLTO,
// focusing on preparing complilation jobs for distribution.
//
//===----------------------------------------------------------------------===//

#include "llvm/DTLTO/DTLTO.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"

#include <string>
#include <system_error>
#include <utility>
#include <vector>

using namespace llvm;

// Experimentation showed that serial deletion is most efficient, hence
// a single thread.
lto::DTLTO::BackgroundDeletion::BackgroundDeletion()
    : DefaultThreadPool(hardware_concurrency(1)) {}

lto::DTLTO::BackgroundDeletion::~BackgroundDeletion() { waitForTasks(); }

void lto::DTLTO::BackgroundDeletion::waitForTasks() {
  wait();
  for (const std::string &Warning : Warnings)
    errs() << "warning: could not remove the file " << Warning << "\n";
  Warnings.clear();
}

void lto::DTLTO::BackgroundDeletion::removeFiles(
    std::vector<std::string> &&Files, const Config &Conf) {
  if (Files.empty())
    return;

  async([this, Files = std::move(Files), TTE = Conf.TimeTraceEnabled,
         TTG = Conf.TimeTraceGranularity] {
    if (LLVM_ENABLE_THREADS && TTE)
      timeTraceProfilerInitialize(TTG, "Remove DTLTO temporary files");
    {
      TimeTraceScope TimeScope("Remove DTLTO temporary files");
      for (const std::string &Path : Files) {
        std::error_code EC = sys::fs::remove(Path, true);
        if (!EC ||
            EC == std::make_error_code(std::errc::no_such_file_or_directory))
          continue;

        Warnings.emplace_back("'" + Path + "': " + EC.message());
      }
    }
    if (LLVM_ENABLE_THREADS && TTE)
      timeTraceProfilerFinishThread();
  });
}

void lto::DTLTO::waitForCleanup() { BackgroundDeleter.waitForTasks(); }

// Remove temporary files created to enable distribution.
void lto::DTLTO::cleanup() {
  if (SaveTemps)
    return;

  BackgroundDeleter.removeFiles(std::move(CleanupList), Conf);
}

// Runs the DTLTO thin link phase, producing per-module summary indices,
// import lists, and cache keys for distribution.
Error lto::DTLTO::performThinLink() {
  size_t NumTasks = getMaxTasks();
  SummaryIndexFiles.resize(NumTasks);
  ImportsFilesList.resize(NumTasks);
  CacheKeysList.resize(NumTasks);

  lto::Config &Cfg = getConfig();
  Cfg.GetSummaryIndexOutputStream =
      [&](size_t task) -> std::unique_ptr<raw_svector_ostream> {
    return std::make_unique<raw_svector_ostream>(SummaryIndexFiles[task]);
  };
  Cfg.GetCacheKeyOutputString = [&](size_t task) -> std::string & {
    return CacheKeysList[task];
  };
  Cfg.GetImportsListOutputArray =
      [&](size_t task) -> std::vector<std::string> & {
    return ImportsFilesList[task];
  };
  return Base::run(AddStreamFunc, {});
}

// Runs the DTLTO pipeline.
LLVM_ABI Error lto::DTLTO::run(AddStreamFn AddStream, FileCache CacheParam) {
  scope_exit CleanUp([this]() { cleanup(); });

  AddStreamFunc = AddStream;
  Cache = std::move(CacheParam);
  Conf.Dtlto = 1;
  UID = itostr(sys::Process::getProcessId());

  if (Error Err = performThinLink())
    return Err;

  ThinLTOTaskOffset = RegularLTO.ParallelCodeGenParallelismLevel;
  DistributorParams.TargetTriple = RegularLTO.CombinedModule->getTargetTriple();

  if (Error Err = prepareDtltoJobs())
    return Err;
  if (Error Err = extractLTOInputs())
    return Err;
  if (Error Err = performCodegen())
    return Err;
  if (Error Err = addObjectFilesToLink())
    return Err;
  return Error::success();
}

// Probes the LTO cache for a compiled native object for the given job.
Error lto::DTLTO::checkCacheHit(Job &J) {
  if (!Cache.isValid())
    return Error::success();

  TimeTraceScope TimeScope("Check cache for DTLTO", J.SummaryIndexPath);

  auto CacheAddStreamExp = Cache(J.Task, J.CacheKey, J.ModuleID);
  if (Error Err = CacheAddStreamExp.takeError())
    return Err;
  AddStreamFn &CacheAddStream = *CacheAddStreamExp;
  // If CacheAddStream is null, we have a cache hit and at this point
  // object file is already passed back to the linker.
  if (!CacheAddStream) {
    J.Cached = true; // Cache hit, mark the job as cached.
    CachedJobs.fetch_add(1);
  } else {
    // If CacheAddStream is not null, we have a cache miss and we need to
    // run the backend for codegen. Save cache 'add stream'
    // function for a later use.
    J.CacheAddStream = std::move(CacheAddStream);
  }
  return Error::success();
}

// Prepares a single DTLTO backend compilation job for a ThinLTO module.
Error lto::DTLTO::prepareDtltoJob(StringRef ModulePath, unsigned Task) {
  assert(Task >= ThinLTOTaskOffset && Task - ThinLTOTaskOffset < Jobs.size() &&
         "Task index out of range for Jobs");
  assert(Task < SummaryIndexFiles.size() && "Task index out of range");

  SString ObjFilePath =
      sys::path::parent_path(DistributorParams.LinkerOutputFile);
  sys::path::append(ObjFilePath, sys::path::stem(ModulePath) + "." +
                                     itostr(Task) + "." + UID + ".native.o");

  SString SummaryIndexPathStr = ObjFilePath;
  SummaryIndexPathStr += ".thinlto.bc";
  SString ImportsPathStr = ModulePath;
  ImportsPathStr += ".imports";

  Job &J = Jobs[Task - ThinLTOTaskOffset];
  J = {Task,
       ModulePath,
       Saver.save(ObjFilePath.str()),
       Saver.save(SummaryIndexPathStr.str()),
       Saver.save(ImportsPathStr.str()),
       ImportsFilesList[Task],
       CacheKeysList[Task],
       nullptr,
       false};

  if (Error Err = checkCacheHit(J))
    return Err;
  if (!J.Cached) {
    InputModuleIDsToExtract.insert(J.ModuleID);
    for (StringRef ImportPath : J.ImportsFilesList)
      InputModuleIDsToExtract.insert(ImportPath);

    TimeTraceScope JobScope("Emit individual index for DTLTO",
                            J.SummaryIndexPath);
    if (Error Err = save(SummaryIndexFiles[Task], J.SummaryIndexPath))
      return Err;
  }
  if (OnIndexWriteCb)
    OnIndexWriteCb(J.SummaryIndexPath.str());

  if (ShouldEmitImportFiles)
    if (Error Err = save(join(J.ImportsFilesList, "\n"), J.ImportsPath))
      return Err;

  if (!SaveTemps) {
    if (!J.Cached)
      addToCleanup(J.NativeObjectPath.str());
    if (!ShouldEmitIndexFiles)
      addToCleanup(J.SummaryIndexPath.str());
    if (!ShouldEmitImportFiles)
      addToCleanup(J.ImportsPath.str());
  }
  return Error::success();
}

// Derive a set of Clang options that will be shared/common for all DTLTO
// backend compilations.
void lto::DTLTO::buildCommonRemoteCompilerOptions() {
  const lto::Config &C = getConfig();
  auto &Ops = DistributorParams.CodegenOptions;

  Ops.push_back(Saver.save("-O" + Twine(C.OptLevel)));

  if (C.Options.EmitAddrsig)
    Ops.push_back("-faddrsig");
  if (C.Options.FunctionSections)
    Ops.push_back("-ffunction-sections");
  if (C.Options.DataSections)
    Ops.push_back("-fdata-sections");
  if (C.PTO.LoopInterchange)
    Ops.push_back("-floop-interchange");

  if (C.RelocModel == Reloc::PIC_)
    // Clang doesn't have -fpic for all triples.
    if (!DistributorParams.TargetTriple.isOSBinFormatCOFF())
      Ops.push_back("-fpic");

  // Turn on/off warnings about profile cfg mismatch (default on)
  // --lto-pgo-warn-mismatch.
  if (!C.PGOWarnMismatch) {
    Ops.push_back("-mllvm");
    Ops.push_back("-no-pgo-warn-mismatch");
  }

  // Enable sample-based profile guided optimizations.
  // Sample profile file path --lto-sample-profile=<value>.
  if (!C.SampleProfile.empty()) {
    Ops.push_back(Saver.save("-fprofile-sample-use=" + Twine(C.SampleProfile)));
    DistributorParams.CommonInputs.insert(C.SampleProfile);
  }

  // We don't know which of options will be used by Clang.
  Ops.push_back("-Wno-unused-command-line-argument");

  // Forward any supplied options.
  if (!DistributorParams.RemoteCompilerArgs.empty())
    for (auto &a : DistributorParams.RemoteCompilerArgs)
      Ops.push_back(a);
}

// Initializes DTLTO state and prepares a job for each ThinLTO module.
Error lto::DTLTO::prepareDtltoJobs() {
  auto &ModuleMap =
      ThinLTO.ModulesToCompile ? *ThinLTO.ModulesToCompile : ThinLTO.ModuleMap;

  InputModuleIDsToExtract.clear();

  if (ModuleMap.empty())
    return Error::success();

  Jobs.resize(ModuleMap.size());

  for (auto [I, Mod] : enumerate(ModuleMap))
    if (Error E = prepareDtltoJob(Mod.first, ThinLTOTaskOffset + I))
      return E;

  return Error::success();
}

// Runs the DTLTO code generation phase. Must be invoked after thinLink().
Error lto::DTLTO::performCodegen() {
  if (Jobs.empty())
    return Error::success();
  // Build common remote compiler options.
  buildCommonRemoteCompilerOptions();

  DistributionDriver Distributor(DistributorParams, Jobs, SaveTemps,
                                 [&](StringRef S) { addToCleanup(S); });

  if (CachedJobs.load() < Jobs.size()) {
    if (Error E = Distributor())
      return E;
  }
  return Error::success();
}

// Adds compiled object files to the link for each non-cached job.
Error lto::DTLTO::addObjectFilesToLink() {
  TimeTraceScope FilesScope("Add DTLTO files to the link");
  for (auto &Job : Jobs) {
    if (!Job.CacheKey.empty() && Job.Cached) {
      assert(Cache.isValid());
      continue;
    }
    // Load the native object from a file into a memory buffer
    // and store its contents in the output buffer.
    auto ObjFileMbOrErr =
        MemoryBuffer::getFile(Job.NativeObjectPath, /*IsText=*/false,
                              /*RequiresNullTerminator=*/false);
    if (std::error_code EC = ObjFileMbOrErr.getError())
      return make_error<StringError>(
          BCError + "cannot open native object file: " + Job.NativeObjectPath +
              ": " + EC.message(),
          inconvertibleErrorCode());

    MemoryBufferRef ObjFileMbRef = ObjFileMbOrErr->get()->getMemBufferRef();
    if (Cache.isValid()) {
      // Cache hits are taken care of earlier. At this point, we could only
      // have cache misses.
      assert(Job.CacheAddStream);
      // Obtain a file stream for a storing a cache entry.
      auto CachedFileStreamOrErr = Job.CacheAddStream(Job.Task, Job.ModuleID);
      if (!CachedFileStreamOrErr)
        return joinErrors(
            CachedFileStreamOrErr.takeError(),
            createStringError(inconvertibleErrorCode(),
                              "Cannot get a cache file stream: %s",
                              Job.NativeObjectPath.data()));
      // Store a file buffer into the cache stream.
      auto &CacheStream = *(CachedFileStreamOrErr->get());
      *(CacheStream.OS) << ObjFileMbRef.getBuffer();
      if (Error Err = CacheStream.commit())
        return Err;
    } else {
      if (AddBuffer) {
        AddBuffer(Job.Task, Job.ModuleID, std::move(ObjFileMbOrErr.get()));
      } else {
        auto StreamOrErr = AddStreamFunc(Job.Task, Job.ModuleID);
        if (Error Err = StreamOrErr.takeError())
          return Err;
        auto &Stream = *StreamOrErr->get();
        *Stream.OS << ObjFileMbRef.getBuffer();
        if (Error Err = Stream.commit())
          return Err;
      }
    }
  }
  return Error::success();
}
