1 #include "OrcTestCommon.h" 2 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" 3 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" 4 #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h" 5 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" 6 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 7 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 8 #include "llvm/Testing/Support/Error.h" 9 #include "gtest/gtest.h" 10 11 using namespace llvm; 12 using namespace llvm::orc; 13 using namespace llvm::jitlink; 14 15 static int initialTarget() { return 42; } 16 static int middleTarget() { return 13; } 17 static int finalTarget() { return 53; } 18 19 class JITLinkRedirectionManagerTest : public testing::Test { 20 public: 21 ~JITLinkRedirectionManagerTest() { 22 if (ES) 23 if (auto Err = ES->endSession()) 24 ES->reportError(std::move(Err)); 25 } 26 27 protected: 28 void SetUp() override { 29 auto JTMB = JITTargetMachineBuilder::detectHost(); 30 // Bail out if we can not detect the host. 31 if (!JTMB) { 32 consumeError(JTMB.takeError()); 33 GTEST_SKIP(); 34 } 35 36 ES = std::make_unique<ExecutionSession>( 37 std::make_unique<UnsupportedExecutorProcessControl>( 38 nullptr, nullptr, JTMB->getTargetTriple().getTriple())); 39 JD = &ES->createBareJITDylib("main"); 40 ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>( 41 *ES, std::make_unique<InProcessMemoryManager>(16384)); 42 DL = std::make_unique<DataLayout>( 43 cantFail(JTMB->getDefaultDataLayoutForTarget())); 44 } 45 JITDylib *JD{nullptr}; 46 std::unique_ptr<ExecutionSession> ES; 47 std::unique_ptr<ObjectLinkingLayer> ObjLinkingLayer; 48 std::unique_ptr<DataLayout> DL; 49 }; 50 51 TEST_F(JITLinkRedirectionManagerTest, BasicRedirectionOperation) { 52 auto RM = JITLinkRedirectableSymbolManager::Create(*ObjLinkingLayer, *JD); 53 // Bail out if we can not create 54 if (!RM) { 55 consumeError(RM.takeError()); 56 GTEST_SKIP(); 57 } 58 59 auto DefineTarget = [&](StringRef TargetName, ExecutorAddr Addr) { 60 SymbolStringPtr Target = ES->intern(TargetName); 61 cantFail(JD->define(std::make_unique<SimpleMaterializationUnit>( 62 SymbolFlagsMap({{Target, JITSymbolFlags::Exported}}), 63 [&](std::unique_ptr<MaterializationResponsibility> R) -> void { 64 // No dependencies registered, can't fail. 65 cantFail( 66 R->notifyResolved({{Target, {Addr, JITSymbolFlags::Exported}}})); 67 cantFail(R->notifyEmitted({})); 68 }))); 69 return cantFail(ES->lookup({JD}, TargetName)); 70 }; 71 72 auto InitialTarget = 73 DefineTarget("InitialTarget", ExecutorAddr::fromPtr(&initialTarget)); 74 auto MiddleTarget = 75 DefineTarget("MiddleTarget", ExecutorAddr::fromPtr(&middleTarget)); 76 auto FinalTarget = 77 DefineTarget("FinalTarget", ExecutorAddr::fromPtr(&finalTarget)); 78 79 auto RedirectableSymbol = ES->intern("RedirectableTarget"); 80 EXPECT_THAT_ERROR( 81 (*RM)->createRedirectableSymbols(JD->getDefaultResourceTracker(), 82 {{RedirectableSymbol, InitialTarget}}), 83 Succeeded()); 84 auto RTDef = cantFail(ES->lookup({JD}, RedirectableSymbol)); 85 86 auto RTPtr = RTDef.getAddress().toPtr<int (*)()>(); 87 auto Result = RTPtr(); 88 EXPECT_EQ(Result, 42) << "Failed to call initial target"; 89 90 EXPECT_THAT_ERROR((*RM)->redirect(*JD, {{RedirectableSymbol, MiddleTarget}}), 91 Succeeded()); 92 Result = RTPtr(); 93 EXPECT_EQ(Result, 13) << "Failed to call middle redirected target"; 94 95 EXPECT_THAT_ERROR((*RM)->redirect(*JD, {{RedirectableSymbol, FinalTarget}}), 96 Succeeded()); 97 Result = RTPtr(); 98 EXPECT_EQ(Result, 53) << "Failed to call redirected target"; 99 } 100