//===-- llvm-offload-binary.cpp - offload binary management utility -------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This tool takes several device object files and bundles them into a single
// binary image using a custom binary format. This is intended to be used to
// embed many device files into an application to create a fat binary. It also
// supports extracting these files from a known location.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/OffloadBinary.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/WithColor.h"

using namespace llvm;
using namespace llvm::object;

static cl::OptionCategory OffloadBinaryCategory("llvm-offload-binary options");

static cl::opt<std::string> OutputFile("o", cl::desc("Write output to <file>."),
                                       cl::value_desc("file"),
                                       cl::cat(OffloadBinaryCategory));

static cl::opt<std::string> InputFile(cl::Positional,
                                      cl::desc("Extract from <file>."),
                                      cl::value_desc("file"),
                                      cl::cat(OffloadBinaryCategory));

static cl::list<std::string>
    DeviceImages("image",
                 cl::desc("List of key and value arguments. Required keywords "
                          "are 'file' and 'triple'."),
                 cl::value_desc("<key>=<value>,..."),
                 cl::cat(OffloadBinaryCategory));

static cl::opt<bool>
    CreateArchive("archive",
                  cl::desc("Write extracted files to a static archive"),
                  cl::cat(OffloadBinaryCategory));

static cl::opt<bool> Compress("compress",
                              cl::desc("Compress the packaged offload binary"),
                              cl::cat(OffloadBinaryCategory));

static cl::opt<compression::Format> CompressionFormat(
    "compression-format", cl::desc("Format used with --compress"),
    cl::values(
        clEnumValN(compression::Format::Zstd, "zstd", "Zstandard compression"),
        clEnumValN(compression::Format::Zlib, "zlib", "zlib compression")),
    cl::init(compression::Format::Zstd), cl::cat(OffloadBinaryCategory));

static cl::opt<int>
    CompressionLevel("compression-level",
                     cl::desc("Compression level used with --compress"),
                     cl::init(-1), cl::cat(OffloadBinaryCategory));

/// Path of the current binary.
static const char *PackagerExecutable;

// Get a map containing all the arguments for the image. Repeated arguments will
// be placed in a comma separated list.
static DenseMap<StringRef, StringRef> getImageArguments(StringRef Image,
                                                        StringSaver &Saver) {
  DenseMap<StringRef, StringRef> Args;
  for (StringRef Arg : llvm::split(Image, ",")) {
    auto [Key, Value] = Arg.split("=");
    auto [It, Inserted] = Args.try_emplace(Key, Value);
    if (!Inserted)
      It->second = Saver.save(It->second + "," + Value);
  }

  return Args;
}

static Error writeFile(StringRef Filename, StringRef Data) {
  Expected<std::unique_ptr<FileOutputBuffer>> OutputOrErr =
      FileOutputBuffer::create(Filename, Data.size());
  if (!OutputOrErr)
    return OutputOrErr.takeError();
  std::unique_ptr<FileOutputBuffer> Output = std::move(*OutputOrErr);
  llvm::copy(Data, Output->getBufferStart());
  if (Error E = Output->commit())
    return E;
  return Error::success();
}

