//===-- BenchmarkResult.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "BenchmarkResult.h"
#include "BenchmarkRunner.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/bit.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ObjectYAML/YAML.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"

static constexpr const char kIntegerPrefix[] = "i_0x";
static constexpr const char kDoublePrefix[] = "f_";
static constexpr const char kInvalidOperand[] = "INVALID";

namespace llvm {

namespace {

// A mutable struct holding an LLVMState that can be passed through the
// serialization process to encode/decode registers and instructions.
struct YamlContext {
  YamlContext(const exegesis::LLVMState &State)
      : State(&State), ErrorStream(LastError) {}

  void serializeMCInst(const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
    OS << getInstrName(MCInst.getOpcode());
    for (const auto &Op : MCInst) {
      OS << ' ';
      serializeMCOperand(Op, OS);
    }
  }

  void deserializeMCInst(llvm::StringRef String, llvm::MCInst &Value) {
    llvm::SmallVector<llvm::StringRef, 8> Pieces;
    String.split(Pieces, " ", /* MaxSplit */ -1, /* KeepEmpty */ false);
    if (Pieces.empty()) {
      ErrorStream << "Unknown Instruction: '" << String << "'";
      return;
    }
    bool ProcessOpcode = true;
    for (llvm::StringRef Piece : Pieces) {
      if (ProcessOpcode)
        Value.setOpcode(getInstrOpcode(Piece));
      else
        Value.addOperand(deserializeMCOperand(Piece));
      ProcessOpcode = false;
    }
  }

  std::string &getLastError() { return ErrorStream.str(); }

  llvm::raw_string_ostream &getErrorStream() { return ErrorStream; }

  llvm::StringRef getRegName(unsigned RegNo) {
    const llvm::StringRef RegName = State->getRegInfo().getName(RegNo);
    if (RegName.empty())
      ErrorStream << "No register with enum value" << RegNo;
    return RegName;
  }

  unsigned getRegNo(llvm::StringRef RegName) {
    const llvm::MCRegisterInfo &RegInfo = State->getRegInfo();
    for (unsigned E = RegInfo.getNumRegs(), I = 0; I < E; ++I)
      if (RegInfo.getName(I) == RegName)
        return I;
    ErrorStream << "No register with name " << RegName;
    return 0;
  }

private:
  void serializeIntegerOperand(llvm::raw_ostream &OS, int64_t Value) {
    OS << kIntegerPrefix;
    OS.write_hex(llvm::bit_cast<uint64_t>(Value));
  }

  bool tryDeserializeIntegerOperand(llvm::StringRef String, int64_t &Value) {
    if (!String.consume_front(kIntegerPrefix))
      return false;
    return !String.consumeInteger(16, Value);
  }

  void serializeFPOperand(llvm::raw_ostream &OS, double Value) {
    OS << kDoublePrefix << llvm::format("%la", Value);
  }

  bool tryDeserializeFPOperand(llvm::StringRef String, double &Value) {
    if (!String.consume_front(kDoublePrefix))
      return false;
    char *EndPointer = nullptr;
    Value = strtod(String.begin(), &EndPointer);
    return EndPointer == String.end();
  }

  void serializeMCOperand(const llvm::MCOperand &MCOperand,
                          llvm::raw_ostream &OS) {
    if (MCOperand.isReg()) {
      OS << getRegName(MCOperand.getReg());
    } else if (MCOperand.isImm()) {
      serializeIntegerOperand(OS, MCOperand.getImm());
    } else if (MCOperand.isFPImm()) {
      serializeFPOperand(OS, MCOperand.getFPImm());
    } else {
      OS << kInvalidOperand;
    }
  }

  llvm::MCOperand deserializeMCOperand(llvm::StringRef String) {
    assert(!String.empty());
    int64_t IntValue = 0;
    double DoubleValue = 0;
    if (tryDeserializeIntegerOperand(String, IntValue))
      return llvm::MCOperand::createImm(IntValue);
    if (tryDeserializeFPOperand(String, DoubleValue))
      return llvm::MCOperand::createFPImm(DoubleValue);
    if (unsigned RegNo = getRegNo(String))
      return llvm::MCOperand::createReg(RegNo);
    if (String != kInvalidOperand)
      ErrorStream << "Unknown Operand: '" << String << "'";
    return {};
  }

  llvm::StringRef getInstrName(unsigned InstrNo) {
    const llvm::StringRef InstrName = State->getInstrInfo().getName(InstrNo);
    if (InstrName.empty())
      ErrorStream << "No opcode with enum value" << InstrNo;
    return InstrName;
  }

  unsigned getInstrOpcode(llvm::StringRef InstrName) {
    const llvm::MCInstrInfo &InstrInfo = State->getInstrInfo();
    for (unsigned E = InstrInfo.getNumOpcodes(), I = 0; I < E; ++I)
      if (InstrInfo.getName(I) == InstrName)
        return I;
    ErrorStream << "No opcode with name " << InstrName;
    return 0;
  }

