From f963cd3e02cc01453cb9fd1d4f9e20a1e6f97ba2 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 15 Mar 2012 06:49:31 +0000 Subject: Follow-up to r152620: restore JIT event listener tests to unittest/ExecutionEngine/JIT git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152780 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../ExecutionEngine/IntelJITEventListenerTest.cpp | 110 ---------- .../JIT/IntelJITEventListenerTest.cpp | 110 ++++++++++ .../ExecutionEngine/JIT/JITEventListenerTest.cpp | 238 +++++++++++++++++++++ .../JIT/JITEventListenerTestCommon.h | 209 ++++++++++++++++++ unittests/ExecutionEngine/JIT/Makefile | 23 ++ .../JIT/OProfileJITEventListenerTest.cpp | 166 ++++++++++++++ unittests/ExecutionEngine/JITEventListenerTest.cpp | 238 --------------------- .../ExecutionEngine/JITEventListenerTestCommon.h | 209 ------------------ unittests/ExecutionEngine/Makefile | 27 +-- .../OProfileJITEventListenerTest.cpp | 166 -------------- 10 files changed, 747 insertions(+), 749 deletions(-) delete mode 100644 unittests/ExecutionEngine/IntelJITEventListenerTest.cpp create mode 100644 unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp create mode 100644 unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp create mode 100644 unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h create mode 100644 unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp delete mode 100644 unittests/ExecutionEngine/JITEventListenerTest.cpp delete mode 100644 unittests/ExecutionEngine/JITEventListenerTestCommon.h delete mode 100644 unittests/ExecutionEngine/OProfileJITEventListenerTest.cpp (limited to 'unittests/ExecutionEngine') diff --git a/unittests/ExecutionEngine/IntelJITEventListenerTest.cpp b/unittests/ExecutionEngine/IntelJITEventListenerTest.cpp deleted file mode 100644 index 8ed7a15be3..0000000000 --- a/unittests/ExecutionEngine/IntelJITEventListenerTest.cpp +++ /dev/null @@ -1,110 +0,0 @@ -//===- JITEventListenerTest.cpp - Tests for Intel JITEventListener --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "JITEventListenerTestCommon.h" - -using namespace llvm; - -#include "llvm/ExecutionEngine/IntelJITEventsWrapper.h" - -#include -#include - -namespace { - -// map of function ("method") IDs to source locations -NativeCodeMap ReportedDebugFuncs; - -} // namespace - -/// Mock implementaion of Intel JIT API jitprofiling library -namespace test_jitprofiling { - -int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { - switch (EventType) { - case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: { - EXPECT_TRUE(0 != EventSpecificData); - iJIT_Method_Load* msg = static_cast(EventSpecificData); - - ReportedDebugFuncs[msg->method_id]; - - for(unsigned int i = 0; i < msg->line_number_size; ++i) { - EXPECT_TRUE(0 != msg->line_number_table); - std::pair loc( - std::string(msg->source_file_name), - msg->line_number_table[i].LineNumber); - ReportedDebugFuncs[msg->method_id].push_back(loc); - } - } - break; - case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: { - EXPECT_TRUE(0 != EventSpecificData); - unsigned int UnloadId - = *reinterpret_cast(EventSpecificData); - EXPECT_TRUE(1 == ReportedDebugFuncs.erase(UnloadId)); - } - default: - break; - } - return 0; -} - -iJIT_IsProfilingActiveFlags IsProfilingActive(void) { - // for testing, pretend we have an Intel Parallel Amplifier XE 2011 - // instance attached - return iJIT_SAMPLING_ON; -} - -unsigned int GetNewMethodID(void) { - static unsigned int id = 0; - return ++id; -} - -} //namespace test_jitprofiling - -class IntelJITEventListenerTest - : public JITEventListenerTestBase { -public: - IntelJITEventListenerTest() - : JITEventListenerTestBase( - new IntelJITEventsWrapper(test_jitprofiling::NotifyEvent, 0, - test_jitprofiling::IsProfilingActive, 0, 0, - test_jitprofiling::GetNewMethodID)) - { - EXPECT_TRUE(0 != MockWrapper); - - Listener.reset(JITEventListener::createIntelJITEventListener( - MockWrapper.get())); - EXPECT_TRUE(0 != Listener); - EE->RegisterJITEventListener(Listener.get()); - } -}; - -TEST_F(IntelJITEventListenerTest, NoDebugInfo) { - TestNoDebugInfo(ReportedDebugFuncs); -} - -TEST_F(IntelJITEventListenerTest, SingleLine) { - TestSingleLine(ReportedDebugFuncs); -} - -TEST_F(IntelJITEventListenerTest, MultipleLines) { - TestMultipleLines(ReportedDebugFuncs); -} - -// This testcase is disabled because the Intel JIT API does not support a single -// JITted function with source lines associated with multiple files -/* -TEST_F(IntelJITEventListenerTest, MultipleFiles) { - TestMultipleFiles(ReportedDebugFuncs); -} -*/ - -testing::Environment* const jit_env = - testing::AddGlobalTestEnvironment(new JITEnvironment); diff --git a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp new file mode 100644 index 0000000000..8ed7a15be3 --- /dev/null +++ b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp @@ -0,0 +1,110 @@ +//===- JITEventListenerTest.cpp - Tests for Intel JITEventListener --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JITEventListenerTestCommon.h" + +using namespace llvm; + +#include "llvm/ExecutionEngine/IntelJITEventsWrapper.h" + +#include +#include + +namespace { + +// map of function ("method") IDs to source locations +NativeCodeMap ReportedDebugFuncs; + +} // namespace + +/// Mock implementaion of Intel JIT API jitprofiling library +namespace test_jitprofiling { + +int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { + switch (EventType) { + case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: { + EXPECT_TRUE(0 != EventSpecificData); + iJIT_Method_Load* msg = static_cast(EventSpecificData); + + ReportedDebugFuncs[msg->method_id]; + + for(unsigned int i = 0; i < msg->line_number_size; ++i) { + EXPECT_TRUE(0 != msg->line_number_table); + std::pair loc( + std::string(msg->source_file_name), + msg->line_number_table[i].LineNumber); + ReportedDebugFuncs[msg->method_id].push_back(loc); + } + } + break; + case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: { + EXPECT_TRUE(0 != EventSpecificData); + unsigned int UnloadId + = *reinterpret_cast(EventSpecificData); + EXPECT_TRUE(1 == ReportedDebugFuncs.erase(UnloadId)); + } + default: + break; + } + return 0; +} + +iJIT_IsProfilingActiveFlags IsProfilingActive(void) { + // for testing, pretend we have an Intel Parallel Amplifier XE 2011 + // instance attached + return iJIT_SAMPLING_ON; +} + +unsigned int GetNewMethodID(void) { + static unsigned int id = 0; + return ++id; +} + +} //namespace test_jitprofiling + +class IntelJITEventListenerTest + : public JITEventListenerTestBase { +public: + IntelJITEventListenerTest() + : JITEventListenerTestBase( + new IntelJITEventsWrapper(test_jitprofiling::NotifyEvent, 0, + test_jitprofiling::IsProfilingActive, 0, 0, + test_jitprofiling::GetNewMethodID)) + { + EXPECT_TRUE(0 != MockWrapper); + + Listener.reset(JITEventListener::createIntelJITEventListener( + MockWrapper.get())); + EXPECT_TRUE(0 != Listener); + EE->RegisterJITEventListener(Listener.get()); + } +}; + +TEST_F(IntelJITEventListenerTest, NoDebugInfo) { + TestNoDebugInfo(ReportedDebugFuncs); +} + +TEST_F(IntelJITEventListenerTest, SingleLine) { + TestSingleLine(ReportedDebugFuncs); +} + +TEST_F(IntelJITEventListenerTest, MultipleLines) { + TestMultipleLines(ReportedDebugFuncs); +} + +// This testcase is disabled because the Intel JIT API does not support a single +// JITted function with source lines associated with multiple files +/* +TEST_F(IntelJITEventListenerTest, MultipleFiles) { + TestMultipleFiles(ReportedDebugFuncs); +} +*/ + +testing::Environment* const jit_env = + testing::AddGlobalTestEnvironment(new JITEnvironment); diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp new file mode 100644 index 0000000000..f8d88301ba --- /dev/null +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp @@ -0,0 +1,238 @@ +//===- 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/LLVMContext.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/CodeGen/MachineCodeInfo.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/Support/TypeBuilder.h" +#include "llvm/Support/TargetSelect.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; + +int dummy; + +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 EmittedEvents; + std::vector 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() + : M(new Module("module", getGlobalContext())), + EE(EngineBuilder(M) + .setEngineKind(EngineKind::JIT) + .create()) { + } + + Module *M; + const OwningPtr EE; +}; + +Function *buildFunction(Module *M) { + Function *Result = Function::Create( + TypeBuilder::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); +} + +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 diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h new file mode 100644 index 0000000000..53608cbfce --- /dev/null +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h @@ -0,0 +1,209 @@ +//===- JITEventListenerTestCommon.h - Helper for JITEventListener tests ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===-------------------------------------------------------------------------------===// + +#ifndef JIT_EVENT_LISTENER_TEST_COMMON_H +#define JIT_EVENT_LISTENER_TEST_COMMON_H + +#include "llvm/Analysis/DIBuilder.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/MachineCodeInfo.h" +#include "llvm/Config/config.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/TypeBuilder.h" +#include "llvm/Support/TargetSelect.h" + +#include "gtest/gtest.h" + +#include +#include +#include + +typedef std::vector > SourceLocations; +typedef std::map NativeCodeMap; + +class JITEnvironment : public testing::Environment { + virtual void SetUp() { + // Required to create a JIT. + llvm::InitializeNativeTarget(); + } +}; + +inline unsigned int getLine() { + return 12; +} + +inline unsigned int getCol() { + return 0; +} + +inline const char* getFilename() { + return "mock_source_file.cpp"; +} + +// Test fixture shared by tests for listener implementations +template +class JITEventListenerTestBase : public testing::Test { +protected: + llvm::OwningPtr MockWrapper; + llvm::OwningPtr Listener; + +public: + llvm::Module* M; + llvm::MDNode* Scope; + llvm::ExecutionEngine* EE; + llvm::DIBuilder* DebugBuilder; + llvm::IRBuilder<> Builder; + + JITEventListenerTestBase(WrapperT* w) + : MockWrapper(w) + , M(new llvm::Module("module", llvm::getGlobalContext())) + , EE(llvm::EngineBuilder(M) + .setEngineKind(llvm::EngineKind::JIT) + .setOptLevel(llvm::CodeGenOpt::None) + .create()) + , DebugBuilder(new llvm::DIBuilder(*M)) + , Builder(llvm::getGlobalContext()) + { + DebugBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C_plus_plus, + "JIT", + "JIT", + "JIT", + true, + "", + 1); + + Scope = DebugBuilder->createFile(getFilename(), "."); + } + + llvm::Function *buildFunction(const SourceLocations& DebugLocations) { + using namespace llvm; + + LLVMContext& GlobalContext = getGlobalContext(); + + SourceLocations::const_iterator CurrentDebugLocation + = DebugLocations.begin(); + + if (CurrentDebugLocation != DebugLocations.end()) { + DebugLoc DebugLocation = DebugLoc::get(getLine(), getCol(), + DebugBuilder->createFile(CurrentDebugLocation->first, ".")); + Builder.SetCurrentDebugLocation(DebugLocation); + CurrentDebugLocation++; + } + + Function *Result = Function::Create( + TypeBuilder::get(GlobalContext), + GlobalValue::ExternalLinkage, "id", M); + Value *Arg = Result->arg_begin(); + BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result); + Builder.SetInsertPoint(BB); + Value* one = ConstantInt::get(GlobalContext, APInt(32, 1)); + for(; CurrentDebugLocation != DebugLocations.end(); + ++CurrentDebugLocation) { + Arg = Builder.CreateMul(Arg, Builder.CreateAdd(Arg, one)); + Builder.SetCurrentDebugLocation( + DebugLoc::get(CurrentDebugLocation->second, 0, + DebugBuilder->createFile(CurrentDebugLocation->first, "."))); + } + Builder.CreateRet(Arg); + return Result; + } + + void TestNoDebugInfo(NativeCodeMap& ReportedDebugFuncs) { + SourceLocations DebugLocations; + llvm::Function* f = buildFunction(DebugLocations); + EXPECT_TRUE(0 != f); + + //Cause JITting and callbacks to our listener + EXPECT_TRUE(0 != EE->getPointerToFunction(f)); + EXPECT_TRUE(1 == ReportedDebugFuncs.size()); + + EE->freeMachineCodeForFunction(f); + EXPECT_TRUE(ReportedDebugFuncs.size() == 0); + } + + void TestSingleLine(NativeCodeMap& ReportedDebugFuncs) { + SourceLocations DebugLocations; + DebugLocations.push_back(std::make_pair(std::string(getFilename()), + getLine())); + llvm::Function* f = buildFunction(DebugLocations); + EXPECT_TRUE(0 != f); + + EXPECT_TRUE(0 != EE->getPointerToFunction(f)); + EXPECT_TRUE(1 == ReportedDebugFuncs.size()); + EXPECT_STREQ(ReportedDebugFuncs.begin()->second.begin()->first.c_str(), + getFilename()); + EXPECT_EQ(ReportedDebugFuncs.begin()->second.begin()->second, getLine()); + + EE->freeMachineCodeForFunction(f); + EXPECT_TRUE(ReportedDebugFuncs.size() == 0); + } + + void TestMultipleLines(NativeCodeMap& ReportedDebugFuncs) { + using namespace std; + + SourceLocations DebugLocations; + unsigned int c = 5; + for(unsigned int i = 0; i < c; ++i) { + DebugLocations.push_back(make_pair(string(getFilename()), getLine() + i)); + } + + llvm::Function* f = buildFunction(DebugLocations); + EXPECT_TRUE(0 != f); + + EXPECT_TRUE(0 != EE->getPointerToFunction(f)); + EXPECT_TRUE(1 == ReportedDebugFuncs.size()); + SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; + EXPECT_EQ(c, FunctionInfo.size()); + + int VerifyCount = 0; + for(SourceLocations::iterator i = FunctionInfo.begin(); + i != FunctionInfo.end(); + ++i) { + EXPECT_STREQ(i->first.c_str(), getFilename()); + EXPECT_EQ(i->second, getLine() + VerifyCount); + VerifyCount++; + } + + EE->freeMachineCodeForFunction(f); + EXPECT_TRUE(ReportedDebugFuncs.size() == 0); + } + + void TestMultipleFiles(NativeCodeMap& ReportedDebugFuncs) { + + std::string secondFilename("another_file.cpp"); + + SourceLocations DebugLocations; + DebugLocations.push_back(std::make_pair(std::string(getFilename()), + getLine())); + DebugLocations.push_back(std::make_pair(secondFilename, getLine())); + llvm::Function* f = buildFunction(DebugLocations); + EXPECT_TRUE(0 != f); + + EXPECT_TRUE(0 != EE->getPointerToFunction(f)); + EXPECT_TRUE(1 == ReportedDebugFuncs.size()); + SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; + EXPECT_TRUE(2 == FunctionInfo.size()); + + EXPECT_STREQ(FunctionInfo.at(0).first.c_str(), getFilename()); + EXPECT_STREQ(FunctionInfo.at(1).first.c_str(), secondFilename.c_str()); + + EXPECT_EQ(FunctionInfo.at(0).second, getLine()); + EXPECT_EQ(FunctionInfo.at(1).second, getLine()); + + EE->freeMachineCodeForFunction(f); + EXPECT_TRUE(ReportedDebugFuncs.size() == 0); + } +}; + +#endif //JIT_EVENT_LISTENER_TEST_COMMON_H diff --git a/unittests/ExecutionEngine/JIT/Makefile b/unittests/ExecutionEngine/JIT/Makefile index f5abe75a8f..b429033b19 100644 --- a/unittests/ExecutionEngine/JIT/Makefile +++ b/unittests/ExecutionEngine/JIT/Makefile @@ -12,6 +12,29 @@ TESTNAME = JIT LINK_COMPONENTS := asmparser bitreader bitwriter core jit native support include $(LEVEL)/Makefile.config + +SOURCES := JITEventListenerTest.cpp + +ifeq ($(USE_INTEL_JITEVENTS), 1) + # Build the Intel JIT Events interface tests + SOURCES += IntelJITEventListenerTest.cpp + + # Add the Intel JIT Events include directory + CPPFLAGS += -I$(INTEL_JITEVENTS_INCDIR) + + # Link against the LLVM Intel JIT Evens interface library + LINK_COMPONENTS += inteljitevents +endif + +ifeq ($(USE_OPROFILE), 1) + # Build the OProfile JIT interface tests + SOURCES += OProfileJITEventListenerTest.cpp + + # Link against the LLVM oprofile interface library + LINK_COMPONENTS += oprofilejit +endif + + include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest # Permit these tests to use the JIT's symbolic lookup. diff --git a/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp new file mode 100644 index 0000000000..9b0ee60992 --- /dev/null +++ b/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp @@ -0,0 +1,166 @@ +//===- OProfileJITEventListenerTest.cpp - Unit tests for OProfileJITEventsListener --------===// +// +// 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/ExecutionEngine/OProfileWrapper.h" +#include "JITEventListenerTestCommon.h" + +#include +#include + +using namespace llvm; + +namespace { + +struct OprofileNativeFunction { + const char* Name; + uint64_t Addr; + const void* CodePtr; + unsigned int CodeSize; + + OprofileNativeFunction(const char* name, + uint64_t addr, + const void* code, + unsigned int size) + : Name(name) + , Addr(addr) + , CodePtr(code) + , CodeSize(size) { + } +}; + +typedef std::list NativeFunctionList; +typedef std::list NativeDebugList; +NativeFunctionList NativeFunctions; + +NativeCodeMap ReportedDebugFuncs; + +} // namespace + +/// Mock implementaion of opagent library +namespace test_opagent { + +op_agent_t globalAgent = reinterpret_cast(42); + +op_agent_t open_agent() +{ + // return non-null op_agent_t + return globalAgent; +} + +int close_agent(op_agent_t agent) +{ + EXPECT_EQ(globalAgent, agent); + return 0; +} + +int write_native_code(op_agent_t agent, + const char* name, + uint64_t addr, + void const* code, + unsigned int size) +{ + EXPECT_EQ(globalAgent, agent); + OprofileNativeFunction func(name, addr, code, size); + NativeFunctions.push_back(func); + + // Verify no other registration has take place for the same address + EXPECT_TRUE(ReportedDebugFuncs.find(addr) == ReportedDebugFuncs.end()); + + ReportedDebugFuncs[addr]; + return 0; +} + +int write_debug_line_info(op_agent_t agent, + void const* code, + size_t num_entries, + struct debug_line_info const* info) +{ + EXPECT_EQ(globalAgent, agent); + + //verify code has been loaded first + uint64_t addr = reinterpret_cast(code); + NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); + EXPECT_TRUE(i != ReportedDebugFuncs.end()); + + NativeDebugList NativeInfo(info, info + num_entries); + + SourceLocations locs; + for(NativeDebugList::iterator i = NativeInfo.begin(); + i != NativeInfo.end(); + ++i) { + locs.push_back(std::make_pair(std::string(i->filename), i->lineno)); + } + ReportedDebugFuncs[addr] = locs; + + return 0; +} + +int unload_native_code(op_agent_t agent, uint64_t addr) { + EXPECT_EQ(globalAgent, agent); + + //verify that something for the given JIT addr has been loaded first + NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); + EXPECT_TRUE(i != ReportedDebugFuncs.end()); + ReportedDebugFuncs.erase(i); + return 0; +} + +int version() { + return 1; +} + +bool is_oprofile_running() { + return true; +} + +} //namespace test_opagent + +class OProfileJITEventListenerTest +: public JITEventListenerTestBase +{ +public: + OProfileJITEventListenerTest() + : JITEventListenerTestBase( + new OProfileWrapper(test_opagent::open_agent, + test_opagent::close_agent, + test_opagent::write_native_code, + test_opagent::write_debug_line_info, + test_opagent::unload_native_code, + test_opagent::version, + test_opagent::version, + test_opagent::is_oprofile_running)) + { + EXPECT_TRUE(0 != MockWrapper); + + Listener.reset(JITEventListener::createOProfileJITEventListener( + MockWrapper.get())); + EXPECT_TRUE(0 != Listener); + EE->RegisterJITEventListener(Listener.get()); + } +}; + +TEST_F(OProfileJITEventListenerTest, NoDebugInfo) { + TestNoDebugInfo(ReportedDebugFuncs); +} + +TEST_F(OProfileJITEventListenerTest, SingleLine) { + TestSingleLine(ReportedDebugFuncs); +} + +TEST_F(OProfileJITEventListenerTest, MultipleLines) { + TestMultipleLines(ReportedDebugFuncs); +} + +TEST_F(OProfileJITEventListenerTest, MultipleFiles) { + TestMultipleFiles(ReportedDebugFuncs); +} + +testing::Environment* const jit_env = + testing::AddGlobalTestEnvironment(new JITEnvironment); diff --git a/unittests/ExecutionEngine/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JITEventListenerTest.cpp deleted file mode 100644 index f8d88301ba..0000000000 --- a/unittests/ExecutionEngine/JITEventListenerTest.cpp +++ /dev/null @@ -1,238 +0,0 @@ -//===- 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/LLVMContext.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/CodeGen/MachineCodeInfo.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/Support/TypeBuilder.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; - -int dummy; - -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 EmittedEvents; - std::vector 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() - : M(new Module("module", getGlobalContext())), - EE(EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .create()) { - } - - Module *M; - const OwningPtr EE; -}; - -Function *buildFunction(Module *M) { - Function *Result = Function::Create( - TypeBuilder::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); -} - -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 diff --git a/unittests/ExecutionEngine/JITEventListenerTestCommon.h b/unittests/ExecutionEngine/JITEventListenerTestCommon.h deleted file mode 100644 index 53608cbfce..0000000000 --- a/unittests/ExecutionEngine/JITEventListenerTestCommon.h +++ /dev/null @@ -1,209 +0,0 @@ -//===- JITEventListenerTestCommon.h - Helper for JITEventListener tests ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===-------------------------------------------------------------------------------===// - -#ifndef JIT_EVENT_LISTENER_TEST_COMMON_H -#define JIT_EVENT_LISTENER_TEST_COMMON_H - -#include "llvm/Analysis/DIBuilder.h" -#include "llvm/Analysis/DebugInfo.h" -#include "llvm/CodeGen/MachineCodeInfo.h" -#include "llvm/Config/config.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/Support/IRBuilder.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/TypeBuilder.h" -#include "llvm/Support/TargetSelect.h" - -#include "gtest/gtest.h" - -#include -#include -#include - -typedef std::vector > SourceLocations; -typedef std::map NativeCodeMap; - -class JITEnvironment : public testing::Environment { - virtual void SetUp() { - // Required to create a JIT. - llvm::InitializeNativeTarget(); - } -}; - -inline unsigned int getLine() { - return 12; -} - -inline unsigned int getCol() { - return 0; -} - -inline const char* getFilename() { - return "mock_source_file.cpp"; -} - -// Test fixture shared by tests for listener implementations -template -class JITEventListenerTestBase : public testing::Test { -protected: - llvm::OwningPtr MockWrapper; - llvm::OwningPtr Listener; - -public: - llvm::Module* M; - llvm::MDNode* Scope; - llvm::ExecutionEngine* EE; - llvm::DIBuilder* DebugBuilder; - llvm::IRBuilder<> Builder; - - JITEventListenerTestBase(WrapperT* w) - : MockWrapper(w) - , M(new llvm::Module("module", llvm::getGlobalContext())) - , EE(llvm::EngineBuilder(M) - .setEngineKind(llvm::EngineKind::JIT) - .setOptLevel(llvm::CodeGenOpt::None) - .create()) - , DebugBuilder(new llvm::DIBuilder(*M)) - , Builder(llvm::getGlobalContext()) - { - DebugBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C_plus_plus, - "JIT", - "JIT", - "JIT", - true, - "", - 1); - - Scope = DebugBuilder->createFile(getFilename(), "."); - } - - llvm::Function *buildFunction(const SourceLocations& DebugLocations) { - using namespace llvm; - - LLVMContext& GlobalContext = getGlobalContext(); - - SourceLocations::const_iterator CurrentDebugLocation - = DebugLocations.begin(); - - if (CurrentDebugLocation != DebugLocations.end()) { - DebugLoc DebugLocation = DebugLoc::get(getLine(), getCol(), - DebugBuilder->createFile(CurrentDebugLocation->first, ".")); - Builder.SetCurrentDebugLocation(DebugLocation); - CurrentDebugLocation++; - } - - Function *Result = Function::Create( - TypeBuilder::get(GlobalContext), - GlobalValue::ExternalLinkage, "id", M); - Value *Arg = Result->arg_begin(); - BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result); - Builder.SetInsertPoint(BB); - Value* one = ConstantInt::get(GlobalContext, APInt(32, 1)); - for(; CurrentDebugLocation != DebugLocations.end(); - ++CurrentDebugLocation) { - Arg = Builder.CreateMul(Arg, Builder.CreateAdd(Arg, one)); - Builder.SetCurrentDebugLocation( - DebugLoc::get(CurrentDebugLocation->second, 0, - DebugBuilder->createFile(CurrentDebugLocation->first, "."))); - } - Builder.CreateRet(Arg); - return Result; - } - - void TestNoDebugInfo(NativeCodeMap& ReportedDebugFuncs) { - SourceLocations DebugLocations; - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - //Cause JITting and callbacks to our listener - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } - - void TestSingleLine(NativeCodeMap& ReportedDebugFuncs) { - SourceLocations DebugLocations; - DebugLocations.push_back(std::make_pair(std::string(getFilename()), - getLine())); - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - EXPECT_STREQ(ReportedDebugFuncs.begin()->second.begin()->first.c_str(), - getFilename()); - EXPECT_EQ(ReportedDebugFuncs.begin()->second.begin()->second, getLine()); - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } - - void TestMultipleLines(NativeCodeMap& ReportedDebugFuncs) { - using namespace std; - - SourceLocations DebugLocations; - unsigned int c = 5; - for(unsigned int i = 0; i < c; ++i) { - DebugLocations.push_back(make_pair(string(getFilename()), getLine() + i)); - } - - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; - EXPECT_EQ(c, FunctionInfo.size()); - - int VerifyCount = 0; - for(SourceLocations::iterator i = FunctionInfo.begin(); - i != FunctionInfo.end(); - ++i) { - EXPECT_STREQ(i->first.c_str(), getFilename()); - EXPECT_EQ(i->second, getLine() + VerifyCount); - VerifyCount++; - } - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } - - void TestMultipleFiles(NativeCodeMap& ReportedDebugFuncs) { - - std::string secondFilename("another_file.cpp"); - - SourceLocations DebugLocations; - DebugLocations.push_back(std::make_pair(std::string(getFilename()), - getLine())); - DebugLocations.push_back(std::make_pair(secondFilename, getLine())); - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; - EXPECT_TRUE(2 == FunctionInfo.size()); - - EXPECT_STREQ(FunctionInfo.at(0).first.c_str(), getFilename()); - EXPECT_STREQ(FunctionInfo.at(1).first.c_str(), secondFilename.c_str()); - - EXPECT_EQ(FunctionInfo.at(0).second, getLine()); - EXPECT_EQ(FunctionInfo.at(1).second, getLine()); - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } -}; - -#endif //JIT_EVENT_LISTENER_TEST_COMMON_H diff --git a/unittests/ExecutionEngine/Makefile b/unittests/ExecutionEngine/Makefile index ffa05be87d..a0395cdad3 100644 --- a/unittests/ExecutionEngine/Makefile +++ b/unittests/ExecutionEngine/Makefile @@ -10,32 +10,7 @@ LEVEL = ../.. TESTNAME = ExecutionEngine LINK_COMPONENTS := engine interpreter - -include $(LEVEL)/Makefile.config - -SOURCES := ExecutionEngineTest.cpp \ - JITEventListenerTest.cpp - -ifeq ($(USE_INTEL_JITEVENTS), 1) - # Build the Intel JIT Events interface tests - SOURCES += IntelJITEventListenerTest.cpp - - # Add the Intel JIT Events include directory - CPPFLAGS += -I$(INTEL_JITEVENTS_INCDIR) - - # Link against the LLVM Intel JIT Evens interface library - LINK_COMPONENTS += inteljitevents -endif - -ifeq ($(USE_OPROFILE), 1) - # Build the OProfile JIT interface tests - SOURCES += OProfileJITEventListenerTest.cpp - - # Link against the LLVM oprofile interface library - LINK_COMPONENTS += oprofilejit -endif - - PARALLEL_DIRS = JIT +include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/OProfileJITEventListenerTest.cpp b/unittests/ExecutionEngine/OProfileJITEventListenerTest.cpp deleted file mode 100644 index 9b0ee60992..0000000000 --- a/unittests/ExecutionEngine/OProfileJITEventListenerTest.cpp +++ /dev/null @@ -1,166 +0,0 @@ -//===- OProfileJITEventListenerTest.cpp - Unit tests for OProfileJITEventsListener --------===// -// -// 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/ExecutionEngine/OProfileWrapper.h" -#include "JITEventListenerTestCommon.h" - -#include -#include - -using namespace llvm; - -namespace { - -struct OprofileNativeFunction { - const char* Name; - uint64_t Addr; - const void* CodePtr; - unsigned int CodeSize; - - OprofileNativeFunction(const char* name, - uint64_t addr, - const void* code, - unsigned int size) - : Name(name) - , Addr(addr) - , CodePtr(code) - , CodeSize(size) { - } -}; - -typedef std::list NativeFunctionList; -typedef std::list NativeDebugList; -NativeFunctionList NativeFunctions; - -NativeCodeMap ReportedDebugFuncs; - -} // namespace - -/// Mock implementaion of opagent library -namespace test_opagent { - -op_agent_t globalAgent = reinterpret_cast(42); - -op_agent_t open_agent() -{ - // return non-null op_agent_t - return globalAgent; -} - -int close_agent(op_agent_t agent) -{ - EXPECT_EQ(globalAgent, agent); - return 0; -} - -int write_native_code(op_agent_t agent, - const char* name, - uint64_t addr, - void const* code, - unsigned int size) -{ - EXPECT_EQ(globalAgent, agent); - OprofileNativeFunction func(name, addr, code, size); - NativeFunctions.push_back(func); - - // Verify no other registration has take place for the same address - EXPECT_TRUE(ReportedDebugFuncs.find(addr) == ReportedDebugFuncs.end()); - - ReportedDebugFuncs[addr]; - return 0; -} - -int write_debug_line_info(op_agent_t agent, - void const* code, - size_t num_entries, - struct debug_line_info const* info) -{ - EXPECT_EQ(globalAgent, agent); - - //verify code has been loaded first - uint64_t addr = reinterpret_cast(code); - NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); - EXPECT_TRUE(i != ReportedDebugFuncs.end()); - - NativeDebugList NativeInfo(info, info + num_entries); - - SourceLocations locs; - for(NativeDebugList::iterator i = NativeInfo.begin(); - i != NativeInfo.end(); - ++i) { - locs.push_back(std::make_pair(std::string(i->filename), i->lineno)); - } - ReportedDebugFuncs[addr] = locs; - - return 0; -} - -int unload_native_code(op_agent_t agent, uint64_t addr) { - EXPECT_EQ(globalAgent, agent); - - //verify that something for the given JIT addr has been loaded first - NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); - EXPECT_TRUE(i != ReportedDebugFuncs.end()); - ReportedDebugFuncs.erase(i); - return 0; -} - -int version() { - return 1; -} - -bool is_oprofile_running() { - return true; -} - -} //namespace test_opagent - -class OProfileJITEventListenerTest -: public JITEventListenerTestBase -{ -public: - OProfileJITEventListenerTest() - : JITEventListenerTestBase( - new OProfileWrapper(test_opagent::open_agent, - test_opagent::close_agent, - test_opagent::write_native_code, - test_opagent::write_debug_line_info, - test_opagent::unload_native_code, - test_opagent::version, - test_opagent::version, - test_opagent::is_oprofile_running)) - { - EXPECT_TRUE(0 != MockWrapper); - - Listener.reset(JITEventListener::createOProfileJITEventListener( - MockWrapper.get())); - EXPECT_TRUE(0 != Listener); - EE->RegisterJITEventListener(Listener.get()); - } -}; - -TEST_F(OProfileJITEventListenerTest, NoDebugInfo) { - TestNoDebugInfo(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, SingleLine) { - TestSingleLine(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, MultipleLines) { - TestMultipleLines(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, MultipleFiles) { - TestMultipleFiles(ReportedDebugFuncs); -} - -testing::Environment* const jit_env = - testing::AddGlobalTestEnvironment(new JITEnvironment); -- cgit v1.2.3