JITEventListenerTest.cpp revision 5a88dda4be791426ab4d20a6a6c9c65d66614a27
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/ADT/OwningPtr.h"
12#include "llvm/CodeGen/MachineCodeInfo.h"
13#include "llvm/ExecutionEngine/JIT.h"
14#include "llvm/Instructions.h"
15#include "llvm/LLVMContext.h"
16#include "llvm/Module.h"
17#include "llvm/Support/TargetSelect.h"
18#include "llvm/TypeBuilder.h"
19#include "gtest/gtest.h"
20#include <vector>
21
22using namespace llvm;
23
24int dummy;
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  void *Code;
41};
42
43struct RecordingJITEventListener : public JITEventListener {
44  std::vector<FunctionEmittedEvent> EmittedEvents;
45  std::vector<FunctionFreedEvent> FreedEvents;
46
47  unsigned 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(void *OldPtr) {
59    FunctionFreedEvent Event = {NextIndex++, OldPtr};
60    FreedEvents.push_back(Event);
61  }
62};
63
64class JITEventListenerTest : public testing::Test {
65 protected:
66  JITEventListenerTest()
67      : M(new Module("module", getGlobalContext())),
68        EE(EngineBuilder(M)
69           .setEngineKind(EngineKind::JIT)
70           .create()) {
71  }
72
73  Module *M;
74  const OwningPtr<ExecutionEngine> EE;
75};
76
77Function *buildFunction(Module *M) {
78  Function *Result = Function::Create(
79      TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()),
80      GlobalValue::ExternalLinkage, "id", M);
81  Value *Arg = Result->arg_begin();
82  BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result);
83  ReturnInst::Create(M->getContext(), Arg, BB);
84  return Result;
85}
86
87// Tests that a single JITEventListener follows JIT events accurately.
88TEST_F(JITEventListenerTest, Simple) {
89  RecordingJITEventListener Listener;
90  EE->RegisterJITEventListener(&Listener);
91  Function *F1 = buildFunction(M);
92  Function *F2 = buildFunction(M);
93
94  void *F1_addr = EE->getPointerToFunction(F1);
95  void *F2_addr = EE->getPointerToFunction(F2);
96  EE->getPointerToFunction(F1);  // Should do nothing.
97  EE->freeMachineCodeForFunction(F1);
98  EE->freeMachineCodeForFunction(F2);
99
100  ASSERT_EQ(2U, Listener.EmittedEvents.size());
101  ASSERT_EQ(2U, Listener.FreedEvents.size());
102
103  EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
104  EXPECT_EQ(F1, Listener.EmittedEvents[0].F);
105  EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code);
106  EXPECT_LT(0U, Listener.EmittedEvents[0].Size)
107      << "We don't know how big the function will be, but it had better"
108      << " contain some bytes.";
109
110  EXPECT_EQ(1U, Listener.EmittedEvents[1].Index);
111  EXPECT_EQ(F2, Listener.EmittedEvents[1].F);
112  EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code);
113  EXPECT_LT(0U, Listener.EmittedEvents[1].Size)
114      << "We don't know how big the function will be, but it had better"
115      << " contain some bytes.";
116
117  EXPECT_EQ(2U, Listener.FreedEvents[0].Index);
118  EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code);
119
120  EXPECT_EQ(3U, Listener.FreedEvents[1].Index);
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.
128TEST_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_addr, Listener1.FreedEvents[0].Code);
165
166  // Listener 2.
167  ASSERT_EQ(2U, Listener2.EmittedEvents.size());
168  ASSERT_EQ(1U, Listener2.FreedEvents.size());
169
170  EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index);
171  EXPECT_EQ(F1, Listener2.EmittedEvents[0].F);
172  EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code);
173  EXPECT_LT(0U, Listener2.EmittedEvents[0].Size)
174      << "We don't know how big the function will be, but it had better"
175      << " contain some bytes.";
176
177  EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index);
178  EXPECT_EQ(F2, Listener2.EmittedEvents[1].F);
179  EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code);
180  EXPECT_LT(0U, Listener2.EmittedEvents[1].Size)
181      << "We don't know how big the function will be, but it had better"
182      << " contain some bytes.";
183
184  EXPECT_EQ(2U, Listener2.FreedEvents[0].Index);
185  EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code);
186
187  // Listener 3.
188  ASSERT_EQ(1U, Listener3.EmittedEvents.size());
189  ASSERT_EQ(1U, Listener3.FreedEvents.size());
190
191  EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index);
192  EXPECT_EQ(F2, Listener3.EmittedEvents[0].F);
193  EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code);
194  EXPECT_LT(0U, Listener3.EmittedEvents[0].Size)
195      << "We don't know how big the function will be, but it had better"
196      << " contain some bytes.";
197
198  EXPECT_EQ(1U, Listener3.FreedEvents[0].Index);
199  EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code);
200
201  F1->eraseFromParent();
202  F2->eraseFromParent();
203}
204
205TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
206  RecordingJITEventListener Listener;
207  MachineCodeInfo MCI;
208  Function *F = buildFunction(M);
209
210  EE->RegisterJITEventListener(&Listener);
211  EE->runJITOnFunction(F, &MCI);
212  void *F_addr = EE->getPointerToFunction(F);
213  EE->freeMachineCodeForFunction(F);
214
215  ASSERT_EQ(1U, Listener.EmittedEvents.size());
216  ASSERT_EQ(1U, Listener.FreedEvents.size());
217
218  EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
219  EXPECT_EQ(F, Listener.EmittedEvents[0].F);
220  EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code);
221  EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code);
222  EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size);
223
224  EXPECT_EQ(1U, Listener.FreedEvents[0].Index);
225  EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code);
226}
227
228class JITEnvironment : public testing::Environment {
229  virtual void SetUp() {
230    // Required to create a JIT.
231    InitializeNativeTarget();
232  }
233};
234testing::Environment* const jit_env =
235  testing::AddGlobalTestEnvironment(new JITEnvironment);
236
237}  // anonymous namespace
238