|  | #include "llvm/ExecutionEngine/Orc/ReOptimizeLayer.h" | 
|  | #include "OrcTestCommon.h" | 
|  | #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" | 
|  | #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h" | 
|  | #include "llvm/ExecutionEngine/Orc/CompileUtils.h" | 
|  | #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" | 
|  | #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/IRPartitionLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h" | 
|  | #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" | 
|  | #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" | 
|  | #include "llvm/IR/IRBuilder.h" | 
|  | #include "llvm/Support/CodeGen.h" | 
|  | #include "llvm/TargetParser/Host.h" | 
|  | #include "llvm/Testing/Support/Error.h" | 
|  | #include "gtest/gtest.h" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::orc; | 
|  | using namespace llvm::jitlink; | 
|  |  | 
|  | class ReOptimizeLayerTest : public testing::Test { | 
|  | public: | 
|  | ~ReOptimizeLayerTest() { | 
|  | if (ES) | 
|  | if (auto Err = ES->endSession()) | 
|  | ES->reportError(std::move(Err)); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | void SetUp() override { | 
|  | auto JTMB = JITTargetMachineBuilder::detectHost(); | 
|  | // Bail out if we can not detect the host. | 
|  | if (!JTMB) { | 
|  | consumeError(JTMB.takeError()); | 
|  | GTEST_SKIP(); | 
|  | } | 
|  |  | 
|  | // COFF-ARM64 is not supported yet | 
|  | auto Triple = JTMB->getTargetTriple(); | 
|  | if (Triple.isOSBinFormatCOFF() && Triple.isAArch64()) | 
|  | GTEST_SKIP(); | 
|  |  | 
|  | // SystemZ is not supported yet. | 
|  | if (Triple.isSystemZ()) | 
|  | GTEST_SKIP(); | 
|  |  | 
|  | // 32-bit X86 is not supported yet. | 
|  | if (Triple.isX86() && Triple.isArch32Bit()) | 
|  | GTEST_SKIP(); | 
|  |  | 
|  | if (Triple.isPPC()) | 
|  | GTEST_SKIP(); | 
|  |  | 
|  | // RISC-V is not supported yet | 
|  | if (Triple.isRISCV()) | 
|  | GTEST_SKIP(); | 
|  |  | 
|  | // ARM is not supported yet. | 
|  | if (Triple.isARM()) | 
|  | GTEST_SKIP(); | 
|  |  | 
|  | auto EPC = SelfExecutorProcessControl::Create(); | 
|  | if (!EPC) { | 
|  | consumeError(EPC.takeError()); | 
|  | GTEST_SKIP(); | 
|  | } | 
|  |  | 
|  | auto DLOrErr = JTMB->getDefaultDataLayoutForTarget(); | 
|  | if (!DLOrErr) { | 
|  | consumeError(DLOrErr.takeError()); | 
|  | GTEST_SKIP(); | 
|  | } | 
|  |  | 
|  | auto PageSize = sys::Process::getPageSize(); | 
|  | if (!PageSize) { | 
|  | consumeError(PageSize.takeError()); | 
|  | GTEST_SKIP(); | 
|  | } | 
|  |  | 
|  | ES = std::make_unique<ExecutionSession>(std::move(*EPC)); | 
|  | JD = &ES->createBareJITDylib("main"); | 
|  | ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>( | 
|  | *ES, std::make_unique<InProcessMemoryManager>(*PageSize)); | 
|  | DL = std::make_unique<DataLayout>(std::move(*DLOrErr)); | 
|  |  | 
|  | auto TM = JTMB->createTargetMachine(); | 
|  | if (!TM) { | 
|  | consumeError(TM.takeError()); | 
|  | GTEST_SKIP(); | 
|  | } | 
|  | auto CompileFunction = | 
|  | std::make_unique<TMOwningSimpleCompiler>(std::move(*TM)); | 
|  | CompileLayer = std::make_unique<IRCompileLayer>(*ES, *ObjLinkingLayer, | 
|  | std::move(CompileFunction)); | 
|  | } | 
|  |  | 
|  | Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) { | 
|  | assert(TSM && "Can not add null module"); | 
|  |  | 
|  | TSM.withModuleDo([&](Module &M) { M.setDataLayout(*DL); }); | 
|  |  | 
|  | return ROLayer->add(std::move(RT), std::move(TSM)); | 
|  | } | 
|  |  | 
|  | JITDylib *JD{nullptr}; | 
|  | std::unique_ptr<ExecutionSession> ES; | 
|  | std::unique_ptr<ObjectLinkingLayer> ObjLinkingLayer; | 
|  | std::unique_ptr<IRCompileLayer> CompileLayer; | 
|  | std::unique_ptr<ReOptimizeLayer> ROLayer; | 
|  | std::unique_ptr<DataLayout> DL; | 
|  | }; | 
|  |  | 
|  | static Function *createRetFunction(Module *M, StringRef Name, | 
|  | uint32_t ReturnCode) { | 
|  | Function *Result = Function::Create( | 
|  | FunctionType::get(Type::getInt32Ty(M->getContext()), {}, false), | 
|  | GlobalValue::ExternalLinkage, Name, M); | 
|  |  | 
|  | BasicBlock *BB = BasicBlock::Create(M->getContext(), Name, Result); | 
|  | IRBuilder<> Builder(M->getContext()); | 
|  | Builder.SetInsertPoint(BB); | 
|  |  | 
|  | Value *RetValue = ConstantInt::get(M->getContext(), APInt(32, ReturnCode)); | 
|  | Builder.CreateRet(RetValue); | 
|  | return Result; | 
|  | } | 
|  |  | 
|  | TEST_F(ReOptimizeLayerTest, BasicReOptimization) { | 
|  | MangleAndInterner Mangle(*ES, *DL); | 
|  |  | 
|  | auto &EPC = ES->getExecutorProcessControl(); | 
|  | EXPECT_THAT_ERROR(JD->define(absoluteSymbols( | 
|  | {{Mangle("__orc_rt_jit_dispatch"), | 
|  | {EPC.getJITDispatchInfo().JITDispatchFunction, | 
|  | JITSymbolFlags::Exported}}, | 
|  | {Mangle("__orc_rt_jit_dispatch_ctx"), | 
|  | {EPC.getJITDispatchInfo().JITDispatchContext, | 
|  | JITSymbolFlags::Exported}}, | 
|  | {Mangle("__orc_rt_reoptimize_tag"), | 
|  | {ExecutorAddr(), JITSymbolFlags::Exported}}})), | 
|  | Succeeded()); | 
|  |  | 
|  | auto RM = JITLinkRedirectableSymbolManager::Create(*ObjLinkingLayer); | 
|  | EXPECT_THAT_ERROR(RM.takeError(), Succeeded()); | 
|  |  | 
|  | ROLayer = std::make_unique<ReOptimizeLayer>(*ES, *DL, *CompileLayer, **RM); | 
|  | ROLayer->setReoptimizeFunc( | 
|  | [&](ReOptimizeLayer &Parent, | 
|  | ReOptimizeLayer::ReOptMaterializationUnitID MUID, unsigned CurVerison, | 
|  | ResourceTrackerSP OldRT, ThreadSafeModule &TSM) { | 
|  | TSM.withModuleDo([&](Module &M) { | 
|  | for (auto &F : M) { | 
|  | if (F.isDeclaration()) | 
|  | continue; | 
|  | for (auto &B : F) { | 
|  | for (auto &I : B) { | 
|  | if (ReturnInst *Ret = dyn_cast<ReturnInst>(&I)) { | 
|  | Value *RetValue = | 
|  | ConstantInt::get(M.getContext(), APInt(32, 53)); | 
|  | Ret->setOperand(0, RetValue); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | }); | 
|  | return Error::success(); | 
|  | }); | 
|  | EXPECT_THAT_ERROR(ROLayer->reigsterRuntimeFunctions(*JD), Succeeded()); | 
|  |  | 
|  | ThreadSafeContext Ctx(std::make_unique<LLVMContext>()); | 
|  | auto M = std::make_unique<Module>("<main>", *Ctx.getContext()); | 
|  | M->setTargetTriple(Triple(sys::getProcessTriple())); | 
|  |  | 
|  | (void)createRetFunction(M.get(), "main", 42); | 
|  |  | 
|  | EXPECT_THAT_ERROR(addIRModule(JD->getDefaultResourceTracker(), | 
|  | ThreadSafeModule(std::move(M), std::move(Ctx))), | 
|  | Succeeded()); | 
|  |  | 
|  | auto Result = cantFail(ES->lookup({JD}, Mangle("main"))); | 
|  | auto FuncPtr = Result.getAddress().toPtr<int (*)()>(); | 
|  | for (size_t I = 0; I <= ReOptimizeLayer::CallCountThreshold; I++) | 
|  | EXPECT_EQ(FuncPtr(), 42); | 
|  | EXPECT_EQ(FuncPtr(), 53); | 
|  | } |