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