//===-- llvm-cgdata.cpp - LLVM CodeGen Data Tool --------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// llvm-cgdata parses raw codegen data embedded in compiled binary files, and
// merges them into a single .cgdata file. It can also inspect and maninuplate
// a .cgdata file. This .cgdata can contain various codegen data like outlining
// information, and it can be used to optimize the code in the subsequent build.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringRef.h"
#include "llvm/CGData/CodeGenDataReader.h"
#include "llvm/CGData/CodeGenDataWriter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/Binary.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;
using namespace llvm::object;

enum CGDataFormat {
  Invalid,
  Text,
  Binary,
};

enum CGDataAction {
  Convert,
  Merge,
  Show,
};

// Command-line option boilerplate.
namespace {
enum ID {
  OPT_INVALID = 0, // This is not an option ID.
#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
#include "Opts.inc"
#undef OPTION
};

#define OPTTABLE_STR_TABLE_CODE
#include "Opts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "Opts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

using namespace llvm::opt;
static constexpr opt::OptTable::Info InfoTable[] = {
#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
#include "Opts.inc"
#undef OPTION
};

class CGDataOptTable : public opt::GenericOptTable {
public:
  CGDataOptTable()
      : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {}
};
} // end anonymous namespace

// Options
static StringRef ToolName;
static StringRef OutputFilename = "-";
static StringRef Filename;
static bool ShowCGDataVersion;
static bool SkipTrim;
static CGDataAction Action;
static std::optional<CGDataFormat> OutputFormat;
static std::vector<std::string> InputFilenames;

static void exitWithError(Twine Message, StringRef Whence = "",
                          StringRef Hint = "") {
  WithColor::error();
  if (!Whence.empty())
    errs() << Whence << ": ";
  errs() << Message << "\n";
  if (!Hint.empty())
    WithColor::note() << Hint << "\n";
  ::exit(1);
}

static void exitWithError(Error E, StringRef Whence = "") {
  if (E.isA<CGDataError>()) {
    handleAllErrors(std::move(E), [&](const CGDataError &IPE) {
      exitWithError(IPE.message(), Whence);
    });
    return;
  }

  exitWithError(toString(std::move(E)), Whence);
}

static void exitWithErrorCode(std::error_code EC, StringRef Whence = "") {
  exitWithError(EC.message(), Whence);
}

static int convert_main(int argc, const char *argv[]) {
  std::error_code EC;
  raw_fd_ostream OS(OutputFilename, EC,
                    OutputFormat == CGDataFormat::Text
                        ? sys::fs::OF_TextWithCRLF
                        : sys::fs::OF_None);
  if (EC)
    exitWithErrorCode(EC, OutputFilename);

  auto FS = vfs::getRealFileSystem();
  auto ReaderOrErr = CodeGenDataReader::create(Filename, *FS);
  if (Error E = ReaderOrErr.takeError())
    exitWithError(std::move(E), Filename);

  CodeGenDataWriter Writer;
  auto Reader = ReaderOrErr->get();
  if (Reader->hasOutlinedHashTree()) {
    OutlinedHashTreeRecord Record(Reader->releaseOutlinedHashTree());
    Writer.addRecord(Record);
  }
  if (Reader->hasStableFunctionMap()) {
    StableFunctionMapRecord Record(Reader->releaseStableFunctionMap());
    Writer.addRecord(Record);
  }

  if (OutputFormat == CGDataFormat::Text) {
    if (Error E = Writer.writeText(OS))
      exitWithError(std::move(E));
  } else {
    if (Error E = Writer.write(OS))
      exitWithError(std::move(E));
  }

  return 0;
}

static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
                         OutlinedHashTreeRecord &GlobalOutlineRecord,
                         StableFunctionMapRecord &GlobalFunctionMapRecord);

