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/ADT/OwningPtr.h" 16 #include "llvm/CodeGen/MachineCodeInfo.h" 17 #include "llvm/ExecutionEngine/JIT.h" 18 #include "llvm/Support/TypeBuilder.h" 19 #include "llvm/Support/TargetSelect.h" 20 #include "gtest/gtest.h" 21 #include <vector> 22 23 using namespace llvm; 24 25 int dummy; 26 27 namespace { 28 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; 38 }; 39 struct FunctionFreedEvent { 40 unsigned Index; 41 void *Code; 42 }; 43 44 struct RecordingJITEventListener : public JITEventListener { 45 std::vector<FunctionEmittedEvent> EmittedEvents; 46 std::vector<FunctionFreedEvent> FreedEvents; 47 48 unsigned NextIndex; 49 50 RecordingJITEventListener() : NextIndex(0) {} 51 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); 57 } 58 59 virtual void NotifyFreeingMachineCode(void *OldPtr) { 60 FunctionFreedEvent Event = {NextIndex++, OldPtr}; 61 FreedEvents.push_back(Event); 62 } 63 }; 64 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()) { 72 } 73 74 Module *M; 75 const OwningPtr<ExecutionEngine> EE; 76 }; 77 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; 86 } 87 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); 94 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); 100 101 ASSERT_EQ(2U, Listener.EmittedEvents.size()); 102 ASSERT_EQ(2U, Listener.FreedEvents.size()); 103 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."; 110 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."; 117 118 EXPECT_EQ(2U, Listener.FreedEvents[0].Index); 119 EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code); 120 121 EXPECT_EQ(3U, Listener.FreedEvents[1].Index); 122 EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code); 123 124 F1->eraseFromParent(); 125 F2->eraseFromParent(); 126 } 127 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); 135 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); 152 153 // Listener 1. 154 ASSERT_EQ(1U, Listener1.EmittedEvents.size()); 155 ASSERT_EQ(1U, Listener1.FreedEvents.size()); 156 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."; 163 164 EXPECT_EQ(1U, Listener1.FreedEvents[0].Index); 165 EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code); 166 167 // Listener 2. 168 ASSERT_EQ(2U, Listener2.EmittedEvents.size()); 169 ASSERT_EQ(1U, Listener2.FreedEvents.size()); 170 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."; 177 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."; 184 185 EXPECT_EQ(2U, Listener2.FreedEvents[0].Index); 186 EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code); 187 188 // Listener 3. 189 ASSERT_EQ(1U, Listener3.EmittedEvents.size()); 190 ASSERT_EQ(1U, Listener3.FreedEvents.size()); 191 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."; 198 199 EXPECT_EQ(1U, Listener3.FreedEvents[0].Index); 200 EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code); 201 202 F1->eraseFromParent(); 203 F2->eraseFromParent(); 204 } 205 206 TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) { 207 RecordingJITEventListener Listener; 208 MachineCodeInfo MCI; 209 Function *F = buildFunction(M); 210 211 EE->RegisterJITEventListener(&Listener); 212 EE->runJITOnFunction(F, &MCI); 213 void *F_addr = EE->getPointerToFunction(F); 214 EE->freeMachineCodeForFunction(F); 215 216 ASSERT_EQ(1U, Listener.EmittedEvents.size()); 217 ASSERT_EQ(1U, Listener.FreedEvents.size()); 218 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); 224 225 EXPECT_EQ(1U, Listener.FreedEvents[0].Index); 226 EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code); 227 } 228 229 class JITEnvironment : public testing::Environment { 230 virtual void SetUp() { 231 // Required to create a JIT. 232 InitializeNativeTarget(); 233 } 234 }; 235 testing::Environment* const jit_env = 236 testing::AddGlobalTestEnvironment(new JITEnvironment); 237 238 } // anonymous namespace 239