//===- TBEHandler.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 "llvm/InterfaceStub/TBEHandler.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/InterfaceStub/ELFStub.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/YAMLTraits.h"

using namespace llvm;
using namespace llvm::elfabi;

LLVM_YAML_STRONG_TYPEDEF(ELFArch, ELFArchMapper)

namespace llvm {
namespace yaml {

/// YAML traits for ELFSymbolType.
template <> struct ScalarEnumerationTraits<ELFSymbolType> {
  static void enumeration(IO &IO, ELFSymbolType &SymbolType) {
    IO.enumCase(SymbolType, "NoType", ELFSymbolType::NoType);
    IO.enumCase(SymbolType, "Func", ELFSymbolType::Func);
    IO.enumCase(SymbolType, "Object", ELFSymbolType::Object);
    IO.enumCase(SymbolType, "TLS", ELFSymbolType::TLS);
    IO.enumCase(SymbolType, "Unknown", ELFSymbolType::Unknown);
    // Treat other symbol types as noise, and map to Unknown.
    if (!IO.outputting() && IO.matchEnumFallback())
      SymbolType = ELFSymbolType::Unknown;
  }
};

/// YAML traits for ELFArch.
template <> struct ScalarTraits<ELFArchMapper> {
  static void output(const ELFArchMapper &Value, void *,
                     llvm::raw_ostream &Out) {
    // Map from integer to architecture string.
    switch (Value) {
    case (ELFArch)ELF::EM_X86_64:
      Out << "x86_64";
      break;
    case (ELFArch)ELF::EM_AARCH64:
      Out << "AArch64";
      break;
    case (ELFArch)ELF::EM_NONE:
    default:
      Out << "Unknown";
    }
  }

  static StringRef input(StringRef Scalar, void *, ELFArchMapper &Value) {
    // Map from architecture string to integer.
    Value = StringSwitch<ELFArch>(Scalar)
                .Case("x86_64", ELF::EM_X86_64)
                .Case("AArch64", ELF::EM_AARCH64)
                .Case("Unknown", ELF::EM_NONE)
                .Default(ELF::EM_NONE);

    // Returning empty StringRef indicates successful parse.
    return StringRef();
  }

  // Don't place quotation marks around architecture value.
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
};

/// YAML traits for ELFSymbol.
template <> struct MappingTraits<ELFSymbol> {
  static void mapping(IO &IO, ELFSymbol &Symbol) {
    IO.mapRequired("Type", Symbol.Type);
    // The need for symbol size depends on the symbol type.
    if (Symbol.Type == ELFSymbolType::NoType) {
      IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
    } else if (Symbol.Type == ELFSymbolType::Func) {
      Symbol.Size = 0;
    } else {
      IO.mapRequired("Size", Symbol.Size);
    }
    IO.mapOptional("Undefined", Symbol.Undefined, false);
    IO.mapOptional("Weak", Symbol.Weak, false);
    IO.mapOptional("Warning", Symbol.Warning);
  }

  // Compacts symbol information into a single line.
  static const bool flow = true;
};

/// YAML traits for set of ELFSymbols.
template <> struct CustomMappingTraits<std::set<ELFSymbol>> {
  static void inputOne(IO &IO, StringRef Key, std::set<ELFSymbol> &Set) {
    ELFSymbol Sym(Key.str());
    IO.mapRequired(Key.str().c_str(), Sym);
    Set.insert(Sym);
  }

  static void output(IO &IO, std::set<ELFSymbol> &Set) {
    for (auto &Sym : Set)
      IO.mapRequired(Sym.Name.c_str(), const_cast<ELFSymbol &>(Sym));
  }
};

/// YAML traits for ELFStub objects.
template <> struct MappingTraits<ELFStub> {
  static void mapping(IO &IO, ELFStub &Stub) {
    if (!IO.mapTag("!tapi-tbe", true))
      IO.setError("Not a .tbe YAML file.");
    IO.mapRequired("TbeVersion", Stub.TbeVersion);
    IO.mapOptional("SoName", Stub.SoName);
    IO.mapRequired("Arch", (ELFArchMapper &)Stub.Arch);
    IO.mapOptional("NeededLibs", Stub.NeededLibs);
    IO.mapRequired("Symbols", Stub.Symbols);
  }
};

} // end namespace yaml
} // end namespace llvm

Expected<std::unique_ptr<ELFStub>> elfabi::readTBEFromBuffer(StringRef Buf) {
  yaml::Input YamlIn(Buf);
  std::unique_ptr<ELFStub> Stub(new ELFStub());
  YamlIn >> *Stub;
  if (std::error_code Err = YamlIn.error())
    return createStringError(Err, "YAML failed reading as TBE");

  if (Stub->TbeVersion > elfabi::TBEVersionCurrent)
    return make_error<StringError>(
        "TBE version " + Stub->TbeVersion.getAsString() + " is unsupported.",
        std::make_error_code(std::errc::invalid_argument));

  return std::move(Stub);
}

Error elfabi::writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub) {
  yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0);

  YamlOut << const_cast<ELFStub &>(Stub);
  return Error::success();
}
