1 //===------- JITLoaderVTune.cpp - Register profiler objects -----*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Register objects for access by profilers via the VTune JIT interface.
10 //===----------------------------------------------------------------------===//
12 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"
13 #include "llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h"
15 #if LLVM_USE_INTEL_JITEVENTS
16 #include "IntelJITEventsWrapper.h"
17 #include "ittnotify.h"
20 using namespace llvm::orc
;
23 class JITEventWrapper
{
25 static std::unique_ptr
<IntelJITEventsWrapper
> Wrapper
;
27 std::unique_ptr
<IntelJITEventsWrapper
> JITEventWrapper::Wrapper
;
30 static Error
registerJITLoaderVTuneRegisterImpl(const VTuneMethodBatch
&MB
) {
31 const size_t StringsSize
= MB
.Strings
.size();
33 for (const auto &MethodInfo
: MB
.Methods
) {
34 iJIT_Method_Load MethodMessage
;
35 memset(&MethodMessage
, 0, sizeof(iJIT_Method_Load
));
37 MethodMessage
.method_id
= MethodInfo
.MethodID
;
38 if (MethodInfo
.NameSI
!= 0 && MethodInfo
.NameSI
< StringsSize
) {
39 MethodMessage
.method_name
=
40 const_cast<char *>(MB
.Strings
.at(MethodInfo
.NameSI
).data());
42 MethodMessage
.method_name
= NULL
;
44 if (MethodInfo
.ClassFileSI
!= 0 && MethodInfo
.ClassFileSI
< StringsSize
) {
45 MethodMessage
.class_file_name
=
46 const_cast<char *>(MB
.Strings
.at(MethodInfo
.ClassFileSI
).data());
48 MethodMessage
.class_file_name
= NULL
;
50 if (MethodInfo
.SourceFileSI
!= 0 && MethodInfo
.SourceFileSI
< StringsSize
) {
51 MethodMessage
.source_file_name
=
52 const_cast<char *>(MB
.Strings
.at(MethodInfo
.SourceFileSI
).data());
54 MethodMessage
.source_file_name
= NULL
;
57 MethodMessage
.method_load_address
= MethodInfo
.LoadAddr
.toPtr
<void *>();
58 MethodMessage
.method_size
= MethodInfo
.LoadSize
;
59 MethodMessage
.class_id
= 0;
61 MethodMessage
.user_data
= NULL
;
62 MethodMessage
.user_data_size
= 0;
63 MethodMessage
.env
= iJDE_JittingAPI
;
65 std::vector
<LineNumberInfo
> LineInfo
;
66 for (const auto &LInfo
: MethodInfo
.LineTable
) {
67 LineInfo
.push_back(LineNumberInfo
{LInfo
.first
, LInfo
.second
});
70 if (LineInfo
.size() == 0) {
71 MethodMessage
.line_number_size
= 0;
72 MethodMessage
.line_number_table
= 0;
74 MethodMessage
.line_number_size
= LineInfo
.size();
75 MethodMessage
.line_number_table
= &*LineInfo
.begin();
77 JITEventWrapper::Wrapper
->iJIT_NotifyEvent(
78 iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED
, &MethodMessage
);
81 return Error::success();
84 static void registerJITLoaderVTuneUnregisterImpl(
85 const std::vector
<std::pair
<uint64_t, uint64_t>> &UM
) {
86 for (auto &Method
: UM
) {
87 JITEventWrapper::Wrapper
->iJIT_NotifyEvent(
88 iJVM_EVENT_TYPE_METHOD_UNLOAD_START
,
89 const_cast<uint64_t *>(&Method
.first
));
93 extern "C" llvm::orc::shared::CWrapperFunctionResult
94 llvm_orc_registerVTuneImpl(const char *Data
, uint64_t Size
) {
95 using namespace orc::shared
;
96 if (!JITEventWrapper::Wrapper
)
97 JITEventWrapper::Wrapper
.reset(new IntelJITEventsWrapper
);
99 return WrapperFunction
<SPSError(SPSVTuneMethodBatch
)>::handle(
100 Data
, Size
, registerJITLoaderVTuneRegisterImpl
)
104 extern "C" llvm::orc::shared::CWrapperFunctionResult
105 llvm_orc_unregisterVTuneImpl(const char *Data
, uint64_t Size
) {
106 using namespace orc::shared
;
107 return WrapperFunction
<void(SPSVTuneUnloadedMethodIDs
)>::handle(
108 Data
, Size
, registerJITLoaderVTuneUnregisterImpl
)
112 // For Testing: following code comes from llvm-jitlistener.cpp in llvm tools
114 using SourceLocations
= std::vector
<std::pair
<std::string
, unsigned int>>;
115 using NativeCodeMap
= std::map
<uint64_t, SourceLocations
>;
116 NativeCodeMap ReportedDebugFuncs
;
119 static int NotifyEvent(iJIT_JVM_EVENT EventType
, void *EventSpecificData
) {
121 case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED
: {
122 if (!EventSpecificData
) {
123 errs() << "Error: The JIT event listener did not provide a event data.";
126 iJIT_Method_Load
*msg
= static_cast<iJIT_Method_Load
*>(EventSpecificData
);
128 ReportedDebugFuncs
[msg
->method_id
];
130 outs() << "Method load [" << msg
->method_id
<< "]: " << msg
->method_name
131 << ", Size = " << msg
->method_size
<< "\n";
133 for (unsigned int i
= 0; i
< msg
->line_number_size
; ++i
) {
134 if (!msg
->line_number_table
) {
135 errs() << "A function with a non-zero line count had no line table.";
138 std::pair
<std::string
, unsigned int> loc(
139 std::string(msg
->source_file_name
),
140 msg
->line_number_table
[i
].LineNumber
);
141 ReportedDebugFuncs
[msg
->method_id
].push_back(loc
);
142 outs() << " Line info @ " << msg
->line_number_table
[i
].Offset
<< ": "
143 << msg
->source_file_name
<< ", line "
144 << msg
->line_number_table
[i
].LineNumber
<< "\n";
148 case iJVM_EVENT_TYPE_METHOD_UNLOAD_START
: {
149 if (!EventSpecificData
) {
150 errs() << "Error: The JIT event listener did not provide a event data.";
153 unsigned int UnloadId
=
154 *reinterpret_cast<unsigned int *>(EventSpecificData
);
155 assert(1 == ReportedDebugFuncs
.erase(UnloadId
));
156 outs() << "Method unload [" << UnloadId
<< "]\n";
164 static iJIT_IsProfilingActiveFlags
IsProfilingActive(void) {
165 // for testing, pretend we have an Intel Parallel Amplifier XE 2011
167 return iJIT_SAMPLING_ON
;
170 static unsigned int GetNewMethodID(void) {
171 static unsigned int id
= 0;
175 extern "C" llvm::orc::shared::CWrapperFunctionResult
176 llvm_orc_test_registerVTuneImpl(const char *Data
, uint64_t Size
) {
177 using namespace orc::shared
;
178 JITEventWrapper::Wrapper
.reset(new IntelJITEventsWrapper(
179 NotifyEvent
, NULL
, NULL
, IsProfilingActive
, 0, 0, GetNewMethodID
));
180 return WrapperFunction
<SPSError(SPSVTuneMethodBatch
)>::handle(
181 Data
, Size
, registerJITLoaderVTuneRegisterImpl
)
187 using namespace llvm
;
188 using namespace llvm::orc
;
190 static Error
unsupportedBatch(const VTuneMethodBatch
&MB
) {
191 return llvm::make_error
<StringError
>("unsupported for Intel VTune",
192 inconvertibleErrorCode());
195 static void unsuppported(const std::vector
<std::pair
<uint64_t, uint64_t>> &UM
) {
199 extern "C" llvm::orc::shared::CWrapperFunctionResult
200 llvm_orc_registerVTuneImpl(const char *Data
, uint64_t Size
) {
201 using namespace orc::shared
;
202 return WrapperFunction
<SPSError(SPSVTuneMethodBatch
)>::handle(
203 Data
, Size
, unsupportedBatch
)
207 extern "C" llvm::orc::shared::CWrapperFunctionResult
208 llvm_orc_unregisterVTuneImpl(const char *Data
, uint64_t Size
) {
209 using namespace orc::shared
;
210 return WrapperFunction
<void(SPSVTuneUnloadedMethodIDs
)>::handle(Data
, Size
,
215 extern "C" llvm::orc::shared::CWrapperFunctionResult
216 llvm_orc_test_registerVTuneImpl(const char *Data
, uint64_t Size
) {
217 using namespace orc::shared
;
218 return WrapperFunction
<SPSError(SPSVTuneMethodBatch
)>::handle(
219 Data
, Size
, unsupportedBatch
)