  const llvm::exegesis::LLVMState *State;
  std::string LastError;
  llvm::raw_string_ostream ErrorStream;
};
} // namespace

// Defining YAML traits for IO.
namespace yaml {

static YamlContext &getTypedContext(void *Ctx) {
  return *reinterpret_cast<YamlContext *>(Ctx);
}

// std::vector<llvm::MCInst> will be rendered as a list.
template <> struct SequenceElementTraits<llvm::MCInst> {
  static const bool flow = false;
};

template <> struct ScalarTraits<llvm::MCInst> {

  static void output(const llvm::MCInst &Value, void *Ctx,
                     llvm::raw_ostream &Out) {
    getTypedContext(Ctx).serializeMCInst(Value, Out);
  }

  static StringRef input(StringRef Scalar, void *Ctx, llvm::MCInst &Value) {
    YamlContext &Context = getTypedContext(Ctx);
    Context.deserializeMCInst(Scalar, Value);
    return Context.getLastError();
  }

  // By default strings are quoted only when necessary.
  // We force the use of single quotes for uniformity.
  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }

  static const bool flow = true;
};

// std::vector<exegesis::Measure> will be rendered as a list.
template <> struct SequenceElementTraits<exegesis::BenchmarkMeasure> {
  static const bool flow = false;
};

// exegesis::Measure is rendererd as a flow instead of a list.
// e.g. { "key": "the key", "value": 0123 }
template <> struct MappingTraits<exegesis::BenchmarkMeasure> {
  static void mapping(IO &Io, exegesis::BenchmarkMeasure &Obj) {
    Io.mapRequired("key", Obj.Key);
    if (!Io.outputting()) {
      // For backward compatibility, interpret debug_string as a key.
      Io.mapOptional("debug_string", Obj.Key);
    }
    Io.mapRequired("value", Obj.PerInstructionValue);
    Io.mapOptional("per_snippet_value", Obj.PerSnippetValue);
  }
  static const bool flow = true;
};

template <>
struct ScalarEnumerationTraits<exegesis::InstructionBenchmark::ModeE> {
  static void enumeration(IO &Io,
                          exegesis::InstructionBenchmark::ModeE &Value) {
    Io.enumCase(Value, "", exegesis::InstructionBenchmark::Unknown);
    Io.enumCase(Value, "latency", exegesis::InstructionBenchmark::Latency);
    Io.enumCase(Value, "uops", exegesis::InstructionBenchmark::Uops);
  }
};

// std::vector<exegesis::RegisterValue> will be rendered as a list.
template <> struct SequenceElementTraits<exegesis::RegisterValue> {
  static const bool flow = false;
};

template <> struct ScalarTraits<exegesis::RegisterValue> {
  static constexpr const unsigned kRadix = 16;
  static constexpr const bool kSigned = false;

  static void output(const exegesis::RegisterValue &RV, void *Ctx,
                     llvm::raw_ostream &Out) {
    YamlContext &Context = getTypedContext(Ctx);
    Out << Context.getRegName(RV.Register) << "=0x"
        << RV.Value.toString(kRadix, kSigned);
  }

  static StringRef input(StringRef String, void *Ctx,
                         exegesis::RegisterValue &RV) {
    llvm::SmallVector<llvm::StringRef, 2> Pieces;
    String.split(Pieces, "=0x", /* MaxSplit */ -1,
                 /* KeepEmpty */ false);
    YamlContext &Context = getTypedContext(Ctx);
    if (Pieces.size() == 2) {
      RV.Register = Context.getRegNo(Pieces[0]);
      const unsigned BitsNeeded = llvm::APInt::getBitsNeeded(Pieces[1], kRadix);
      RV.Value = llvm::APInt(BitsNeeded, Pieces[1], kRadix);
    } else {
      Context.getErrorStream()
          << "Unknown initial register value: '" << String << "'";
    }
    return Context.getLastError();
  }

  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }

  static const bool flow = true;
};

template <>
struct MappingContextTraits<exegesis::InstructionBenchmarkKey, YamlContext> {
  static void mapping(IO &Io, exegesis::InstructionBenchmarkKey &Obj,
                      YamlContext &Context) {
    Io.setContext(&Context);
    Io.mapRequired("instructions", Obj.Instructions);
    Io.mapOptional("config", Obj.Config);
    Io.mapRequired("register_initial_values", Obj.RegisterInitialValues);
  }
};

template <>
struct MappingContextTraits<exegesis::InstructionBenchmark, YamlContext> {
  struct NormalizedBinary {
    NormalizedBinary(IO &io) {}
    NormalizedBinary(IO &, std::vector<uint8_t> &Data) : Binary(Data) {}
    std::vector<uint8_t> denormalize(IO &) {
      std::vector<uint8_t> Data;
      std::string Str;
      raw_string_ostream OSS(Str);
      Binary.writeAsBinary(OSS);
      OSS.flush();
      Data.assign(Str.begin(), Str.end());
      return Data;
    }

