1 //===-- llvm-jitlistener.cpp - Utility for testing MCJIT event listener ---===//
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 // This program is a used by lit tests to verify the MCJIT JITEventListener
10 // interface. It registers a mock JIT event listener, generates a module from
11 // an input IR file and dumps the reported event information to stdout.
13 //===----------------------------------------------------------------------===//
15 #include "../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h"
16 #include "llvm/ExecutionEngine/JITEventListener.h"
17 #include "llvm/ExecutionEngine/MCJIT.h"
18 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
19 #include "llvm/IR/LLVMContext.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/IRReader/IRReader.h"
22 #include "llvm/Support/CommandLine.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/InitLLVM.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/SourceMgr.h"
27 #include "llvm/Support/TargetSelect.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include "llvm/TargetParser/Host.h"
30 #include "llvm/TargetParser/Triple.h"
37 typedef std::vector
<std::pair
<std::string
, unsigned int> > SourceLocations
;
38 typedef std::map
<uint64_t, SourceLocations
> NativeCodeMap
;
40 NativeCodeMap ReportedDebugFuncs
;
42 int NotifyEvent(iJIT_JVM_EVENT EventType
, void *EventSpecificData
) {
44 case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED
: {
45 if (!EventSpecificData
) {
47 "Error: The JIT event listener did not provide a event data.";
50 iJIT_Method_Load
* msg
= static_cast<iJIT_Method_Load
*>(EventSpecificData
);
52 ReportedDebugFuncs
[msg
->method_id
];
54 outs() << "Method load [" << msg
->method_id
<< "]: " << msg
->method_name
55 << ", Size = " << msg
->method_size
<< "\n";
57 for(unsigned int i
= 0; i
< msg
->line_number_size
; ++i
) {
58 if (!msg
->line_number_table
) {
59 errs() << "A function with a non-zero line count had no line table.";
62 std::pair
<std::string
, unsigned int> loc(
63 std::string(msg
->source_file_name
),
64 msg
->line_number_table
[i
].LineNumber
);
65 ReportedDebugFuncs
[msg
->method_id
].push_back(loc
);
66 outs() << " Line info @ " << msg
->line_number_table
[i
].Offset
67 << ": " << msg
->source_file_name
68 << ", line " << msg
->line_number_table
[i
].LineNumber
<< "\n";
73 case iJVM_EVENT_TYPE_METHOD_UNLOAD_START
: {
74 if (!EventSpecificData
) {
76 "Error: The JIT event listener did not provide a event data.";
80 = *reinterpret_cast<unsigned int*>(EventSpecificData
);
81 assert(1 == ReportedDebugFuncs
.erase(UnloadId
));
82 outs() << "Method unload [" << UnloadId
<< "]\n";
91 int ittNotifyInfo(IttEventType EventType
, const char *Name
, unsigned int Size
) {
93 case LoadBinaryModule
: {
95 errs() << "Error: The IttNotify event listener did not provide a module "
99 outs() << "Module loaded : Name = " << Name
<< ", Size = " << Size
<< "\n";
101 case LoadBinarySection
: {
103 errs() << "Error: The IttNotify event listener did not provide a section "
107 outs() << "Loaded section : Name = " << Name
<< ", Size = " << Size
<< "\n";
109 case UnloadBinaryModule
: {
111 errs() << "Error: The IttNotify event listener did not provide a module "
115 outs() << "Module unloaded : Name = " << Name
<< ", Size = " << Size
118 case UnloadBinarySection
: {
120 errs() << "Error: The IttNotify event listener did not provide a section "
124 outs() << "Unloaded section : Name = " << Name
<< ", Size = " << Size
131 iJIT_IsProfilingActiveFlags
IsProfilingActive(void) {
132 // for testing, pretend we have an Intel Parallel Amplifier XE 2011
134 return iJIT_SAMPLING_ON
;
137 unsigned int GetNewMethodID(void) {
138 static unsigned int id
= 0;
142 class JitEventListenerTest
{
144 void InitEE(const std::string
&IRFile
) {
145 // If we have a native target, initialize it to ensure it is linked in and
146 // usable by the JIT.
147 InitializeNativeTarget();
148 InitializeNativeTargetAsmPrinter();
150 // Parse the bitcode...
152 std::unique_ptr
<Module
> TheModule(parseIRFile(IRFile
, Err
, Context
));
154 errs() << Err
.getMessage();
158 RTDyldMemoryManager
*MemMgr
= new SectionMemoryManager();
160 errs() << "Unable to create memory manager.";
164 // Override the triple to generate ELF on Windows since that's supported
165 Triple
Tuple(TheModule
->getTargetTriple());
166 if (Tuple
.getTriple().empty())
167 Tuple
.setTriple(sys::getProcessTriple());
169 if (Tuple
.isOSWindows() && !Tuple
.isOSBinFormatELF()) {
170 Tuple
.setObjectFormat(Triple::ELF
);
171 TheModule
->setTargetTriple(Tuple
.getTriple());
176 TheJIT
.reset(EngineBuilder(std::move(TheModule
))
177 .setEngineKind(EngineKind::JIT
)
179 .setMCJITMemoryManager(std::unique_ptr
<RTDyldMemoryManager
>(MemMgr
))
181 if (Error
.empty() == false)
189 LLVMContext Context
; // Global ownership
190 std::unique_ptr
<ExecutionEngine
> TheJIT
;
193 void ProcessInput(const std::string
&Filename
) {
196 std::unique_ptr
<llvm::JITEventListener
> Listener(
197 JITEventListener::createIntelJITEventListener(new IntelJITEventsWrapper(
198 NotifyEvent
, ittNotifyInfo
, 0, IsProfilingActive
, 0, 0,
201 TheJIT
->RegisterJITEventListener(Listener
.get());
203 TheJIT
->finalizeObject();
205 // Destroy the JIT engine instead of unregistering to get unload events.
212 } // end anonymous namespace
214 static cl::opt
<std::string
>
215 InputFilename(cl::Positional
, cl::desc("<input IR file>"),
218 int main(int argc
, char **argv
) {
219 InitLLVM
X(argc
, argv
);
220 cl::ParseCommandLineOptions(argc
, argv
, "llvm jit event listener test utility\n");
222 JitEventListenerTest Test
;
223 Test
.ProcessInput(InputFilename
);