You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
@ -1,32 +0,0 @@
|
||||
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
Core
|
||||
ExecutionEngine
|
||||
Object
|
||||
OrcJIT
|
||||
RuntimeDyld
|
||||
Support
|
||||
native
|
||||
)
|
||||
|
||||
add_llvm_unittest(OrcJITTests
|
||||
CompileOnDemandLayerTest.cpp
|
||||
IndirectionUtilsTest.cpp
|
||||
GlobalMappingLayerTest.cpp
|
||||
LazyEmittingLayerTest.cpp
|
||||
ObjectTransformLayerTest.cpp
|
||||
OrcCAPITest.cpp
|
||||
OrcTestCommon.cpp
|
||||
QueueChannel.cpp
|
||||
RemoteObjectLayerTest.cpp
|
||||
RPCUtilsTest.cpp
|
||||
RTDyldObjectLinkingLayerTest.cpp
|
||||
SymbolStringPoolTest.cpp
|
||||
)
|
||||
|
||||
set(ORC_JIT_TEST_LIBS ${LLVM_PTHREAD_LIB})
|
||||
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
|
||||
list(APPEND ORC_JIT_TEST_LIBS atomic)
|
||||
endif()
|
||||
|
||||
target_link_libraries(OrcJITTests PRIVATE ${ORC_JIT_TEST_LIBS})
|
@ -1,71 +0,0 @@
|
||||
//===----- CompileOnDemandLayerTest.cpp - Unit tests for the COD layer ----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
|
||||
#include "OrcTestCommon.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::orc;
|
||||
|
||||
namespace {
|
||||
|
||||
class DummyCallbackManager : public orc::JITCompileCallbackManager {
|
||||
public:
|
||||
DummyCallbackManager() : JITCompileCallbackManager(0) {}
|
||||
|
||||
public:
|
||||
Error grow() override { llvm_unreachable("not implemented"); }
|
||||
};
|
||||
|
||||
class DummyStubsManager : public orc::IndirectStubsManager {
|
||||
public:
|
||||
Error createStub(StringRef StubName, JITTargetAddress InitAddr,
|
||||
JITSymbolFlags Flags) override {
|
||||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
|
||||
Error createStubs(const StubInitsMap &StubInits) override {
|
||||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
|
||||
JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
|
||||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
|
||||
JITSymbol findPointer(StringRef Name) override {
|
||||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
|
||||
Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
|
||||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
};
|
||||
|
||||
TEST(CompileOnDemandLayerTest, FindSymbol) {
|
||||
MockBaseLayer<int, std::shared_ptr<Module>> TestBaseLayer;
|
||||
TestBaseLayer.findSymbolImpl =
|
||||
[](const std::string &Name, bool) {
|
||||
if (Name == "foo")
|
||||
return JITSymbol(1, JITSymbolFlags::Exported);
|
||||
return JITSymbol(nullptr);
|
||||
};
|
||||
|
||||
DummyCallbackManager CallbackMgr;
|
||||
|
||||
llvm::orc::CompileOnDemandLayer<decltype(TestBaseLayer)> COD(
|
||||
TestBaseLayer, [](Function &F) { return std::set<Function *>{&F}; },
|
||||
CallbackMgr, [] { return llvm::make_unique<DummyStubsManager>(); }, true);
|
||||
|
||||
auto Sym = COD.findSymbol("foo", true);
|
||||
|
||||
EXPECT_TRUE(!!Sym) << "CompileOnDemand::findSymbol should call findSymbol in "
|
||||
"the base layer.";
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
//===--- GlobalMappingLayerTest.cpp - Unit test the global mapping layer --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/GlobalMappingLayer.h"
|
||||
#include "OrcTestCommon.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::orc;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(GlobalMappingLayerTest, Empty) {
|
||||
MockBaseLayer<int, std::shared_ptr<Module>> TestBaseLayer;
|
||||
|
||||
TestBaseLayer.addModuleImpl =
|
||||
[](std::shared_ptr<Module> M, std::shared_ptr<JITSymbolResolver> R) {
|
||||
return 42;
|
||||
};
|
||||
|
||||
TestBaseLayer.findSymbolImpl =
|
||||
[](const std::string &Name, bool ExportedSymbolsOnly) -> JITSymbol {
|
||||
if (Name == "bar")
|
||||
return llvm::JITSymbol(0x4567, JITSymbolFlags::Exported);
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
GlobalMappingLayer<decltype(TestBaseLayer)> L(TestBaseLayer);
|
||||
|
||||
// Test addModule interface.
|
||||
int H = cantFail(L.addModule(nullptr, nullptr));
|
||||
EXPECT_EQ(H, 42) << "Incorrect result from addModule";
|
||||
|
||||
// Test fall-through for missing symbol.
|
||||
auto FooSym = L.findSymbol("foo", true);
|
||||
EXPECT_FALSE(FooSym) << "Found unexpected symbol.";
|
||||
|
||||
// Test fall-through for symbol in base layer.
|
||||
auto BarSym = L.findSymbol("bar", true);
|
||||
EXPECT_EQ(cantFail(BarSym.getAddress()),
|
||||
static_cast<JITTargetAddress>(0x4567))
|
||||
<< "Symbol lookup fall-through failed.";
|
||||
|
||||
// Test setup of a global mapping.
|
||||
L.setGlobalMapping("foo", 0x0123);
|
||||
auto FooSym2 = L.findSymbol("foo", true);
|
||||
EXPECT_EQ(cantFail(FooSym2.getAddress()),
|
||||
static_cast<JITTargetAddress>(0x0123))
|
||||
<< "Symbol mapping setup failed.";
|
||||
|
||||
// Test removal of a global mapping.
|
||||
L.eraseGlobalMapping("foo");
|
||||
auto FooSym3 = L.findSymbol("foo", true);
|
||||
EXPECT_FALSE(FooSym3) << "Symbol mapping removal failed.";
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
//===- LazyEmittingLayerTest.cpp - Unit tests for the lazy emitting layer -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
|
||||
#include "OrcTestCommon.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(IndirectionUtilsTest, MakeStub) {
|
||||
LLVMContext Context;
|
||||
ModuleBuilder MB(Context, "x86_64-apple-macosx10.10", "");
|
||||
Function *F = MB.createFunctionDecl<void(DummyStruct, DummyStruct)>("");
|
||||
AttributeSet FnAttrs = AttributeSet::get(
|
||||
Context, AttrBuilder().addAttribute(Attribute::NoUnwind));
|
||||
AttributeSet RetAttrs; // None
|
||||
AttributeSet ArgAttrs[2] = {
|
||||
AttributeSet::get(Context,
|
||||
AttrBuilder().addAttribute(Attribute::StructRet)),
|
||||
AttributeSet::get(Context, AttrBuilder().addAttribute(Attribute::ByVal)),
|
||||
};
|
||||
F->setAttributes(AttributeList::get(Context, FnAttrs, RetAttrs, ArgAttrs));
|
||||
|
||||
auto ImplPtr = orc::createImplPointer(*F->getType(), *MB.getModule(), "", nullptr);
|
||||
orc::makeStub(*F, *ImplPtr);
|
||||
|
||||
auto II = F->getEntryBlock().begin();
|
||||
EXPECT_TRUE(isa<LoadInst>(*II)) << "First instruction of stub should be a load.";
|
||||
auto *Call = dyn_cast<CallInst>(std::next(II));
|
||||
EXPECT_TRUE(Call != nullptr) << "Second instruction of stub should be a call.";
|
||||
EXPECT_TRUE(Call->isTailCall()) << "Indirect call from stub should be tail call.";
|
||||
EXPECT_TRUE(Call->hasStructRetAttr())
|
||||
<< "makeStub should propagate sret attr on 1st argument.";
|
||||
EXPECT_TRUE(Call->paramHasAttr(1U, Attribute::ByVal))
|
||||
<< "makeStub should propagate byval attr on 2nd argument.";
|
||||
}
|
||||
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
//===- LazyEmittingLayerTest.cpp - Unit tests for the lazy emitting layer -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
|
||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct MockBaseLayer {
|
||||
typedef int ModuleHandleT;
|
||||
ModuleHandleT addModule(
|
||||
std::shared_ptr<llvm::Module>,
|
||||
std::unique_ptr<llvm::RuntimeDyld::MemoryManager> MemMgr,
|
||||
std::unique_ptr<llvm::JITSymbolResolver> Resolver) {
|
||||
EXPECT_FALSE(MemMgr);
|
||||
return 42;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(LazyEmittingLayerTest, Empty) {
|
||||
MockBaseLayer M;
|
||||
llvm::orc::LazyEmittingLayer<MockBaseLayer> L(M);
|
||||
cantFail(L.addModule(std::unique_ptr<llvm::Module>(), nullptr));
|
||||
}
|
||||
|
||||
}
|
@ -1,326 +0,0 @@
|
||||
//===- ObjectTransformLayerTest.cpp - Unit tests for ObjectTransformLayer -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/NullResolver.h"
|
||||
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
|
||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm::orc;
|
||||
|
||||
namespace {
|
||||
|
||||
// stand-in for object::ObjectFile
|
||||
typedef int MockObjectFile;
|
||||
|
||||
// stand-in for llvm::MemoryBuffer set
|
||||
typedef int MockMemoryBuffer;
|
||||
|
||||
// Mock transform that operates on unique pointers to object files, and
|
||||
// allocates new object files rather than mutating the given ones.
|
||||
struct AllocatingTransform {
|
||||
std::shared_ptr<MockObjectFile>
|
||||
operator()(std::shared_ptr<MockObjectFile> Obj) const {
|
||||
return std::make_shared<MockObjectFile>(*Obj + 1);
|
||||
}
|
||||
};
|
||||
|
||||
// Mock base layer for verifying behavior of transform layer.
|
||||
// Each method "T foo(args)" is accompanied by two auxiliary methods:
|
||||
// - "void expectFoo(args)", to be called before calling foo on the transform
|
||||
// layer; saves values of args, which mock layer foo then verifies against.
|
||||
// - "void verifyFoo(T)", to be called after foo, which verifies that the
|
||||
// transform layer called the base layer and forwarded any return value.
|
||||
class MockBaseLayer {
|
||||
public:
|
||||
typedef int ObjHandleT;
|
||||
|
||||
MockBaseLayer() : MockSymbol(nullptr) { resetExpectations(); }
|
||||
|
||||
template <typename ObjPtrT>
|
||||
llvm::Expected<ObjHandleT>
|
||||
addObject(ObjPtrT Obj,
|
||||
std::shared_ptr<llvm::JITSymbolResolver> Resolver) {
|
||||
EXPECT_EQ(MockResolver, Resolver) << "Resolver should pass through";
|
||||
EXPECT_EQ(MockObject + 1, *Obj) << "Transform should be applied";
|
||||
LastCalled = "addObject";
|
||||
MockObjHandle = 111;
|
||||
return MockObjHandle;
|
||||
}
|
||||
|
||||
template <typename ObjPtrT>
|
||||
void expectAddObject(ObjPtrT Obj,
|
||||
std::shared_ptr<llvm::JITSymbolResolver> Resolver) {
|
||||
MockResolver = Resolver;
|
||||
MockObject = *Obj;
|
||||
}
|
||||
|
||||
|
||||
void verifyAddObject(ObjHandleT Returned) {
|
||||
EXPECT_EQ("addObject", LastCalled);
|
||||
EXPECT_EQ(MockObjHandle, Returned) << "Return should pass through";
|
||||
resetExpectations();
|
||||
}
|
||||
|
||||
llvm::Error removeObject(ObjHandleT H) {
|
||||
EXPECT_EQ(MockObjHandle, H);
|
||||
LastCalled = "removeObject";
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
void expectRemoveObject(ObjHandleT H) { MockObjHandle = H; }
|
||||
void verifyRemoveObject() {
|
||||
EXPECT_EQ("removeObject", LastCalled);
|
||||
resetExpectations();
|
||||
}
|
||||
|
||||
llvm::JITSymbol findSymbol(const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
EXPECT_EQ(MockName, Name) << "Name should pass through";
|
||||
EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
|
||||
LastCalled = "findSymbol";
|
||||
MockSymbol = llvm::JITSymbol(122, llvm::JITSymbolFlags::None);
|
||||
return llvm::JITSymbol(122, llvm::JITSymbolFlags::None);
|
||||
}
|
||||
void expectFindSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
|
||||
MockName = Name;
|
||||
MockBool = ExportedSymbolsOnly;
|
||||
}
|
||||
void verifyFindSymbol(llvm::JITSymbol Returned) {
|
||||
EXPECT_EQ("findSymbol", LastCalled);
|
||||
EXPECT_EQ(cantFail(MockSymbol.getAddress()),
|
||||
cantFail(Returned.getAddress()))
|
||||
<< "Return should pass through";
|
||||
resetExpectations();
|
||||
}
|
||||
|
||||
llvm::JITSymbol findSymbolIn(ObjHandleT H, const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
EXPECT_EQ(MockObjHandle, H) << "Handle should pass through";
|
||||
EXPECT_EQ(MockName, Name) << "Name should pass through";
|
||||
EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
|
||||
LastCalled = "findSymbolIn";
|
||||
MockSymbol = llvm::JITSymbol(122, llvm::JITSymbolFlags::None);
|
||||
return llvm::JITSymbol(122, llvm::JITSymbolFlags::None);
|
||||
}
|
||||
void expectFindSymbolIn(ObjHandleT H, const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
MockObjHandle = H;
|
||||
MockName = Name;
|
||||
MockBool = ExportedSymbolsOnly;
|
||||
}
|
||||
void verifyFindSymbolIn(llvm::JITSymbol Returned) {
|
||||
EXPECT_EQ("findSymbolIn", LastCalled);
|
||||
EXPECT_EQ(cantFail(MockSymbol.getAddress()),
|
||||
cantFail(Returned.getAddress()))
|
||||
<< "Return should pass through";
|
||||
resetExpectations();
|
||||
}
|
||||
|
||||
llvm::Error emitAndFinalize(ObjHandleT H) {
|
||||
EXPECT_EQ(MockObjHandle, H) << "Handle should pass through";
|
||||
LastCalled = "emitAndFinalize";
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
void expectEmitAndFinalize(ObjHandleT H) { MockObjHandle = H; }
|
||||
|
||||
void verifyEmitAndFinalize() {
|
||||
EXPECT_EQ("emitAndFinalize", LastCalled);
|
||||
resetExpectations();
|
||||
}
|
||||
|
||||
void mapSectionAddress(ObjHandleT H, const void *LocalAddress,
|
||||
llvm::JITTargetAddress TargetAddr) {
|
||||
EXPECT_EQ(MockObjHandle, H);
|
||||
EXPECT_EQ(MockLocalAddress, LocalAddress);
|
||||
EXPECT_EQ(MockTargetAddress, TargetAddr);
|
||||
LastCalled = "mapSectionAddress";
|
||||
}
|
||||
void expectMapSectionAddress(ObjHandleT H, const void *LocalAddress,
|
||||
llvm::JITTargetAddress TargetAddr) {
|
||||
MockObjHandle = H;
|
||||
MockLocalAddress = LocalAddress;
|
||||
MockTargetAddress = TargetAddr;
|
||||
}
|
||||
void verifyMapSectionAddress() {
|
||||
EXPECT_EQ("mapSectionAddress", LastCalled);
|
||||
resetExpectations();
|
||||
}
|
||||
|
||||
private:
|
||||
// Backing fields for remembering parameter/return values
|
||||
std::string LastCalled;
|
||||
std::shared_ptr<llvm::JITSymbolResolver> MockResolver;
|
||||
MockObjectFile MockObject;
|
||||
ObjHandleT MockObjHandle;
|
||||
std::string MockName;
|
||||
bool MockBool;
|
||||
llvm::JITSymbol MockSymbol;
|
||||
const void *MockLocalAddress;
|
||||
llvm::JITTargetAddress MockTargetAddress;
|
||||
MockMemoryBuffer MockBuffer;
|
||||
|
||||
// Clear remembered parameters between calls
|
||||
void resetExpectations() {
|
||||
LastCalled = "nothing";
|
||||
MockResolver = nullptr;
|
||||
MockObject = 0;
|
||||
MockObjHandle = 0;
|
||||
MockName = "bogus";
|
||||
MockSymbol = llvm::JITSymbol(nullptr);
|
||||
MockLocalAddress = nullptr;
|
||||
MockTargetAddress = 0;
|
||||
MockBuffer = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Test each operation on ObjectTransformLayer.
|
||||
TEST(ObjectTransformLayerTest, Main) {
|
||||
MockBaseLayer M;
|
||||
|
||||
// Create one object transform layer using a transform (as a functor)
|
||||
// that allocates new objects, and deals in unique pointers.
|
||||
ObjectTransformLayer<MockBaseLayer, AllocatingTransform> T1(M);
|
||||
|
||||
// Create a second object transform layer using a transform (as a lambda)
|
||||
// that mutates objects in place, and deals in naked pointers
|
||||
ObjectTransformLayer<MockBaseLayer,
|
||||
std::function<std::shared_ptr<MockObjectFile>(
|
||||
std::shared_ptr<MockObjectFile>)>>
|
||||
T2(M, [](std::shared_ptr<MockObjectFile> Obj) {
|
||||
++(*Obj);
|
||||
return Obj;
|
||||
});
|
||||
|
||||
// Test addObject with T1 (allocating)
|
||||
auto Obj1 = std::make_shared<MockObjectFile>(211);
|
||||
auto SR = std::make_shared<NullResolver>();
|
||||
M.expectAddObject(Obj1, SR);
|
||||
auto H = cantFail(T1.addObject(std::move(Obj1), SR));
|
||||
M.verifyAddObject(H);
|
||||
|
||||
// Test addObjectSet with T2 (mutating)
|
||||
auto Obj2 = std::make_shared<MockObjectFile>(222);
|
||||
M.expectAddObject(Obj2, SR);
|
||||
H = cantFail(T2.addObject(Obj2, SR));
|
||||
M.verifyAddObject(H);
|
||||
EXPECT_EQ(223, *Obj2) << "Expected mutation";
|
||||
|
||||
// Test removeObjectSet
|
||||
M.expectRemoveObject(H);
|
||||
cantFail(T1.removeObject(H));
|
||||
M.verifyRemoveObject();
|
||||
|
||||
// Test findSymbol
|
||||
std::string Name = "foo";
|
||||
bool ExportedOnly = true;
|
||||
M.expectFindSymbol(Name, ExportedOnly);
|
||||
llvm::JITSymbol Sym1 = T2.findSymbol(Name, ExportedOnly);
|
||||
M.verifyFindSymbol(std::move(Sym1));
|
||||
|
||||
// Test findSymbolIn
|
||||
Name = "bar";
|
||||
ExportedOnly = false;
|
||||
M.expectFindSymbolIn(H, Name, ExportedOnly);
|
||||
llvm::JITSymbol Sym2 = T1.findSymbolIn(H, Name, ExportedOnly);
|
||||
M.verifyFindSymbolIn(std::move(Sym2));
|
||||
|
||||
// Test emitAndFinalize
|
||||
M.expectEmitAndFinalize(H);
|
||||
cantFail(T2.emitAndFinalize(H));
|
||||
M.verifyEmitAndFinalize();
|
||||
|
||||
// Test mapSectionAddress
|
||||
char Buffer[24];
|
||||
llvm::JITTargetAddress MockAddress = 255;
|
||||
M.expectMapSectionAddress(H, Buffer, MockAddress);
|
||||
T1.mapSectionAddress(H, Buffer, MockAddress);
|
||||
M.verifyMapSectionAddress();
|
||||
|
||||
// Verify transform getter (non-const)
|
||||
auto Mutatee = std::make_shared<MockObjectFile>(277);
|
||||
auto Out = T2.getTransform()(Mutatee);
|
||||
EXPECT_EQ(*Mutatee, *Out) << "Expected in-place transform";
|
||||
EXPECT_EQ(278, *Mutatee) << "Expected incrementing transform";
|
||||
|
||||
// Verify transform getter (const)
|
||||
auto OwnedObj = std::make_shared<MockObjectFile>(288);
|
||||
const auto &T1C = T1;
|
||||
OwnedObj = T1C.getTransform()(std::move(OwnedObj));
|
||||
EXPECT_EQ(289, *OwnedObj) << "Expected incrementing transform";
|
||||
|
||||
volatile bool RunStaticChecks = false;
|
||||
if (!RunStaticChecks)
|
||||
return;
|
||||
|
||||
// Make sure that ObjectTransformLayer implements the object layer concept
|
||||
// correctly by sandwitching one between an ObjectLinkingLayer and an
|
||||
// IRCompileLayer, verifying that it compiles if we have a call to the
|
||||
// IRComileLayer's addModule that should call the transform layer's
|
||||
// addObject, and also calling the other public transform layer methods
|
||||
// directly to make sure the methods they intend to forward to exist on
|
||||
// the ObjectLinkingLayer.
|
||||
|
||||
// We'll need a concrete MemoryManager class.
|
||||
class NullManager : public llvm::RuntimeDyld::MemoryManager {
|
||||
public:
|
||||
uint8_t *allocateCodeSection(uintptr_t, unsigned, unsigned,
|
||||
llvm::StringRef) override {
|
||||
return nullptr;
|
||||
}
|
||||
uint8_t *allocateDataSection(uintptr_t, unsigned, unsigned, llvm::StringRef,
|
||||
bool) override {
|
||||
return nullptr;
|
||||
}
|
||||
void registerEHFrames(uint8_t *, uint64_t, size_t) override {}
|
||||
void deregisterEHFrames() override {}
|
||||
bool finalizeMemory(std::string *) override { return false; }
|
||||
};
|
||||
|
||||
// Construct the jit layers.
|
||||
RTDyldObjectLinkingLayer BaseLayer(
|
||||
[]() {
|
||||
return std::make_shared<llvm::SectionMemoryManager>();
|
||||
});
|
||||
|
||||
auto IdentityTransform =
|
||||
[](std::shared_ptr<llvm::object::OwningBinary<llvm::object::ObjectFile>>
|
||||
Obj) {
|
||||
return Obj;
|
||||
};
|
||||
ObjectTransformLayer<decltype(BaseLayer), decltype(IdentityTransform)>
|
||||
TransformLayer(BaseLayer, IdentityTransform);
|
||||
auto NullCompiler = [](llvm::Module &) {
|
||||
return llvm::object::OwningBinary<llvm::object::ObjectFile>(nullptr,
|
||||
nullptr);
|
||||
};
|
||||
IRCompileLayer<decltype(TransformLayer), decltype(NullCompiler)>
|
||||
CompileLayer(TransformLayer, NullCompiler);
|
||||
|
||||
// Make sure that the calls from IRCompileLayer to ObjectTransformLayer
|
||||
// compile.
|
||||
auto Resolver = std::make_shared<NullResolver>();
|
||||
cantFail(CompileLayer.addModule(std::shared_ptr<llvm::Module>(), Resolver));
|
||||
|
||||
// Make sure that the calls from ObjectTransformLayer to ObjectLinkingLayer
|
||||
// compile.
|
||||
decltype(TransformLayer)::ObjHandleT H2;
|
||||
cantFail(TransformLayer.emitAndFinalize(H2));
|
||||
TransformLayer.findSymbolIn(H2, Name, false);
|
||||
TransformLayer.findSymbol(Name, true);
|
||||
TransformLayer.mapSectionAddress(H2, nullptr, 0);
|
||||
cantFail(TransformLayer.removeObject(H2));
|
||||
}
|
||||
}
|
@ -1,211 +0,0 @@
|
||||
//===--------------- OrcCAPITest.cpp - Unit tests Orc C API ---------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OrcTestCommon.h"
|
||||
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/OrcBindings.h"
|
||||
#include "llvm-c/Target.h"
|
||||
#include "llvm-c/TargetMachine.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
|
||||
|
||||
class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest {
|
||||
protected:
|
||||
std::unique_ptr<Module> createTestModule(const Triple &TT) {
|
||||
ModuleBuilder MB(Context, TT.str(), "");
|
||||
Function *TestFunc = MB.createFunctionDecl<int()>("testFunc");
|
||||
Function *Main = MB.createFunctionDecl<int(int, char*[])>("main");
|
||||
|
||||
Main->getBasicBlockList().push_back(BasicBlock::Create(Context));
|
||||
IRBuilder<> B(&Main->back());
|
||||
Value* Result = B.CreateCall(TestFunc);
|
||||
B.CreateRet(Result);
|
||||
|
||||
return MB.takeModule();
|
||||
}
|
||||
|
||||
std::shared_ptr<object::OwningBinary<object::ObjectFile>>
|
||||
createTestObject() {
|
||||
orc::SimpleCompiler IRCompiler(*TM);
|
||||
auto M = createTestModule(TM->getTargetTriple());
|
||||
M->setDataLayout(TM->createDataLayout());
|
||||
return std::make_shared<object::OwningBinary<object::ObjectFile>>(
|
||||
IRCompiler(*M));
|
||||
}
|
||||
|
||||
typedef int (*MainFnTy)();
|
||||
|
||||
static int myTestFuncImpl() {
|
||||
return 42;
|
||||
}
|
||||
|
||||
static char *testFuncName;
|
||||
|
||||
static uint64_t myResolver(const char *Name, void *Ctx) {
|
||||
if (!strncmp(Name, testFuncName, 8))
|
||||
return (uint64_t)&myTestFuncImpl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct CompileContext {
|
||||
CompileContext() : Compiled(false) { }
|
||||
|
||||
OrcCAPIExecutionTest* APIExecTest;
|
||||
std::unique_ptr<Module> M;
|
||||
LLVMOrcModuleHandle H;
|
||||
bool Compiled;
|
||||
};
|
||||
|
||||
static LLVMOrcTargetAddress myCompileCallback(LLVMOrcJITStackRef JITStack,
|
||||
void *Ctx) {
|
||||
CompileContext *CCtx = static_cast<CompileContext*>(Ctx);
|
||||
auto *ET = CCtx->APIExecTest;
|
||||
CCtx->M = ET->createTestModule(ET->TM->getTargetTriple());
|
||||
LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(CCtx->M.release()));
|
||||
LLVMOrcAddEagerlyCompiledIR(JITStack, &CCtx->H, SM, myResolver, nullptr);
|
||||
LLVMOrcDisposeSharedModuleRef(SM);
|
||||
CCtx->Compiled = true;
|
||||
LLVMOrcTargetAddress MainAddr;
|
||||
LLVMOrcGetSymbolAddress(JITStack, &MainAddr, "main");
|
||||
LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr);
|
||||
return MainAddr;
|
||||
}
|
||||
};
|
||||
|
||||
char *OrcCAPIExecutionTest::testFuncName = nullptr;
|
||||
|
||||
TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
|
||||
if (!TM)
|
||||
return;
|
||||
|
||||
LLVMOrcJITStackRef JIT =
|
||||
LLVMOrcCreateInstance(wrap(TM.get()));
|
||||
|
||||
std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
|
||||
|
||||
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
|
||||
|
||||
LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release()));
|
||||
LLVMOrcModuleHandle H;
|
||||
LLVMOrcAddEagerlyCompiledIR(JIT, &H, SM, myResolver, nullptr);
|
||||
LLVMOrcDisposeSharedModuleRef(SM);
|
||||
LLVMOrcTargetAddress MainAddr;
|
||||
LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
|
||||
MainFnTy MainFn = (MainFnTy)MainAddr;
|
||||
int Result = MainFn();
|
||||
EXPECT_EQ(Result, 42)
|
||||
<< "Eagerly JIT'd code did not return expected result";
|
||||
|
||||
LLVMOrcRemoveModule(JIT, H);
|
||||
|
||||
LLVMOrcDisposeMangledSymbol(testFuncName);
|
||||
LLVMOrcDisposeInstance(JIT);
|
||||
}
|
||||
|
||||
TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
|
||||
if (!TM)
|
||||
return;
|
||||
|
||||
LLVMOrcJITStackRef JIT =
|
||||
LLVMOrcCreateInstance(wrap(TM.get()));
|
||||
|
||||
std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
|
||||
|
||||
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
|
||||
|
||||
LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release()));
|
||||
LLVMOrcModuleHandle H;
|
||||
LLVMOrcAddLazilyCompiledIR(JIT, &H, SM, myResolver, nullptr);
|
||||
LLVMOrcDisposeSharedModuleRef(SM);
|
||||
LLVMOrcTargetAddress MainAddr;
|
||||
LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
|
||||
MainFnTy MainFn = (MainFnTy)MainAddr;
|
||||
int Result = MainFn();
|
||||
EXPECT_EQ(Result, 42)
|
||||
<< "Lazily JIT'd code did not return expected result";
|
||||
|
||||
LLVMOrcRemoveModule(JIT, H);
|
||||
|
||||
LLVMOrcDisposeMangledSymbol(testFuncName);
|
||||
LLVMOrcDisposeInstance(JIT);
|
||||
}
|
||||
|
||||
TEST_F(OrcCAPIExecutionTest, TestAddObjectFile) {
|
||||
if (!TM)
|
||||
return;
|
||||
|
||||
std::unique_ptr<MemoryBuffer> ObjBuffer;
|
||||
{
|
||||
auto OwningObj = createTestObject();
|
||||
auto ObjAndBuffer = OwningObj->takeBinary();
|
||||
ObjBuffer = std::move(ObjAndBuffer.second);
|
||||
}
|
||||
|
||||
LLVMOrcJITStackRef JIT =
|
||||
LLVMOrcCreateInstance(wrap(TM.get()));
|
||||
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
|
||||
|
||||
LLVMOrcModuleHandle H;
|
||||
LLVMOrcAddObjectFile(JIT, &H, wrap(ObjBuffer.release()), myResolver, nullptr);
|
||||
LLVMOrcTargetAddress MainAddr;
|
||||
LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
|
||||
MainFnTy MainFn = (MainFnTy)MainAddr;
|
||||
int Result = MainFn();
|
||||
EXPECT_EQ(Result, 42)
|
||||
<< "Lazily JIT'd code did not return expected result";
|
||||
|
||||
LLVMOrcRemoveModule(JIT, H);
|
||||
|
||||
LLVMOrcDisposeMangledSymbol(testFuncName);
|
||||
LLVMOrcDisposeInstance(JIT);
|
||||
}
|
||||
|
||||
TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
|
||||
if (!TM)
|
||||
return;
|
||||
|
||||
LLVMOrcJITStackRef JIT =
|
||||
LLVMOrcCreateInstance(wrap(TM.get()));
|
||||
|
||||
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
|
||||
|
||||
CompileContext C;
|
||||
C.APIExecTest = this;
|
||||
LLVMOrcTargetAddress CCAddr;
|
||||
LLVMOrcCreateLazyCompileCallback(JIT, &CCAddr, myCompileCallback, &C);
|
||||
LLVMOrcCreateIndirectStub(JIT, "foo", CCAddr);
|
||||
LLVMOrcTargetAddress MainAddr;
|
||||
LLVMOrcGetSymbolAddress(JIT, &MainAddr, "foo");
|
||||
MainFnTy FooFn = (MainFnTy)MainAddr;
|
||||
int Result = FooFn();
|
||||
EXPECT_TRUE(C.Compiled)
|
||||
<< "Function wasn't lazily compiled";
|
||||
EXPECT_EQ(Result, 42)
|
||||
<< "Direct-callback JIT'd code did not return expected result";
|
||||
|
||||
C.Compiled = false;
|
||||
FooFn();
|
||||
EXPECT_FALSE(C.Compiled)
|
||||
<< "Direct-callback JIT'd code was JIT'd twice";
|
||||
|
||||
LLVMOrcRemoveModule(JIT, C.H);
|
||||
|
||||
LLVMOrcDisposeMangledSymbol(testFuncName);
|
||||
LLVMOrcDisposeInstance(JIT);
|
||||
}
|
||||
|
||||
} // namespace llvm
|
@ -1,25 +0,0 @@
|
||||
//===--------- OrcTestCommon.cpp - Utilities for Orc Unit Tests -----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Common utilities for Orc unit tests.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OrcTestCommon.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
bool OrcNativeTarget::NativeTargetInitialized = false;
|
||||
|
||||
ModuleBuilder::ModuleBuilder(LLVMContext &Context, StringRef Triple,
|
||||
StringRef Name)
|
||||
: M(new Module(Name, Context)) {
|
||||
if (Triple != "")
|
||||
M->setTargetTriple(Triple);
|
||||
}
|
@ -1,193 +0,0 @@
|
||||
//===------ OrcTestCommon.h - Utilities for Orc Unit Tests ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Common utilities for the Orc unit tests.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
|
||||
#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
|
||||
|
||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/TypeBuilder.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class OrcNativeTarget {
|
||||
public:
|
||||
static void initialize() {
|
||||
if (!NativeTargetInitialized) {
|
||||
InitializeNativeTarget();
|
||||
InitializeNativeTargetAsmParser();
|
||||
InitializeNativeTargetAsmPrinter();
|
||||
NativeTargetInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static bool NativeTargetInitialized;
|
||||
};
|
||||
|
||||
// Base class for Orc tests that will execute code.
|
||||
class OrcExecutionTest {
|
||||
public:
|
||||
|
||||
OrcExecutionTest() {
|
||||
|
||||
// Initialize the native target if it hasn't been done already.
|
||||
OrcNativeTarget::initialize();
|
||||
|
||||
// Try to select a TargetMachine for the host.
|
||||
TM.reset(EngineBuilder().selectTarget());
|
||||
|
||||
if (TM) {
|
||||
// If we found a TargetMachine, check that it's one that Orc supports.
|
||||
const Triple& TT = TM->getTargetTriple();
|
||||
|
||||
if ((TT.getArch() != Triple::x86_64 && TT.getArch() != Triple::x86) ||
|
||||
TT.isOSWindows())
|
||||
TM = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
LLVMContext Context;
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
};
|
||||
|
||||
class ModuleBuilder {
|
||||
public:
|
||||
ModuleBuilder(LLVMContext &Context, StringRef Triple,
|
||||
StringRef Name);
|
||||
|
||||
template <typename FuncType>
|
||||
Function* createFunctionDecl(StringRef Name) {
|
||||
return Function::Create(
|
||||
TypeBuilder<FuncType, false>::get(M->getContext()),
|
||||
GlobalValue::ExternalLinkage, Name, M.get());
|
||||
}
|
||||
|
||||
Module* getModule() { return M.get(); }
|
||||
const Module* getModule() const { return M.get(); }
|
||||
std::unique_ptr<Module> takeModule() { return std::move(M); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<Module> M;
|
||||
};
|
||||
|
||||
// Dummy struct type.
|
||||
struct DummyStruct {
|
||||
int X[256];
|
||||
};
|
||||
|
||||
// TypeBuilder specialization for DummyStruct.
|
||||
template <bool XCompile>
|
||||
class TypeBuilder<DummyStruct, XCompile> {
|
||||
public:
|
||||
static StructType *get(LLVMContext &Context) {
|
||||
return StructType::get(
|
||||
TypeBuilder<types::i<32>[256], XCompile>::get(Context));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename HandleT, typename ModuleT>
|
||||
class MockBaseLayer {
|
||||
public:
|
||||
|
||||
using ModuleHandleT = HandleT;
|
||||
|
||||
using AddModuleSignature =
|
||||
Expected<ModuleHandleT>(ModuleT M,
|
||||
std::shared_ptr<JITSymbolResolver> R);
|
||||
|
||||
using RemoveModuleSignature = Error(ModuleHandleT H);
|
||||
using FindSymbolSignature = JITSymbol(const std::string &Name,
|
||||
bool ExportedSymbolsOnly);
|
||||
using FindSymbolInSignature = JITSymbol(ModuleHandleT H,
|
||||
const std::string &Name,
|
||||
bool ExportedSymbolsONly);
|
||||
using EmitAndFinalizeSignature = Error(ModuleHandleT H);
|
||||
|
||||
std::function<AddModuleSignature> addModuleImpl;
|
||||
std::function<RemoveModuleSignature> removeModuleImpl;
|
||||
std::function<FindSymbolSignature> findSymbolImpl;
|
||||
std::function<FindSymbolInSignature> findSymbolInImpl;
|
||||
std::function<EmitAndFinalizeSignature> emitAndFinalizeImpl;
|
||||
|
||||
Expected<ModuleHandleT> addModule(ModuleT M,
|
||||
std::shared_ptr<JITSymbolResolver> R) {
|
||||
assert(addModuleImpl &&
|
||||
"addModule called, but no mock implementation was provided");
|
||||
return addModuleImpl(std::move(M), std::move(R));
|
||||
}
|
||||
|
||||
Error removeModule(ModuleHandleT H) {
|
||||
assert(removeModuleImpl &&
|
||||
"removeModule called, but no mock implementation was provided");
|
||||
return removeModuleImpl(H);
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
|
||||
assert(findSymbolImpl &&
|
||||
"findSymbol called, but no mock implementation was provided");
|
||||
return findSymbolImpl(Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
assert(findSymbolInImpl &&
|
||||
"findSymbolIn called, but no mock implementation was provided");
|
||||
return findSymbolInImpl(H, Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
Error emitAndFinaliez(ModuleHandleT H) {
|
||||
assert(emitAndFinalizeImpl &&
|
||||
"emitAndFinalize called, but no mock implementation was provided");
|
||||
return emitAndFinalizeImpl(H);
|
||||
}
|
||||
};
|
||||
|
||||
class ReturnNullJITSymbol {
|
||||
public:
|
||||
template <typename... Args>
|
||||
JITSymbol operator()(Args...) const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ReturnT>
|
||||
class DoNothingAndReturn {
|
||||
public:
|
||||
DoNothingAndReturn(ReturnT Ret) : Ret(std::move(Ret)) {}
|
||||
|
||||
template <typename... Args>
|
||||
void operator()(Args...) const { return Ret; }
|
||||
private:
|
||||
ReturnT Ret;
|
||||
};
|
||||
|
||||
template <>
|
||||
class DoNothingAndReturn<void> {
|
||||
public:
|
||||
template <typename... Args>
|
||||
void operator()(Args...) const { }
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -1,14 +0,0 @@
|
||||
//===-------- QueueChannel.cpp - Unit tests the remote executors ----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "QueueChannel.h"
|
||||
|
||||
char llvm::QueueChannelError::ID;
|
||||
char llvm::QueueChannelClosedError::ID;
|
||||
|
@ -1,146 +0,0 @@
|
||||
//===----------------------- Queue.h - RPC Queue ------------------*-c++-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_QUEUECHANNEL_H
|
||||
#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_QUEUECHANNEL_H
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/RawByteChannel.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <queue>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class QueueChannelError : public ErrorInfo<QueueChannelError> {
|
||||
public:
|
||||
static char ID;
|
||||
};
|
||||
|
||||
class QueueChannelClosedError
|
||||
: public ErrorInfo<QueueChannelClosedError, QueueChannelError> {
|
||||
public:
|
||||
static char ID;
|
||||
std::error_code convertToErrorCode() const override {
|
||||
return inconvertibleErrorCode();
|
||||
}
|
||||
|
||||
void log(raw_ostream &OS) const override {
|
||||
OS << "Queue closed";
|
||||
}
|
||||
};
|
||||
|
||||
class Queue : public std::queue<char> {
|
||||
public:
|
||||
using ErrorInjector = std::function<Error()>;
|
||||
|
||||
Queue()
|
||||
: ReadError([]() { return Error::success(); }),
|
||||
WriteError([]() { return Error::success(); }) {}
|
||||
|
||||
Queue(const Queue&) = delete;
|
||||
Queue& operator=(const Queue&) = delete;
|
||||
Queue(Queue&&) = delete;
|
||||
Queue& operator=(Queue&&) = delete;
|
||||
|
||||
std::mutex &getMutex() { return M; }
|
||||
std::condition_variable &getCondVar() { return CV; }
|
||||
Error checkReadError() { return ReadError(); }
|
||||
Error checkWriteError() { return WriteError(); }
|
||||
void setReadError(ErrorInjector NewReadError) {
|
||||
{
|
||||
std::lock_guard<std::mutex> Lock(M);
|
||||
ReadError = std::move(NewReadError);
|
||||
}
|
||||
CV.notify_one();
|
||||
}
|
||||
void setWriteError(ErrorInjector NewWriteError) {
|
||||
std::lock_guard<std::mutex> Lock(M);
|
||||
WriteError = std::move(NewWriteError);
|
||||
}
|
||||
private:
|
||||
std::mutex M;
|
||||
std::condition_variable CV;
|
||||
std::function<Error()> ReadError, WriteError;
|
||||
};
|
||||
|
||||
class QueueChannel : public orc::rpc::RawByteChannel {
|
||||
public:
|
||||
QueueChannel(std::shared_ptr<Queue> InQueue,
|
||||
std::shared_ptr<Queue> OutQueue)
|
||||
: InQueue(InQueue), OutQueue(OutQueue) {}
|
||||
|
||||
QueueChannel(const QueueChannel&) = delete;
|
||||
QueueChannel& operator=(const QueueChannel&) = delete;
|
||||
QueueChannel(QueueChannel&&) = delete;
|
||||
QueueChannel& operator=(QueueChannel&&) = delete;
|
||||
|
||||
Error readBytes(char *Dst, unsigned Size) override {
|
||||
std::unique_lock<std::mutex> Lock(InQueue->getMutex());
|
||||
while (Size) {
|
||||
{
|
||||
Error Err = InQueue->checkReadError();
|
||||
while (!Err && InQueue->empty()) {
|
||||
InQueue->getCondVar().wait(Lock);
|
||||
Err = InQueue->checkReadError();
|
||||
}
|
||||
if (Err)
|
||||
return Err;
|
||||
}
|
||||
*Dst++ = InQueue->front();
|
||||
--Size;
|
||||
++NumRead;
|
||||
InQueue->pop();
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error appendBytes(const char *Src, unsigned Size) override {
|
||||
std::unique_lock<std::mutex> Lock(OutQueue->getMutex());
|
||||
while (Size--) {
|
||||
if (Error Err = OutQueue->checkWriteError())
|
||||
return Err;
|
||||
OutQueue->push(*Src++);
|
||||
++NumWritten;
|
||||
}
|
||||
OutQueue->getCondVar().notify_one();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error send() override { return Error::success(); }
|
||||
|
||||
void close() {
|
||||
auto ChannelClosed = []() { return make_error<QueueChannelClosedError>(); };
|
||||
InQueue->setReadError(ChannelClosed);
|
||||
InQueue->setWriteError(ChannelClosed);
|
||||
OutQueue->setReadError(ChannelClosed);
|
||||
OutQueue->setWriteError(ChannelClosed);
|
||||
}
|
||||
|
||||
uint64_t NumWritten = 0;
|
||||
uint64_t NumRead = 0;
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<Queue> InQueue;
|
||||
std::shared_ptr<Queue> OutQueue;
|
||||
};
|
||||
|
||||
inline std::pair<std::unique_ptr<QueueChannel>, std::unique_ptr<QueueChannel>>
|
||||
createPairedQueueChannels() {
|
||||
auto Q1 = std::make_shared<Queue>();
|
||||
auto Q2 = std::make_shared<Queue>();
|
||||
auto C1 = llvm::make_unique<QueueChannel>(Q1, Q2);
|
||||
auto C2 = llvm::make_unique<QueueChannel>(Q2, Q1);
|
||||
return std::make_pair(std::move(C1), std::move(C2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,266 +0,0 @@
|
||||
//===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
|
||||
#include "OrcTestCommon.h"
|
||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
|
||||
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
|
||||
#include "llvm/ExecutionEngine/Orc/NullResolver.h"
|
||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::orc;
|
||||
|
||||
namespace {
|
||||
|
||||
class RTDyldObjectLinkingLayerExecutionTest : public testing::Test,
|
||||
public OrcExecutionTest {
|
||||
|
||||
};
|
||||
|
||||
class SectionMemoryManagerWrapper : public SectionMemoryManager {
|
||||
public:
|
||||
int FinalizationCount = 0;
|
||||
int NeedsToReserveAllocationSpaceCount = 0;
|
||||
|
||||
bool needsToReserveAllocationSpace() override {
|
||||
++NeedsToReserveAllocationSpaceCount;
|
||||
return SectionMemoryManager::needsToReserveAllocationSpace();
|
||||
}
|
||||
|
||||
bool finalizeMemory(std::string *ErrMsg = nullptr) override {
|
||||
++FinalizationCount;
|
||||
return SectionMemoryManager::finalizeMemory(ErrMsg);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
|
||||
class MemoryManagerWrapper : public SectionMemoryManager {
|
||||
public:
|
||||
MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
|
||||
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||
unsigned SectionID,
|
||||
StringRef SectionName,
|
||||
bool IsReadOnly) override {
|
||||
if (SectionName == ".debug_str")
|
||||
DebugSeen = true;
|
||||
return SectionMemoryManager::allocateDataSection(Size, Alignment,
|
||||
SectionID,
|
||||
SectionName,
|
||||
IsReadOnly);
|
||||
}
|
||||
private:
|
||||
bool &DebugSeen;
|
||||
};
|
||||
|
||||
bool DebugSectionSeen = false;
|
||||
auto MM = std::make_shared<MemoryManagerWrapper>(DebugSectionSeen);
|
||||
|
||||
RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; });
|
||||
|
||||
LLVMContext Context;
|
||||
auto M = llvm::make_unique<Module>("", Context);
|
||||
M->setTargetTriple("x86_64-unknown-linux-gnu");
|
||||
Type *Int32Ty = IntegerType::get(Context, 32);
|
||||
GlobalVariable *GV =
|
||||
new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
|
||||
ConstantInt::get(Int32Ty, 42), "foo");
|
||||
|
||||
GV->setSection(".debug_str");
|
||||
|
||||
|
||||
// Initialize the native target in case this is the first unit test
|
||||
// to try to build a TM.
|
||||
OrcNativeTarget::initialize();
|
||||
std::unique_ptr<TargetMachine> TM(
|
||||
EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
|
||||
SmallVector<std::string, 1>()));
|
||||
if (!TM)
|
||||
return;
|
||||
|
||||
auto Obj =
|
||||
std::make_shared<object::OwningBinary<object::ObjectFile>>(
|
||||
SimpleCompiler(*TM)(*M));
|
||||
|
||||
auto Resolver =
|
||||
createLambdaResolver(
|
||||
[](const std::string &Name) {
|
||||
return JITSymbol(nullptr);
|
||||
},
|
||||
[](const std::string &Name) {
|
||||
return JITSymbol(nullptr);
|
||||
});
|
||||
|
||||
{
|
||||
// Test with ProcessAllSections = false (the default).
|
||||
auto H = cantFail(ObjLayer.addObject(Obj, Resolver));
|
||||
cantFail(ObjLayer.emitAndFinalize(H));
|
||||
EXPECT_EQ(DebugSectionSeen, false)
|
||||
<< "Unexpected debug info section";
|
||||
cantFail(ObjLayer.removeObject(H));
|
||||
}
|
||||
|
||||
{
|
||||
// Test with ProcessAllSections = true.
|
||||
ObjLayer.setProcessAllSections(true);
|
||||
auto H = cantFail(ObjLayer.addObject(Obj, Resolver));
|
||||
cantFail(ObjLayer.emitAndFinalize(H));
|
||||
EXPECT_EQ(DebugSectionSeen, true)
|
||||
<< "Expected debug info section not seen";
|
||||
cantFail(ObjLayer.removeObject(H));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
|
||||
if (!TM)
|
||||
return;
|
||||
|
||||
auto MM = std::make_shared<SectionMemoryManagerWrapper>();
|
||||
|
||||
RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; });
|
||||
SimpleCompiler Compile(*TM);
|
||||
|
||||
// Create a pair of modules that will trigger recursive finalization:
|
||||
// Module 1:
|
||||
// int bar() { return 42; }
|
||||
// Module 2:
|
||||
// int bar();
|
||||
// int foo() { return bar(); }
|
||||
//
|
||||
// Verify that the memory manager is only finalized once (for Module 2).
|
||||
// Failure suggests that finalize is being called on the inner RTDyld
|
||||
// instance (for Module 1) which is unsafe, as it will prevent relocation of
|
||||
// Module 2.
|
||||
|
||||
ModuleBuilder MB1(Context, "", "dummy");
|
||||
{
|
||||
MB1.getModule()->setDataLayout(TM->createDataLayout());
|
||||
Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
|
||||
BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
|
||||
IRBuilder<> Builder(BarEntry);
|
||||
IntegerType *Int32Ty = IntegerType::get(Context, 32);
|
||||
Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
|
||||
Builder.CreateRet(FourtyTwo);
|
||||
}
|
||||
|
||||
auto Obj1 =
|
||||
std::make_shared<object::OwningBinary<object::ObjectFile>>(
|
||||
Compile(*MB1.getModule()));
|
||||
|
||||
ModuleBuilder MB2(Context, "", "dummy");
|
||||
{
|
||||
MB2.getModule()->setDataLayout(TM->createDataLayout());
|
||||
Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
|
||||
Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
|
||||
BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
|
||||
IRBuilder<> Builder(FooEntry);
|
||||
Builder.CreateRet(Builder.CreateCall(BarDecl));
|
||||
}
|
||||
auto Obj2 =
|
||||
std::make_shared<object::OwningBinary<object::ObjectFile>>(
|
||||
Compile(*MB2.getModule()));
|
||||
|
||||
auto Resolver =
|
||||
createLambdaResolver(
|
||||
[&](const std::string &Name) {
|
||||
if (auto Sym = ObjLayer.findSymbol(Name, true))
|
||||
return Sym;
|
||||
return JITSymbol(nullptr);
|
||||
},
|
||||
[](const std::string &Name) {
|
||||
return JITSymbol(nullptr);
|
||||
});
|
||||
|
||||
cantFail(ObjLayer.addObject(std::move(Obj1), Resolver));
|
||||
auto H = cantFail(ObjLayer.addObject(std::move(Obj2), Resolver));
|
||||
cantFail(ObjLayer.emitAndFinalize(H));
|
||||
cantFail(ObjLayer.removeObject(H));
|
||||
|
||||
// Finalization of module 2 should trigger finalization of module 1.
|
||||
// Verify that finalize on SMMW is only called once.
|
||||
EXPECT_EQ(MM->FinalizationCount, 1)
|
||||
<< "Extra call to finalize";
|
||||
}
|
||||
|
||||
TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
|
||||
if (!TM)
|
||||
return;
|
||||
|
||||
auto MM = std::make_shared<SectionMemoryManagerWrapper>();
|
||||
|
||||
RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; });
|
||||
SimpleCompiler Compile(*TM);
|
||||
|
||||
// Create a pair of unrelated modules:
|
||||
//
|
||||
// Module 1:
|
||||
// int foo() { return 42; }
|
||||
// Module 2:
|
||||
// int bar() { return 7; }
|
||||
//
|
||||
// Both modules will share a memory manager. We want to verify that the
|
||||
// second object is not loaded before the first one is finalized. To do this
|
||||
// in a portable way, we abuse the
|
||||
// RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
|
||||
// called once per object before any sections are allocated.
|
||||
|
||||
ModuleBuilder MB1(Context, "", "dummy");
|
||||
{
|
||||
MB1.getModule()->setDataLayout(TM->createDataLayout());
|
||||
Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
|
||||
BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
|
||||
IRBuilder<> Builder(BarEntry);
|
||||
IntegerType *Int32Ty = IntegerType::get(Context, 32);
|
||||
Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
|
||||
Builder.CreateRet(FourtyTwo);
|
||||
}
|
||||
|
||||
auto Obj1 =
|
||||
std::make_shared<object::OwningBinary<object::ObjectFile>>(
|
||||
Compile(*MB1.getModule()));
|
||||
|
||||
ModuleBuilder MB2(Context, "", "dummy");
|
||||
{
|
||||
MB2.getModule()->setDataLayout(TM->createDataLayout());
|
||||
Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
|
||||
BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
|
||||
IRBuilder<> Builder(BarEntry);
|
||||
IntegerType *Int32Ty = IntegerType::get(Context, 32);
|
||||
Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
|
||||
Builder.CreateRet(Seven);
|
||||
}
|
||||
auto Obj2 =
|
||||
std::make_shared<object::OwningBinary<object::ObjectFile>>(
|
||||
Compile(*MB2.getModule()));
|
||||
|
||||
auto NR = std::make_shared<NullResolver>();
|
||||
auto H = cantFail(ObjLayer.addObject(std::move(Obj1), NR));
|
||||
cantFail(ObjLayer.addObject(std::move(Obj2), NR));
|
||||
cantFail(ObjLayer.emitAndFinalize(H));
|
||||
cantFail(ObjLayer.removeObject(H));
|
||||
|
||||
// Only one call to needsToReserveAllocationSpace should have been made.
|
||||
EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1)
|
||||
<< "More than one call to needsToReserveAllocationSpace "
|
||||
"(multiple unrelated objects loaded prior to finalization)";
|
||||
}
|
||||
|
||||
TEST_F(RTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) {
|
||||
RTDyldObjectLinkingLayer ObjLayer(
|
||||
[]() { return nullptr; },
|
||||
[](RTDyldObjectLinkingLayer::ObjHandleT,
|
||||
const RTDyldObjectLinkingLayer::ObjectPtr &obj,
|
||||
const RuntimeDyld::LoadedObjectInfo &info) {});
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
File diff suppressed because it is too large
Load Diff
@ -1,48 +0,0 @@
|
||||
//===----- SymbolStringPoolTest.cpp - Unit tests for SymbolStringPool -----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::orc;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(SymbolStringPool, UniquingAndComparisons) {
|
||||
SymbolStringPool SP;
|
||||
auto P1 = SP.intern("hello");
|
||||
|
||||
std::string S("hel");
|
||||
S += "lo";
|
||||
auto P2 = SP.intern(S);
|
||||
|
||||
auto P3 = SP.intern("goodbye");
|
||||
|
||||
EXPECT_EQ(P1, P2) << "Failed to unique entries";
|
||||
EXPECT_NE(P1, P3) << "Inequal pooled symbol strings comparing equal";
|
||||
|
||||
// We want to test that less-than comparison of SymbolStringPtrs compiles,
|
||||
// however we can't test the actual result as this is a pointer comparison and
|
||||
// SymbolStringPtr doesn't expose the underlying address of the string.
|
||||
(void)(P1 < P3);
|
||||
}
|
||||
|
||||
TEST(SymbolStringPool, ClearDeadEntries) {
|
||||
SymbolStringPool SP;
|
||||
{
|
||||
auto P1 = SP.intern("s1");
|
||||
SP.clearDeadEntries();
|
||||
EXPECT_FALSE(SP.empty()) << "\"s1\" entry in pool should still be retained";
|
||||
}
|
||||
SP.clearDeadEntries();
|
||||
EXPECT_TRUE(SP.empty()) << "pool should be empty";
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user