static Error bundleImages() {
  SmallVector<OffloadBinary::OffloadingImage> AllImages;
  BumpPtrAllocator Alloc;
  StringSaver Saver(Alloc);
  for (StringRef Image : DeviceImages) {
    DenseMap<StringRef, StringRef> Args = getImageArguments(Image, Saver);

    if (!Args.count("file"))
      return createStringError(inconvertibleErrorCode(),
                               "'file' is a required image arguments");

    // Permit using multiple instances of `file` in a single string.
    for (auto &File : llvm::split(Args["file"], ",")) {
      OffloadBinary::OffloadingImage ImageBinary{};

      llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ObjectOrErr =
          llvm::MemoryBuffer::getFileOrSTDIN(File);
      if (std::error_code EC = ObjectOrErr.getError())
        return errorCodeToError(EC);

      // Clang uses the '.o' suffix for LTO bitcode.
      if (identify_magic((*ObjectOrErr)->getBuffer()) == file_magic::bitcode)
        ImageBinary.TheImageKind = object::IMG_Bitcode;
      else if (sys::path::has_extension(File))
        ImageBinary.TheImageKind =
            getImageKind(sys::path::extension(File).drop_front());
      else
        ImageBinary.TheImageKind = IMG_None;
      ImageBinary.Image = std::move(*ObjectOrErr);
      for (const auto &[Key, Value] : Args) {
        if (Key == "kind") {
          ImageBinary.TheOffloadKind = getOffloadKind(Value);
        } else if (Key != "file") {
          ImageBinary.StringData[Key] = Value;
        }
      }
      AllImages.emplace_back(std::move(ImageBinary));
    }
  }

  SmallString<0> Buffer;
  if (Compress) {
    if (const char *Reason =
            compression::getReasonIfUnsupported(CompressionFormat))
      return createStringError(inconvertibleErrorCode(), Reason);
    compression::Params Params(CompressionFormat);
    if (CompressionLevel.getNumOccurrences())
      Params.level = CompressionLevel;
    Expected<SmallString<0>> CompressedOrErr =
        OffloadBinary::write(AllImages, Params);
    if (!CompressedOrErr)
      return CompressedOrErr.takeError();
    Buffer = std::move(*CompressedOrErr);
  } else {
    Buffer = OffloadBinary::write(AllImages);
  }
  if (Buffer.size() % OffloadBinary::getAlignment() != 0)
    return createStringError(inconvertibleErrorCode(),
                             "Offload binary has invalid size alignment");

  if (Error E = writeFile(OutputFile, StringRef(Buffer.data(), Buffer.size())))
    return E;
  return Error::success();
}

// Extract a single OffloadBinary, recursively handling nested OffloadBinaries.
static Error extractBinary(const OffloadBinary *Binary, StringRef InputFile,
                           uint64_t &Idx, StringSaver &Saver) {
  StringRef ImageData = Binary->getImage();

  // Check if the image contains a nested OffloadBinary.
  if (identify_magic(ImageData) == file_magic::offload_binary) {
    // Parse nested OffloadBinary.
    MemoryBufferRef InnerBuffer(ImageData, "nested-offload-binary");
    SmallVector<OffloadFile> InnerBinaries;
    if (Error Err = extractOffloadBinaries(InnerBuffer, InnerBinaries))
      return Err;

    // Recursively extract each nested binary.
    for (const auto &InnerBinary : InnerBinaries) {
      if (Error E =
              extractBinary(InnerBinary.getBinary(), InputFile, Idx, Saver))
        return E;
    }
    return Error::success();
  }

  // Base case: extract the actual device image.
  std::string Filename;
  raw_string_ostream SS(Filename);
  SS << sys::path::stem(InputFile) << "-" << Binary->getTriple();
  StringRef Arch = Binary->getArch();
  if (!Arch.empty())
    SS << "-" << Arch;
  SS << "." << Idx++ << "." << getImageKindName(Binary->getImageKind());

  if (Error E = writeFile(Saver.save(Filename), ImageData))
    return E;

  outs() << "Extracted: " << Filename << "\n";
  return Error::success();
}

