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