217 lines · c
1//===------ OrcTestCommon.h - Utilities for Orc Unit Tests ------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Common utilities for the Orc unit tests.10//11//===----------------------------------------------------------------------===//12 13 14#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H15#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H16 17#include "llvm/ExecutionEngine/JITSymbol.h"18#include "llvm/ExecutionEngine/Orc/Core.h"19#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"20#include "llvm/ExecutionEngine/Orc/InProcessMemoryAccess.h"21#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"22#include "llvm/IR/Function.h"23#include "llvm/IR/IRBuilder.h"24#include "llvm/IR/LLVMContext.h"25#include "llvm/IR/Module.h"26#include "llvm/MC/TargetRegistry.h"27#include "llvm/Object/ObjectFile.h"28#include "llvm/Support/TargetSelect.h"29#include "gtest/gtest.h"30 31#include <memory>32 33namespace llvm {34 35namespace orc {36// CoreAPIsStandardTest that saves a bunch of boilerplate by providing the37// following:38//39// (1) ES -- An ExecutionSession40// (2) Foo, Bar, Baz, Qux -- SymbolStringPtrs for strings "foo", "bar", "baz",41// and "qux" respectively.42// (3) FooAddr, BarAddr, BazAddr, QuxAddr -- Dummy addresses. Guaranteed43// distinct and non-null.44// (4) FooSym, BarSym, BazSym, QuxSym -- JITEvaluatedSymbols with FooAddr,45// BarAddr, BazAddr, and QuxAddr respectively. All with default strong,46// linkage and non-hidden visibility.47// (5) V -- A JITDylib associated with ES.48class CoreAPIsBasedStandardTest : public testing::Test {49public:50 ~CoreAPIsBasedStandardTest() override {51 if (auto Err = ES.endSession())52 ES.reportError(std::move(Err));53 }54 55protected:56 class OverridableDispatcher : public InPlaceTaskDispatcher {57 public:58 OverridableDispatcher(CoreAPIsBasedStandardTest &Parent) : Parent(Parent) {}59 void dispatch(std::unique_ptr<Task> T) override;60 61 private:62 CoreAPIsBasedStandardTest &Parent;63 };64 65 std::unique_ptr<llvm::orc::ExecutorProcessControl>66 makeEPC(std::shared_ptr<SymbolStringPool> SSP);67 68 std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();69 ExecutionSession ES{makeEPC(SSP)};70 JITDylib &JD = ES.createBareJITDylib("JD");71 SymbolStringPtr Foo = ES.intern("foo");72 SymbolStringPtr Bar = ES.intern("bar");73 SymbolStringPtr Baz = ES.intern("baz");74 SymbolStringPtr Qux = ES.intern("qux");75 static constexpr ExecutorAddr FooAddr{1};76 static constexpr ExecutorAddr BarAddr{2};77 static constexpr ExecutorAddr BazAddr{3};78 static constexpr ExecutorAddr QuxAddr{4};79 ExecutorSymbolDef FooSym{FooAddr, JITSymbolFlags::Exported};80 ExecutorSymbolDef BarSym{BarAddr, JITSymbolFlags::Exported};81 ExecutorSymbolDef BazSym{BazAddr, JITSymbolFlags::Exported};82 ExecutorSymbolDef QuxSym{QuxAddr, JITSymbolFlags::Exported};83 unique_function<void(std::unique_ptr<Task>)> DispatchOverride;84};85 86/// A ExecutorProcessControl instance that asserts if any of its methods are87/// used. Suitable for use is unit tests, and by ORC clients who haven't moved88/// to ExecutorProcessControl-based APIs yet.89class UnsupportedExecutorProcessControl : public ExecutorProcessControl,90 private InProcessMemoryAccess {91public:92 UnsupportedExecutorProcessControl(93 std::shared_ptr<SymbolStringPool> SSP = nullptr,94 std::unique_ptr<TaskDispatcher> D = nullptr, const std::string &TT = "",95 unsigned PageSize = 0)96 : ExecutorProcessControl(97 SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>(),98 D ? std::move(D) : std::make_unique<InPlaceTaskDispatcher>()),99 InProcessMemoryAccess(Triple(TT).isArch64Bit()) {100 this->TargetTriple = Triple(TT);101 this->PageSize = PageSize;102 this->MemAccess = this;103 }104 105 Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,106 ArrayRef<std::string> Args) override {107 llvm_unreachable("Unsupported");108 }109 110 Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override {111 llvm_unreachable("Unsupported");112 }113 114 Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override {115 llvm_unreachable("Unsupported");116 }117 118 void callWrapperAsync(ExecutorAddr WrapperFnAddr,119 IncomingWFRHandler OnComplete,120 ArrayRef<char> ArgBuffer) override {121 llvm_unreachable("Unsupported");122 }123 124 Error disconnect() override { return Error::success(); }125};126 127} // end namespace orc128 129class OrcNativeTarget {130public:131 static void initialize() {132 if (!NativeTargetInitialized) {133 InitializeNativeTarget();134 InitializeNativeTargetAsmParser();135 InitializeNativeTargetAsmPrinter();136 NativeTargetInitialized = true;137 }138 }139 140private:141 static bool NativeTargetInitialized;142};143 144class SimpleMaterializationUnit : public orc::MaterializationUnit {145public:146 using MaterializeFunction =147 std::function<void(std::unique_ptr<orc::MaterializationResponsibility>)>;148 using DiscardFunction =149 std::function<void(const orc::JITDylib &, orc::SymbolStringPtr)>;150 using DestructorFunction = std::function<void()>;151 152 SimpleMaterializationUnit(153 orc::SymbolFlagsMap SymbolFlags, MaterializeFunction Materialize,154 orc::SymbolStringPtr InitSym = nullptr,155 DiscardFunction Discard = DiscardFunction(),156 DestructorFunction Destructor = DestructorFunction())157 : MaterializationUnit(158 Interface(std::move(SymbolFlags), std::move(InitSym))),159 Materialize(std::move(Materialize)), Discard(std::move(Discard)),160 Destructor(std::move(Destructor)) {}161 162 ~SimpleMaterializationUnit() override {163 if (Destructor)164 Destructor();165 }166 167 StringRef getName() const override { return "<Simple>"; }168 169 void170 materialize(std::unique_ptr<orc::MaterializationResponsibility> R) override {171 Materialize(std::move(R));172 }173 174 void discard(const orc::JITDylib &JD,175 const orc::SymbolStringPtr &Name) override {176 if (Discard)177 Discard(JD, std::move(Name));178 else179 llvm_unreachable("Discard not supported");180 }181 182private:183 MaterializeFunction Materialize;184 DiscardFunction Discard;185 DestructorFunction Destructor;186};187 188class ModuleBuilder {189public:190 ModuleBuilder(LLVMContext &Context, StringRef Triple,191 StringRef Name);192 193 Function *createFunctionDecl(FunctionType *FTy, StringRef Name) {194 return Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M.get());195 }196 197 Module* getModule() { return M.get(); }198 const Module* getModule() const { return M.get(); }199 std::unique_ptr<Module> takeModule() { return std::move(M); }200 201private:202 std::unique_ptr<Module> M;203};204 205// Dummy struct type.206struct DummyStruct {207 int X[256];208};209 210inline StructType *getDummyStructTy(LLVMContext &Context) {211 return StructType::get(ArrayType::get(Type::getInt32Ty(Context), 256));212}213 214} // namespace llvm215 216#endif217