When removing a function from the function set and adding it to deferred, we
[llvm.git] / unittests / ExecutionEngine / JIT / JITEventListenerTest.cpp
bloba36ec3bf2a1be054a0bcadd7389c53bde1a69a20
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 //===----------------------------------------------------------------------===//
10 #include "llvm/ExecutionEngine/JITEventListener.h"
12 #include "llvm/LLVMContext.h"
13 #include "llvm/Instructions.h"
14 #include "llvm/Module.h"
15 #include "llvm/ADT/OwningPtr.h"
16 #include "llvm/CodeGen/MachineCodeInfo.h"
17 #include "llvm/ExecutionEngine/JIT.h"
18 #include "llvm/Support/TypeBuilder.h"
19 #include "llvm/Target/TargetSelect.h"
20 #include "gtest/gtest.h"
21 #include <vector>
23 using namespace llvm;
25 int dummy;
27 namespace {
29 struct FunctionEmittedEvent {
30 // Indices are local to the RecordingJITEventListener, since the
31 // JITEventListener interface makes no guarantees about the order of
32 // calls between Listeners.
33 unsigned Index;
34 const Function *F;
35 void *Code;
36 size_t Size;
37 JITEvent_EmittedFunctionDetails Details;
39 struct FunctionFreedEvent {
40 unsigned Index;
41 void *Code;
44 struct RecordingJITEventListener : public JITEventListener {
45 std::vector<FunctionEmittedEvent> EmittedEvents;
46 std::vector<FunctionFreedEvent> FreedEvents;
48 int NextIndex;
50 RecordingJITEventListener() : NextIndex(0) {}
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);
59 virtual void NotifyFreeingMachineCode(void *OldPtr) {
60 FunctionFreedEvent Event = {NextIndex++, OldPtr};
61 FreedEvents.push_back(Event);
65 class JITEventListenerTest : public testing::Test {
66 protected:
67 JITEventListenerTest()
68 : M(new Module("module", getGlobalContext())),
69 EE(EngineBuilder(M)
70 .setEngineKind(EngineKind::JIT)
71 .create()) {
74 Module *M;
75 const OwningPtr<ExecutionEngine> EE;
78 Function *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(M->getContext(), "entry", Result);
84 ReturnInst::Create(M->getContext(), Arg, BB);
85 return Result;
88 // Tests that a single JITEventListener follows JIT events accurately.
89 TEST_F(JITEventListenerTest, Simple) {
90 RecordingJITEventListener Listener;
91 EE->RegisterJITEventListener(&Listener);
92 Function *F1 = buildFunction(M);
93 Function *F2 = buildFunction(M);
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);
101 ASSERT_EQ(2U, Listener.EmittedEvents.size());
102 ASSERT_EQ(2U, Listener.FreedEvents.size());
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.";
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.";
118 EXPECT_EQ(2U, Listener.FreedEvents[0].Index);
119 EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code);
121 EXPECT_EQ(3U, Listener.FreedEvents[1].Index);
122 EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code);
124 F1->eraseFromParent();
125 F2->eraseFromParent();
128 // Tests that a single JITEventListener follows JIT events accurately.
129 TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) {
130 RecordingJITEventListener Listener1;
131 RecordingJITEventListener Listener2;
132 RecordingJITEventListener Listener3;
133 Function *F1 = buildFunction(M);
134 Function *F2 = buildFunction(M);
136 EE->RegisterJITEventListener(&Listener1);
137 EE->RegisterJITEventListener(&Listener2);
138 void *F1_addr = EE->getPointerToFunction(F1);
139 EE->RegisterJITEventListener(&Listener3);
140 EE->UnregisterJITEventListener(&Listener1);
141 void *F2_addr = EE->getPointerToFunction(F2);
142 EE->UnregisterJITEventListener(&Listener2);
143 EE->UnregisterJITEventListener(&Listener3);
144 EE->freeMachineCodeForFunction(F1);
145 EE->RegisterJITEventListener(&Listener2);
146 EE->RegisterJITEventListener(&Listener3);
147 EE->RegisterJITEventListener(&Listener1);
148 EE->freeMachineCodeForFunction(F2);
149 EE->UnregisterJITEventListener(&Listener1);
150 EE->UnregisterJITEventListener(&Listener2);
151 EE->UnregisterJITEventListener(&Listener3);
153 // Listener 1.
154 ASSERT_EQ(1U, Listener1.EmittedEvents.size());
155 ASSERT_EQ(1U, Listener1.FreedEvents.size());
157 EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index);
158 EXPECT_EQ(F1, Listener1.EmittedEvents[0].F);
159 EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code);
160 EXPECT_LT(0U, Listener1.EmittedEvents[0].Size)
161 << "We don't know how big the function will be, but it had better"
162 << " contain some bytes.";
164 EXPECT_EQ(1U, Listener1.FreedEvents[0].Index);
165 EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code);
167 // Listener 2.
168 ASSERT_EQ(2U, Listener2.EmittedEvents.size());
169 ASSERT_EQ(1U, Listener2.FreedEvents.size());
171 EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index);
172 EXPECT_EQ(F1, Listener2.EmittedEvents[0].F);
173 EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code);
174 EXPECT_LT(0U, Listener2.EmittedEvents[0].Size)
175 << "We don't know how big the function will be, but it had better"
176 << " contain some bytes.";
178 EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index);
179 EXPECT_EQ(F2, Listener2.EmittedEvents[1].F);
180 EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code);
181 EXPECT_LT(0U, Listener2.EmittedEvents[1].Size)
182 << "We don't know how big the function will be, but it had better"
183 << " contain some bytes.";
185 EXPECT_EQ(2U, Listener2.FreedEvents[0].Index);
186 EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code);
188 // Listener 3.
189 ASSERT_EQ(1U, Listener3.EmittedEvents.size());
190 ASSERT_EQ(1U, Listener3.FreedEvents.size());
192 EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index);
193 EXPECT_EQ(F2, Listener3.EmittedEvents[0].F);
194 EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code);
195 EXPECT_LT(0U, Listener3.EmittedEvents[0].Size)
196 << "We don't know how big the function will be, but it had better"
197 << " contain some bytes.";
199 EXPECT_EQ(1U, Listener3.FreedEvents[0].Index);
200 EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code);
202 F1->eraseFromParent();
203 F2->eraseFromParent();
206 TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
207 RecordingJITEventListener Listener;
208 MachineCodeInfo MCI;
209 Function *F = buildFunction(M);
211 EE->RegisterJITEventListener(&Listener);
212 EE->runJITOnFunction(F, &MCI);
213 void *F_addr = EE->getPointerToFunction(F);
214 EE->freeMachineCodeForFunction(F);
216 ASSERT_EQ(1U, Listener.EmittedEvents.size());
217 ASSERT_EQ(1U, Listener.FreedEvents.size());
219 EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
220 EXPECT_EQ(F, Listener.EmittedEvents[0].F);
221 EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code);
222 EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code);
223 EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size);
225 EXPECT_EQ(1U, Listener.FreedEvents[0].Index);
226 EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code);
229 class JITEnvironment : public testing::Environment {
230 virtual void SetUp() {
231 // Required to create a JIT.
232 InitializeNativeTarget();
235 testing::Environment* const jit_env =
236 testing::AddGlobalTestEnvironment(new JITEnvironment);
238 } // anonymous namespace