xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1ac9a064cSDimitry Andric //===------- JITLoaderVTune.cpp - Register profiler objects -----*- C++ -*-===//
2ac9a064cSDimitry Andric //
3ac9a064cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ac9a064cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5ac9a064cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ac9a064cSDimitry Andric //
7ac9a064cSDimitry Andric //===----------------------------------------------------------------------===//
8ac9a064cSDimitry Andric //
9ac9a064cSDimitry Andric // Register objects for access by profilers via the VTune JIT interface.
10ac9a064cSDimitry Andric //===----------------------------------------------------------------------===//
11ac9a064cSDimitry Andric 
12ac9a064cSDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"
13ac9a064cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h"
14ac9a064cSDimitry Andric #include <map>
15ac9a064cSDimitry Andric 
16ac9a064cSDimitry Andric #if LLVM_USE_INTEL_JITEVENTS
17ac9a064cSDimitry Andric #include "IntelJITEventsWrapper.h"
18ac9a064cSDimitry Andric #include "ittnotify.h"
19ac9a064cSDimitry Andric 
20ac9a064cSDimitry Andric using namespace llvm;
21ac9a064cSDimitry Andric using namespace llvm::orc;
22ac9a064cSDimitry Andric 
23ac9a064cSDimitry Andric namespace {
24ac9a064cSDimitry Andric class JITEventWrapper {
25ac9a064cSDimitry Andric public:
26ac9a064cSDimitry Andric   static std::unique_ptr<IntelJITEventsWrapper> Wrapper;
27ac9a064cSDimitry Andric };
28ac9a064cSDimitry Andric std::unique_ptr<IntelJITEventsWrapper> JITEventWrapper::Wrapper;
29ac9a064cSDimitry Andric } // namespace
30ac9a064cSDimitry Andric 
registerJITLoaderVTuneRegisterImpl(const VTuneMethodBatch & MB)31ac9a064cSDimitry Andric static Error registerJITLoaderVTuneRegisterImpl(const VTuneMethodBatch &MB) {
32ac9a064cSDimitry Andric   const size_t StringsSize = MB.Strings.size();
33ac9a064cSDimitry Andric 
34ac9a064cSDimitry Andric   for (const auto &MethodInfo : MB.Methods) {
35ac9a064cSDimitry Andric     iJIT_Method_Load MethodMessage;
36ac9a064cSDimitry Andric     memset(&MethodMessage, 0, sizeof(iJIT_Method_Load));
37ac9a064cSDimitry Andric 
38ac9a064cSDimitry Andric     MethodMessage.method_id = MethodInfo.MethodID;
39ac9a064cSDimitry Andric     if (MethodInfo.NameSI != 0 && MethodInfo.NameSI < StringsSize) {
40ac9a064cSDimitry Andric       MethodMessage.method_name =
41ac9a064cSDimitry Andric           const_cast<char *>(MB.Strings.at(MethodInfo.NameSI).data());
42ac9a064cSDimitry Andric     } else {
43ac9a064cSDimitry Andric       MethodMessage.method_name = NULL;
44ac9a064cSDimitry Andric     }
45ac9a064cSDimitry Andric     if (MethodInfo.ClassFileSI != 0 && MethodInfo.ClassFileSI < StringsSize) {
46ac9a064cSDimitry Andric       MethodMessage.class_file_name =
47ac9a064cSDimitry Andric           const_cast<char *>(MB.Strings.at(MethodInfo.ClassFileSI).data());
48ac9a064cSDimitry Andric     } else {
49ac9a064cSDimitry Andric       MethodMessage.class_file_name = NULL;
50ac9a064cSDimitry Andric     }
51ac9a064cSDimitry Andric     if (MethodInfo.SourceFileSI != 0 && MethodInfo.SourceFileSI < StringsSize) {
52ac9a064cSDimitry Andric       MethodMessage.source_file_name =
53ac9a064cSDimitry Andric           const_cast<char *>(MB.Strings.at(MethodInfo.SourceFileSI).data());
54ac9a064cSDimitry Andric     } else {
55ac9a064cSDimitry Andric       MethodMessage.source_file_name = NULL;
56ac9a064cSDimitry Andric     }
57ac9a064cSDimitry Andric 
58ac9a064cSDimitry Andric     MethodMessage.method_load_address = MethodInfo.LoadAddr.toPtr<void *>();
59ac9a064cSDimitry Andric     MethodMessage.method_size = MethodInfo.LoadSize;
60ac9a064cSDimitry Andric     MethodMessage.class_id = 0;
61ac9a064cSDimitry Andric 
62ac9a064cSDimitry Andric     MethodMessage.user_data = NULL;
63ac9a064cSDimitry Andric     MethodMessage.user_data_size = 0;
64ac9a064cSDimitry Andric     MethodMessage.env = iJDE_JittingAPI;
65ac9a064cSDimitry Andric 
66ac9a064cSDimitry Andric     std::vector<LineNumberInfo> LineInfo;
67ac9a064cSDimitry Andric     for (const auto &LInfo : MethodInfo.LineTable) {
68ac9a064cSDimitry Andric       LineInfo.push_back(LineNumberInfo{LInfo.first, LInfo.second});
69ac9a064cSDimitry Andric     }
70ac9a064cSDimitry Andric 
71ac9a064cSDimitry Andric     if (LineInfo.size() == 0) {
72ac9a064cSDimitry Andric       MethodMessage.line_number_size = 0;
73ac9a064cSDimitry Andric       MethodMessage.line_number_table = 0;
74ac9a064cSDimitry Andric     } else {
75ac9a064cSDimitry Andric       MethodMessage.line_number_size = LineInfo.size();
76ac9a064cSDimitry Andric       MethodMessage.line_number_table = &*LineInfo.begin();
77ac9a064cSDimitry Andric     }
78ac9a064cSDimitry Andric     JITEventWrapper::Wrapper->iJIT_NotifyEvent(
79ac9a064cSDimitry Andric         iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &MethodMessage);
80ac9a064cSDimitry Andric   }
81ac9a064cSDimitry Andric 
82ac9a064cSDimitry Andric   return Error::success();
83ac9a064cSDimitry Andric }
84ac9a064cSDimitry Andric 
registerJITLoaderVTuneUnregisterImpl(const std::vector<std::pair<uint64_t,uint64_t>> & UM)85ac9a064cSDimitry Andric static void registerJITLoaderVTuneUnregisterImpl(
86ac9a064cSDimitry Andric     const std::vector<std::pair<uint64_t, uint64_t>> &UM) {
87ac9a064cSDimitry Andric   for (auto &Method : UM) {
88ac9a064cSDimitry Andric     JITEventWrapper::Wrapper->iJIT_NotifyEvent(
89ac9a064cSDimitry Andric         iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
90ac9a064cSDimitry Andric         const_cast<uint64_t *>(&Method.first));
91ac9a064cSDimitry Andric   }
92ac9a064cSDimitry Andric }
93ac9a064cSDimitry Andric 
94ac9a064cSDimitry Andric extern "C" llvm::orc::shared::CWrapperFunctionResult
llvm_orc_registerVTuneImpl(const char * Data,uint64_t Size)95ac9a064cSDimitry Andric llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) {
96ac9a064cSDimitry Andric   using namespace orc::shared;
97ac9a064cSDimitry Andric   if (!JITEventWrapper::Wrapper)
98ac9a064cSDimitry Andric     JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper);
99ac9a064cSDimitry Andric 
100ac9a064cSDimitry Andric   return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
101ac9a064cSDimitry Andric              Data, Size, registerJITLoaderVTuneRegisterImpl)
102ac9a064cSDimitry Andric       .release();
103ac9a064cSDimitry Andric }
104ac9a064cSDimitry Andric 
105ac9a064cSDimitry Andric extern "C" llvm::orc::shared::CWrapperFunctionResult
llvm_orc_unregisterVTuneImpl(const char * Data,uint64_t Size)106ac9a064cSDimitry Andric llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) {
107ac9a064cSDimitry Andric   using namespace orc::shared;
108ac9a064cSDimitry Andric   return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(
109ac9a064cSDimitry Andric              Data, Size, registerJITLoaderVTuneUnregisterImpl)
110ac9a064cSDimitry Andric       .release();
111ac9a064cSDimitry Andric }
112ac9a064cSDimitry Andric 
113ac9a064cSDimitry Andric // For Testing: following code comes from llvm-jitlistener.cpp in llvm tools
114ac9a064cSDimitry Andric namespace {
115ac9a064cSDimitry Andric using SourceLocations = std::vector<std::pair<std::string, unsigned int>>;
116ac9a064cSDimitry Andric using NativeCodeMap = std::map<uint64_t, SourceLocations>;
117ac9a064cSDimitry Andric NativeCodeMap ReportedDebugFuncs;
118ac9a064cSDimitry Andric } // namespace
119ac9a064cSDimitry Andric 
NotifyEvent(iJIT_JVM_EVENT EventType,void * EventSpecificData)120ac9a064cSDimitry Andric static int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
121ac9a064cSDimitry Andric   switch (EventType) {
122ac9a064cSDimitry Andric   case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
123ac9a064cSDimitry Andric     if (!EventSpecificData) {
124ac9a064cSDimitry Andric       errs() << "Error: The JIT event listener did not provide a event data.";
125ac9a064cSDimitry Andric       return -1;
126ac9a064cSDimitry Andric     }
127ac9a064cSDimitry Andric     iJIT_Method_Load *msg = static_cast<iJIT_Method_Load *>(EventSpecificData);
128ac9a064cSDimitry Andric 
129ac9a064cSDimitry Andric     ReportedDebugFuncs[msg->method_id];
130ac9a064cSDimitry Andric 
131ac9a064cSDimitry Andric     outs() << "Method load [" << msg->method_id << "]: " << msg->method_name
132ac9a064cSDimitry Andric            << ", Size = " << msg->method_size << "\n";
133ac9a064cSDimitry Andric 
134ac9a064cSDimitry Andric     for (unsigned int i = 0; i < msg->line_number_size; ++i) {
135ac9a064cSDimitry Andric       if (!msg->line_number_table) {
136ac9a064cSDimitry Andric         errs() << "A function with a non-zero line count had no line table.";
137ac9a064cSDimitry Andric         return -1;
138ac9a064cSDimitry Andric       }
139ac9a064cSDimitry Andric       std::pair<std::string, unsigned int> loc(
140ac9a064cSDimitry Andric           std::string(msg->source_file_name),
141ac9a064cSDimitry Andric           msg->line_number_table[i].LineNumber);
142ac9a064cSDimitry Andric       ReportedDebugFuncs[msg->method_id].push_back(loc);
143ac9a064cSDimitry Andric       outs() << "  Line info @ " << msg->line_number_table[i].Offset << ": "
144ac9a064cSDimitry Andric              << msg->source_file_name << ", line "
145ac9a064cSDimitry Andric              << msg->line_number_table[i].LineNumber << "\n";
146ac9a064cSDimitry Andric     }
147ac9a064cSDimitry Andric     outs() << "\n";
148ac9a064cSDimitry Andric   } break;
149ac9a064cSDimitry Andric   case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {
150ac9a064cSDimitry Andric     if (!EventSpecificData) {
151ac9a064cSDimitry Andric       errs() << "Error: The JIT event listener did not provide a event data.";
152ac9a064cSDimitry Andric       return -1;
153ac9a064cSDimitry Andric     }
154ac9a064cSDimitry Andric     unsigned int UnloadId =
155ac9a064cSDimitry Andric         *reinterpret_cast<unsigned int *>(EventSpecificData);
156ac9a064cSDimitry Andric     assert(1 == ReportedDebugFuncs.erase(UnloadId));
157ac9a064cSDimitry Andric     outs() << "Method unload [" << UnloadId << "]\n";
158ac9a064cSDimitry Andric   } break;
159ac9a064cSDimitry Andric   default:
160ac9a064cSDimitry Andric     break;
161ac9a064cSDimitry Andric   }
162ac9a064cSDimitry Andric   return 0;
163ac9a064cSDimitry Andric }
164ac9a064cSDimitry Andric 
IsProfilingActive(void)165ac9a064cSDimitry Andric static iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
166ac9a064cSDimitry Andric   // for testing, pretend we have an Intel Parallel Amplifier XE 2011
167ac9a064cSDimitry Andric   // instance attached
168ac9a064cSDimitry Andric   return iJIT_SAMPLING_ON;
169ac9a064cSDimitry Andric }
170ac9a064cSDimitry Andric 
GetNewMethodID(void)171ac9a064cSDimitry Andric static unsigned int GetNewMethodID(void) {
172ac9a064cSDimitry Andric   static unsigned int id = 0;
173ac9a064cSDimitry Andric   return ++id;
174ac9a064cSDimitry Andric }
175ac9a064cSDimitry Andric 
176ac9a064cSDimitry Andric extern "C" llvm::orc::shared::CWrapperFunctionResult
llvm_orc_test_registerVTuneImpl(const char * Data,uint64_t Size)177ac9a064cSDimitry Andric llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) {
178ac9a064cSDimitry Andric   using namespace orc::shared;
179ac9a064cSDimitry Andric   JITEventWrapper::Wrapper.reset(new IntelJITEventsWrapper(
180ac9a064cSDimitry Andric       NotifyEvent, NULL, NULL, IsProfilingActive, 0, 0, GetNewMethodID));
181ac9a064cSDimitry Andric   return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
182ac9a064cSDimitry Andric              Data, Size, registerJITLoaderVTuneRegisterImpl)
183ac9a064cSDimitry Andric       .release();
184ac9a064cSDimitry Andric }
185ac9a064cSDimitry Andric 
186ac9a064cSDimitry Andric #else
187ac9a064cSDimitry Andric 
188ac9a064cSDimitry Andric using namespace llvm;
189ac9a064cSDimitry Andric using namespace llvm::orc;
190ac9a064cSDimitry Andric 
unsupportedBatch(const VTuneMethodBatch & MB)191ac9a064cSDimitry Andric static Error unsupportedBatch(const VTuneMethodBatch &MB) {
192ac9a064cSDimitry Andric   return llvm::make_error<StringError>("unsupported for Intel VTune",
193ac9a064cSDimitry Andric                                        inconvertibleErrorCode());
194ac9a064cSDimitry Andric }
195ac9a064cSDimitry Andric 
unsuppported(const std::vector<std::pair<uint64_t,uint64_t>> & UM)196ac9a064cSDimitry Andric static void unsuppported(const std::vector<std::pair<uint64_t, uint64_t>> &UM) {
197ac9a064cSDimitry Andric 
198ac9a064cSDimitry Andric }
199ac9a064cSDimitry Andric 
200ac9a064cSDimitry Andric extern "C" llvm::orc::shared::CWrapperFunctionResult
llvm_orc_registerVTuneImpl(const char * Data,uint64_t Size)201ac9a064cSDimitry Andric llvm_orc_registerVTuneImpl(const char *Data, uint64_t Size) {
202ac9a064cSDimitry Andric   using namespace orc::shared;
203ac9a064cSDimitry Andric   return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
204ac9a064cSDimitry Andric              Data, Size, unsupportedBatch)
205ac9a064cSDimitry Andric       .release();
206ac9a064cSDimitry Andric }
207ac9a064cSDimitry Andric 
208ac9a064cSDimitry Andric extern "C" llvm::orc::shared::CWrapperFunctionResult
llvm_orc_unregisterVTuneImpl(const char * Data,uint64_t Size)209ac9a064cSDimitry Andric llvm_orc_unregisterVTuneImpl(const char *Data, uint64_t Size) {
210ac9a064cSDimitry Andric   using namespace orc::shared;
211ac9a064cSDimitry Andric   return WrapperFunction<void(SPSVTuneUnloadedMethodIDs)>::handle(Data, Size,
212ac9a064cSDimitry Andric                                                                   unsuppported)
213ac9a064cSDimitry Andric       .release();
214ac9a064cSDimitry Andric }
215ac9a064cSDimitry Andric 
216ac9a064cSDimitry Andric extern "C" llvm::orc::shared::CWrapperFunctionResult
llvm_orc_test_registerVTuneImpl(const char * Data,uint64_t Size)217ac9a064cSDimitry Andric llvm_orc_test_registerVTuneImpl(const char *Data, uint64_t Size) {
218ac9a064cSDimitry Andric   using namespace orc::shared;
219ac9a064cSDimitry Andric   return WrapperFunction<SPSError(SPSVTuneMethodBatch)>::handle(
220ac9a064cSDimitry Andric              Data, Size, unsupportedBatch)
221ac9a064cSDimitry Andric       .release();
222ac9a064cSDimitry Andric }
223ac9a064cSDimitry Andric 
224ac9a064cSDimitry Andric #endif
225