aboutsummaryrefslogtreecommitdiffstats
path: root/unittests/ExecutionEngine
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-12-01 14:51:49 -0800
committerStephen Hines <srhines@google.com>2014-12-02 16:08:10 -0800
commit37ed9c199ca639565f6ce88105f9e39e898d82d0 (patch)
tree8fb36d3910e3ee4c4e1b7422f4f017108efc52f5 /unittests/ExecutionEngine
parentd2327b22152ced7bc46dc629fc908959e8a52d03 (diff)
downloadexternal_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.zip
external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.gz
external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.bz2
Update aosp/master LLVM for rebase to r222494.
Change-Id: Ic787f5e0124df789bd26f3f24680f45e678eef2d
Diffstat (limited to 'unittests/ExecutionEngine')
-rw-r--r--unittests/ExecutionEngine/CMakeLists.txt4
-rw-r--r--unittests/ExecutionEngine/ExecutionEngineTest.cpp48
-rw-r--r--unittests/ExecutionEngine/JIT/CMakeLists.txt64
-rw-r--r--unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp113
-rw-r--r--unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp237
-rw-r--r--unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h207
-rw-r--r--unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp302
-rw-r--r--unittests/ExecutionEngine/JIT/JITTest.cpp728
-rw-r--r--unittests/ExecutionEngine/JIT/JITTests.def4
-rw-r--r--unittests/ExecutionEngine/JIT/Makefile52
-rw-r--r--unittests/ExecutionEngine/JIT/MultiJITTest.cpp190
-rw-r--r--unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp165
-rw-r--r--unittests/ExecutionEngine/MCJIT/CMakeLists.txt2
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp2
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp1
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp60
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp39
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITTest.cpp22
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h6
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITTestBase.h22
-rw-r--r--unittests/ExecutionEngine/MCJIT/Makefile2
-rw-r--r--unittests/ExecutionEngine/Makefile2
22 files changed, 127 insertions, 2145 deletions
diff --git a/unittests/ExecutionEngine/CMakeLists.txt b/unittests/ExecutionEngine/CMakeLists.txt
index 489eaaf..783c9b5 100644
--- a/unittests/ExecutionEngine/CMakeLists.txt
+++ b/unittests/ExecutionEngine/CMakeLists.txt
@@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS
Core
ExecutionEngine
Interpreter
+ MC
Support
)
@@ -9,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/ExecutionEngineTest.cpp b/unittests/ExecutionEngine/ExecutionEngineTest.cpp
index f23745c..19917a4 100644
--- a/unittests/ExecutionEngine/ExecutionEngineTest.cpp
+++ b/unittests/ExecutionEngine/ExecutionEngineTest.cpp
@@ -8,10 +8,13 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Interpreter.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/ManagedStatic.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -19,10 +22,14 @@ using namespace llvm;
namespace {
class ExecutionEngineTest : public testing::Test {
+private:
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
protected:
- ExecutionEngineTest()
- : M(new Module("<main>", getGlobalContext())), Error(""),
- Engine(EngineBuilder(M).setErrorStr(&Error).create()) {
+ ExecutionEngineTest() {
+ auto Owner = make_unique<Module>("<main>", getGlobalContext());
+ M = Owner.get();
+ Engine.reset(EngineBuilder(std::move(Owner)).setErrorStr(&Error).create());
}
virtual void SetUp() {
@@ -35,9 +42,9 @@ protected:
GlobalValue::ExternalLinkage, nullptr, Name);
}
- Module *const M;
std::string Error;
- const std::unique_ptr<ExecutionEngine> Engine;
+ Module *M; // Owned by ExecutionEngine.
+ std::unique_ptr<ExecutionEngine> Engine;
};
TEST_F(ExecutionEngineTest, ForwardGlobalMapping) {
@@ -127,4 +134,35 @@ TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) {
EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
}
+TEST_F(ExecutionEngineTest, LookupWithMangledName) {
+ int x;
+ llvm::sys::DynamicLibrary::AddSymbol("x", &x);
+
+ // Demonstrate that getSymbolAddress accepts mangled names and always strips
+ // the leading underscore.
+ EXPECT_EQ(reinterpret_cast<uint64_t>(&x),
+ RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
+}
+
+TEST_F(ExecutionEngineTest, LookupWithMangledAndDemangledSymbol) {
+ int x;
+ int _x;
+ llvm::sys::DynamicLibrary::AddSymbol("x", &x);
+ llvm::sys::DynamicLibrary::AddSymbol("_x", &_x);
+
+ // Lookup the demangled name first, even if there's a demangled symbol that
+ // matches the input already.
+ EXPECT_EQ(reinterpret_cast<uint64_t>(&x),
+ RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
+}
+
+TEST_F(ExecutionEngineTest, LookupwithDemangledName) {
+ int _x;
+ llvm::sys::DynamicLibrary::AddSymbol("_x", &_x);
+
+ // But do fallback to looking up a demangled name if there's no ambiguity
+ EXPECT_EQ(reinterpret_cast<uint64_t>(&_x),
+ RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
+}
+
}
diff --git a/unittests/ExecutionEngine/JIT/CMakeLists.txt b/unittests/ExecutionEngine/JIT/CMakeLists.txt
deleted file mode 100644
index 72c1df7..0000000
--- a/unittests/ExecutionEngine/JIT/CMakeLists.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- AsmParser
- BitReader
- BitWriter
- Core
- ExecutionEngine
- JIT
- 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 db90887..0000000
--- 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 175b9fb..0000000
--- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
+++ /dev/null
@@ -1,237 +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()
- : M(new Module("module", getGlobalContext())),
- EE(EngineBuilder(M)
- .setEngineKind(EngineKind::JIT)
- .create()) {
- }
-
- Module *M;
- const 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 61220f5..0000000
--- 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(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 296838d..0000000
--- 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, 0);
- 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 817d207..0000000
--- a/unittests/ExecutionEngine/JIT/JITTest.cpp
+++ /dev/null
@@ -1,728 +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);
- }
-};
-
-bool LoadAssemblyInto(Module *M, const char *assembly) {
- SMDiagnostic Error;
- bool success =
- nullptr != ParseAssemblyString(assembly, M, Error, M->getContext());
- std::string errMsg;
- raw_string_ostream os(errMsg);
- Error.print("", os);
- EXPECT_TRUE(success) << os.str();
- return success;
-}
-
-class JITTest : public testing::Test {
- protected:
- virtual RecordingJITMemoryManager *createMemoryManager() {
- return new RecordingJITMemoryManager;
- }
-
- virtual void SetUp() {
- M = new Module("<main>", Context);
- RJMM = createMemoryManager();
- RJMM->setPoisonMemory(true);
- std::string Error;
- TargetOptions Options;
- TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
- .setJITMemoryManager(RJMM)
- .setErrorStr(&Error)
- .setTargetOptions(Options).create());
- ASSERT_TRUE(TheJIT.get() != nullptr) << Error;
- }
-
- void LoadAssembly(const char *assembly) {
- LoadAssemblyInto(M, assembly);
- }
-
- 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;
- Module *M = new Module("<main>", context);
-
- 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(M)
- .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) {
- Module TempModule("TempModule", Context);
- if (!LoadAssemblyInto(&TempModule, Assembly)) {
- return "";
- }
-
- std::string Result;
- raw_string_ostream OS(Result);
- WriteBitcodeToFile(&TempModule, 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.
- 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();
- delete BitcodeBuffer;
- return nullptr;
- }
- M = ModuleOrErr.get();
- std::string errMsg;
- ExecutionEngine *TheJIT = EngineBuilder(M)
- .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 17c91e8..0000000
--- 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 d86c03b..0000000
--- 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 f530e0d..0000000
--- a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp
+++ /dev/null
@@ -1,190 +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__)
-
-bool LoadAssemblyInto(Module *M, const char *assembly) {
- SMDiagnostic Error;
- bool success =
- nullptr != ParseAssemblyString(assembly, M, Error, M->getContext());
- std::string errMsg;
- raw_string_ostream os(errMsg);
- Error.print("", os);
- EXPECT_TRUE(success) << os.str();
- return success;
-}
-
-void createModule1(LLVMContext &Context1, Module *&M1, Function *&FooF1) {
- M1 = new Module("test1", Context1);
- LoadAssemblyInto(M1,
- "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 = M1->getFunction("foo1");
-}
-
-void createModule2(LLVMContext &Context2, Module *&M2, Function *&FooF2) {
- M2 = new Module("test2", Context2);
- LoadAssemblyInto(M2,
- "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 = M2->getFunction("foo2");
-}
-
-TEST(MultiJitTest, EagerMode) {
- LLVMContext Context1;
- Module *M1 = nullptr;
- Function *FooF1 = nullptr;
- createModule1(Context1, M1, FooF1);
-
- LLVMContext Context2;
- Module *M2 = nullptr;
- Function *FooF2 = nullptr;
- createModule2(Context2, M2, FooF2);
-
- // Now we create the JIT in eager mode
- std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create());
- EE1->DisableLazyCompilation(true);
- std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(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;
- Module *M1 = nullptr;
- Function *FooF1 = nullptr;
- createModule1(Context1, M1, FooF1);
-
- LLVMContext Context2;
- Module *M2 = nullptr;
- Function *FooF2 = nullptr;
- createModule2(Context2, M2, FooF2);
-
- // Now we create the JIT in lazy mode
- std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create());
- EE1->DisableLazyCompilation(false);
- std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(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;
- Module *M1 = nullptr;
- Function *FooF1 = nullptr;
- createModule1(Context1, M1, FooF1);
-
- LLVMContext Context2;
- Module *M2 = nullptr;
- Function *FooF2 = nullptr;
- createModule2(Context2, M2, FooF2);
-
- // Now we create two JITs
- std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create());
- std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(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 7057fca..0000000
--- 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 afa3f2a..b10cbb4 100644
--- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
+++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
@@ -3,7 +3,7 @@ set(LLVM_LINK_COMPONENTS
Core
ExecutionEngine
IPO
- JIT
+ MC
MCJIT
ScalarOpts
Support
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
index d03de89..c80b88b 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
@@ -139,8 +139,6 @@ protected:
// The operating systems below are known to be sufficiently incompatible
// that they will fail the MCJIT C API tests.
- UnsupportedOSs.push_back(Triple::Cygwin);
-
UnsupportedEnvironments.push_back(Triple::Cygnus);
}
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
index 98587f7..0582c92 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/MCJITMultipleModuleTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp
index c5ca36e..b0d1bb3 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp
@@ -94,8 +94,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_case) {
Function *FA, *FB;
createTwoModuleCase(A, FA, B, FB);
- createJIT(A.release());
- TheJIT->addModule(B.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
checkAdd(ptr);
@@ -114,8 +114,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) {
Function *FA, *FB;
createTwoModuleCase(A, FA, B, FB);
- createJIT(A.release());
- TheJIT->addModule(B.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
TheJIT->finalizeObject();
@@ -135,8 +135,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) {
Function *FA, *FB;
createTwoModuleExternCase(A, FA, B, FB);
- createJIT(A.release());
- TheJIT->addModule(B.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
TheJIT->finalizeObject();
@@ -156,8 +156,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_case) {
Function *FA, *FB;
createTwoModuleExternCase(A, FA, B, FB);
- createJIT(A.release());
- TheJIT->addModule(B.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
checkAdd(ptr);
@@ -177,8 +177,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) {
createTwoModuleExternCase(A, FA1, B, FB);
FA2 = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(A.get(), FA1);
- createJIT(A.release());
- TheJIT->addModule(B.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
TheJIT->finalizeObject();
@@ -213,8 +213,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) {
FB = startFunction<int32_t(void)>(B.get(), "FB");
endFunctionWithRet(FB, Builder.CreateLoad(GVB));
- createJIT(A.release());
- TheJIT->addModule(B.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str());
TheJIT->finalizeObject();
@@ -241,9 +241,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_case) {
Function *FA, *FB, *FC;
createThreeModuleCase(A, FA, B, FB, C, FC);
- createJIT(A.release());
- TheJIT->addModule(B.release());
- TheJIT->addModule(C.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+ TheJIT->addModule(std::move(C));
uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
checkAdd(ptr);
@@ -266,9 +266,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) {
Function *FA, *FB, *FC;
createThreeModuleCase(A, FA, B, FB, C, FC);
- createJIT(A.release());
- TheJIT->addModule(B.release());
- TheJIT->addModule(C.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+ TheJIT->addModule(std::move(C));
uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
checkAdd(ptr);
@@ -291,9 +291,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_chain_case) {
Function *FA, *FB, *FC;
createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
- createJIT(A.release());
- TheJIT->addModule(B.release());
- TheJIT->addModule(C.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+ TheJIT->addModule(std::move(C));
uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
checkAdd(ptr);
@@ -316,9 +316,9 @@ TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) {
Function *FA, *FB, *FC;
createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
- createJIT(A.release());
- TheJIT->addModule(B.release());
- TheJIT->addModule(C.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+ TheJIT->addModule(std::move(C));
uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
checkAdd(ptr);
@@ -341,8 +341,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) {
Function *FA, *FB1, *FB2;
createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
- createJIT(A.release());
- TheJIT->addModule(B.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
checkAccumulate(ptr);
@@ -362,8 +362,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) {
Function *FA, *FB1, *FB2;
createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
- createJIT(A.release());
- TheJIT->addModule(B.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
checkAccumulate(ptr);
@@ -383,8 +383,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) {
Function *FA, *FB1, *FB2;
createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
- createJIT(A.release());
- TheJIT->addModule(B.release());
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
checkAccumulate(ptr);
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
index fbbab42..2736383 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"
@@ -25,17 +24,7 @@ class TestObjectCache : public ObjectCache {
public:
TestObjectCache() : DuplicateInserted(false) { }
- virtual ~TestObjectCache() {
- // Free any buffers we've allocated.
- SmallVectorImpl<MemoryBuffer *>::iterator it, end;
- end = AllocatedBuffers.end();
- for (it = AllocatedBuffers.begin(); it != end; ++it) {
- delete *it;
- }
- AllocatedBuffers.clear();
- }
-
- virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) {
+ void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override {
// If we've seen this module before, note that.
const std::string ModuleID = M->getModuleIdentifier();
if (ObjMap.find(ModuleID) != ObjMap.end())
@@ -44,7 +33,7 @@ public:
ObjMap[ModuleID] = copyBuffer(Obj);
}
- virtual MemoryBuffer* getObject(const Module* M) {
+ virtual std::unique_ptr<MemoryBuffer> getObject(const Module* M) override {
const MemoryBuffer* BufferFound = getObjectInternal(M);
ModulesLookedUp.insert(M->getModuleIdentifier());
if (!BufferFound)
@@ -72,16 +61,18 @@ public:
}
private:
- MemoryBuffer *copyBuffer(const MemoryBuffer *Buf) {
+ MemoryBuffer *copyBuffer(MemoryBufferRef Buf) {
// Create a local copy of the buffer.
- MemoryBuffer *NewBuffer = MemoryBuffer::getMemBufferCopy(Buf->getBuffer());
- AllocatedBuffers.push_back(NewBuffer);
- return NewBuffer;
+ std::unique_ptr<MemoryBuffer> NewBuffer =
+ MemoryBuffer::getMemBufferCopy(Buf.getBuffer());
+ MemoryBuffer *Ret = NewBuffer.get();
+ AllocatedBuffers.push_back(std::move(NewBuffer));
+ return Ret;
}
StringMap<const MemoryBuffer *> ObjMap;
StringSet<> ModulesLookedUp;
- SmallVector<MemoryBuffer *, 2> AllocatedBuffers;
+ SmallVector<std::unique_ptr<MemoryBuffer>, 2> AllocatedBuffers;
bool DuplicateInserted;
};
@@ -121,7 +112,7 @@ protected:
TEST_F(MCJITObjectCacheTest, SetNullObjectCache) {
SKIP_UNSUPPORTED_PLATFORM;
- createJIT(M.release());
+ createJIT(std::move(M));
TheJIT->setObjectCache(nullptr);
@@ -137,7 +128,7 @@ TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) {
// Save a copy of the module pointer before handing it off to MCJIT.
const Module * SavedModulePointer = M.get();
- createJIT(M.release());
+ createJIT(std::move(M));
TheJIT->setObjectCache(Cache.get());
@@ -164,7 +155,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) {
std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);
// Compile this module with an MCJIT engine
- createJIT(M.release());
+ createJIT(std::move(M));
TheJIT->setObjectCache(Cache.get());
TheJIT->finalizeObject();
@@ -181,7 +172,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) {
const Module * SecondModulePointer = M.get();
// Create a new MCJIT instance to load this module then execute it.
- createJIT(M.release());
+ createJIT(std::move(M));
TheJIT->setObjectCache(Cache.get());
compileAndRun();
@@ -198,7 +189,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) {
std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);
// Compile this module with an MCJIT engine
- createJIT(M.release());
+ createJIT(std::move(M));
TheJIT->setObjectCache(Cache.get());
TheJIT->finalizeObject();
@@ -216,7 +207,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) {
const Module * SecondModulePointer = M.get();
// Create a new MCJIT instance to load this module then execute it.
- createJIT(M.release());
+ createJIT(std::move(M));
TheJIT->setObjectCache(Cache.get());
// Verify that our object cache does not contain the module yet.
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
index c37c1d1..64d8c2f 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
@@ -49,7 +49,7 @@ TEST_F(MCJITTest, global_variable) {
int initialValue = 5;
GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue);
- createJIT(M.release());
+ createJIT(std::move(M));
void *globalPtr = TheJIT->getPointerToGlobal(Global);
EXPECT_TRUE(nullptr != globalPtr)
<< "Unable to get pointer to global value from JIT";
@@ -62,7 +62,7 @@ TEST_F(MCJITTest, add_function) {
SKIP_UNSUPPORTED_PLATFORM;
Function *F = insertAddFunction(M.get());
- createJIT(M.release());
+ createJIT(std::move(M));
uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str());
EXPECT_TRUE(0 != addPtr)
<< "Unable to get pointer to function from JIT";
@@ -83,7 +83,7 @@ TEST_F(MCJITTest, run_main) {
int rc = 6;
Function *Main = insertMainFunction(M.get(), 6);
- createJIT(M.release());
+ createJIT(std::move(M));
uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str());
EXPECT_TRUE(0 != ptr)
<< "Unable to get pointer to main() from JIT";
@@ -104,7 +104,7 @@ TEST_F(MCJITTest, return_global) {
Value *ReadGlobal = Builder.CreateLoad(GV);
endFunctionWithRet(ReturnGlobal, ReadGlobal);
- createJIT(M.release());
+ createJIT(std::move(M));
uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str());
EXPECT_TRUE(0 != rgvPtr);
@@ -175,7 +175,7 @@ TEST_F(MCJITTest, multiple_functions) {
Inner = Outer;
}
- createJIT(M.release());
+ createJIT(std::move(M));
uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str());
EXPECT_TRUE(0 != ptr)
<< "Unable to get pointer to outer function from JIT";
@@ -187,4 +187,16 @@ TEST_F(MCJITTest, multiple_functions) {
#endif /*!defined(__arm__)*/
+TEST_F(MCJITTest, multiple_decl_lookups) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ Function *Foo = insertExternalReferenceToFunction<void(void)>(M.get(), "_exit");
+ createJIT(std::move(M));
+ void *A = TheJIT->getPointerToFunction(Foo);
+ void *B = TheJIT->getPointerToFunction(Foo);
+
+ EXPECT_TRUE(A != 0) << "Failed lookup - test not correctly configured.";
+ EXPECT_EQ(A, B) << "Repeat calls to getPointerToFunction fail.";
+}
+
}
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h
index a48c071..7d704de 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h
+++ b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef MCJIT_TEST_API_COMMON_H
-#define MCJIT_TEST_API_COMMON_H
+#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H
+#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
@@ -93,5 +93,5 @@ protected:
} // namespace llvm
-#endif // MCJIT_TEST_API_COMMON_H
+#endif
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
index 25de312..eea88bb 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
+++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
@@ -14,8 +14,8 @@
//===----------------------------------------------------------------------===//
-#ifndef MCJIT_TEST_BASE_H
-#define MCJIT_TEST_BASE_H
+#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
+#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
#include "MCJITTestAPICommon.h"
#include "llvm/Config/config.h"
@@ -107,6 +107,15 @@ protected:
return Result;
}
+ // Inserts a declaration to a function defined elsewhere
+ template <typename FuncType>
+ Function *insertExternalReferenceToFunction(Module *M, StringRef Name) {
+ Function *Result = Function::Create(
+ TypeBuilder<FuncType, false>::get(Context),
+ GlobalValue::ExternalLinkage, Name, M);
+ return Result;
+ }
+
// Inserts an declaration to a function defined elsewhere
Function *insertExternalReferenceToFunction(Module *M, StringRef Name,
FunctionType *FuncTy) {
@@ -302,26 +311,23 @@ protected:
// The operating systems below are known to be incompatible with MCJIT as
// they are copied from the test/ExecutionEngine/MCJIT/lit.local.cfg and
// should be kept in sync.
- UnsupportedOSs.push_back(Triple::Cygwin);
UnsupportedOSs.push_back(Triple::Darwin);
UnsupportedEnvironments.push_back(Triple::Cygnus);
}
- void createJIT(Module *M) {
+ void createJIT(std::unique_ptr<Module> M) {
// Due to the EngineBuilder constructor, it is required to have a Module
// in order to construct an ExecutionEngine (i.e. MCJIT)
assert(M != 0 && "a non-null Module must be provided to create MCJIT");
- EngineBuilder EB(M);
+ 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)
@@ -345,4 +351,4 @@ protected:
} // namespace llvm
-#endif // MCJIT_TEST_H
+#endif
diff --git a/unittests/ExecutionEngine/MCJIT/Makefile b/unittests/ExecutionEngine/MCJIT/Makefile
index c4dd740..2822b20 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 38e667f..8ecb883 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