1 //===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/ExecutionEngine/JITEventListener.h"
12 #include "llvm/LLVMContext.h"
13 #include "llvm/Instructions.h"
14 #include "llvm/Module.h"
15 #include "llvm/ModuleProvider.h"
16 #include "llvm/ADT/OwningPtr.h"
17 #include "llvm/CodeGen/MachineCodeInfo.h"
18 #include "llvm/ExecutionEngine/JIT.h"
19 #include "llvm/Support/TypeBuilder.h"
20 #include "llvm/Target/TargetSelect.h"
21 #include "gtest/gtest.h"
28 struct FunctionEmittedEvent
{
29 // Indices are local to the RecordingJITEventListener, since the
30 // JITEventListener interface makes no guarantees about the order of
31 // calls between Listeners.
36 JITEvent_EmittedFunctionDetails Details
;
38 struct FunctionFreedEvent
{
44 struct RecordingJITEventListener
: public JITEventListener
{
45 std::vector
<FunctionEmittedEvent
> EmittedEvents
;
46 std::vector
<FunctionFreedEvent
> FreedEvents
;
50 RecordingJITEventListener() : NextIndex(0) {}
52 virtual void NotifyFunctionEmitted(const Function
&F
,
53 void *Code
, size_t Size
,
54 const EmittedFunctionDetails
&Details
) {
55 FunctionEmittedEvent Event
= {NextIndex
++, &F
, Code
, Size
, Details
};
56 EmittedEvents
.push_back(Event
);
59 virtual void NotifyFreeingMachineCode(const Function
&F
, void *OldPtr
) {
60 FunctionFreedEvent Event
= {NextIndex
++, &F
, OldPtr
};
61 FreedEvents
.push_back(Event
);
65 class JITEventListenerTest
: public testing::Test
{
67 JITEventListenerTest()
68 : M(new Module("module", getGlobalContext())),
70 .setEngineKind(EngineKind::JIT
)
75 const OwningPtr
<ExecutionEngine
> EE
;
78 Function
*buildFunction(Module
*M
) {
79 Function
*Result
= Function::Create(
80 TypeBuilder
<int32_t(int32_t), false>::get(getGlobalContext()),
81 GlobalValue::ExternalLinkage
, "id", M
);
82 Value
*Arg
= Result
->arg_begin();
83 BasicBlock
*BB
= BasicBlock::Create(M
->getContext(), "entry", Result
);
84 ReturnInst::Create(M
->getContext(), Arg
, BB
);
88 // Tests that a single JITEventListener follows JIT events accurately.
89 TEST_F(JITEventListenerTest
, Simple
) {
90 RecordingJITEventListener Listener
;
91 EE
->RegisterJITEventListener(&Listener
);
92 Function
*F1
= buildFunction(M
);
93 Function
*F2
= buildFunction(M
);
95 void *F1_addr
= EE
->getPointerToFunction(F1
);
96 void *F2_addr
= EE
->getPointerToFunction(F2
);
97 EE
->getPointerToFunction(F1
); // Should do nothing.
98 EE
->freeMachineCodeForFunction(F1
);
99 EE
->freeMachineCodeForFunction(F2
);
101 ASSERT_EQ(2U, Listener
.EmittedEvents
.size());
102 ASSERT_EQ(2U, Listener
.FreedEvents
.size());
104 EXPECT_EQ(0U, Listener
.EmittedEvents
[0].Index
);
105 EXPECT_EQ(F1
, Listener
.EmittedEvents
[0].F
);
106 EXPECT_EQ(F1_addr
, Listener
.EmittedEvents
[0].Code
);
107 EXPECT_LT(0U, Listener
.EmittedEvents
[0].Size
)
108 << "We don't know how big the function will be, but it had better"
109 << " contain some bytes.";
111 EXPECT_EQ(1U, Listener
.EmittedEvents
[1].Index
);
112 EXPECT_EQ(F2
, Listener
.EmittedEvents
[1].F
);
113 EXPECT_EQ(F2_addr
, Listener
.EmittedEvents
[1].Code
);
114 EXPECT_LT(0U, Listener
.EmittedEvents
[1].Size
)
115 << "We don't know how big the function will be, but it had better"
116 << " contain some bytes.";
118 EXPECT_EQ(2U, Listener
.FreedEvents
[0].Index
);
119 EXPECT_EQ(F1
, Listener
.FreedEvents
[0].F
);
120 EXPECT_EQ(F1_addr
, Listener
.FreedEvents
[0].Code
);
122 EXPECT_EQ(3U, Listener
.FreedEvents
[1].Index
);
123 EXPECT_EQ(F2
, Listener
.FreedEvents
[1].F
);
124 EXPECT_EQ(F2_addr
, Listener
.FreedEvents
[1].Code
);
126 F1
->eraseFromParent();
127 F2
->eraseFromParent();
130 // Tests that a single JITEventListener follows JIT events accurately.
131 TEST_F(JITEventListenerTest
, MultipleListenersDontInterfere
) {
132 RecordingJITEventListener Listener1
;
133 RecordingJITEventListener Listener2
;
134 RecordingJITEventListener Listener3
;
135 Function
*F1
= buildFunction(M
);
136 Function
*F2
= buildFunction(M
);
138 EE
->RegisterJITEventListener(&Listener1
);
139 EE
->RegisterJITEventListener(&Listener2
);
140 void *F1_addr
= EE
->getPointerToFunction(F1
);
141 EE
->RegisterJITEventListener(&Listener3
);
142 EE
->UnregisterJITEventListener(&Listener1
);
143 void *F2_addr
= EE
->getPointerToFunction(F2
);
144 EE
->UnregisterJITEventListener(&Listener2
);
145 EE
->UnregisterJITEventListener(&Listener3
);
146 EE
->freeMachineCodeForFunction(F1
);
147 EE
->RegisterJITEventListener(&Listener2
);
148 EE
->RegisterJITEventListener(&Listener3
);
149 EE
->RegisterJITEventListener(&Listener1
);
150 EE
->freeMachineCodeForFunction(F2
);
151 EE
->UnregisterJITEventListener(&Listener1
);
152 EE
->UnregisterJITEventListener(&Listener2
);
153 EE
->UnregisterJITEventListener(&Listener3
);
156 ASSERT_EQ(1U, Listener1
.EmittedEvents
.size());
157 ASSERT_EQ(1U, Listener1
.FreedEvents
.size());
159 EXPECT_EQ(0U, Listener1
.EmittedEvents
[0].Index
);
160 EXPECT_EQ(F1
, Listener1
.EmittedEvents
[0].F
);
161 EXPECT_EQ(F1_addr
, Listener1
.EmittedEvents
[0].Code
);
162 EXPECT_LT(0U, Listener1
.EmittedEvents
[0].Size
)
163 << "We don't know how big the function will be, but it had better"
164 << " contain some bytes.";
166 EXPECT_EQ(1U, Listener1
.FreedEvents
[0].Index
);
167 EXPECT_EQ(F2
, Listener1
.FreedEvents
[0].F
);
168 EXPECT_EQ(F2_addr
, Listener1
.FreedEvents
[0].Code
);
171 ASSERT_EQ(2U, Listener2
.EmittedEvents
.size());
172 ASSERT_EQ(1U, Listener2
.FreedEvents
.size());
174 EXPECT_EQ(0U, Listener2
.EmittedEvents
[0].Index
);
175 EXPECT_EQ(F1
, Listener2
.EmittedEvents
[0].F
);
176 EXPECT_EQ(F1_addr
, Listener2
.EmittedEvents
[0].Code
);
177 EXPECT_LT(0U, Listener2
.EmittedEvents
[0].Size
)
178 << "We don't know how big the function will be, but it had better"
179 << " contain some bytes.";
181 EXPECT_EQ(1U, Listener2
.EmittedEvents
[1].Index
);
182 EXPECT_EQ(F2
, Listener2
.EmittedEvents
[1].F
);
183 EXPECT_EQ(F2_addr
, Listener2
.EmittedEvents
[1].Code
);
184 EXPECT_LT(0U, Listener2
.EmittedEvents
[1].Size
)
185 << "We don't know how big the function will be, but it had better"
186 << " contain some bytes.";
188 EXPECT_EQ(2U, Listener2
.FreedEvents
[0].Index
);
189 EXPECT_EQ(F2
, Listener2
.FreedEvents
[0].F
);
190 EXPECT_EQ(F2_addr
, Listener2
.FreedEvents
[0].Code
);
193 ASSERT_EQ(1U, Listener3
.EmittedEvents
.size());
194 ASSERT_EQ(1U, Listener3
.FreedEvents
.size());
196 EXPECT_EQ(0U, Listener3
.EmittedEvents
[0].Index
);
197 EXPECT_EQ(F2
, Listener3
.EmittedEvents
[0].F
);
198 EXPECT_EQ(F2_addr
, Listener3
.EmittedEvents
[0].Code
);
199 EXPECT_LT(0U, Listener3
.EmittedEvents
[0].Size
)
200 << "We don't know how big the function will be, but it had better"
201 << " contain some bytes.";
203 EXPECT_EQ(1U, Listener3
.FreedEvents
[0].Index
);
204 EXPECT_EQ(F2
, Listener3
.FreedEvents
[0].F
);
205 EXPECT_EQ(F2_addr
, Listener3
.FreedEvents
[0].Code
);
207 F1
->eraseFromParent();
208 F2
->eraseFromParent();
211 TEST_F(JITEventListenerTest
, MatchesMachineCodeInfo
) {
212 RecordingJITEventListener Listener
;
214 Function
*F
= buildFunction(M
);
216 EE
->RegisterJITEventListener(&Listener
);
217 EE
->runJITOnFunction(F
, &MCI
);
218 void *F_addr
= EE
->getPointerToFunction(F
);
219 EE
->freeMachineCodeForFunction(F
);
221 ASSERT_EQ(1U, Listener
.EmittedEvents
.size());
222 ASSERT_EQ(1U, Listener
.FreedEvents
.size());
224 EXPECT_EQ(0U, Listener
.EmittedEvents
[0].Index
);
225 EXPECT_EQ(F
, Listener
.EmittedEvents
[0].F
);
226 EXPECT_EQ(F_addr
, Listener
.EmittedEvents
[0].Code
);
227 EXPECT_EQ(MCI
.address(), Listener
.EmittedEvents
[0].Code
);
228 EXPECT_EQ(MCI
.size(), Listener
.EmittedEvents
[0].Size
);
230 EXPECT_EQ(1U, Listener
.FreedEvents
[0].Index
);
231 EXPECT_EQ(F
, Listener
.FreedEvents
[0].F
);
232 EXPECT_EQ(F_addr
, Listener
.FreedEvents
[0].Code
);
235 class JITEnvironment
: public testing::Environment
{
236 virtual void SetUp() {
237 // Required to create a JIT.
238 InitializeNativeTarget();
241 testing::Environment
* const jit_env
=
242 testing::AddGlobalTestEnvironment(new JITEnvironment
);
244 } // anonymous namespace