123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- //===------ OrcTestCommon.h - Utilities for Orc Unit Tests ------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // 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/ExecutionEngine/Orc/IndirectionUtils.h"
- #include "llvm/IR/Function.h"
- #include "llvm/IR/IRBuilder.h"
- #include "llvm/IR/LLVMContext.h"
- #include "llvm/IR/Module.h"
- #include "llvm/Object/ObjectFile.h"
- #include "llvm/Support/TargetRegistry.h"
- #include "llvm/Support/TargetSelect.h"
- #include "gtest/gtest.h"
- #include <memory>
- namespace llvm {
- namespace orc {
- // CoreAPIsStandardTest that saves a bunch of boilerplate by providing the
- // following:
- //
- // (1) ES -- An ExecutionSession
- // (2) Foo, Bar, Baz, Qux -- SymbolStringPtrs for strings "foo", "bar", "baz",
- // and "qux" respectively.
- // (3) FooAddr, BarAddr, BazAddr, QuxAddr -- Dummy addresses. Guaranteed
- // distinct and non-null.
- // (4) FooSym, BarSym, BazSym, QuxSym -- JITEvaluatedSymbols with FooAddr,
- // BarAddr, BazAddr, and QuxAddr respectively. All with default strong,
- // linkage and non-hidden visibility.
- // (5) V -- A JITDylib associated with ES.
- class CoreAPIsBasedStandardTest : public testing::Test {
- protected:
- std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();
- ExecutionSession ES{SSP};
- JITDylib &JD = ES.createJITDylib("JD");
- SymbolStringPtr Foo = ES.intern("foo");
- SymbolStringPtr Bar = ES.intern("bar");
- SymbolStringPtr Baz = ES.intern("baz");
- SymbolStringPtr Qux = ES.intern("qux");
- static const JITTargetAddress FooAddr = 1U;
- static const JITTargetAddress BarAddr = 2U;
- static const JITTargetAddress BazAddr = 3U;
- static const JITTargetAddress QuxAddr = 4U;
- JITEvaluatedSymbol FooSym =
- JITEvaluatedSymbol(FooAddr, JITSymbolFlags::Exported);
- JITEvaluatedSymbol BarSym =
- JITEvaluatedSymbol(BarAddr, JITSymbolFlags::Exported);
- JITEvaluatedSymbol BazSym =
- JITEvaluatedSymbol(BazAddr, JITSymbolFlags::Exported);
- JITEvaluatedSymbol QuxSym =
- JITEvaluatedSymbol(QuxAddr, JITSymbolFlags::Exported);
- };
- } // end namespace orc
- class OrcNativeTarget {
- public:
- static void initialize() {
- if (!NativeTargetInitialized) {
- InitializeNativeTarget();
- InitializeNativeTargetAsmParser();
- InitializeNativeTargetAsmPrinter();
- NativeTargetInitialized = true;
- }
- }
- private:
- static bool NativeTargetInitialized;
- };
- class SimpleMaterializationUnit : public orc::MaterializationUnit {
- public:
- using MaterializeFunction =
- std::function<void(orc::MaterializationResponsibility)>;
- using DiscardFunction =
- std::function<void(const orc::JITDylib &, orc::SymbolStringPtr)>;
- using DestructorFunction = std::function<void()>;
- SimpleMaterializationUnit(
- orc::SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize,
- DiscardFunction Discard = DiscardFunction(),
- DestructorFunction Destructor = DestructorFunction())
- : MaterializationUnit(std::move(SymbolFlags), orc::VModuleKey()),
- Materialize(std::move(Materialize)), Discard(std::move(Discard)),
- Destructor(std::move(Destructor)) {}
- ~SimpleMaterializationUnit() override {
- if (Destructor)
- Destructor();
- }
- StringRef getName() const override { return "<Simple>"; }
- void materialize(orc::MaterializationResponsibility R) override {
- Materialize(std::move(R));
- }
- void discard(const orc::JITDylib &JD,
- const orc::SymbolStringPtr &Name) override {
- if (Discard)
- Discard(JD, std::move(Name));
- else
- llvm_unreachable("Discard not supported");
- }
- private:
- MaterializeFunction Materialize;
- DiscardFunction Discard;
- DestructorFunction Destructor;
- };
- // 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();
- // Bail out for windows platforms. We do not support these yet.
- if ((TT.getArch() != Triple::x86_64 && TT.getArch() != Triple::x86) ||
- TT.isOSWindows())
- return;
- // Target can JIT?
- SupportsJIT = TM->getTarget().hasJIT();
- // Use ability to create callback manager to detect whether Orc
- // has indirection support on this platform. This way the test
- // and Orc code do not get out of sync.
- SupportsIndirection = !!orc::createLocalCompileCallbackManager(TT, ES, 0);
- }
- };
- protected:
- orc::ExecutionSession ES;
- LLVMContext Context;
- std::unique_ptr<TargetMachine> TM;
- bool SupportsJIT = false;
- bool SupportsIndirection = false;
- };
- class ModuleBuilder {
- public:
- ModuleBuilder(LLVMContext &Context, StringRef Triple,
- StringRef Name);
- Function *createFunctionDecl(FunctionType *FTy, StringRef Name) {
- return Function::Create(FTy, 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];
- };
- inline StructType *getDummyStructTy(LLVMContext &Context) {
- return StructType::get(ArrayType::get(Type::getInt32Ty(Context), 256));
- }
- 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
|