xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/JITLinkRedirectionManagerTest.cpp (revision 2ccf7ed277df28651b94bbee9fccefdf22fb074f)
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);
67   // Bail out if we can not create
68   if (!RM) {
69     consumeError(RM.takeError());
70     GTEST_SKIP();
71   }
72 
73   auto MakeTarget = [](int (*Fn)()) {
74     return ExecutorSymbolDef(ExecutorAddr::fromPtr(Fn),
75                              JITSymbolFlags::Exported |
76                                  JITSymbolFlags::Callable);
77   };
78 
79   auto RedirectableSymbol = ES->intern("RedirectableTarget");
80   EXPECT_THAT_ERROR((*RM)->createRedirectableSymbols(
81                         JD->getDefaultResourceTracker(),
82                         {{RedirectableSymbol, MakeTarget(initialTarget)}}),
83                     Succeeded());
84 
85   auto RTDef = cantFail(ES->lookup({JD}, RedirectableSymbol));
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(
91       (*RM)->redirect(*JD, {{RedirectableSymbol, MakeTarget(middleTarget)}}),
92       Succeeded());
93   Result = RTPtr();
94   EXPECT_EQ(Result, 13) << "Failed to call middle redirected target";
95 
96   EXPECT_THAT_ERROR(
97       (*RM)->redirect(*JD, {{RedirectableSymbol, MakeTarget(finalTarget)}}),
98       Succeeded());
99   Result = RTPtr();
100   EXPECT_EQ(Result, 53) << "Failed to call redirected target";
101 }
102