1 //===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ExecutionEngine/JITEventListener.h"
11 #include "llvm/CodeGen/MachineCodeInfo.h"
12 #include "llvm/ExecutionEngine/JIT.h"
13 #include "llvm/IR/Instructions.h"
14 #include "llvm/IR/LLVMContext.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/IR/TypeBuilder.h"
17 #include "llvm/Support/TargetSelect.h"
18 #include "gtest/gtest.h"
19 #include <vector>
20
21 using namespace llvm;
22
23 namespace {
24
25 struct FunctionEmittedEvent {
26 // Indices are local to the RecordingJITEventListener, since the
27 // JITEventListener interface makes no guarantees about the order of
28 // calls between Listeners.
29 unsigned Index;
30 const Function *F;
31 void *Code;
32 size_t Size;
33 JITEvent_EmittedFunctionDetails Details;
34 };
35 struct FunctionFreedEvent {
36 unsigned Index;
37 void *Code;
38 };
39
40 struct RecordingJITEventListener : public JITEventListener {
41 std::vector<FunctionEmittedEvent> EmittedEvents;
42 std::vector<FunctionFreedEvent> FreedEvents;
43
44 unsigned NextIndex;
45
RecordingJITEventListener__anon9f9469700111::RecordingJITEventListener46 RecordingJITEventListener() : NextIndex(0) {}
47
NotifyFunctionEmitted__anon9f9469700111::RecordingJITEventListener48 virtual void NotifyFunctionEmitted(const Function &F,
49 void *Code, size_t Size,
50 const EmittedFunctionDetails &Details) {
51 FunctionEmittedEvent Event = {NextIndex++, &F, Code, Size, Details};
52 EmittedEvents.push_back(Event);
53 }
54
NotifyFreeingMachineCode__anon9f9469700111::RecordingJITEventListener55 virtual void NotifyFreeingMachineCode(void *OldPtr) {
56 FunctionFreedEvent Event = {NextIndex++, OldPtr};
57 FreedEvents.push_back(Event);
58 }
59 };
60
61 class JITEventListenerTest : public testing::Test {
62 protected:
JITEventListenerTest()63 JITEventListenerTest()
64 : M(new Module("module", getGlobalContext())),
65 EE(EngineBuilder(M)
66 .setEngineKind(EngineKind::JIT)
67 .create()) {
68 }
69
70 Module *M;
71 const std::unique_ptr<ExecutionEngine> EE;
72 };
73
74 // Tests on SystemZ disabled as we're running the old JIT
75 #if !defined(__s390__) && !defined(__aarch64__)
buildFunction(Module * M)76 Function *buildFunction(Module *M) {
77 Function *Result = Function::Create(
78 TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()),
79 GlobalValue::ExternalLinkage, "id", M);
80 Value *Arg = Result->arg_begin();
81 BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result);
82 ReturnInst::Create(M->getContext(), Arg, BB);
83 return Result;
84 }
85
86 // Tests that a single JITEventListener follows JIT events accurately.
TEST_F(JITEventListenerTest,Simple)87 TEST_F(JITEventListenerTest, Simple) {
88 RecordingJITEventListener Listener;
89 EE->RegisterJITEventListener(&Listener);
90 Function *F1 = buildFunction(M);
91 Function *F2 = buildFunction(M);
92
93 void *F1_addr = EE->getPointerToFunction(F1);
94 void *F2_addr = EE->getPointerToFunction(F2);
95 EE->getPointerToFunction(F1); // Should do nothing.
96 EE->freeMachineCodeForFunction(F1);
97 EE->freeMachineCodeForFunction(F2);
98
99 ASSERT_EQ(2U, Listener.EmittedEvents.size());
100 ASSERT_EQ(2U, Listener.FreedEvents.size());
101
102 EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
103 EXPECT_EQ(F1, Listener.EmittedEvents[0].F);
104 EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code);
105 EXPECT_LT(0U, Listener.EmittedEvents[0].Size)
106 << "We don't know how big the function will be, but it had better"
107 << " contain some bytes.";
108
109 EXPECT_EQ(1U, Listener.EmittedEvents[1].Index);
110 EXPECT_EQ(F2, Listener.EmittedEvents[1].F);
111 EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code);
112 EXPECT_LT(0U, Listener.EmittedEvents[1].Size)
113 << "We don't know how big the function will be, but it had better"
114 << " contain some bytes.";
115
116 EXPECT_EQ(2U, Listener.FreedEvents[0].Index);
117 EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code);
118
119 EXPECT_EQ(3U, Listener.FreedEvents[1].Index);
120 EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code);
121
122 F1->eraseFromParent();
123 F2->eraseFromParent();
124 }
125
126 // Tests that a single JITEventListener follows JIT events accurately.
TEST_F(JITEventListenerTest,MultipleListenersDontInterfere)127 TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) {
128 RecordingJITEventListener Listener1;
129 RecordingJITEventListener Listener2;
130 RecordingJITEventListener Listener3;
131 Function *F1 = buildFunction(M);
132 Function *F2 = buildFunction(M);
133
134 EE->RegisterJITEventListener(&Listener1);
135 EE->RegisterJITEventListener(&Listener2);
136 void *F1_addr = EE->getPointerToFunction(F1);
137 EE->RegisterJITEventListener(&Listener3);
138 EE->UnregisterJITEventListener(&Listener1);
139 void *F2_addr = EE->getPointerToFunction(F2);
140 EE->UnregisterJITEventListener(&Listener2);
141 EE->UnregisterJITEventListener(&Listener3);
142 EE->freeMachineCodeForFunction(F1);
143 EE->RegisterJITEventListener(&Listener2);
144 EE->RegisterJITEventListener(&Listener3);
145 EE->RegisterJITEventListener(&Listener1);
146 EE->freeMachineCodeForFunction(F2);
147 EE->UnregisterJITEventListener(&Listener1);
148 EE->UnregisterJITEventListener(&Listener2);
149 EE->UnregisterJITEventListener(&Listener3);
150
151 // Listener 1.
152 ASSERT_EQ(1U, Listener1.EmittedEvents.size());
153 ASSERT_EQ(1U, Listener1.FreedEvents.size());
154
155 EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index);
156 EXPECT_EQ(F1, Listener1.EmittedEvents[0].F);
157 EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code);
158 EXPECT_LT(0U, Listener1.EmittedEvents[0].Size)
159 << "We don't know how big the function will be, but it had better"
160 << " contain some bytes.";
161
162 EXPECT_EQ(1U, Listener1.FreedEvents[0].Index);
163 EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code);
164
165 // Listener 2.
166 ASSERT_EQ(2U, Listener2.EmittedEvents.size());
167 ASSERT_EQ(1U, Listener2.FreedEvents.size());
168
169 EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index);
170 EXPECT_EQ(F1, Listener2.EmittedEvents[0].F);
171 EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code);
172 EXPECT_LT(0U, Listener2.EmittedEvents[0].Size)
173 << "We don't know how big the function will be, but it had better"
174 << " contain some bytes.";
175
176 EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index);
177 EXPECT_EQ(F2, Listener2.EmittedEvents[1].F);
178 EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code);
179 EXPECT_LT(0U, Listener2.EmittedEvents[1].Size)
180 << "We don't know how big the function will be, but it had better"
181 << " contain some bytes.";
182
183 EXPECT_EQ(2U, Listener2.FreedEvents[0].Index);
184 EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code);
185
186 // Listener 3.
187 ASSERT_EQ(1U, Listener3.EmittedEvents.size());
188 ASSERT_EQ(1U, Listener3.FreedEvents.size());
189
190 EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index);
191 EXPECT_EQ(F2, Listener3.EmittedEvents[0].F);
192 EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code);
193 EXPECT_LT(0U, Listener3.EmittedEvents[0].Size)
194 << "We don't know how big the function will be, but it had better"
195 << " contain some bytes.";
196
197 EXPECT_EQ(1U, Listener3.FreedEvents[0].Index);
198 EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code);
199
200 F1->eraseFromParent();
201 F2->eraseFromParent();
202 }
203
TEST_F(JITEventListenerTest,MatchesMachineCodeInfo)204 TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
205 RecordingJITEventListener Listener;
206 MachineCodeInfo MCI;
207 Function *F = buildFunction(M);
208
209 EE->RegisterJITEventListener(&Listener);
210 EE->runJITOnFunction(F, &MCI);
211 void *F_addr = EE->getPointerToFunction(F);
212 EE->freeMachineCodeForFunction(F);
213
214 ASSERT_EQ(1U, Listener.EmittedEvents.size());
215 ASSERT_EQ(1U, Listener.FreedEvents.size());
216
217 EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
218 EXPECT_EQ(F, Listener.EmittedEvents[0].F);
219 EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code);
220 EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code);
221 EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size);
222
223 EXPECT_EQ(1U, Listener.FreedEvents[0].Index);
224 EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code);
225 }
226 #endif
227
228 class JITEnvironment : public testing::Environment {
SetUp()229 virtual void SetUp() {
230 // Required to create a JIT.
231 InitializeNativeTarget();
232 }
233 };
234 testing::Environment* const jit_env =
235 testing::AddGlobalTestEnvironment(new JITEnvironment);
236
237 } // anonymous namespace
238