blob: 7e2104ef8e0103fe27d109257bc0e669de129acf [file] [log] [blame]
Jeffrey Yasskindf5a7da2009-06-25 02:04:04 +00001//===- 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
Owen Anderson0b19bb72009-07-01 18:14:20 +000012#include "llvm/LLVMContext.h"
Jeffrey Yasskindf5a7da2009-06-25 02:04:04 +000013#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"
22#include <vector>
23
24using namespace llvm;
25
26namespace {
27
28struct FunctionEmittedEvent {
29 // Indices are local to the RecordingJITEventListener, since the
30 // JITEventListener interface makes no guarantees about the order of
31 // calls between Listeners.
32 unsigned Index;
33 const Function *F;
34 void *Code;
35 size_t Size;
36 JITEvent_EmittedFunctionDetails Details;
37};
38struct FunctionFreedEvent {
39 unsigned Index;
40 const Function *F;
41 void *Code;
42};
43
44struct RecordingJITEventListener : public JITEventListener {
45 std::vector<FunctionEmittedEvent> EmittedEvents;
46 std::vector<FunctionFreedEvent> FreedEvents;
47
48 int NextIndex;
49
50 RecordingJITEventListener() : NextIndex(0) {}
51
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);
57 }
58
59 virtual void NotifyFreeingMachineCode(const Function &F, void *OldPtr) {
60 FunctionFreedEvent Event = {NextIndex++, &F, OldPtr};
61 FreedEvents.push_back(Event);
62 }
63};
64
65class JITEventListenerTest : public testing::Test {
66 protected:
67 JITEventListenerTest()
Owen Andersona439ee02009-07-10 18:58:29 +000068 : M(new Module("module", getGlobalContext())),
Reid Kleckner4b1511b2009-07-18 00:42:18 +000069 EE(EngineBuilder(M)
70 .setEngineToCreate(EngineBuilder::ENG_JIT)
71 .create()) {
Jeffrey Yasskindf5a7da2009-06-25 02:04:04 +000072 }
73
74 Module *M;
75 const OwningPtr<ExecutionEngine> EE;
76};
77
78Function *buildFunction(Module *M) {
79 Function *Result = Function::Create(
Owen Andersona439ee02009-07-10 18:58:29 +000080 TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()),
Jeffrey Yasskindf5a7da2009-06-25 02:04:04 +000081 GlobalValue::ExternalLinkage, "id", M);
82 Value *Arg = Result->arg_begin();
83 BasicBlock *BB = BasicBlock::Create("entry", Result);
84 ReturnInst::Create(Arg, BB);
85 return Result;
86}
87
88// Tests that a single JITEventListener follows JIT events accurately.
89TEST_F(JITEventListenerTest, Simple) {
90 RecordingJITEventListener Listener;
91 EE->RegisterJITEventListener(&Listener);
92 Function *F1 = buildFunction(M);
93 Function *F2 = buildFunction(M);
94
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);
100
101 ASSERT_EQ(2U, Listener.EmittedEvents.size());
102 ASSERT_EQ(2U, Listener.FreedEvents.size());
103
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.";
110
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.";
117
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);
121
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);
125
126 F1->eraseFromParent();
127 F2->eraseFromParent();
128}
129
130// Tests that a single JITEventListener follows JIT events accurately.
131TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) {
132 RecordingJITEventListener Listener1;
133 RecordingJITEventListener Listener2;
134 RecordingJITEventListener Listener3;
135 Function *F1 = buildFunction(M);
136 Function *F2 = buildFunction(M);
137
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);
154
155 // Listener 1.
156 ASSERT_EQ(1U, Listener1.EmittedEvents.size());
157 ASSERT_EQ(1U, Listener1.FreedEvents.size());
158
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.";
165
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);
169
170 // Listener 2.
171 ASSERT_EQ(2U, Listener2.EmittedEvents.size());
172 ASSERT_EQ(1U, Listener2.FreedEvents.size());
173
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.";
180
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.";
187
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);
191
192 // Listener 3.
193 ASSERT_EQ(1U, Listener3.EmittedEvents.size());
194 ASSERT_EQ(1U, Listener3.FreedEvents.size());
195
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.";
202
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);
206
207 F1->eraseFromParent();
208 F2->eraseFromParent();
209}
210
211TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
212 RecordingJITEventListener Listener;
213 MachineCodeInfo MCI;
214 Function *F = buildFunction(M);
215
216 EE->RegisterJITEventListener(&Listener);
217 EE->runJITOnFunction(F, &MCI);
218 void *F_addr = EE->getPointerToFunction(F);
219 EE->freeMachineCodeForFunction(F);
220
221 ASSERT_EQ(1U, Listener.EmittedEvents.size());
222 ASSERT_EQ(1U, Listener.FreedEvents.size());
223
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);
229
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);
233}
234
235class JITEnvironment : public testing::Environment {
236 virtual void SetUp() {
Reid Kleckner4b1511b2009-07-18 00:42:18 +0000237 // Required to create a JIT.
Jeffrey Yasskindf5a7da2009-06-25 02:04:04 +0000238 InitializeNativeTarget();
239 }
240};
241testing::Environment* const jit_env =
242 testing::AddGlobalTestEnvironment(new JITEnvironment);
243
244} // anonymous namespace