static bool handleArchive(StringRef Filename, Archive &Arch,
                          OutlinedHashTreeRecord &GlobalOutlineRecord,
                          StableFunctionMapRecord &GlobalFunctionMapRecord) {
  bool Result = true;
  Error Err = Error::success();
  for (const auto &Child : Arch.children(Err)) {
    auto BuffOrErr = Child.getMemoryBufferRef();
    if (Error E = BuffOrErr.takeError())
      exitWithError(std::move(E), Filename);
    auto NameOrErr = Child.getName();
    if (Error E = NameOrErr.takeError())
      exitWithError(std::move(E), Filename);
    std::string Name = (Filename + "(" + NameOrErr.get() + ")").str();
    Result &= handleBuffer(Name, BuffOrErr.get(), GlobalOutlineRecord,
                           GlobalFunctionMapRecord);
  }
  if (Err)
    exitWithError(std::move(Err), Filename);
  return Result;
}

static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
                         OutlinedHashTreeRecord &GlobalOutlineRecord,
                         StableFunctionMapRecord &GlobalFunctionMapRecord) {
  Expected<std::unique_ptr<object::Binary>> BinOrErr =
      object::createBinary(Buffer);
  if (Error E = BinOrErr.takeError())
    exitWithError(std::move(E), Filename);

  bool Result = true;
  if (auto *Obj = dyn_cast<ObjectFile>(BinOrErr->get())) {
    if (Error E = CodeGenDataReader::mergeFromObjectFile(
            Obj, GlobalOutlineRecord, GlobalFunctionMapRecord))
      exitWithError(std::move(E), Filename);
  } else if (auto *Arch = dyn_cast<Archive>(BinOrErr->get())) {
    Result &= handleArchive(Filename, *Arch, GlobalOutlineRecord,
                            GlobalFunctionMapRecord);
  } else {
    // TODO: Support for the MachO universal binary format.
    errs() << "Error: unsupported binary file: " << Filename << "\n";
    Result = false;
  }

  return Result;
}

static bool handleFile(StringRef Filename,
                       OutlinedHashTreeRecord &GlobalOutlineRecord,
                       StableFunctionMapRecord &GlobalFunctionMapRecord) {
  ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
      MemoryBuffer::getFileOrSTDIN(Filename);
  if (std::error_code EC = BuffOrErr.getError())
    exitWithErrorCode(EC, Filename);
  return handleBuffer(Filename, *BuffOrErr.get(), GlobalOutlineRecord,
                      GlobalFunctionMapRecord);
}

static int merge_main(int argc, const char *argv[]) {
  bool Result = true;
  OutlinedHashTreeRecord GlobalOutlineRecord;
  StableFunctionMapRecord GlobalFunctionMapRecord;
  for (auto &Filename : InputFilenames)
    Result &=
        handleFile(Filename, GlobalOutlineRecord, GlobalFunctionMapRecord);

  if (!Result)
    exitWithError("failed to merge codegen data files.");

  GlobalFunctionMapRecord.finalize(SkipTrim);

  CodeGenDataWriter Writer;
  if (!GlobalOutlineRecord.empty())
    Writer.addRecord(GlobalOutlineRecord);
  if (!GlobalFunctionMapRecord.empty())
    Writer.addRecord(GlobalFunctionMapRecord);

  std::error_code EC;
  raw_fd_ostream OS(OutputFilename, EC,
                    OutputFormat == CGDataFormat::Text
                        ? sys::fs::OF_TextWithCRLF
                        : sys::fs::OF_None);
  if (EC)
    exitWithErrorCode(EC, OutputFilename);

  if (OutputFormat == CGDataFormat::Text) {
    if (Error E = Writer.writeText(OS))
      exitWithError(std::move(E));
  } else {
    if (Error E = Writer.write(OS))
      exitWithError(std::move(E));
  }

  return 0;
}

