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