//===------- JITLoaderVTune.cpp - Register profiler objects -----*- 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
//
//===----------------------------------------------------------------------===//
//
// Register objects for access by profilers via the VTune JIT interface.
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"
#include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h"

#if LLVM_USE_INTEL_JITEVENTS
#include "IntelJITEventsWrapper.h"
#include "ittnotify.h"
#include <map>

using namespace llvm;
using namespace llvm::orc;

namespace {
class JITEventWrapper {
public:
  static std::unique_ptr<IntelJITEventsWrapper> Wrapper;
};
std::unique_ptr<IntelJITEventsWrapper> JITEventWrapper::Wrapper;
} // namespace

static Error registerJITLoaderVTuneRegisterImpl(const VTuneMethodBatch &MB) {
  const size_t StringsSize = MB.Strings.size();

  for (const auto &MethodInfo : MB.Methods) {
    iJIT_Method_Load MethodMessage;
    memset(&MethodMessage, 0, sizeof(iJIT_Method_Load));

    MethodMessage.method_id = MethodInfo.MethodID;
    if (MethodInfo.NameSI != 0 && MethodInfo.NameSI < StringsSize) {
      MethodMessage.method_name =
          const_cast<char *>(MB.Strings.at(MethodInfo.NameSI).data());
    } else {
      MethodMessage.method_name = NULL;
    }
    if (MethodInfo.ClassFileSI != 0 && MethodInfo.ClassFileSI < StringsSize) {
      MethodMessage.class_file_name =
          const_cast<char *>(MB.Strings.at(MethodInfo.ClassFileSI).data());
    } else {
      MethodMessage.class_file_name = NULL;
    }
    if (MethodInfo.SourceFileSI != 0 && MethodInfo.SourceFileSI < StringsSize) {
      MethodMessage.source_file_name =
          const_cast<char *>(MB.Strings.at(MethodInfo.SourceFileSI).data());
    } else {
      MethodMessage.source_file_name = NULL;
    }

    MethodMessage.method_load_address = MethodInfo.LoadAddr.toPtr<void *>();
    MethodMessage.method_size = MethodInfo.LoadSize;
    MethodMessage.class_id = 0;

    MethodMessage.user_data = NULL;
    MethodMessage.user_data_size = 0;
    MethodMessage.env = iJDE_JittingAPI;

    std::vector<LineNumberInfo> LineInfo;
    for (const auto &LInfo : MethodInfo.LineTable) {
      LineInfo.push_back(LineNumberInfo{LInfo.first, LInfo.second});
    }

    if (LineInfo.size() == 0) {
      MethodMessage.line_number_size = 0;
      MethodMessage.line_number_table = 0;
    } else {
      MethodMessage.line_number_size = LineInfo.size();
      MethodMessage.line_number_table = &*LineInfo.begin();
    }
    JITEventWrapper::Wrapper->iJIT_NotifyEvent(
        iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &MethodMessage);
  }

  return Error::success();
}

static void registerJITLoaderVTuneUnregisterImpl(
    const std::vector<std::pair<uint64_t, uint64_t>> &UM) {
  for (auto &Method : UM) {
    JITEventWrapper::Wrapper->iJIT_NotifyEvent(
        iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
        const_cast<uint64_t *>(&Method.first));
  }
}

extern "C" llvm::orc::shared::CWrapperFunctionBuffer
llvm_orc_registerVTuneImpl(const char *ArgData, size_t ArgSize) {
  using namespace orc::shared;
  if (!JITEventWrapper::Wrapper)
    JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper);

  return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
             ArgData, ArgSize, registerJITLoaderVTuneRegisterImpl)
      .release();
}

extern "C" llvm::orc::shared::CWrapperFunctionBuffer
llvm_orc_unregisterVTuneImpl(const char *ArgData, size_t ArgSize) {
  using namespace orc::shared;
  return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(
             ArgData, ArgSize, registerJITLoaderVTuneUnregisterImpl)
      .release();
}

// For Testing: following code comes from llvm-jitlistener.cpp in llvm tools
namespace {
using SourceLocations = std::vector<std::pair<std::string, unsigned int>>;
using NativeCodeMap = std::map<uint64_t, SourceLocations>;
NativeCodeMap ReportedDebugFuncs;
} // namespace

static int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
  switch (EventType) {
  case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
    if (!EventSpecificData) {
      errs() << "Error: The JIT event listener did not provide a event data.";
      return -1;
    }
    iJIT_Method_Load *msg = static_cast<iJIT_Method_Load *>(EventSpecificData);

    ReportedDebugFuncs[msg->method_id];

    outs() << "Method load [" << msg->method_id << "]: " << msg->method_name
           << ", Size = " << msg->method_size << "\n";

    for (unsigned int i = 0; i < msg->line_number_size; ++i) {
      if (!msg->line_number_table) {
        errs() << "A function with a non-zero line count had no line table.";
        return -1;
      }
      std::pair<std::string, unsigned int> loc(
          std::string(msg->source_file_name),
          msg->line_number_table[i].LineNumber);
      ReportedDebugFuncs[msg->method_id].push_back(loc);
      outs() << "  Line info @ " << msg->line_number_table[i].Offset << ": "
             << msg->source_file_name << ", line "
             << msg->line_number_table[i].LineNumber << "\n";
    }
    outs() << "\n";
  } break;
  case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {
    if (!EventSpecificData) {
      errs() << "Error: The JIT event listener did not provide a event data.";
      return -1;
    }
    unsigned int UnloadId =
        *reinterpret_cast<unsigned int *>(EventSpecificData);
    assert(1 == ReportedDebugFuncs.erase(UnloadId));
    outs() << "Method unload [" << UnloadId << "]\n";
  } break;
  default:
    break;
  }
  return 0;
}

static iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
  // for testing, pretend we have an Intel Parallel Amplifier XE 2011
  // instance attached
  return iJIT_SAMPLING_ON;
}

static unsigned int GetNewMethodID(void) {
  static unsigned int id = 0;
  return ++id;
}

extern "C" llvm::orc::shared::CWrapperFunctionBuffer
llvm_orc_test_registerVTuneImpl(const char *ArgData, size_t ArgSize) {
  using namespace orc::shared;
  JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper(
      NotifyEvent, NULL, NULL, IsProfilingActive, 0, 0, GetNewMethodID));
  return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
             ArgData, ArgSize, registerJITLoaderVTuneRegisterImpl)
      .release();
}

#else

using namespace llvm;
using namespace llvm::orc;

static Error unsupportedBatch(const VTuneMethodBatch &MB) {
  return llvm::make_error<StringError>("unsupported for Intel VTune",
                                       inconvertibleErrorCode());
}

static void unsuppported(const std::vector<std::pair<uint64_t, uint64_t>> &UM) {

}

extern "C" llvm::orc::shared::CWrapperFunctionBuffer
llvm_orc_registerVTuneImpl(const char *ArgData, size_t ArgSize) {
  using namespace orc::shared;
  return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
             ArgData, ArgSize, unsupportedBatch)
      .release();
}

extern "C" llvm::orc::shared::CWrapperFunctionBuffer
llvm_orc_unregisterVTuneImpl(const char *ArgData, size_t ArgSize) {
  using namespace orc::shared;
  return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(
             ArgData, ArgSize, unsuppported)
      .release();
}

extern "C" llvm::orc::shared::CWrapperFunctionBuffer
llvm_orc_test_registerVTuneImpl(const char *ArgData, size_t ArgSize) {
  using namespace orc::shared;
  return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
             ArgData, ArgSize, unsupportedBatch)
      .release();
}

#endif
