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