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