xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/JITLinkRedirectionManagerTest.cpp (revision 1d657cfeac4a040acfff249d43ca6987b8a05281)
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     OrcNativeTarget::initialize();
30 
31     auto JTMB = JITTargetMachineBuilder::detectHost();
32     // Bail out if we can not detect the host.
33     if (!JTMB) {
34       consumeError(JTMB.takeError());
35       GTEST_SKIP();
36     }
37     auto DLOrErr = JTMB->getDefaultDataLayoutForTarget();
38     if (!DLOrErr) {
39       consumeError(DLOrErr.takeError());
40       GTEST_SKIP();
41     }
42 
43     // COFF-ARM64 is not supported yet
44     auto Triple = JTMB->getTargetTriple();
45     if (Triple.isOSBinFormatCOFF() && Triple.isAArch64())
46       GTEST_SKIP();
47 
48     if (Triple.isPPC())
49       GTEST_SKIP();
50 
51     ES = std::make_unique<ExecutionSession>(
52         std::make_unique<UnsupportedExecutorProcessControl>(
53             nullptr, nullptr, JTMB->getTargetTriple().getTriple()));
54     JD = &ES->createBareJITDylib("main");
55     ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(
56         *ES, std::make_unique<InProcessMemoryManager>(16384));
57     DL = std::make_unique<DataLayout>(std::move(*DLOrErr));
58   }
59   JITDylib *JD{nullptr};
60   std::unique_ptr<ExecutionSession> ES;
61   std::unique_ptr<ObjectLinkingLayer> ObjLinkingLayer;
62   std::unique_ptr<DataLayout> DL;
63 };
64 
65 TEST_F(JITLinkRedirectionManagerTest, BasicRedirectionOperation) {
66   auto RM = JITLinkRedirectableSymbolManager::Create(*ObjLinkingLayer, *JD);
67   // Bail out if we can not create
68   if (!RM) {
69     consumeError(RM.takeError());
70     GTEST_SKIP();
71   }
72 
73   auto DefineTarget = [&](StringRef TargetName, ExecutorAddr Addr) {
74     SymbolStringPtr Target = ES->intern(TargetName);
75     cantFail(JD->define(std::make_unique<SimpleMaterializationUnit>(
76         SymbolFlagsMap({{Target, JITSymbolFlags::Exported}}),
77         [&](std::unique_ptr<MaterializationResponsibility> R) -> void {
78           // No dependencies registered, can't fail.
79           cantFail(
80               R->notifyResolved({{Target, {Addr, JITSymbolFlags::Exported}}}));
81           cantFail(R->notifyEmitted({}));
82         })));
83     return cantFail(ES->lookup({JD}, TargetName));
84   };
85 
86   auto InitialTarget =
87       DefineTarget("InitialTarget", ExecutorAddr::fromPtr(&initialTarget));
88   auto MiddleTarget =
89       DefineTarget("MiddleTarget", ExecutorAddr::fromPtr(&middleTarget));
90   auto FinalTarget =
91       DefineTarget("FinalTarget", ExecutorAddr::fromPtr(&finalTarget));
92 
93   auto RedirectableSymbol = ES->intern("RedirectableTarget");
94   EXPECT_THAT_ERROR(
95       (*RM)->createRedirectableSymbols(JD->getDefaultResourceTracker(),
96                                        {{RedirectableSymbol, InitialTarget}}),
97       Succeeded());
98   auto RTDef = cantFail(ES->lookup({JD}, RedirectableSymbol));
99 
100   auto RTPtr = RTDef.getAddress().toPtr<int (*)()>();
101   auto Result = RTPtr();
102   EXPECT_EQ(Result, 42) << "Failed to call initial target";
103 
104   EXPECT_THAT_ERROR((*RM)->redirect(*JD, {{RedirectableSymbol, MiddleTarget}}),
105                     Succeeded());
106   Result = RTPtr();
107   EXPECT_EQ(Result, 13) << "Failed to call middle redirected target";
108 
109   EXPECT_THAT_ERROR((*RM)->redirect(*JD, {{RedirectableSymbol, FinalTarget}}),
110                     Succeeded());
111   Result = RTPtr();
112   EXPECT_EQ(Result, 53) << "Failed to call redirected target";
113 }
114