//===- LTO.cpp ------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "LTO.h"
#include "Config.h"
#include "Driver.h"
#include "InputFiles.h"
#include "Symbols.h"
#include "Target.h"

#include "lld/Common/Args.h"
#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Strings.h"
#include "lld/Common/TargetOptionsCommandFlags.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/LTO/Config.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Support/Caching.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/ObjCARC.h"

using namespace lld;
using namespace lld::macho;
using namespace llvm;
using namespace llvm::MachO;
using namespace llvm::sys;

// Creates an empty file to store a list of object files for final
// linking of distributed ThinLTO.
static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
  std::error_code ec;
  auto ret =
      std::make_unique<raw_fd_ostream>(file, ec, sys::fs::OpenFlags::OF_None);
  if (ec) {
    error("cannot open " + file + ": " + ec.message());
    return nullptr;
  }
  return ret;
}

static std::string getThinLTOOutputFile(StringRef modulePath) {
  return lto::getThinLTOOutputFile(modulePath, config->thinLTOPrefixReplaceOld,
                                   config->thinLTOPrefixReplaceNew);
}

static lto::Config createConfig() {
  lto::Config c;
  c.Options = initTargetOptionsFromCodeGenFlags();
  c.Options.EmitAddrsig = config->icfLevel == ICFLevel::safe;
  for (StringRef C : config->mllvmOpts)
    c.MllvmArgs.emplace_back(C.str());
  c.CodeModel = getCodeModelFromCMModel();
  c.CPU = getCPUStr();
  c.MAttrs = getMAttrs();
  c.DiagHandler = diagnosticHandler;
  c.PreCodeGenPassesHook = [](legacy::PassManager &pm) {
    pm.add(createObjCARCContractPass());
  };

  c.AlwaysEmitRegularLTOObj = !config->ltoObjPath.empty();

  c.TimeTraceEnabled = config->timeTraceEnabled;
  c.TimeTraceGranularity = config->timeTraceGranularity;
  c.OptLevel = config->ltoo;
  c.CGOptLevel = config->ltoCgo;
  if (config->saveTemps)
    checkError(c.addSaveTemps(config->outputFile.str() + ".",
                              /*UseInputModulePath=*/true));
  return c;
}

// If `originalPath` exists, hardlinks `path` to `originalPath`. If that fails,
// or `originalPath` is not set, saves `buffer` to `path`.
static void saveOrHardlinkBuffer(StringRef buffer, const Twine &path,
                                 std::optional<StringRef> originalPath) {
  if (originalPath) {
    auto err = fs::create_hard_link(*originalPath, path);
    if (!err)
      return;
  }
  saveBuffer(buffer, path);
}

BitcodeCompiler::BitcodeCompiler() {
  // Initialize indexFile.
  if (!config->thinLTOIndexOnlyArg.empty())
    indexFile = openFile(config->thinLTOIndexOnlyArg);

  // Initialize ltoObj.
  lto::ThinBackend backend;
  auto onIndexWrite = [&](StringRef S) { thinIndices.erase(S); };
  if (config->thinLTOIndexOnly) {
    backend = lto::createWriteIndexesThinBackend(
        std::string(config->thinLTOPrefixReplaceOld),
        std::string(config->thinLTOPrefixReplaceNew),
        std::string(config->thinLTOPrefixReplaceNativeObject),
        config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite);
  } else {
    backend = lto::createInProcessThinBackend(
        llvm::heavyweight_hardware_concurrency(config->thinLTOJobs),
        onIndexWrite, config->thinLTOEmitIndexFiles,
        config->thinLTOEmitImportsFiles);
  }

  ltoObj = std::make_unique<lto::LTO>(createConfig(), backend);
}

void BitcodeCompiler::add(BitcodeFile &f) {
  lto::InputFile &obj = *f.obj;

  if (config->thinLTOEmitIndexFiles)
    thinIndices.insert(obj.getName());

  ArrayRef<lto::InputFile::Symbol> objSyms = obj.symbols();
  std::vector<lto::SymbolResolution> resols;
  resols.reserve(objSyms.size());

  // Provide a resolution to the LTO API for each symbol.
  bool exportDynamic =
      config->outputType != MH_EXECUTE || config->exportDynamic;
  auto symIt = f.symbols.begin();
  for (const lto::InputFile::Symbol &objSym : objSyms) {
    resols.emplace_back();
    lto::SymbolResolution &r = resols.back();
    Symbol *sym = *symIt++;

    // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
    // reports two symbols for module ASM defined. Without this check, lld
    // flags an undefined in IR with a definition in ASM as prevailing.
    // Once IRObjectFile is fixed to report only one symbol this hack can
    // be removed.
    r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f;

    if (const auto *defined = dyn_cast<Defined>(sym)) {
      r.ExportDynamic =
          defined->isExternal() && !defined->privateExtern && exportDynamic;
      r.FinalDefinitionInLinkageUnit =
          !defined->isExternalWeakDef() && !defined->interposable;
    } else if (const auto *common = dyn_cast<CommonSymbol>(sym)) {
      r.ExportDynamic = !common->privateExtern && exportDynamic;
      r.FinalDefinitionInLinkageUnit = true;
    }

    r.VisibleToRegularObj =
        sym->isUsedInRegularObj || (r.Prevailing && r.ExportDynamic);

    // Un-define the symbol so that we don't get duplicate symbol errors when we
    // load the ObjFile emitted by LTO compilation.
    if (r.Prevailing)
      replaceSymbol<Undefined>(sym, sym->getName(), sym->getFile(),
                               RefState::Strong, /*wasBitcodeSymbol=*/true);

    // TODO: set the other resolution configs properly
  }
  checkError(ltoObj->add(std::move(f.obj), resols));
  hasFiles = true;
}

// If LazyObjFile has not been added to link, emit empty index files.
// This is needed because this is what GNU gold plugin does and we have a
// distributed build system that depends on that behavior.
static void thinLTOCreateEmptyIndexFiles() {
  DenseSet<StringRef> linkedBitCodeFiles;
  for (InputFile *file : inputFiles)
    if (auto *f = dyn_cast<BitcodeFile>(file))
      if (!f->lazy)
        linkedBitCodeFiles.insert(f->getName());

  for (InputFile *file : inputFiles) {
    if (auto *f = dyn_cast<BitcodeFile>(file)) {
      if (!f->lazy)
        continue;
      if (linkedBitCodeFiles.contains(f->getName()))
        continue;
      std::string path =
          replaceThinLTOSuffix(getThinLTOOutputFile(f->obj->getName()));
      std::unique_ptr<raw_fd_ostream> os = openFile(path + ".thinlto.bc");
      if (!os)
        continue;

      ModuleSummaryIndex m(/*HaveGVs=*/false);
      m.setSkipModuleByDistributedBackend();
      writeIndexToFile(m, *os);
      if (config->thinLTOEmitImportsFiles)
        openFile(path + ".imports");
    }
  }
}

// Merge all the bitcode files we have seen, codegen the result
// and return the resulting ObjectFile(s).
std::vector<ObjFile *> BitcodeCompiler::compile() {
  unsigned maxTasks = ltoObj->getMaxTasks();
  buf.resize(maxTasks);
  files.resize(maxTasks);

  // The -cache_path_lto option specifies the path to a directory in which
  // to cache native object files for ThinLTO incremental builds. If a path was
  // specified, configure LTO to use it as the cache directory.
  FileCache cache;
  if (!config->thinLTOCacheDir.empty())
    cache = check(localCache("ThinLTO", "Thin", config->thinLTOCacheDir,
                             [&](size_t task, const Twine &moduleName,
                                 std::unique_ptr<MemoryBuffer> mb) {
                               files[task] = std::move(mb);
                             }));

  if (hasFiles)
    checkError(ltoObj->run(
        [&](size_t task, const Twine &moduleName) {
          return std::make_unique<CachedFileStream>(
              std::make_unique<raw_svector_ostream>(buf[task]));
        },
        cache));

  // Emit empty index files for non-indexed files
  for (StringRef s : thinIndices) {
    std::string path = getThinLTOOutputFile(s);
    openFile(path + ".thinlto.bc");
    if (config->thinLTOEmitImportsFiles)
      openFile(path + ".imports");
  }

  if (config->thinLTOEmitIndexFiles)
    thinLTOCreateEmptyIndexFiles();

  // In ThinLTO mode, Clang passes a temporary directory in -object_path_lto,
  // while the argument is a single file in FullLTO mode.
  bool objPathIsDir = true;
  if (!config->ltoObjPath.empty()) {
    if (std::error_code ec = fs::create_directories(config->ltoObjPath))
      fatal("cannot create LTO object path " + config->ltoObjPath + ": " +
            ec.message());

    if (!fs::is_directory(config->ltoObjPath)) {
      objPathIsDir = false;
      unsigned objCount =
          count_if(buf, [](const SmallString<0> &b) { return !b.empty(); });
      if (objCount > 1)
        fatal("-object_path_lto must specify a directory when using ThinLTO");
    }
  }

  auto outputFilePath = [objPathIsDir](int i) {
    SmallString<261> filePath("/tmp/lto.tmp");
    if (!config->ltoObjPath.empty()) {
      filePath = config->ltoObjPath;
      if (objPathIsDir)
        path::append(filePath, Twine(i) + "." +
                                   getArchitectureName(config->arch()) +
                                   ".lto.o");
    }
    return filePath;
  };

  // ThinLTO with index only option is required to generate only the index
  // files. After that, we exit from linker and ThinLTO backend runs in a
  // distributed environment.
  if (config->thinLTOIndexOnly) {
    if (!config->ltoObjPath.empty())
      saveBuffer(buf[0], outputFilePath(0));
    if (indexFile)
      indexFile->close();
    return {};
  }

  if (!config->thinLTOCacheDir.empty())
    pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy, files);

  std::vector<ObjFile *> ret;
  for (unsigned i = 0; i < maxTasks; ++i) {
    // Get the native object contents either from the cache or from memory.  Do
    // not use the cached MemoryBuffer directly to ensure dsymutil does not
    // race with the cache pruner.
    StringRef objBuf;
    std::optional<StringRef> cachePath;
    if (files[i]) {
      objBuf = files[i]->getBuffer();
      cachePath = files[i]->getBufferIdentifier();
    } else {
      objBuf = buf[i];
    }
    if (objBuf.empty())
      continue;

    // FIXME: should `saveTemps` and `ltoObjPath` use the same file name?
    if (config->saveTemps)
      saveBuffer(objBuf,
                 config->outputFile + ((i == 0) ? "" : Twine(i)) + ".lto.o");

    auto filePath = outputFilePath(i);
    uint32_t modTime = 0;
    if (!config->ltoObjPath.empty()) {
      saveOrHardlinkBuffer(objBuf, filePath, cachePath);
      modTime = getModTime(filePath);
    }
    ret.push_back(make<ObjFile>(
        MemoryBufferRef(objBuf, saver().save(filePath.str())), modTime, ""));
  }

  return ret;
}
