• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 using namespace llvm;
22 
23 namespace {
24 
25 struct 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 };
35 struct FunctionFreedEvent {
36   unsigned Index;
37   void *Code;
38 };
39 
40 struct RecordingJITEventListener : public JITEventListener {
41   std::vector<FunctionEmittedEvent> EmittedEvents;
42   std::vector<FunctionFreedEvent> FreedEvents;
43 
44   unsigned NextIndex;
45 
RecordingJITEventListener__anon9f9469700111::RecordingJITEventListener46   RecordingJITEventListener() : NextIndex(0) {}
47 
NotifyFunctionEmitted__anon9f9469700111::RecordingJITEventListener48   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 
NotifyFreeingMachineCode__anon9f9469700111::RecordingJITEventListener55   virtual void NotifyFreeingMachineCode(void *OldPtr) {
56     FunctionFreedEvent Event = {NextIndex++, OldPtr};
57     FreedEvents.push_back(Event);
58   }
59 };
60 
61 class JITEventListenerTest : public testing::Test {
62  protected:
JITEventListenerTest()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__)
buildFunction(Module * M)76 Function *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.
TEST_F(JITEventListenerTest,Simple)87 TEST_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.
TEST_F(JITEventListenerTest,MultipleListenersDontInterfere)127 TEST_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 
TEST_F(JITEventListenerTest,MatchesMachineCodeInfo)204 TEST_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 
228 class JITEnvironment : public testing::Environment {
SetUp()229   virtual void SetUp() {
230     // Required to create a JIT.
231     InitializeNativeTarget();
232   }
233 };
234 testing::Environment* const jit_env =
235   testing::AddGlobalTestEnvironment(new JITEnvironment);
236 
237 }  // anonymous namespace
238