//===- llvm/IR/LLVMRemarkStreamer.cpp - Remark Streamer -*- C++ ---------*-===//
//
// 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 file contains the implementation of the conversion between IR
// Diagnostics and serializable remarks::Remark objects.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/FileSystem.h"

using namespace llvm;

/// DiagnosticKind -> remarks::Type
static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
  switch (Kind) {
  default:
    return remarks::Type::Unknown;
  case DK_OptimizationRemark:
  case DK_MachineOptimizationRemark:
    return remarks::Type::Passed;
  case DK_OptimizationRemarkMissed:
  case DK_MachineOptimizationRemarkMissed:
    return remarks::Type::Missed;
  case DK_OptimizationRemarkAnalysis:
  case DK_MachineOptimizationRemarkAnalysis:
    return remarks::Type::Analysis;
  case DK_OptimizationRemarkAnalysisFPCommute:
    return remarks::Type::AnalysisFPCommute;
  case DK_OptimizationRemarkAnalysisAliasing:
    return remarks::Type::AnalysisAliasing;
  case DK_OptimizationFailure:
    return remarks::Type::Failure;
  }
}

/// DiagnosticLocation -> remarks::RemarkLocation.
static Optional<remarks::RemarkLocation>
toRemarkLocation(const DiagnosticLocation &DL) {
  if (!DL.isValid())
    return None;
  StringRef File = DL.getRelativePath();
  unsigned Line = DL.getLine();
  unsigned Col = DL.getColumn();
  return remarks::RemarkLocation{File, Line, Col};
}

/// LLVM Diagnostic -> Remark
remarks::Remark
LLVMRemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) const {
  remarks::Remark R; // The result.
  R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
  R.PassName = Diag.getPassName();
  R.RemarkName = Diag.getRemarkName();
  R.FunctionName =
      GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
  R.Loc = toRemarkLocation(Diag.getLocation());
  R.Hotness = Diag.getHotness();

  for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
    R.Args.emplace_back();
    R.Args.back().Key = Arg.Key;
    R.Args.back().Val = Arg.Val;
    R.Args.back().Loc = toRemarkLocation(Arg.Loc);
  }

  return R;
}

void LLVMRemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
  if (!RS.matchesFilter(Diag.getPassName()))
      return;

  // First, convert the diagnostic to a remark.
  remarks::Remark R = toRemark(Diag);
  // Then, emit the remark through the serializer.
  RS.getSerializer().emit(R);
}

char LLVMRemarkSetupFileError::ID = 0;
char LLVMRemarkSetupPatternError::ID = 0;
char LLVMRemarkSetupFormatError::ID = 0;

Expected<std::unique_ptr<ToolOutputFile>> llvm::setupLLVMOptimizationRemarks(
    LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
    StringRef RemarksFormat, bool RemarksWithHotness,
    Optional<uint64_t> RemarksHotnessThreshold) {
  if (RemarksWithHotness)
    Context.setDiagnosticsHotnessRequested(true);

  Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);

  if (RemarksFilename.empty())
    return nullptr;

  Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
  if (Error E = Format.takeError())
    return make_error<LLVMRemarkSetupFormatError>(std::move(E));

  std::error_code EC;
  auto Flags = *Format == remarks::Format::YAML ? sys::fs::OF_TextWithCRLF
                                                : sys::fs::OF_None;
  auto RemarksFile =
      std::make_unique<ToolOutputFile>(RemarksFilename, EC, Flags);
  // We don't use llvm::FileError here because some diagnostics want the file
  // name separately.
  if (EC)
    return make_error<LLVMRemarkSetupFileError>(errorCodeToError(EC));

  Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
      remarks::createRemarkSerializer(
          *Format, remarks::SerializerMode::Separate, RemarksFile->os());
  if (Error E = RemarkSerializer.takeError())
    return make_error<LLVMRemarkSetupFormatError>(std::move(E));

  // Create the main remark streamer.
  Context.setMainRemarkStreamer(std::make_unique<remarks::RemarkStreamer>(
      std::move(*RemarkSerializer), RemarksFilename));

  // Create LLVM's optimization remarks streamer.
  Context.setLLVMRemarkStreamer(
      std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));

  if (!RemarksPasses.empty())
    if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
      return make_error<LLVMRemarkSetupPatternError>(std::move(E));

  return std::move(RemarksFile);
}

Error llvm::setupLLVMOptimizationRemarks(
    LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses,
    StringRef RemarksFormat, bool RemarksWithHotness,
    Optional<uint64_t> RemarksHotnessThreshold) {
  if (RemarksWithHotness)
    Context.setDiagnosticsHotnessRequested(true);

  Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);

  Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
  if (Error E = Format.takeError())
    return make_error<LLVMRemarkSetupFormatError>(std::move(E));

  Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
      remarks::createRemarkSerializer(*Format,
                                      remarks::SerializerMode::Separate, OS);
  if (Error E = RemarkSerializer.takeError())
    return make_error<LLVMRemarkSetupFormatError>(std::move(E));

  // Create the main remark streamer.
  Context.setMainRemarkStreamer(
      std::make_unique<remarks::RemarkStreamer>(std::move(*RemarkSerializer)));

  // Create LLVM's optimization remarks streamer.
  Context.setLLVMRemarkStreamer(
      std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));

  if (!RemarksPasses.empty())
    if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
      return make_error<LLVMRemarkSetupPatternError>(std::move(E));

  return Error::success();
}
