diff options
author | Eric Christopher <echristo@gmail.com> | 2014-09-02 22:28:02 +0000 |
---|---|---|
committer | Eric Christopher <echristo@gmail.com> | 2014-09-02 22:28:02 +0000 |
commit | d5dd8ce2a5336df4e4b4cc04d23e4018d93944f9 (patch) | |
tree | 1670cbdc4a7095c2ef1f0d68cdb7ad10162b91fb /unittests/ExecutionEngine | |
parent | 4437658aff84fa25563740c806a091de1395e5f4 (diff) |
Reinstate "Nuke the old JIT."
Approved by Jim Grosbach, Lang Hames, Rafael Espindola.
This reinstates commits r215111, 215115, 215116, 215117, 215136.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216982 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/ExecutionEngine')
17 files changed, 3 insertions, 2069 deletions
diff --git a/unittests/ExecutionEngine/CMakeLists.txt b/unittests/ExecutionEngine/CMakeLists.txt index 5e462220e5c..783c9b51921 100644 --- a/unittests/ExecutionEngine/CMakeLists.txt +++ b/unittests/ExecutionEngine/CMakeLists.txt @@ -10,10 +10,9 @@ add_llvm_unittest(ExecutionEngineTests ExecutionEngineTest.cpp ) -# Include JIT/MCJIT tests only if native arch is a built JIT target. +# Include MCJIT tests only if native arch is a built JIT target. list(FIND LLVM_TARGETS_TO_BUILD "${LLVM_NATIVE_ARCH}" build_idx) list(FIND LLVM_TARGETS_WITH_JIT "${LLVM_NATIVE_ARCH}" jit_idx) if (NOT build_idx LESS 0 AND NOT jit_idx LESS 0) - add_subdirectory(JIT) add_subdirectory(MCJIT) endif() diff --git a/unittests/ExecutionEngine/JIT/CMakeLists.txt b/unittests/ExecutionEngine/JIT/CMakeLists.txt deleted file mode 100644 index 5ace1c6ee48..00000000000 --- a/unittests/ExecutionEngine/JIT/CMakeLists.txt +++ /dev/null @@ -1,65 +0,0 @@ -set(LLVM_LINK_COMPONENTS - AsmParser - BitReader - BitWriter - Core - ExecutionEngine - JIT - MC - Support - nativecodegen - ) - -# HACK: Declare a couple of source files as optionally compiled to satisfy the -# missing-file-checker in LLVM's weird CMake build. -set(LLVM_OPTIONAL_SOURCES - IntelJITEventListenerTest.cpp - OProfileJITEventListenerTest.cpp - ) - -if( LLVM_USE_INTEL_JITEVENTS ) - set(ProfileTestSources - IntelJITEventListenerTest.cpp - ) - set(LLVM_LINK_COMPONENTS - ${LLVM_LINK_COMPONENTS} - DebugInfo - IntelJITEvents - Object - ) -endif( LLVM_USE_INTEL_JITEVENTS ) - -if( LLVM_USE_OPROFILE ) - set(ProfileTestSources - ${ProfileTestSources} - OProfileJITEventListenerTest.cpp - ) - set(LLVM_LINK_COMPONENTS - ${LLVM_LINK_COMPONENTS} - OProfileJIT - ) -endif( LLVM_USE_OPROFILE ) - -set(JITTestsSources - JITEventListenerTest.cpp - JITMemoryManagerTest.cpp - JITTest.cpp - MultiJITTest.cpp - ${ProfileTestSources} - ) - -if(MSVC) - list(APPEND JITTestsSources JITTests.def) -endif() - -# The JIT tests need to dlopen things. -set(LLVM_NO_DEAD_STRIP 1) - -add_llvm_unittest(JITTests - ${JITTestsSources} - ) - -if(MINGW OR CYGWIN) - set_property(TARGET JITTests PROPERTY LINK_FLAGS -Wl,--export-all-symbols) -endif() -set_target_properties(JITTests PROPERTIES ENABLE_EXPORTS 1) diff --git a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp deleted file mode 100644 index db9088777a9..00000000000 --- a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp +++ /dev/null @@ -1,113 +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; - -// Because we want to keep the implementation details of the Intel API used to -// communicate with Amplifier out of the public header files, the header below -// is included from the source tree instead. -#include "../../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h" - -#include <map> -#include <list> - -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<iJIT_Method_Load*>(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<std::string, unsigned int> 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<unsigned int*>(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<IntelJITEventsWrapper> { -public: - IntelJITEventListenerTest() - : JITEventListenerTestBase<IntelJITEventsWrapper>( - new IntelJITEventsWrapper(test_jitprofiling::NotifyEvent, 0, - test_jitprofiling::IsProfilingActive, 0, 0, - test_jitprofiling::GetNewMethodID)) - { - EXPECT_TRUE(0 != MockWrapper); - - Listener.reset(JITEventListener::createIntelJITEventListener( - MockWrapper.release())); - 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 deleted file mode 100644 index 4b0862e948b..00000000000 --- a/unittests/ExecutionEngine/JIT/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/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 diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h deleted file mode 100644 index 2af688c777e..00000000000 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h +++ /dev/null @@ -1,207 +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/CodeGen/MachineCodeInfo.h" -#include "llvm/Config/config.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include <string> -#include <utility> -#include <vector> - -typedef std::vector<std::pair<std::string, unsigned int> > SourceLocations; -typedef std::map<uint64_t, SourceLocations> 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<typename WrapperT> -class JITEventListenerTestBase : public testing::Test { -protected: - std::unique_ptr<WrapperT> MockWrapper; - std::unique_ptr<llvm::JITEventListener> 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(std::unique_ptr<llvm::Module>(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<int32_t(int32_t), false>::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/JITMemoryManagerTest.cpp b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp deleted file mode 100644 index 0a6a38cef08..00000000000 --- a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +++ /dev/null @@ -1,302 +0,0 @@ -//===- JITMemoryManagerTest.cpp - Unit tests for the JIT memory manager ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/LLVMContext.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -Function *makeFakeFunction() { - std::vector<Type*> params; - FunctionType *FTy = - FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false); - return Function::Create(FTy, GlobalValue::ExternalLinkage); -} - -// Allocate three simple functions that fit in the initial slab. This exercises -// the code in the case that we don't have to allocate more memory to store the -// function bodies. -TEST(JITMemoryManagerTest, NoAllocations) { - std::unique_ptr<JITMemoryManager> MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uintptr_t size; - std::string Error; - - // Allocate the functions. - std::unique_ptr<Function> F1(makeFakeFunction()); - size = 1024; - uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); - memset(FunctionBody1, 0xFF, 1024); - MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + 1024); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr<Function> F2(makeFakeFunction()); - size = 1024; - uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); - memset(FunctionBody2, 0xFF, 1024); - MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + 1024); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr<Function> F3(makeFakeFunction()); - size = 1024; - uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); - memset(FunctionBody3, 0xFF, 1024); - MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + 1024); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - // Deallocate them out of order, in case that matters. - MemMgr->deallocateFunctionBody(FunctionBody2); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody1); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody3); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -} - -// Make three large functions that take up most of the space in the slab. Then -// try allocating three smaller functions that don't require additional slabs. -TEST(JITMemoryManagerTest, TestCodeAllocation) { - std::unique_ptr<JITMemoryManager> MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uintptr_t size; - std::string Error; - - // Big functions are a little less than the largest block size. - const uintptr_t smallFuncSize = 1024; - const uintptr_t bigFuncSize = (MemMgr->GetDefaultCodeSlabSize() - - smallFuncSize * 2); - - // Allocate big functions - std::unique_ptr<Function> F1(makeFakeFunction()); - size = bigFuncSize; - uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); - ASSERT_LE(bigFuncSize, size); - memset(FunctionBody1, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr<Function> F2(makeFakeFunction()); - size = bigFuncSize; - uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); - ASSERT_LE(bigFuncSize, size); - memset(FunctionBody2, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr<Function> F3(makeFakeFunction()); - size = bigFuncSize; - uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); - ASSERT_LE(bigFuncSize, size); - memset(FunctionBody3, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + bigFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - // Check that each large function took it's own slab. - EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); - - // Allocate small functions - std::unique_ptr<Function> F4(makeFakeFunction()); - size = smallFuncSize; - uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size); - ASSERT_LE(smallFuncSize, size); - memset(FunctionBody4, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F4.get(), FunctionBody4, - FunctionBody4 + smallFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr<Function> F5(makeFakeFunction()); - size = smallFuncSize; - uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size); - ASSERT_LE(smallFuncSize, size); - memset(FunctionBody5, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F5.get(), FunctionBody5, - FunctionBody5 + smallFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr<Function> F6(makeFakeFunction()); - size = smallFuncSize; - uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size); - ASSERT_LE(smallFuncSize, size); - memset(FunctionBody6, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F6.get(), FunctionBody6, - FunctionBody6 + smallFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - // Check that the small functions didn't allocate any new slabs. - EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); - - // Deallocate them out of order, in case that matters. - MemMgr->deallocateFunctionBody(FunctionBody2); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody1); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody4); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody3); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody5); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody6); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -} - -// Allocate five global ints of varying widths and alignment, and check their -// alignment and overlap. -TEST(JITMemoryManagerTest, TestSmallGlobalInts) { - std::unique_ptr<JITMemoryManager> MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uint8_t *a = (uint8_t *)MemMgr->allocateGlobal(8, 1); - uint16_t *b = (uint16_t*)MemMgr->allocateGlobal(16, 2); - uint32_t *c = (uint32_t*)MemMgr->allocateGlobal(32, 4); - uint64_t *d = (uint64_t*)MemMgr->allocateGlobal(64, 8); - - // Check the alignment. - EXPECT_EQ(0U, ((uintptr_t)b) & 0x1); - EXPECT_EQ(0U, ((uintptr_t)c) & 0x3); - EXPECT_EQ(0U, ((uintptr_t)d) & 0x7); - - // Initialize them each one at a time and make sure they don't overlap. - *a = 0xff; - *b = 0U; - *c = 0U; - *d = 0U; - EXPECT_EQ(0xffU, *a); - EXPECT_EQ(0U, *b); - EXPECT_EQ(0U, *c); - EXPECT_EQ(0U, *d); - *a = 0U; - *b = 0xffffU; - EXPECT_EQ(0U, *a); - EXPECT_EQ(0xffffU, *b); - EXPECT_EQ(0U, *c); - EXPECT_EQ(0U, *d); - *b = 0U; - *c = 0xffffffffU; - EXPECT_EQ(0U, *a); - EXPECT_EQ(0U, *b); - EXPECT_EQ(0xffffffffU, *c); - EXPECT_EQ(0U, *d); - *c = 0U; - *d = 0xffffffffffffffffULL; - EXPECT_EQ(0U, *a); - EXPECT_EQ(0U, *b); - EXPECT_EQ(0U, *c); - EXPECT_EQ(0xffffffffffffffffULL, *d); - - // Make sure we didn't allocate any extra slabs for this tiny amount of data. - EXPECT_EQ(1U, MemMgr->GetNumDataSlabs()); -} - -// Allocate a small global, a big global, and a third global, and make sure we -// only use two slabs for that. -TEST(JITMemoryManagerTest, TestLargeGlobalArray) { - std::unique_ptr<JITMemoryManager> MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - size_t Size = 4 * MemMgr->GetDefaultDataSlabSize(); - uint64_t *a = (uint64_t*)MemMgr->allocateGlobal(64, 8); - uint8_t *g = MemMgr->allocateGlobal(Size, 8); - uint64_t *b = (uint64_t*)MemMgr->allocateGlobal(64, 8); - - // Check the alignment. - EXPECT_EQ(0U, ((uintptr_t)a) & 0x7); - EXPECT_EQ(0U, ((uintptr_t)g) & 0x7); - EXPECT_EQ(0U, ((uintptr_t)b) & 0x7); - - // Initialize them to make sure we don't segfault and make sure they don't - // overlap. - memset(a, 0x1, 8); - memset(g, 0x2, Size); - memset(b, 0x3, 8); - EXPECT_EQ(0x0101010101010101ULL, *a); - // Just check the edges. - EXPECT_EQ(0x02U, g[0]); - EXPECT_EQ(0x02U, g[Size - 1]); - EXPECT_EQ(0x0303030303030303ULL, *b); - - // Check the number of slabs. - EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); -} - -// Allocate lots of medium globals so that we can test moving the bump allocator -// to a new slab. -TEST(JITMemoryManagerTest, TestManyGlobals) { - std::unique_ptr<JITMemoryManager> MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - size_t SlabSize = MemMgr->GetDefaultDataSlabSize(); - size_t Size = 128; - int Iters = (SlabSize / Size) + 1; - - // We should start with no slabs. - EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); - - // After allocating a bunch of globals, we should have two. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateGlobal(Size, 8); - EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); - - // And after much more, we should have three. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateGlobal(Size, 8); - EXPECT_EQ(3U, MemMgr->GetNumDataSlabs()); -} - -// Allocate lots of function stubs so that we can test moving the stub bump -// allocator to a new slab. -TEST(JITMemoryManagerTest, TestManyStubs) { - std::unique_ptr<JITMemoryManager> MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - size_t SlabSize = MemMgr->GetDefaultStubSlabSize(); - size_t Size = 128; - int Iters = (SlabSize / Size) + 1; - - // We should start with no slabs. - EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); - - // After allocating a bunch of stubs, we should have two. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateStub(nullptr, Size, 8); - EXPECT_EQ(2U, MemMgr->GetNumStubSlabs()); - - // And after much more, we should have three. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateStub(nullptr, Size, 8); - EXPECT_EQ(3U, MemMgr->GetNumStubSlabs()); -} - -// Check section allocation and alignment -TEST(JITMemoryManagerTest, AllocateSection) { - std::unique_ptr<JITMemoryManager> MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, StringRef()); - uint8_t *data1 = MemMgr->allocateDataSection(256, 16, 2, StringRef(), true); - uint8_t *code2 = MemMgr->allocateCodeSection(257, 32, 3, StringRef()); - uint8_t *data2 = MemMgr->allocateDataSection(256, 64, 4, StringRef(), false); - uint8_t *code3 = MemMgr->allocateCodeSection(258, 64, 5, StringRef()); - - EXPECT_NE((uint8_t*)nullptr, code1); - EXPECT_NE((uint8_t*)nullptr, code2); - EXPECT_NE((uint8_t*)nullptr, data1); - EXPECT_NE((uint8_t*)nullptr, data2); - - // Check alignment - EXPECT_EQ((uint64_t)code1 & 0xf, 0u); - EXPECT_EQ((uint64_t)code2 & 0x1f, 0u); - EXPECT_EQ((uint64_t)code3 & 0x3f, 0u); - EXPECT_EQ((uint64_t)data1 & 0xf, 0u); - EXPECT_EQ((uint64_t)data2 & 0x3f, 0u); -} - -} diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp deleted file mode 100644 index ffedbfc1239..00000000000 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ /dev/null @@ -1,730 +0,0 @@ -//===- JITTest.cpp - Unit tests for the JIT -------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include <vector> - -using namespace llvm; - -// This variable is intentionally defined differently in the statically-compiled -// program from the IR input to the JIT to assert that the JIT doesn't use its -// definition. Note that this variable must be defined even on platforms where -// JIT tests are disabled as it is referenced from the .def file. -extern "C" int32_t JITTest_AvailableExternallyGlobal; -int32_t JITTest_AvailableExternallyGlobal LLVM_ATTRIBUTE_USED = 42; - -// This function is intentionally defined differently in the statically-compiled -// program from the IR input to the JIT to assert that the JIT doesn't use its -// definition. Note that this function must be defined even on platforms where -// JIT tests are disabled as it is referenced from the .def file. -extern "C" int32_t JITTest_AvailableExternallyFunction() LLVM_ATTRIBUTE_USED; -extern "C" int32_t JITTest_AvailableExternallyFunction() { - return 42; -} - -namespace { - -// Tests on ARM, PowerPC and SystemZ disabled as we're running the old jit -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ - && !defined(__aarch64__) - -Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) { - std::vector<Type*> params; - FunctionType *FTy = FunctionType::get(G->getType()->getElementType(), - params, false); - Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M); - BasicBlock *Entry = BasicBlock::Create(M->getContext(), "entry", F); - IRBuilder<> builder(Entry); - Value *Load = builder.CreateLoad(G); - Type *GTy = G->getType()->getElementType(); - Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL)); - builder.CreateStore(Add, G); - builder.CreateRet(Add); - return F; -} - -std::string DumpFunction(const Function *F) { - std::string Result; - raw_string_ostream(Result) << "" << *F; - return Result; -} - -class RecordingJITMemoryManager : public JITMemoryManager { - const std::unique_ptr<JITMemoryManager> Base; - -public: - RecordingJITMemoryManager() - : Base(JITMemoryManager::CreateDefaultMemManager()) { - stubsAllocated = 0; - } - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) { - return Base->getPointerToNamedFunction(Name, AbortOnFailure); - } - - virtual void setMemoryWritable() { Base->setMemoryWritable(); } - virtual void setMemoryExecutable() { Base->setMemoryExecutable(); } - virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); } - virtual void AllocateGOT() { Base->AllocateGOT(); } - virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); } - struct StartFunctionBodyCall { - StartFunctionBodyCall(uint8_t *Result, const Function *F, - uintptr_t ActualSize, uintptr_t ActualSizeResult) - : Result(Result), F(F), F_dump(DumpFunction(F)), - ActualSize(ActualSize), ActualSizeResult(ActualSizeResult) {} - uint8_t *Result; - const Function *F; - std::string F_dump; - uintptr_t ActualSize; - uintptr_t ActualSizeResult; - }; - std::vector<StartFunctionBodyCall> startFunctionBodyCalls; - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize) { - uintptr_t InitialActualSize = ActualSize; - uint8_t *Result = Base->startFunctionBody(F, ActualSize); - startFunctionBodyCalls.push_back( - StartFunctionBodyCall(Result, F, InitialActualSize, ActualSize)); - return Result; - } - int stubsAllocated; - uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, - unsigned Alignment) override { - stubsAllocated++; - return Base->allocateStub(F, StubSize, Alignment); - } - struct EndFunctionBodyCall { - EndFunctionBodyCall(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) - : F(F), F_dump(DumpFunction(F)), - FunctionStart(FunctionStart), FunctionEnd(FunctionEnd) {} - const Function *F; - std::string F_dump; - uint8_t *FunctionStart; - uint8_t *FunctionEnd; - }; - std::vector<EndFunctionBodyCall> endFunctionBodyCalls; - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - endFunctionBodyCalls.push_back( - EndFunctionBodyCall(F, FunctionStart, FunctionEnd)); - Base->endFunctionBody(F, FunctionStart, FunctionEnd); - } - virtual uint8_t *allocateDataSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName, bool IsReadOnly) { - return Base->allocateDataSection( - Size, Alignment, SectionID, SectionName, IsReadOnly); - } - virtual uint8_t *allocateCodeSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName) { - return Base->allocateCodeSection( - Size, Alignment, SectionID, SectionName); - } - virtual bool finalizeMemory(std::string *ErrMsg) { return false; } - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { - return Base->allocateSpace(Size, Alignment); - } - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { - return Base->allocateGlobal(Size, Alignment); - } - struct DeallocateFunctionBodyCall { - DeallocateFunctionBodyCall(const void *Body) : Body(Body) {} - const void *Body; - }; - std::vector<DeallocateFunctionBodyCall> deallocateFunctionBodyCalls; - virtual void deallocateFunctionBody(void *Body) { - deallocateFunctionBodyCalls.push_back(DeallocateFunctionBodyCall(Body)); - Base->deallocateFunctionBody(Body); - } -}; - -std::unique_ptr<Module> loadAssembly(LLVMContext &C, const char *Assembly) { - SMDiagnostic Error; - std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, C); - std::string errMsg; - raw_string_ostream os(errMsg); - Error.print("", os); - EXPECT_TRUE((bool)M) << os.str(); - return M; -} - -class JITTest : public testing::Test { - protected: - virtual RecordingJITMemoryManager *createMemoryManager() { - return new RecordingJITMemoryManager; - } - - virtual void SetUp() { - std::unique_ptr<Module> Owner = make_unique<Module>("<main>", Context); - M = Owner.get(); - RJMM = createMemoryManager(); - RJMM->setPoisonMemory(true); - std::string Error; - TargetOptions Options; - TheJIT.reset(EngineBuilder(std::move(Owner)) - .setEngineKind(EngineKind::JIT) - .setJITMemoryManager(RJMM) - .setErrorStr(&Error) - .setTargetOptions(Options) - .create()); - ASSERT_TRUE(TheJIT.get() != nullptr) << Error; - } - - void LoadAssembly(const char *assembly) { - M = loadAssembly(Context, assembly).release(); - } - - LLVMContext Context; - Module *M; // Owned by ExecutionEngine. - RecordingJITMemoryManager *RJMM; - std::unique_ptr<ExecutionEngine> TheJIT; -}; - -// Regression test for a bug. The JIT used to allocate globals inside the same -// memory block used for the function, and when the function code was freed, -// the global was left in the same place. This test allocates a function -// that uses and global, deallocates it, and then makes sure that the global -// stays alive after that. -TEST(JIT, GlobalInFunction) { - LLVMContext context; - std::unique_ptr<Module> Owner = make_unique<Module>("<main>", context); - Module *M = Owner.get(); - - JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager(); - // Tell the memory manager to poison freed memory so that accessing freed - // memory is more easily tested. - MemMgr->setPoisonMemory(true); - std::string Error; - std::unique_ptr<ExecutionEngine> JIT(EngineBuilder(std::move(Owner)) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&Error) - .setJITMemoryManager(MemMgr) - // The next line enables the fix: - .setAllocateGVsWithCode(false) - .create()); - ASSERT_EQ(Error, ""); - - // Create a global variable. - Type *GTy = Type::getInt32Ty(context); - GlobalVariable *G = new GlobalVariable( - *M, - GTy, - false, // Not constant. - GlobalValue::InternalLinkage, - Constant::getNullValue(GTy), - "myglobal"); - - // Make a function that points to a global. - Function *F1 = makeReturnGlobal("F1", G, M); - - // Get the pointer to the native code to force it to JIT the function and - // allocate space for the global. - void (*F1Ptr)() = - reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F1)); - - // Since F1 was codegen'd, a pointer to G should be available. - int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G); - ASSERT_NE((int32_t*)nullptr, GPtr); - EXPECT_EQ(0, *GPtr); - - // F1() should increment G. - F1Ptr(); - EXPECT_EQ(1, *GPtr); - - // Make a second function identical to the first, referring to the same - // global. - Function *F2 = makeReturnGlobal("F2", G, M); - void (*F2Ptr)() = - reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F2)); - - // F2() should increment G. - F2Ptr(); - EXPECT_EQ(2, *GPtr); - - // Deallocate F1. - JIT->freeMachineCodeForFunction(F1); - - // F2() should *still* increment G. - F2Ptr(); - EXPECT_EQ(3, *GPtr); -} - -int PlusOne(int arg) { - return arg + 1; -} - -TEST_F(JITTest, FarCallToKnownFunction) { - // x86-64 can only make direct calls to functions within 32 bits of - // the current PC. To call anything farther away, we have to load - // the address into a register and call through the register. The - // current JIT does this by allocating a stub for any far call. - // There was a bug in which the JIT tried to emit a direct call when - // the target was already in the JIT's global mappings and lazy - // compilation was disabled. - - Function *KnownFunction = Function::Create( - TypeBuilder<int(int), false>::get(Context), - GlobalValue::ExternalLinkage, "known", M); - TheJIT->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne); - - // int test() { return known(7); } - Function *TestFunction = Function::Create( - TypeBuilder<int(), false>::get(Context), - GlobalValue::ExternalLinkage, "test", M); - BasicBlock *Entry = BasicBlock::Create(Context, "entry", TestFunction); - IRBuilder<> Builder(Entry); - Value *result = Builder.CreateCall( - KnownFunction, - ConstantInt::get(TypeBuilder<int, false>::get(Context), 7)); - Builder.CreateRet(result); - - TheJIT->DisableLazyCompilation(true); - int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>( - (intptr_t)TheJIT->getPointerToFunction(TestFunction)); - // This used to crash in trying to call PlusOne(). - EXPECT_EQ(8, TestFunctionPtr()); -} - -// Test a function C which calls A and B which call each other. -TEST_F(JITTest, NonLazyCompilationStillNeedsStubs) { - TheJIT->DisableLazyCompilation(true); - - FunctionType *Func1Ty = - cast<FunctionType>(TypeBuilder<void(void), false>::get(Context)); - std::vector<Type*> arg_types; - arg_types.push_back(Type::getInt1Ty(Context)); - FunctionType *FuncTy = FunctionType::get( - Type::getVoidTy(Context), arg_types, false); - Function *Func1 = Function::Create(Func1Ty, Function::ExternalLinkage, - "func1", M); - Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, - "func2", M); - Function *Func3 = Function::Create(FuncTy, Function::InternalLinkage, - "func3", M); - BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); - BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); - BasicBlock *True2 = BasicBlock::Create(Context, "cond_true", Func2); - BasicBlock *False2 = BasicBlock::Create(Context, "cond_false", Func2); - BasicBlock *Block3 = BasicBlock::Create(Context, "block3", Func3); - BasicBlock *True3 = BasicBlock::Create(Context, "cond_true", Func3); - BasicBlock *False3 = BasicBlock::Create(Context, "cond_false", Func3); - - // Make Func1 call Func2(0) and Func3(0). - IRBuilder<> Builder(Block1); - Builder.CreateCall(Func2, ConstantInt::getTrue(Context)); - Builder.CreateCall(Func3, ConstantInt::getTrue(Context)); - Builder.CreateRetVoid(); - - // void Func2(bool b) { if (b) { Func3(false); return; } return; } - Builder.SetInsertPoint(Block2); - Builder.CreateCondBr(Func2->arg_begin(), True2, False2); - Builder.SetInsertPoint(True2); - Builder.CreateCall(Func3, ConstantInt::getFalse(Context)); - Builder.CreateRetVoid(); - Builder.SetInsertPoint(False2); - Builder.CreateRetVoid(); - - // void Func3(bool b) { if (b) { Func2(false); return; } return; } - Builder.SetInsertPoint(Block3); - Builder.CreateCondBr(Func3->arg_begin(), True3, False3); - Builder.SetInsertPoint(True3); - Builder.CreateCall(Func2, ConstantInt::getFalse(Context)); - Builder.CreateRetVoid(); - Builder.SetInsertPoint(False3); - Builder.CreateRetVoid(); - - // Compile the function to native code - void (*F1Ptr)() = - reinterpret_cast<void(*)()>((intptr_t)TheJIT->getPointerToFunction(Func1)); - - F1Ptr(); -} - -// Regression test for PR5162. This used to trigger an AssertingVH inside the -// JIT's Function to stub mapping. -TEST_F(JITTest, NonLazyLeaksNoStubs) { - TheJIT->DisableLazyCompilation(true); - - // Create two functions with a single basic block each. - FunctionType *FuncTy = - cast<FunctionType>(TypeBuilder<int(), false>::get(Context)); - Function *Func1 = Function::Create(FuncTy, Function::ExternalLinkage, - "func1", M); - Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, - "func2", M); - BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); - BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); - - // The first function calls the second and returns the result - IRBuilder<> Builder(Block1); - Value *Result = Builder.CreateCall(Func2); - Builder.CreateRet(Result); - - // The second function just returns a constant - Builder.SetInsertPoint(Block2); - Builder.CreateRet(ConstantInt::get(TypeBuilder<int, false>::get(Context),42)); - - // Compile the function to native code - (void)TheJIT->getPointerToFunction(Func1); - - // Free the JIT state for the functions - TheJIT->freeMachineCodeForFunction(Func1); - TheJIT->freeMachineCodeForFunction(Func2); - - // Delete the first function (and show that is has no users) - EXPECT_EQ(Func1->getNumUses(), 0u); - Func1->eraseFromParent(); - - // Delete the second function (and show that it has no users - it had one, - // func1 but that's gone now) - EXPECT_EQ(Func2->getNumUses(), 0u); - Func2->eraseFromParent(); -} - -TEST_F(JITTest, ModuleDeletion) { - TheJIT->DisableLazyCompilation(false); - LoadAssembly("define void @main() { " - " call i32 @computeVal() " - " ret void " - "} " - " " - "define internal i32 @computeVal() { " - " ret i32 0 " - "} "); - Function *func = M->getFunction("main"); - TheJIT->getPointerToFunction(func); - TheJIT->removeModule(M); - delete M; - - SmallPtrSet<const void*, 2> FunctionsDeallocated; - for (unsigned i = 0, e = RJMM->deallocateFunctionBodyCalls.size(); - i != e; ++i) { - FunctionsDeallocated.insert(RJMM->deallocateFunctionBodyCalls[i].Body); - } - for (unsigned i = 0, e = RJMM->startFunctionBodyCalls.size(); i != e; ++i) { - EXPECT_TRUE(FunctionsDeallocated.count( - RJMM->startFunctionBodyCalls[i].Result)) - << "Function leaked: \n" << RJMM->startFunctionBodyCalls[i].F_dump; - } - EXPECT_EQ(RJMM->startFunctionBodyCalls.size(), - RJMM->deallocateFunctionBodyCalls.size()); -} - -// ARM, MIPS and PPC still emit stubs for calls since the target may be -// too far away to call directly. This #if can probably be removed when -// http://llvm.org/PR5201 is fixed. -#if !defined(__arm__) && !defined(__mips__) && \ - !defined(__powerpc__) && !defined(__ppc__) && !defined(__aarch64__) -typedef int (*FooPtr) (); - -TEST_F(JITTest, NoStubs) { - LoadAssembly("define void @bar() {" - "entry: " - "ret void" - "}" - " " - "define i32 @foo() {" - "entry:" - "call void @bar()" - "ret i32 undef" - "}" - " " - "define i32 @main() {" - "entry:" - "%0 = call i32 @foo()" - "call void @bar()" - "ret i32 undef" - "}"); - Function *foo = M->getFunction("foo"); - uintptr_t tmp = (uintptr_t)(TheJIT->getPointerToFunction(foo)); - FooPtr ptr = (FooPtr)(tmp); - - (ptr)(); - - // We should now allocate no more stubs, we have the code to foo - // and the existing stub for bar. - int stubsBefore = RJMM->stubsAllocated; - Function *func = M->getFunction("main"); - TheJIT->getPointerToFunction(func); - - Function *bar = M->getFunction("bar"); - TheJIT->getPointerToFunction(bar); - - ASSERT_EQ(stubsBefore, RJMM->stubsAllocated); -} -#endif // !ARM && !PPC - -TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { - TheJIT->DisableLazyCompilation(true); - LoadAssembly("define i8()* @get_foo_addr() { " - " ret i8()* @foo " - "} " - " " - "define i8 @foo() { " - " ret i8 42 " - "} "); - Function *F_get_foo_addr = M->getFunction("get_foo_addr"); - - typedef char(*fooT)(); - fooT (*get_foo_addr)() = reinterpret_cast<fooT(*)()>( - (intptr_t)TheJIT->getPointerToFunction(F_get_foo_addr)); - fooT foo_addr = get_foo_addr(); - - // Now free get_foo_addr. This should not free the machine code for foo or - // any call stub returned as foo's canonical address. - TheJIT->freeMachineCodeForFunction(F_get_foo_addr); - - // Check by calling the reported address of foo. - EXPECT_EQ(42, foo_addr()); - - // The reported address should also be the same as the result of a subsequent - // getPointerToFunction(foo). -#if 0 - // Fails until PR5126 is fixed: - Function *F_foo = M->getFunction("foo"); - fooT foo = reinterpret_cast<fooT>( - (intptr_t)TheJIT->getPointerToFunction(F_foo)); - EXPECT_EQ((intptr_t)foo, (intptr_t)foo_addr); -#endif -} - -// ARM does not have an implementation of replaceMachineCodeForFunction(), -// so recompileAndRelinkFunction doesn't work. -#if !defined(__arm__) && !defined(__aarch64__) -TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { - Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context), - GlobalValue::ExternalLinkage, "test", M); - BasicBlock *Entry = BasicBlock::Create(Context, "entry", F); - IRBuilder<> Builder(Entry); - Value *Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 1); - Builder.CreateRet(Val); - - TheJIT->DisableLazyCompilation(true); - // Compile the function once, and make sure it works. - int (*OrigFPtr)() = reinterpret_cast<int(*)()>( - (intptr_t)TheJIT->recompileAndRelinkFunction(F)); - EXPECT_EQ(1, OrigFPtr()); - - // Now change the function to return a different value. - Entry->eraseFromParent(); - BasicBlock *NewEntry = BasicBlock::Create(Context, "new_entry", F); - Builder.SetInsertPoint(NewEntry); - Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 2); - Builder.CreateRet(Val); - // Recompile it, which should produce a new function pointer _and_ update the - // old one. - int (*NewFPtr)() = reinterpret_cast<int(*)()>( - (intptr_t)TheJIT->recompileAndRelinkFunction(F)); - - EXPECT_EQ(2, NewFPtr()) - << "The new pointer should call the new version of the function"; - EXPECT_EQ(2, OrigFPtr()) - << "The old pointer's target should now jump to the new version"; -} -#endif // !defined(__arm__) - -TEST_F(JITTest, AvailableExternallyGlobalIsntEmitted) { - TheJIT->DisableLazyCompilation(true); - LoadAssembly("@JITTest_AvailableExternallyGlobal = " - " available_externally global i32 7 " - " " - "define i32 @loader() { " - " %result = load i32* @JITTest_AvailableExternallyGlobal " - " ret i32 %result " - "} "); - Function *loaderIR = M->getFunction("loader"); - - int32_t (*loader)() = reinterpret_cast<int32_t(*)()>( - (intptr_t)TheJIT->getPointerToFunction(loaderIR)); - EXPECT_EQ(42, loader()) << "func should return 42 from the external global," - << " not 7 from the IR version."; -} - -TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) { - TheJIT->DisableLazyCompilation(true); - LoadAssembly("define available_externally i32 " - " @JITTest_AvailableExternallyFunction() { " - " ret i32 7 " - "} " - " " - "define i32 @func() { " - " %result = tail call i32 " - " @JITTest_AvailableExternallyFunction() " - " ret i32 %result " - "} "); - Function *funcIR = M->getFunction("func"); - - int32_t (*func)() = reinterpret_cast<int32_t(*)()>( - (intptr_t)TheJIT->getPointerToFunction(funcIR)); - EXPECT_EQ(42, func()) << "func should return 42 from the static version," - << " not 7 from the IR version."; -} - -TEST_F(JITTest, EscapedLazyStubStillCallable) { - TheJIT->DisableLazyCompilation(false); - LoadAssembly("define internal i32 @stubbed() { " - " ret i32 42 " - "} " - " " - "define i32()* @get_stub() { " - " ret i32()* @stubbed " - "} "); - typedef int32_t(*StubTy)(); - - // Call get_stub() to get the address of @stubbed without actually JITting it. - Function *get_stubIR = M->getFunction("get_stub"); - StubTy (*get_stub)() = reinterpret_cast<StubTy(*)()>( - (intptr_t)TheJIT->getPointerToFunction(get_stubIR)); - StubTy stubbed = get_stub(); - // Now get_stubIR is the only reference to stubbed's stub. - get_stubIR->eraseFromParent(); - // Now there are no references inside the JIT, but we've got a pointer outside - // it. The stub should be callable and return the right value. - EXPECT_EQ(42, stubbed()); -} - -// Converts the LLVM assembly to bitcode and returns it in a std::string. An -// empty string indicates an error. -std::string AssembleToBitcode(LLVMContext &Context, const char *Assembly) { - std::unique_ptr<Module> TempModule = loadAssembly(Context, Assembly); - if (!TempModule) - return ""; - - std::string Result; - raw_string_ostream OS(Result); - WriteBitcodeToFile(TempModule.get(), OS); - OS.flush(); - return Result; -} - -// Returns a newly-created ExecutionEngine that reads the bitcode in 'Bitcode' -// lazily. The associated Module (owned by the ExecutionEngine) is returned in -// M. Both will be NULL on an error. Bitcode must live at least as long as the -// ExecutionEngine. -ExecutionEngine *getJITFromBitcode( - LLVMContext &Context, const std::string &Bitcode, Module *&M) { - // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires. - std::unique_ptr<MemoryBuffer> BitcodeBuffer = - MemoryBuffer::getMemBuffer(Bitcode, "Bitcode for test"); - ErrorOr<Module *> ModuleOrErr = getLazyBitcodeModule(BitcodeBuffer, Context); - if (std::error_code EC = ModuleOrErr.getError()) { - ADD_FAILURE() << EC.message(); - return nullptr; - } - std::unique_ptr<Module> Owner(ModuleOrErr.get()); - M = Owner.get(); - std::string errMsg; - ExecutionEngine *TheJIT = EngineBuilder(std::move(Owner)) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&errMsg) - .create(); - if (TheJIT == nullptr) { - ADD_FAILURE() << errMsg; - delete M; - M = nullptr; - return nullptr; - } - return TheJIT; -} - -TEST(LazyLoadedJITTest, MaterializableAvailableExternallyFunctionIsntCompiled) { - LLVMContext Context; - const std::string Bitcode = - AssembleToBitcode(Context, - "define available_externally i32 " - " @JITTest_AvailableExternallyFunction() { " - " ret i32 7 " - "} " - " " - "define i32 @func() { " - " %result = tail call i32 " - " @JITTest_AvailableExternallyFunction() " - " ret i32 %result " - "} "); - ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; - Module *M; - std::unique_ptr<ExecutionEngine> TheJIT( - getJITFromBitcode(Context, Bitcode, M)); - ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; - TheJIT->DisableLazyCompilation(true); - - Function *funcIR = M->getFunction("func"); - Function *availableFunctionIR = - M->getFunction("JITTest_AvailableExternallyFunction"); - - // Double-check that the available_externally function is still unmaterialized - // when getPointerToFunction needs to find out if it's available_externally. - EXPECT_TRUE(availableFunctionIR->isMaterializable()); - - int32_t (*func)() = reinterpret_cast<int32_t(*)()>( - (intptr_t)TheJIT->getPointerToFunction(funcIR)); - EXPECT_EQ(42, func()) << "func should return 42 from the static version," - << " not 7 from the IR version."; -} - -TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) { - LLVMContext Context; - const std::string Bitcode = - AssembleToBitcode(Context, - "define i32 @recur1(i32 %a) { " - " %zero = icmp eq i32 %a, 0 " - " br i1 %zero, label %done, label %notdone " - "done: " - " ret i32 3 " - "notdone: " - " %am1 = sub i32 %a, 1 " - " %result = call i32 @recur2(i32 %am1) " - " ret i32 %result " - "} " - " " - "define i32 @recur2(i32 %b) { " - " %result = call i32 @recur1(i32 %b) " - " ret i32 %result " - "} "); - ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; - Module *M; - std::unique_ptr<ExecutionEngine> TheJIT( - getJITFromBitcode(Context, Bitcode, M)); - ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; - TheJIT->DisableLazyCompilation(true); - - Function *recur1IR = M->getFunction("recur1"); - Function *recur2IR = M->getFunction("recur2"); - EXPECT_TRUE(recur1IR->isMaterializable()); - EXPECT_TRUE(recur2IR->isMaterializable()); - - int32_t (*recur1)(int32_t) = reinterpret_cast<int32_t(*)(int32_t)>( - (intptr_t)TheJIT->getPointerToFunction(recur1IR)); - EXPECT_EQ(3, recur1(4)); -} -#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) - -} diff --git a/unittests/ExecutionEngine/JIT/JITTests.def b/unittests/ExecutionEngine/JIT/JITTests.def deleted file mode 100644 index 17c91e87bcd..00000000000 --- a/unittests/ExecutionEngine/JIT/JITTests.def +++ /dev/null @@ -1,4 +0,0 @@ -EXPORTS -getPointerToNamedFunction -JITTest_AvailableExternallyFunction -JITTest_AvailableExternallyGlobal diff --git a/unittests/ExecutionEngine/JIT/Makefile b/unittests/ExecutionEngine/JIT/Makefile deleted file mode 100644 index d86c03bfc80..00000000000 --- a/unittests/ExecutionEngine/JIT/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -##===- unittests/ExecutionEngine/JIT/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -TESTNAME = JIT -LINK_COMPONENTS := asmparser bitreader bitwriter jit native - -# The JIT tests need to dlopen things. -NO_DEAD_STRIP := 1 - -include $(LEVEL)/Makefile.config - -SOURCES := JITEventListenerTest.cpp JITMemoryManagerTest.cpp JITTest.cpp MultiJITTest.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 += debuginfo inteljitevents object -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 - -EXPORTED_SYMBOL_FILE = $(PROJ_OBJ_DIR)/JITTests.exports - -include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest - -# Permit these tests to use the JIT's symbolic lookup. -LD.Flags += $(RDYNAMIC) - -# Symbol exports are necessary (at least for now) when building with LTO. -$(LLVMUnitTestExe): $(NativeExportsFile) -$(PROJ_OBJ_DIR)/JITTests.exports: $(PROJ_SRC_DIR)/JITTests.def $(PROJ_OBJ_DIR)/.dir - tail -n +2 $< > $@ - diff --git a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp deleted file mode 100644 index ceed7e826ad..00000000000 --- a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp +++ /dev/null @@ -1,184 +0,0 @@ -//===- MultiJITTest.cpp - Unit tests for instantiating multiple JITs ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/SourceMgr.h" -#include "gtest/gtest.h" -#include <vector> - -using namespace llvm; - -namespace { - -// ARM, PowerPC and SystemZ tests disabled pending fix for PR10783. -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ - && !defined(__aarch64__) - -std::unique_ptr<Module> loadAssembly(LLVMContext &Context, - const char *Assembly) { - SMDiagnostic Error; - std::unique_ptr<Module> Ret = parseAssemblyString(Assembly, Error, Context); - std::string errMsg; - raw_string_ostream os(errMsg); - Error.print("", os); - EXPECT_TRUE((bool)Ret) << os.str(); - return std::move(Ret); -} - -std::unique_ptr<Module> createModule1(LLVMContext &Context1, Function *&FooF1) { - std::unique_ptr<Module> Ret = loadAssembly(Context1, - "define i32 @add1(i32 %ArgX1) { " - "entry: " - " %addresult = add i32 1, %ArgX1 " - " ret i32 %addresult " - "} " - " " - "define i32 @foo1() { " - "entry: " - " %add1 = call i32 @add1(i32 10) " - " ret i32 %add1 " - "} "); - FooF1 = Ret->getFunction("foo1"); - return std::move(Ret); -} - -std::unique_ptr<Module> createModule2(LLVMContext &Context2, Function *&FooF2) { - std::unique_ptr<Module> Ret = loadAssembly(Context2, - "define i32 @add2(i32 %ArgX2) { " - "entry: " - " %addresult = add i32 2, %ArgX2 " - " ret i32 %addresult " - "} " - " " - "define i32 @foo2() { " - "entry: " - " %add2 = call i32 @add2(i32 10) " - " ret i32 %add2 " - "} "); - FooF2 = Ret->getFunction("foo2"); - return std::move(Ret); -} - -TEST(MultiJitTest, EagerMode) { - LLVMContext Context1; - Function *FooF1 = nullptr; - std::unique_ptr<Module> M1 = createModule1(Context1, FooF1); - - LLVMContext Context2; - Function *FooF2 = nullptr; - std::unique_ptr<Module> M2 = createModule2(Context2, FooF2); - - // Now we create the JIT in eager mode - std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(std::move(M1)).create()); - EE1->DisableLazyCompilation(true); - std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(std::move(M2)).create()); - EE2->DisableLazyCompilation(true); - - // Call the `foo' function with no arguments: - std::vector<GenericValue> noargs; - GenericValue gv1 = EE1->runFunction(FooF1, noargs); - GenericValue gv2 = EE2->runFunction(FooF2, noargs); - - // Import result of execution: - EXPECT_EQ(gv1.IntVal, 11); - EXPECT_EQ(gv2.IntVal, 12); - - EE1->freeMachineCodeForFunction(FooF1); - EE2->freeMachineCodeForFunction(FooF2); -} - -TEST(MultiJitTest, LazyMode) { - LLVMContext Context1; - Function *FooF1 = nullptr; - std::unique_ptr<Module> M1 = createModule1(Context1, FooF1); - - LLVMContext Context2; - Function *FooF2 = nullptr; - std::unique_ptr<Module> M2 = createModule2(Context2, FooF2); - - // Now we create the JIT in lazy mode - std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(std::move(M1)).create()); - EE1->DisableLazyCompilation(false); - std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(std::move(M2)).create()); - EE2->DisableLazyCompilation(false); - - // Call the `foo' function with no arguments: - std::vector<GenericValue> noargs; - GenericValue gv1 = EE1->runFunction(FooF1, noargs); - GenericValue gv2 = EE2->runFunction(FooF2, noargs); - - // Import result of execution: - EXPECT_EQ(gv1.IntVal, 11); - EXPECT_EQ(gv2.IntVal, 12); - - EE1->freeMachineCodeForFunction(FooF1); - EE2->freeMachineCodeForFunction(FooF2); -} - -extern "C" { - extern void *getPointerToNamedFunction(const char *Name); -} - -TEST(MultiJitTest, JitPool) { - LLVMContext Context1; - Function *FooF1 = nullptr; - std::unique_ptr<Module> M1 = createModule1(Context1, FooF1); - - LLVMContext Context2; - Function *FooF2 = nullptr; - std::unique_ptr<Module> M2 = createModule2(Context2, FooF2); - - // Now we create two JITs - std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(std::move(M1)).create()); - std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(std::move(M2)).create()); - - Function *F1 = EE1->FindFunctionNamed("foo1"); - void *foo1 = EE1->getPointerToFunction(F1); - - Function *F2 = EE2->FindFunctionNamed("foo2"); - void *foo2 = EE2->getPointerToFunction(F2); - - // Function in M1 - EXPECT_EQ(getPointerToNamedFunction("foo1"), foo1); - - // Function in M2 - EXPECT_EQ(getPointerToNamedFunction("foo2"), foo2); - - // Symbol search - intptr_t - sa = (intptr_t)getPointerToNamedFunction("getPointerToNamedFunction"); - EXPECT_TRUE(sa != 0); - intptr_t fa = (intptr_t)&getPointerToNamedFunction; - EXPECT_TRUE(fa != 0); -#ifdef __i386__ - // getPointerToNamedFunction might be indirect jump on Win32 --enable-shared. - // FF 25 <disp32>: jmp *(pointer to IAT) - if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) { - fa = *(intptr_t *)(fa + 2); // Address to IAT - EXPECT_TRUE(fa != 0); - fa = *(intptr_t *)fa; // Bound value of IAT - } -#elif defined(__x86_64__) - // getPointerToNamedFunction might be indirect jump - // on Win32 x64 --enable-shared. - // FF 25 <pcrel32>: jmp *(RIP + pointer to IAT) - if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) { - fa += *(int32_t *)(fa + 2) + 6; // Address to IAT(RIP) - fa = *(intptr_t *)fa; // Bound value of IAT - } -#endif - EXPECT_TRUE(sa == fa); -} -#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) - -} // anonymous namespace diff --git a/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp deleted file mode 100644 index 7057fcaf1d6..00000000000 --- a/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp +++ /dev/null @@ -1,165 +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/OProfileWrapper.h" -#include "JITEventListenerTestCommon.h" -#include "llvm/ExecutionEngine/JITEventListener.h" -#include <list> -#include <map> - -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<OprofileNativeFunction> NativeFunctionList; -typedef std::list<debug_line_info> NativeDebugList; -NativeFunctionList NativeFunctions; - -NativeCodeMap ReportedDebugFuncs; - -} // namespace - -/// Mock implementaion of opagent library -namespace test_opagent { - -op_agent_t globalAgent = reinterpret_cast<op_agent_t>(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<uint64_t>(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<OProfileWrapper> -{ -public: - OProfileJITEventListenerTest() - : JITEventListenerTestBase<OProfileWrapper>( - 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/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index cbd08fe9b8e..b10cbb4c9ea 100644 --- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -3,7 +3,6 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine IPO - JIT MC MCJIT ScalarOpts diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp index 98587f7e85c..0582c92b5f8 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "llvm/ExecutionEngine/JIT.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp index 8756a2b1782..01113d00af6 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp @@ -11,7 +11,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h index 1a365793a5c..bc44418003c 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -316,11 +316,9 @@ protected: EngineBuilder EB(std::move(M)); std::string Error; TheJIT.reset(EB.setEngineKind(EngineKind::JIT) - .setUseMCJIT(true) /* can this be folded into the EngineKind enum? */ .setMCJITMemoryManager(MM) .setErrorStr(&Error) .setOptLevel(CodeGenOpt::None) - .setAllocateGVsWithCode(false) /*does this do anything?*/ .setCodeModel(CodeModel::JITDefault) .setRelocationModel(Reloc::Default) .setMArch(MArch) diff --git a/unittests/ExecutionEngine/MCJIT/Makefile b/unittests/ExecutionEngine/MCJIT/Makefile index c4dd740e057..2822b20cdda 100644 --- a/unittests/ExecutionEngine/MCJIT/Makefile +++ b/unittests/ExecutionEngine/MCJIT/Makefile @@ -9,7 +9,7 @@ LEVEL = ../../.. TESTNAME = MCJIT -LINK_COMPONENTS := core ipo jit mcjit native support +LINK_COMPONENTS := core ipo mcjit native support include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/Makefile b/unittests/ExecutionEngine/Makefile index 38e667ff988..8ecb883ba9d 100644 --- a/unittests/ExecutionEngine/Makefile +++ b/unittests/ExecutionEngine/Makefile @@ -14,7 +14,7 @@ LINK_COMPONENTS :=interpreter include $(LEVEL)/Makefile.config ifeq ($(TARGET_HAS_JIT),1) - PARALLEL_DIRS = JIT MCJIT + PARALLEL_DIRS = MCJIT endif include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest |