xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp (revision bda39a6067833c9353adbc42bddb1b5808bcf44b)
100f41216SHongyu Chen //===------- JITLoaderVTune.cpp - Register profiler objects -----*- C++ -*-===//
200f41216SHongyu Chen //
300f41216SHongyu Chen // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
400f41216SHongyu Chen // See https://llvm.org/LICENSE.txt for license information.
500f41216SHongyu Chen // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
600f41216SHongyu Chen //
700f41216SHongyu Chen //===----------------------------------------------------------------------===//
800f41216SHongyu Chen //
900f41216SHongyu Chen // Register objects for access by profilers via the VTune JIT interface.
1000f41216SHongyu Chen //===----------------------------------------------------------------------===//
1100f41216SHongyu Chen 
1200f41216SHongyu Chen #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"
1300f41216SHongyu Chen #include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h"
1400f41216SHongyu Chen 
1500f41216SHongyu Chen #if LLVM_USE_INTEL_JITEVENTS
1600f41216SHongyu Chen #include "IntelJITEventsWrapper.h"
1700f41216SHongyu Chen #include "ittnotify.h"
18*bda39a60SKazu Hirata #include <map>
1900f41216SHongyu Chen 
2000f41216SHongyu Chen using namespace llvm;
2100f41216SHongyu Chen using namespace llvm::orc;
2200f41216SHongyu Chen 
2300f41216SHongyu Chen namespace {
2400f41216SHongyu Chen class JITEventWrapper {
2500f41216SHongyu Chen public:
2600f41216SHongyu Chen   static std::unique_ptr<IntelJITEventsWrapper> Wrapper;
2700f41216SHongyu Chen };
2800f41216SHongyu Chen std::unique_ptr<IntelJITEventsWrapper> JITEventWrapper::Wrapper;
2900f41216SHongyu Chen } // namespace
3000f41216SHongyu Chen 
3100f41216SHongyu Chen static Error registerJITLoaderVTuneRegisterImpl(const VTuneMethodBatch &MB) {
3200f41216SHongyu Chen   const size_t StringsSize = MB.Strings.size();
3300f41216SHongyu Chen 
3400f41216SHongyu Chen   for (const auto &MethodInfo : MB.Methods) {
3500f41216SHongyu Chen     iJIT_Method_Load MethodMessage;
3600f41216SHongyu Chen     memset(&MethodMessage, 0, sizeof(iJIT_Method_Load));
3700f41216SHongyu Chen 
3800f41216SHongyu Chen     MethodMessage.method_id = MethodInfo.MethodID;
3900f41216SHongyu Chen     if (MethodInfo.NameSI != 0 && MethodInfo.NameSI < StringsSize) {
4000f41216SHongyu Chen       MethodMessage.method_name =
4100f41216SHongyu Chen           const_cast<char *>(MB.Strings.at(MethodInfo.NameSI).data());
4200f41216SHongyu Chen     } else {
4300f41216SHongyu Chen       MethodMessage.method_name = NULL;
4400f41216SHongyu Chen     }
4500f41216SHongyu Chen     if (MethodInfo.ClassFileSI != 0 && MethodInfo.ClassFileSI < StringsSize) {
4600f41216SHongyu Chen       MethodMessage.class_file_name =
4700f41216SHongyu Chen           const_cast<char *>(MB.Strings.at(MethodInfo.ClassFileSI).data());
4800f41216SHongyu Chen     } else {
4900f41216SHongyu Chen       MethodMessage.class_file_name = NULL;
5000f41216SHongyu Chen     }
5100f41216SHongyu Chen     if (MethodInfo.SourceFileSI != 0 && MethodInfo.SourceFileSI < StringsSize) {
5200f41216SHongyu Chen       MethodMessage.source_file_name =
5300f41216SHongyu Chen           const_cast<char *>(MB.Strings.at(MethodInfo.SourceFileSI).data());
5400f41216SHongyu Chen     } else {
5500f41216SHongyu Chen       MethodMessage.source_file_name = NULL;
5600f41216SHongyu Chen     }
5700f41216SHongyu Chen 
5800f41216SHongyu Chen     MethodMessage.method_load_address = MethodInfo.LoadAddr.toPtr<void *>();
5900f41216SHongyu Chen     MethodMessage.method_size = MethodInfo.LoadSize;
6000f41216SHongyu Chen     MethodMessage.class_id = 0;
6100f41216SHongyu Chen 
6200f41216SHongyu Chen     MethodMessage.user_data = NULL;
6300f41216SHongyu Chen     MethodMessage.user_data_size = 0;
6400f41216SHongyu Chen     MethodMessage.env = iJDE_JittingAPI;
6500f41216SHongyu Chen 
6600f41216SHongyu Chen     std::vector<LineNumberInfo> LineInfo;
6700f41216SHongyu Chen     for (const auto &LInfo : MethodInfo.LineTable) {
6800f41216SHongyu Chen       LineInfo.push_back(LineNumberInfo{LInfo.first, LInfo.second});
6900f41216SHongyu Chen     }
7000f41216SHongyu Chen 
7100f41216SHongyu Chen     if (LineInfo.size() == 0) {
7200f41216SHongyu Chen       MethodMessage.line_number_size = 0;
7300f41216SHongyu Chen       MethodMessage.line_number_table = 0;
7400f41216SHongyu Chen     } else {
7500f41216SHongyu Chen       MethodMessage.line_number_size = LineInfo.size();
7600f41216SHongyu Chen       MethodMessage.line_number_table = &*LineInfo.begin();
7700f41216SHongyu Chen     }
7800f41216SHongyu Chen     JITEventWrapper::Wrapper->iJIT_NotifyEvent(
7900f41216SHongyu Chen         iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &MethodMessage);
8000f41216SHongyu Chen   }
8100f41216SHongyu Chen 
8200f41216SHongyu Chen   return Error::success();
8300f41216SHongyu Chen }
8400f41216SHongyu Chen 
8500f41216SHongyu Chen static void registerJITLoaderVTuneUnregisterImpl(
8600f41216SHongyu Chen     const std::vector<std::pair<uint64_t, uint64_t>> &UM) {
8700f41216SHongyu Chen   for (auto &Method : UM) {
8800f41216SHongyu Chen     JITEventWrapper::Wrapper->iJIT_NotifyEvent(
8900f41216SHongyu Chen         iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
9035f5caeaSChen Cheng         const_cast<uint64_t *>(&Method.first));
9100f41216SHongyu Chen   }
9200f41216SHongyu Chen }
9300f41216SHongyu Chen 
9400f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult
9500f41216SHongyu Chen llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) {
9600f41216SHongyu Chen   using namespace orc::shared;
9700f41216SHongyu Chen   if (!JITEventWrapper::Wrapper)
9800f41216SHongyu Chen     JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper);
9900f41216SHongyu Chen 
10000f41216SHongyu Chen   return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
10100f41216SHongyu Chen              Data, Size, registerJITLoaderVTuneRegisterImpl)
10200f41216SHongyu Chen       .release();
10300f41216SHongyu Chen }
10400f41216SHongyu Chen 
10500f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult
10600f41216SHongyu Chen llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) {
10700f41216SHongyu Chen   using namespace orc::shared;
10800f41216SHongyu Chen   return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(
10900f41216SHongyu Chen              Data, Size, registerJITLoaderVTuneUnregisterImpl)
11000f41216SHongyu Chen       .release();
11100f41216SHongyu Chen }
11200f41216SHongyu Chen 
11300f41216SHongyu Chen // For Testing: following code comes from llvm-jitlistener.cpp in llvm tools
11400f41216SHongyu Chen namespace {
11500f41216SHongyu Chen using SourceLocations = std::vector<std::pair<std::string, unsigned int>>;
11600f41216SHongyu Chen using NativeCodeMap = std::map<uint64_t, SourceLocations>;
11700f41216SHongyu Chen NativeCodeMap ReportedDebugFuncs;
11800f41216SHongyu Chen } // namespace
11900f41216SHongyu Chen 
12000f41216SHongyu Chen static int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
12100f41216SHongyu Chen   switch (EventType) {
12200f41216SHongyu Chen   case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
12300f41216SHongyu Chen     if (!EventSpecificData) {
12400f41216SHongyu Chen       errs() << "Error: The JIT event listener did not provide a event data.";
12500f41216SHongyu Chen       return -1;
12600f41216SHongyu Chen     }
12700f41216SHongyu Chen     iJIT_Method_Load *msg = static_cast<iJIT_Method_Load *>(EventSpecificData);
12800f41216SHongyu Chen 
12900f41216SHongyu Chen     ReportedDebugFuncs[msg->method_id];
13000f41216SHongyu Chen 
13100f41216SHongyu Chen     outs() << "Method load [" << msg->method_id << "]: " << msg->method_name
13200f41216SHongyu Chen            << ", Size = " << msg->method_size << "\n";
13300f41216SHongyu Chen 
13400f41216SHongyu Chen     for (unsigned int i = 0; i < msg->line_number_size; ++i) {
13500f41216SHongyu Chen       if (!msg->line_number_table) {
13600f41216SHongyu Chen         errs() << "A function with a non-zero line count had no line table.";
13700f41216SHongyu Chen         return -1;
13800f41216SHongyu Chen       }
13900f41216SHongyu Chen       std::pair<std::string, unsigned int> loc(
14000f41216SHongyu Chen           std::string(msg->source_file_name),
14100f41216SHongyu Chen           msg->line_number_table[i].LineNumber);
14200f41216SHongyu Chen       ReportedDebugFuncs[msg->method_id].push_back(loc);
14300f41216SHongyu Chen       outs() << "  Line info @ " << msg->line_number_table[i].Offset << ": "
14400f41216SHongyu Chen              << msg->source_file_name << ", line "
14500f41216SHongyu Chen              << msg->line_number_table[i].LineNumber << "\n";
14600f41216SHongyu Chen     }
14700f41216SHongyu Chen     outs() << "\n";
14800f41216SHongyu Chen   } break;
14900f41216SHongyu Chen   case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {
15000f41216SHongyu Chen     if (!EventSpecificData) {
15100f41216SHongyu Chen       errs() << "Error: The JIT event listener did not provide a event data.";
15200f41216SHongyu Chen       return -1;
15300f41216SHongyu Chen     }
15400f41216SHongyu Chen     unsigned int UnloadId =
15500f41216SHongyu Chen         *reinterpret_cast<unsigned int *>(EventSpecificData);
15600f41216SHongyu Chen     assert(1 == ReportedDebugFuncs.erase(UnloadId));
15700f41216SHongyu Chen     outs() << "Method unload [" << UnloadId << "]\n";
15800f41216SHongyu Chen   } break;
15900f41216SHongyu Chen   default:
16000f41216SHongyu Chen     break;
16100f41216SHongyu Chen   }
16200f41216SHongyu Chen   return 0;
16300f41216SHongyu Chen }
16400f41216SHongyu Chen 
16500f41216SHongyu Chen static iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
16600f41216SHongyu Chen   // for testing, pretend we have an Intel Parallel Amplifier XE 2011
16700f41216SHongyu Chen   // instance attached
16800f41216SHongyu Chen   return iJIT_SAMPLING_ON;
16900f41216SHongyu Chen }
17000f41216SHongyu Chen 
17100f41216SHongyu Chen static unsigned int GetNewMethodID(void) {
17200f41216SHongyu Chen   static unsigned int id = 0;
17300f41216SHongyu Chen   return ++id;
17400f41216SHongyu Chen }
17500f41216SHongyu Chen 
17600f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult
17700f41216SHongyu Chen llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) {
17800f41216SHongyu Chen   using namespace orc::shared;
17900f41216SHongyu Chen   JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper(
18000f41216SHongyu Chen       NotifyEvent, NULL, NULL, IsProfilingActive, 0, 0, GetNewMethodID));
18100f41216SHongyu Chen   return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
18200f41216SHongyu Chen              Data, Size, registerJITLoaderVTuneRegisterImpl)
18300f41216SHongyu Chen       .release();
18400f41216SHongyu Chen }
18500f41216SHongyu Chen 
18600f41216SHongyu Chen #else
18700f41216SHongyu Chen 
18800f41216SHongyu Chen using namespace llvm;
18900f41216SHongyu Chen using namespace llvm::orc;
19000f41216SHongyu Chen 
19100f41216SHongyu Chen static Error unsupportedBatch(const VTuneMethodBatch &MB) {
19200f41216SHongyu Chen   return llvm::make_error<StringError>("unsupported for Intel VTune",
19300f41216SHongyu Chen                                        inconvertibleErrorCode());
19400f41216SHongyu Chen }
19500f41216SHongyu Chen 
19600f41216SHongyu Chen static void unsuppported(const std::vector<std::pair<uint64_t, uint64_t>> &UM) {
19700f41216SHongyu Chen 
19800f41216SHongyu Chen }
19900f41216SHongyu Chen 
20000f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult
20100f41216SHongyu Chen llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) {
20200f41216SHongyu Chen   using namespace orc::shared;
20300f41216SHongyu Chen   return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
20400f41216SHongyu Chen              Data, Size, unsupportedBatch)
20500f41216SHongyu Chen       .release();
20600f41216SHongyu Chen }
20700f41216SHongyu Chen 
20800f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult
20900f41216SHongyu Chen llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) {
21000f41216SHongyu Chen   using namespace orc::shared;
21100f41216SHongyu Chen   return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(Data, Size,
21200f41216SHongyu Chen                                                                   unsuppported)
21300f41216SHongyu Chen       .release();
21400f41216SHongyu Chen }
21500f41216SHongyu Chen 
21600f41216SHongyu Chen extern "C" llvm::orc::shared::CWrapperFunctionResult
21700f41216SHongyu Chen llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) {
21800f41216SHongyu Chen   using namespace orc::shared;
21900f41216SHongyu Chen   return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
22000f41216SHongyu Chen              Data, Size, unsupportedBatch)
22100f41216SHongyu Chen       .release();
22200f41216SHongyu Chen }
22300f41216SHongyu Chen 
22400f41216SHongyu Chen #endif
225