    BinaryRef Binary;
  };

  static void mapping(IO &Io, exegesis::InstructionBenchmark &Obj,
                      YamlContext &Context) {
    Io.mapRequired("mode", Obj.Mode);
    Io.mapRequired("key", Obj.Key, Context);
    Io.mapRequired("cpu_name", Obj.CpuName);
    Io.mapRequired("llvm_triple", Obj.LLVMTriple);
    Io.mapRequired("num_repetitions", Obj.NumRepetitions);
    Io.mapRequired("measurements", Obj.Measurements);
    Io.mapRequired("error", Obj.Error);
    Io.mapOptional("info", Obj.Info);
    // AssembledSnippet
    MappingNormalization<NormalizedBinary, std::vector<uint8_t>> BinaryString(
        Io, Obj.AssembledSnippet);
    Io.mapOptional("assembled_snippet", BinaryString->Binary);
  }
};

} // namespace yaml

namespace exegesis {

llvm::Expected<InstructionBenchmark>
InstructionBenchmark::readYaml(const LLVMState &State,
                               llvm::StringRef Filename) {
  if (auto ExpectedMemoryBuffer =
          llvm::errorOrToExpected(llvm::MemoryBuffer::getFile(Filename))) {
    llvm::yaml::Input Yin(*ExpectedMemoryBuffer.get());
    YamlContext Context(State);
    InstructionBenchmark Benchmark;
    if (Yin.setCurrentDocument())
      llvm::yaml::yamlize(Yin, Benchmark, /*unused*/ true, Context);
    if (!Context.getLastError().empty())
      return llvm::make_error<BenchmarkFailure>(Context.getLastError());
    return Benchmark;
  } else {
    return ExpectedMemoryBuffer.takeError();
  }
}

llvm::Expected<std::vector<InstructionBenchmark>>
InstructionBenchmark::readYamls(const LLVMState &State,
                                llvm::StringRef Filename) {
  if (auto ExpectedMemoryBuffer =
          llvm::errorOrToExpected(llvm::MemoryBuffer::getFile(Filename))) {
    llvm::yaml::Input Yin(*ExpectedMemoryBuffer.get());
    YamlContext Context(State);
    std::vector<InstructionBenchmark> Benchmarks;
    while (Yin.setCurrentDocument()) {
      Benchmarks.emplace_back();
      yamlize(Yin, Benchmarks.back(), /*unused*/ true, Context);
      if (Yin.error())
        return llvm::errorCodeToError(Yin.error());
      if (!Context.getLastError().empty())
        return llvm::make_error<BenchmarkFailure>(Context.getLastError());
      Yin.nextDocument();
    }
    return Benchmarks;
  } else {
    return ExpectedMemoryBuffer.takeError();
  }
}

void InstructionBenchmark::writeYamlTo(const LLVMState &State,
                                       llvm::raw_ostream &OS) {
  llvm::yaml::Output Yout(OS, nullptr /*Ctx*/, 200 /*WrapColumn*/);
  YamlContext Context(State);
  Yout.beginDocuments();
  llvm::yaml::yamlize(Yout, *this, /*unused*/ true, Context);
  Yout.endDocuments();
}

void InstructionBenchmark::readYamlFrom(const LLVMState &State,
                                        llvm::StringRef InputContent) {
  llvm::yaml::Input Yin(InputContent);
  YamlContext Context(State);
  if (Yin.setCurrentDocument())
    llvm::yaml::yamlize(Yin, *this, /*unused*/ true, Context);
}

llvm::Error InstructionBenchmark::writeYaml(const LLVMState &State,
                                            const llvm::StringRef Filename) {
  if (Filename == "-") {
    writeYamlTo(State, llvm::outs());
  } else {
    int ResultFD = 0;
    if (auto E = llvm::errorCodeToError(
            openFileForWrite(Filename, ResultFD, llvm::sys::fs::CD_CreateAlways,
                             llvm::sys::fs::F_Text))) {
      return E;
    }
    llvm::raw_fd_ostream Ostr(ResultFD, true /*shouldClose*/);
    writeYamlTo(State, Ostr);
  }
  return llvm::Error::success();
}

void PerInstructionStats::push(const BenchmarkMeasure &BM) {
  if (Key.empty())
    Key = BM.Key;
  assert(Key == BM.Key);
  ++NumValues;
  SumValues += BM.PerInstructionValue;
  MaxValue = std::max(MaxValue, BM.PerInstructionValue);
  MinValue = std::min(MinValue, BM.PerInstructionValue);
}

} // namespace exegesis
} // namespace llvm
