123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- //===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ExecutionEngine/JITEventListener.h"
- #include "llvm/CodeGen/MachineCodeInfo.h"
- #include "llvm/ExecutionEngine/JIT.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/LLVMContext.h"
- #include "llvm/IR/Module.h"
- #include "llvm/IR/TypeBuilder.h"
- #include "llvm/Support/TargetSelect.h"
- #include "gtest/gtest.h"
- #include <vector>
- using namespace llvm;
- namespace {
- struct FunctionEmittedEvent {
- // Indices are local to the RecordingJITEventListener, since the
- // JITEventListener interface makes no guarantees about the order of
- // calls between Listeners.
- unsigned Index;
- const Function *F;
- void *Code;
- size_t Size;
- JITEvent_EmittedFunctionDetails Details;
- };
- struct FunctionFreedEvent {
- unsigned Index;
- void *Code;
- };
- struct RecordingJITEventListener : public JITEventListener {
- std::vector<FunctionEmittedEvent> EmittedEvents;
- std::vector<FunctionFreedEvent> FreedEvents;
- unsigned NextIndex;
- RecordingJITEventListener() : NextIndex(0) {}
- virtual void NotifyFunctionEmitted(const Function &F,
- void *Code, size_t Size,
- const EmittedFunctionDetails &Details) {
- FunctionEmittedEvent Event = {NextIndex++, &F, Code, Size, Details};
- EmittedEvents.push_back(Event);
- }
- virtual void NotifyFreeingMachineCode(void *OldPtr) {
- FunctionFreedEvent Event = {NextIndex++, OldPtr};
- FreedEvents.push_back(Event);
- }
- };
- class JITEventListenerTest : public testing::Test {
- protected:
- JITEventListenerTest() {
- auto Owner = make_unique<Module>("module", getGlobalContext());
- M = Owner.get();
- EE.reset(EngineBuilder(std::move(Owner))
- .setEngineKind(EngineKind::JIT)
- .create());
- }
- Module *M;
- std::unique_ptr<ExecutionEngine> EE;
- };
- // Tests on SystemZ disabled as we're running the old JIT
- #if !defined(__s390__) && !defined(__aarch64__)
- Function *buildFunction(Module *M) {
- Function *Result = Function::Create(
- TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()),
- GlobalValue::ExternalLinkage, "id", M);
- Value *Arg = Result->arg_begin();
- BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result);
- ReturnInst::Create(M->getContext(), Arg, BB);
- return Result;
- }
- // Tests that a single JITEventListener follows JIT events accurately.
- TEST_F(JITEventListenerTest, Simple) {
- RecordingJITEventListener Listener;
- EE->RegisterJITEventListener(&Listener);
- Function *F1 = buildFunction(M);
- Function *F2 = buildFunction(M);
- void *F1_addr = EE->getPointerToFunction(F1);
- void *F2_addr = EE->getPointerToFunction(F2);
- EE->getPointerToFunction(F1); // Should do nothing.
- EE->freeMachineCodeForFunction(F1);
- EE->freeMachineCodeForFunction(F2);
- ASSERT_EQ(2U, Listener.EmittedEvents.size());
- ASSERT_EQ(2U, Listener.FreedEvents.size());
- EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
- EXPECT_EQ(F1, Listener.EmittedEvents[0].F);
- EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code);
- EXPECT_LT(0U, Listener.EmittedEvents[0].Size)
- << "We don't know how big the function will be, but it had better"
- << " contain some bytes.";
- EXPECT_EQ(1U, Listener.EmittedEvents[1].Index);
- EXPECT_EQ(F2, Listener.EmittedEvents[1].F);
- EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code);
- EXPECT_LT(0U, Listener.EmittedEvents[1].Size)
- << "We don't know how big the function will be, but it had better"
- << " contain some bytes.";
- EXPECT_EQ(2U, Listener.FreedEvents[0].Index);
- EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code);
- EXPECT_EQ(3U, Listener.FreedEvents[1].Index);
- EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code);
- F1->eraseFromParent();
- F2->eraseFromParent();
- }
- // Tests that a single JITEventListener follows JIT events accurately.
- TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) {
- RecordingJITEventListener Listener1;
- RecordingJITEventListener Listener2;
- RecordingJITEventListener Listener3;
- Function *F1 = buildFunction(M);
- Function *F2 = buildFunction(M);
- EE->RegisterJITEventListener(&Listener1);
- EE->RegisterJITEventListener(&Listener2);
- void *F1_addr = EE->getPointerToFunction(F1);
- EE->RegisterJITEventListener(&Listener3);
- EE->UnregisterJITEventListener(&Listener1);
- void *F2_addr = EE->getPointerToFunction(F2);
- EE->UnregisterJITEventListener(&Listener2);
- EE->UnregisterJITEventListener(&Listener3);
- EE->freeMachineCodeForFunction(F1);
- EE->RegisterJITEventListener(&Listener2);
- EE->RegisterJITEventListener(&Listener3);
- EE->RegisterJITEventListener(&Listener1);
- EE->freeMachineCodeForFunction(F2);
- EE->UnregisterJITEventListener(&Listener1);
- EE->UnregisterJITEventListener(&Listener2);
- EE->UnregisterJITEventListener(&Listener3);
- // Listener 1.
- ASSERT_EQ(1U, Listener1.EmittedEvents.size());
- ASSERT_EQ(1U, Listener1.FreedEvents.size());
- EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index);
- EXPECT_EQ(F1, Listener1.EmittedEvents[0].F);
- EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code);
- EXPECT_LT(0U, Listener1.EmittedEvents[0].Size)
- << "We don't know how big the function will be, but it had better"
- << " contain some bytes.";
- EXPECT_EQ(1U, Listener1.FreedEvents[0].Index);
- EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code);
- // Listener 2.
- ASSERT_EQ(2U, Listener2.EmittedEvents.size());
- ASSERT_EQ(1U, Listener2.FreedEvents.size());
- EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index);
- EXPECT_EQ(F1, Listener2.EmittedEvents[0].F);
- EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code);
- EXPECT_LT(0U, Listener2.EmittedEvents[0].Size)
- << "We don't know how big the function will be, but it had better"
- << " contain some bytes.";
- EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index);
- EXPECT_EQ(F2, Listener2.EmittedEvents[1].F);
- EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code);
- EXPECT_LT(0U, Listener2.EmittedEvents[1].Size)
- << "We don't know how big the function will be, but it had better"
- << " contain some bytes.";
- EXPECT_EQ(2U, Listener2.FreedEvents[0].Index);
- EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code);
- // Listener 3.
- ASSERT_EQ(1U, Listener3.EmittedEvents.size());
- ASSERT_EQ(1U, Listener3.FreedEvents.size());
- EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index);
- EXPECT_EQ(F2, Listener3.EmittedEvents[0].F);
- EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code);
- EXPECT_LT(0U, Listener3.EmittedEvents[0].Size)
- << "We don't know how big the function will be, but it had better"
- << " contain some bytes.";
- EXPECT_EQ(1U, Listener3.FreedEvents[0].Index);
- EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code);
- F1->eraseFromParent();
- F2->eraseFromParent();
- }
- TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
- RecordingJITEventListener Listener;
- MachineCodeInfo MCI;
- Function *F = buildFunction(M);
- EE->RegisterJITEventListener(&Listener);
- EE->runJITOnFunction(F, &MCI);
- void *F_addr = EE->getPointerToFunction(F);
- EE->freeMachineCodeForFunction(F);
- ASSERT_EQ(1U, Listener.EmittedEvents.size());
- ASSERT_EQ(1U, Listener.FreedEvents.size());
- EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
- EXPECT_EQ(F, Listener.EmittedEvents[0].F);
- EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code);
- EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code);
- EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size);
- EXPECT_EQ(1U, Listener.FreedEvents[0].Index);
- EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code);
- }
- #endif
- class JITEnvironment : public testing::Environment {
- virtual void SetUp() {
- // Required to create a JIT.
- InitializeNativeTarget();
- }
- };
- testing::Environment* const jit_env =
- testing::AddGlobalTestEnvironment(new JITEnvironment);
- } // anonymous namespace
|