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