JITEventListenerTest.cpp revision 4b1511b027ce0b648b3379f2891816c25b46f515
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/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"
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()
68      : M(new Module("module", getGlobalContext())),
69        EE(EngineBuilder(M)
70           .setEngineToCreate(EngineBuilder::ENG_JIT)
71           .create()) {
72  }
73
74  Module *M;
75  const OwningPtr<ExecutionEngine> EE;
76};
77
78Function *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("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() {
237    // Required to create a JIT.
238    InitializeNativeTarget();
239  }
240};
241testing::Environment* const jit_env =
242  testing::AddGlobalTestEnvironment(new JITEnvironment);
243
244}  // anonymous namespace
245