static int show_main(int argc, const char *argv[]) {
  std::error_code EC;
  raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
  if (EC)
    exitWithErrorCode(EC, OutputFilename);

  auto FS = vfs::getRealFileSystem();
  auto ReaderOrErr = CodeGenDataReader::create(Filename, *FS);
  if (Error E = ReaderOrErr.takeError())
    exitWithError(std::move(E), Filename);

  auto Reader = ReaderOrErr->get();
  if (ShowCGDataVersion)
    OS << "Version: " << Reader->getVersion() << "\n";

  if (Reader->hasOutlinedHashTree()) {
    auto Tree = Reader->releaseOutlinedHashTree();
    OS << "Outlined hash tree:\n";
    OS << "  Total Node Count: " << Tree->size() << "\n";
    OS << "  Terminal Node Count: " << Tree->size(/*GetTerminalCountOnly=*/true)
       << "\n";
    OS << "  Depth: " << Tree->depth() << "\n";
  }
  if (Reader->hasStableFunctionMap()) {
    auto Map = Reader->releaseStableFunctionMap();
    OS << "Stable function map:\n";
    OS << "  Unique hash Count: " << Map->size() << "\n";
    OS << "  Total function Count: "
       << Map->size(StableFunctionMap::TotalFunctionCount) << "\n";
    OS << "  Mergeable function Count: "
       << Map->size(StableFunctionMap::MergeableFunctionCount) << "\n";
  }

  return 0;
}

static void parseArgs(int argc, char **argv) {
  CGDataOptTable Tbl;
  ToolName = argv[0];
  llvm::BumpPtrAllocator A;
  llvm::StringSaver Saver{A};
  llvm::opt::InputArgList Args =
      Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
        llvm::errs() << Msg << '\n';
        std::exit(1);
      });

  if (Args.hasArg(OPT_help)) {
    Tbl.printHelp(
        llvm::outs(),
        "llvm-cgdata <action> [options] (<binary files>|<.cgdata file>)",
        ToolName.str().c_str());
    std::exit(0);
  }
  if (Args.hasArg(OPT_version)) {
    cl::PrintVersionMessage();
    std::exit(0);
  }

  ShowCGDataVersion = Args.hasArg(OPT_cgdata_version);
  SkipTrim = Args.hasArg(OPT_skip_trim);

  if (opt::Arg *A = Args.getLastArg(OPT_format)) {
    StringRef OF = A->getValue();
    OutputFormat = StringSwitch<CGDataFormat>(OF)
                       .Case("text", CGDataFormat::Text)
                       .Case("binary", CGDataFormat::Binary)
                       .Default(CGDataFormat::Invalid);
    if (OutputFormat == CGDataFormat::Invalid)
      exitWithError("unsupported format '" + OF + "'");
  }

  InputFilenames = Args.getAllArgValues(OPT_INPUT);
  if (InputFilenames.empty())
    exitWithError("No input file is specified.");
  Filename = InputFilenames[0];

  if (Args.hasArg(OPT_output)) {
    OutputFilename = Args.getLastArgValue(OPT_output);
    for (auto &Filename : InputFilenames)
      if (Filename == OutputFilename)
        exitWithError(
            "Input file name cannot be the same as the output file name!\n");
  }

  opt::Arg *ActionArg = nullptr;
  for (opt::Arg *Arg : Args.filtered(OPT_action_group)) {
    if (ActionArg)
      exitWithError("Only one action is allowed.");
    ActionArg = Arg;
  }
  if (!ActionArg)
    exitWithError("One action is required.");

  switch (ActionArg->getOption().getID()) {
  case OPT_show:
    if (InputFilenames.size() != 1)
      exitWithError("only one input file is allowed.");
    Action = CGDataAction::Show;
    break;
  case OPT_convert:
    // The default output format is text for convert.
    if (!OutputFormat)
      OutputFormat = CGDataFormat::Text;
    if (InputFilenames.size() != 1)
      exitWithError("only one input file is allowed.");
    Action = CGDataAction::Convert;
    break;
  case OPT_merge:
    // The default output format is binary for merge.
    if (!OutputFormat)
      OutputFormat = CGDataFormat::Binary;
    Action = CGDataAction::Merge;
    break;
  default:
    llvm_unreachable("unrecognized action");
  }
}

int llvm_cgdata_main(int argc, char **argvNonConst, const llvm::ToolContext &) {
  const char **argv = const_cast<const char **>(argvNonConst);
  parseArgs(argc, argvNonConst);

  switch (Action) {
  case CGDataAction::Convert:
    return convert_main(argc, argv);
  case CGDataAction::Merge:
    return merge_main(argc, argv);
  case CGDataAction::Show:
    return show_main(argc, argv);
  }

  llvm_unreachable("unrecognized action");
}