static Error unbundleImages() {
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFileOrSTDIN(InputFile);
  if (std::error_code EC = BufferOrErr.getError())
    return createFileError(InputFile, EC);
  std::unique_ptr<MemoryBuffer> Buffer = std::move(*BufferOrErr);

  // This data can be misaligned if extracted from an archive.
  if (!isAddrAligned(Align(OffloadBinary::getAlignment()),
                     Buffer->getBufferStart()))
    Buffer = MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(),
                                            Buffer->getBufferIdentifier());

  SmallVector<OffloadFile> Binaries;
  if (Error Err = extractOffloadBinaries(*Buffer, Binaries))
    return Err;

  // If no filters specified, extract all images.
  if (DeviceImages.empty()) {
    BumpPtrAllocator Alloc;
    StringSaver Saver(Alloc);
    uint64_t Idx = 0;
    for (const OffloadFile &File : Binaries) {
      if (Error E = extractBinary(File.getBinary(), InputFile, Idx, Saver))
        return E;
    }
    return Error::success();
  }

  // Try to extract each device image specified by the user from the input file.
  for (StringRef Image : DeviceImages) {
    BumpPtrAllocator Alloc;
    StringSaver Saver(Alloc);
    auto Args = getImageArguments(Image, Saver);

    SmallVector<const OffloadBinary *> Extracted;
    for (const OffloadFile &File : Binaries) {
      const auto *Binary = File.getBinary();
      // We handle the 'file', 'kind', and 'member' identifiers differently.
      bool Match = llvm::all_of(Args, [&](auto &Arg) {
        const auto [Key, Value] = Arg;
        if (Key == "file")
          return true;
        if (Key == "kind")
          return Binary->getOffloadKind() == getOffloadKind(Value);
        if (Key == "member")
          return sys::path::filename(
                     Binary->getMemoryBufferRef().getBufferIdentifier()) ==
                 Value;
        return Binary->getString(Key) == Value;
      });
      if (Match)
        Extracted.push_back(Binary);
    }

    if (Extracted.empty())
      continue;

    if (CreateArchive) {
      if (!Args.count("file"))
        return createStringError(inconvertibleErrorCode(),
                                 "Image must have a 'file' argument.");

      SmallVector<NewArchiveMember> Members;
      for (const OffloadBinary *Binary : Extracted)
        Members.emplace_back(MemoryBufferRef(
            Binary->getImage(),
            Binary->getMemoryBufferRef().getBufferIdentifier()));

      if (Error E = writeArchive(
              Args["file"], Members, SymtabWritingMode::NormalSymtab,
              Archive::getDefaultKind(), true, false, nullptr))
        return E;
    } else if (auto It = Args.find("file"); It != Args.end()) {
      if (Extracted.size() > 1)
        WithColor::warning(errs(), PackagerExecutable)
            << "Multiple inputs match to a single file, '" << It->second
            << "'\n";
      if (Error E = writeFile(It->second, Extracted.back()->getImage()))
        return E;
    } else {
      uint64_t Idx = 0;
      for (const OffloadBinary *Binary : Extracted) {
        if (Error E = extractBinary(Binary, InputFile, Idx, Saver))
          return E;
      }
    }
  }

  return Error::success();
}

int main(int argc, const char **argv) {
  sys::PrintStackTraceOnErrorSignal(argv[0]);
  cl::HideUnrelatedOptions(OffloadBinaryCategory);
  cl::ParseCommandLineOptions(
      argc, argv,
      "A utility for bundling several object files into a single binary.\n"
      "The output binary can then be embedded into the host section table\n"
      "to create a fatbinary containing offloading code.\n");

  if (sys::path::stem(argv[0]).ends_with("clang-offload-packager"))
    WithColor::warning(errs(), PackagerExecutable)
        << "'clang-offload-packager' is deprecated. Use 'llvm-offload-binary' "
           "instead.\n";

  if (OutputFile.empty() && InputFile.empty()) {
    cl::PrintHelpMessage();
    return EXIT_SUCCESS;
  }

  PackagerExecutable = argv[0];
  auto reportError = [argv](Error E) {
    logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0]));
    return EXIT_FAILURE;
  };

  if (!InputFile.empty() && !OutputFile.empty())
    return reportError(
        createStringError(inconvertibleErrorCode(),
                          "Packaging to an output file and extracting from an "
                          "input file are mutually exclusive."));

  if (!OutputFile.empty()) {
    if (Error Err = bundleImages())
      return reportError(std::move(Err));
  } else if (!InputFile.empty()) {
    if (Error Err = unbundleImages())
      return reportError(std::move(Err));
  }

  return EXIT_SUCCESS;
}
