153ccf888SLang Hames //===---- IndirectionUtils.cpp - Utilities for call indirection in Orc ----===//
253ccf888SLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
653ccf888SLang Hames //
753ccf888SLang Hames //===----------------------------------------------------------------------===//
853ccf888SLang Hames 
96bda14b3SChandler Carruth #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
100a446fd5SBenjamin Kramer #include "llvm/ADT/STLExtras.h"
1193de2a12SLang Hames #include "llvm/ADT/Triple.h"
12a2639dcbSBen Langmuir #include "llvm/ExecutionEngine/JITLink/x86_64.h"
13105518feSLang Hames #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
1493de2a12SLang Hames #include "llvm/IR/IRBuilder.h"
15a2639dcbSBen Langmuir #include "llvm/MC/MCDisassembler/MCDisassembler.h"
16a2639dcbSBen Langmuir #include "llvm/MC/MCInstrAnalysis.h"
17bd0cb787SLang Hames #include "llvm/Support/Format.h"
18cd68eba3SLang Hames #include "llvm/Transforms/Utils/Cloning.h"
19c6de458fSLang Hames #include <sstream>
2093de2a12SLang Hames 
21a2639dcbSBen Langmuir #define DEBUG_TYPE "orc"
22a2639dcbSBen Langmuir 
23bd0cb787SLang Hames using namespace llvm;
24bd0cb787SLang Hames using namespace llvm::orc;
25bd0cb787SLang Hames 
26bd0cb787SLang Hames namespace {
27bd0cb787SLang Hames 
28bd0cb787SLang Hames class CompileCallbackMaterializationUnit : public orc::MaterializationUnit {
29bd0cb787SLang Hames public:
30bd0cb787SLang Hames   using CompileFunction = JITCompileCallbackManager::CompileFunction;
31bd0cb787SLang Hames 
CompileCallbackMaterializationUnit(SymbolStringPtr Name,CompileFunction Compile)32bd0cb787SLang Hames   CompileCallbackMaterializationUnit(SymbolStringPtr Name,
330aec49c8SLang Hames                                      CompileFunction Compile)
34ae73f3fdSLang Hames       : MaterializationUnit(Interface(
35ae73f3fdSLang Hames             SymbolFlagsMap({{Name, JITSymbolFlags::Exported}}), nullptr)),
36bd0cb787SLang Hames         Name(std::move(Name)), Compile(std::move(Compile)) {}
37bd0cb787SLang Hames 
getName() const3846f40a71SLang Hames   StringRef getName() const override { return "<Compile Callbacks>"; }
3946f40a71SLang Hames 
40bd0cb787SLang Hames private:
materialize(std::unique_ptr<MaterializationResponsibility> R)417dcd0042SLang Hames   void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
42bd0cb787SLang Hames     SymbolMap Result;
43bd0cb787SLang Hames     Result[Name] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported);
44e00585c7SLang Hames     // No dependencies, so these calls cannot fail.
457dcd0042SLang Hames     cantFail(R->notifyResolved(Result));
467dcd0042SLang Hames     cantFail(R->notifyEmitted());
47bd0cb787SLang Hames   }
48bd0cb787SLang Hames 
discard(const JITDylib & JD,const SymbolStringPtr & Name)49cb5702c3SLang Hames   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
50bd0cb787SLang Hames     llvm_unreachable("Discard should never occur on a LMU?");
51bd0cb787SLang Hames   }
52bd0cb787SLang Hames 
53bd0cb787SLang Hames   SymbolStringPtr Name;
54bd0cb787SLang Hames   CompileFunction Compile;
55bd0cb787SLang Hames };
56bd0cb787SLang Hames 
57bd0cb787SLang Hames } // namespace
58bd0cb787SLang Hames 
5993de2a12SLang Hames namespace llvm {
60e738061cSLang Hames namespace orc {
6193de2a12SLang Hames 
623a3cb929SKazu Hirata TrampolinePool::~TrampolinePool() = default;
anchor()63ea39de81SLang Hames void IndirectStubsManager::anchor() {}
6498c2ac13SLang Hames 
65bd0cb787SLang Hames Expected<JITTargetAddress>
getCompileCallback(CompileFunction Compile)66bd0cb787SLang Hames JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
6750b33441SLang Hames   if (auto TrampolineAddr = TP->getTrampoline()) {
6871d781c4SLang Hames     auto CallbackName =
6971d781c4SLang Hames         ES.intern(std::string("cc") + std::to_string(++NextCallbackId));
70bd0cb787SLang Hames 
71bd0cb787SLang Hames     std::lock_guard<std::mutex> Lock(CCMgrMutex);
72bd0cb787SLang Hames     AddrToSymbol[*TrampolineAddr] = CallbackName;
730aec49c8SLang Hames     cantFail(
740aec49c8SLang Hames         CallbacksJD.define(std::make_unique<CompileCallbackMaterializationUnit>(
750aec49c8SLang Hames             std::move(CallbackName), std::move(Compile))));
76bd0cb787SLang Hames     return *TrampolineAddr;
77bd0cb787SLang Hames   } else
78bd0cb787SLang Hames     return TrampolineAddr.takeError();
79bd0cb787SLang Hames }
80bd0cb787SLang Hames 
executeCompileCallback(JITTargetAddress TrampolineAddr)81bd0cb787SLang Hames JITTargetAddress JITCompileCallbackManager::executeCompileCallback(
82bd0cb787SLang Hames     JITTargetAddress TrampolineAddr) {
83bd0cb787SLang Hames   SymbolStringPtr Name;
84bd0cb787SLang Hames 
85bd0cb787SLang Hames   {
86bd0cb787SLang Hames     std::unique_lock<std::mutex> Lock(CCMgrMutex);
87bd0cb787SLang Hames     auto I = AddrToSymbol.find(TrampolineAddr);
88bd0cb787SLang Hames 
89bd0cb787SLang Hames     // If this address is not associated with a compile callback then report an
90bd0cb787SLang Hames     // error to the execution session and return ErrorHandlerAddress to the
91bd0cb787SLang Hames     // callee.
92bd0cb787SLang Hames     if (I == AddrToSymbol.end()) {
93bd0cb787SLang Hames       Lock.unlock();
94bd0cb787SLang Hames       std::string ErrMsg;
95bd0cb787SLang Hames       {
96bd0cb787SLang Hames         raw_string_ostream ErrMsgStream(ErrMsg);
97bd0cb787SLang Hames         ErrMsgStream << "No compile callback for trampoline at "
9891449355SLang Hames                      << format("0x%016" PRIx64, TrampolineAddr);
99bd0cb787SLang Hames       }
100bd0cb787SLang Hames       ES.reportError(
101bd0cb787SLang Hames           make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()));
102bd0cb787SLang Hames       return ErrorHandlerAddress;
103bd0cb787SLang Hames     } else
104bd0cb787SLang Hames       Name = I->second;
105bd0cb787SLang Hames   }
106bd0cb787SLang Hames 
107674df13bSLang Hames   if (auto Sym =
108674df13bSLang Hames           ES.lookup(makeJITDylibSearchOrder(
109674df13bSLang Hames                         &CallbacksJD, JITDylibLookupFlags::MatchAllSymbols),
110674df13bSLang Hames                     Name))
111bd0cb787SLang Hames     return Sym->getAddress();
112bd0cb787SLang Hames   else {
1137899ccbcSLang Hames     llvm::dbgs() << "Didn't find callback.\n";
114bd0cb787SLang Hames     // If anything goes wrong materializing Sym then report it to the session
115bd0cb787SLang Hames     // and return the ErrorHandlerAddress;
116bd0cb787SLang Hames     ES.reportError(Sym.takeError());
117bd0cb787SLang Hames     return ErrorHandlerAddress;
118bd0cb787SLang Hames   }
119bd0cb787SLang Hames }
120bd0cb787SLang Hames 
12150b33441SLang Hames Expected<std::unique_ptr<JITCompileCallbackManager>>
createLocalCompileCallbackManager(const Triple & T,ExecutionSession & ES,JITTargetAddress ErrorHandlerAddress)122bd0cb787SLang Hames createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
123ad4a911fSLang Hames                                   JITTargetAddress ErrorHandlerAddress) {
124105518feSLang Hames   switch (T.getArch()) {
12550b33441SLang Hames   default:
12650b33441SLang Hames     return make_error<StringError>(
12750b33441SLang Hames         std::string("No callback manager available for ") + T.str(),
12850b33441SLang Hames         inconvertibleErrorCode());
129f1c28929STim Northover   case Triple::aarch64:
130f1c28929STim Northover   case Triple::aarch64_32: {
131359983bdSLang Hames     typedef orc::LocalJITCompileCallbackManager<orc::OrcAArch64> CCMgrT;
13250b33441SLang Hames     return CCMgrT::Create(ES, ErrorHandlerAddress);
133359983bdSLang Hames     }
134359983bdSLang Hames 
135105518feSLang Hames     case Triple::x86: {
136105518feSLang Hames       typedef orc::LocalJITCompileCallbackManager<orc::OrcI386> CCMgrT;
13750b33441SLang Hames       return CCMgrT::Create(ES, ErrorHandlerAddress);
138105518feSLang Hames     }
139105518feSLang Hames 
1405abf4bb5SPetar Jovanovic     case Triple::mips: {
1415abf4bb5SPetar Jovanovic       typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Be> CCMgrT;
14250b33441SLang Hames       return CCMgrT::Create(ES, ErrorHandlerAddress);
1435abf4bb5SPetar Jovanovic     }
1445abf4bb5SPetar Jovanovic     case Triple::mipsel: {
1455abf4bb5SPetar Jovanovic       typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Le> CCMgrT;
14650b33441SLang Hames       return CCMgrT::Create(ES, ErrorHandlerAddress);
1475abf4bb5SPetar Jovanovic     }
1485abf4bb5SPetar Jovanovic 
1495abf4bb5SPetar Jovanovic     case Triple::mips64:
1505abf4bb5SPetar Jovanovic     case Triple::mips64el: {
1515abf4bb5SPetar Jovanovic       typedef orc::LocalJITCompileCallbackManager<orc::OrcMips64> CCMgrT;
15250b33441SLang Hames       return CCMgrT::Create(ES, ErrorHandlerAddress);
1535abf4bb5SPetar Jovanovic     }
1545abf4bb5SPetar Jovanovic 
155acb408fbSAlex Fan     case Triple::riscv64: {
156acb408fbSAlex Fan       typedef orc::LocalJITCompileCallbackManager<orc::OrcRiscv64> CCMgrT;
157acb408fbSAlex Fan       return CCMgrT::Create(ES, ErrorHandlerAddress);
158acb408fbSAlex Fan     }
159acb408fbSAlex Fan 
160105518feSLang Hames     case Triple::x86_64: {
161105518feSLang Hames       if (T.getOS() == Triple::OSType::Win32) {
162105518feSLang Hames         typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_Win32> CCMgrT;
16350b33441SLang Hames         return CCMgrT::Create(ES, ErrorHandlerAddress);
164105518feSLang Hames       } else {
165105518feSLang Hames         typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_SysV> CCMgrT;
16650b33441SLang Hames         return CCMgrT::Create(ES, ErrorHandlerAddress);
167105518feSLang Hames       }
168105518feSLang Hames     }
169359983bdSLang Hames 
170105518feSLang Hames   }
171105518feSLang Hames }
172105518feSLang Hames 
173105518feSLang Hames std::function<std::unique_ptr<IndirectStubsManager>()>
createLocalIndirectStubsManagerBuilder(const Triple & T)174c321e534SBenjamin Kramer createLocalIndirectStubsManagerBuilder(const Triple &T) {
175105518feSLang Hames   switch (T.getArch()) {
176a95b0df5SLang Hames     default:
177a95b0df5SLang Hames       return [](){
1780eaee545SJonas Devlieghere         return std::make_unique<
179a95b0df5SLang Hames                        orc::LocalIndirectStubsManager<orc::OrcGenericABI>>();
180a95b0df5SLang Hames       };
181105518feSLang Hames 
182359983bdSLang Hames     case Triple::aarch64:
183f1c28929STim Northover     case Triple::aarch64_32:
184359983bdSLang Hames       return [](){
1850eaee545SJonas Devlieghere         return std::make_unique<
186359983bdSLang Hames                        orc::LocalIndirectStubsManager<orc::OrcAArch64>>();
187359983bdSLang Hames       };
188359983bdSLang Hames 
189105518feSLang Hames     case Triple::x86:
190105518feSLang Hames       return [](){
1910eaee545SJonas Devlieghere         return std::make_unique<
192105518feSLang Hames                        orc::LocalIndirectStubsManager<orc::OrcI386>>();
193105518feSLang Hames       };
194105518feSLang Hames 
1955abf4bb5SPetar Jovanovic     case Triple::mips:
1965abf4bb5SPetar Jovanovic       return [](){
1970eaee545SJonas Devlieghere           return std::make_unique<
1985abf4bb5SPetar Jovanovic                       orc::LocalIndirectStubsManager<orc::OrcMips32Be>>();
1995abf4bb5SPetar Jovanovic       };
2005abf4bb5SPetar Jovanovic 
2015abf4bb5SPetar Jovanovic     case Triple::mipsel:
2025abf4bb5SPetar Jovanovic       return [](){
2030eaee545SJonas Devlieghere           return std::make_unique<
2045abf4bb5SPetar Jovanovic                       orc::LocalIndirectStubsManager<orc::OrcMips32Le>>();
2055abf4bb5SPetar Jovanovic       };
2065abf4bb5SPetar Jovanovic 
2075abf4bb5SPetar Jovanovic     case Triple::mips64:
2085abf4bb5SPetar Jovanovic     case Triple::mips64el:
2095abf4bb5SPetar Jovanovic       return [](){
2100eaee545SJonas Devlieghere           return std::make_unique<
2115abf4bb5SPetar Jovanovic                       orc::LocalIndirectStubsManager<orc::OrcMips64>>();
2125abf4bb5SPetar Jovanovic       };
2135abf4bb5SPetar Jovanovic 
214acb408fbSAlex Fan     case Triple::riscv64:
215acb408fbSAlex Fan       return []() {
216acb408fbSAlex Fan         return std::make_unique<
217acb408fbSAlex Fan             orc::LocalIndirectStubsManager<orc::OrcRiscv64>>();
218acb408fbSAlex Fan       };
219acb408fbSAlex Fan 
220105518feSLang Hames     case Triple::x86_64:
221105518feSLang Hames       if (T.getOS() == Triple::OSType::Win32) {
222105518feSLang Hames         return [](){
2230eaee545SJonas Devlieghere           return std::make_unique<
224105518feSLang Hames                      orc::LocalIndirectStubsManager<orc::OrcX86_64_Win32>>();
225105518feSLang Hames         };
226105518feSLang Hames       } else {
227105518feSLang Hames         return [](){
2280eaee545SJonas Devlieghere           return std::make_unique<
229105518feSLang Hames                      orc::LocalIndirectStubsManager<orc::OrcX86_64_SysV>>();
230105518feSLang Hames         };
231105518feSLang Hames       }
232359983bdSLang Hames 
233105518feSLang Hames   }
234105518feSLang Hames }
235105518feSLang Hames 
createIRTypedAddress(FunctionType & FT,JITTargetAddress Addr)236ad4a911fSLang Hames Constant* createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr) {
237eb9bdb5dSLang Hames   Constant *AddrIntVal =
238eb9bdb5dSLang Hames     ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr);
239eb9bdb5dSLang Hames   Constant *AddrPtrVal =
240eb9bdb5dSLang Hames     ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal,
241eb9bdb5dSLang Hames                           PointerType::get(&FT, 0));
242eb9bdb5dSLang Hames   return AddrPtrVal;
243eb9bdb5dSLang Hames }
244eb9bdb5dSLang Hames 
createImplPointer(PointerType & PT,Module & M,const Twine & Name,Constant * Initializer)245eb9bdb5dSLang Hames GlobalVariable* createImplPointer(PointerType &PT, Module &M,
246eb9bdb5dSLang Hames                                   const Twine &Name, Constant *Initializer) {
247cd68eba3SLang Hames   auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage,
2482754714fSLang Hames                                Initializer, Name, nullptr,
24993de2a12SLang Hames                                GlobalValue::NotThreadLocal, 0, true);
250cd68eba3SLang Hames   IP->setVisibility(GlobalValue::HiddenVisibility);
251cd68eba3SLang Hames   return IP;
2522754714fSLang Hames }
25393de2a12SLang Hames 
makeStub(Function & F,Value & ImplPointer)25498c2ac13SLang Hames void makeStub(Function &F, Value &ImplPointer) {
2552754714fSLang Hames   assert(F.isDeclaration() && "Can't turn a definition into a stub.");
2562754714fSLang Hames   assert(F.getParent() && "Function isn't in a module.");
2572754714fSLang Hames   Module &M = *F.getParent();
2582754714fSLang Hames   BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F);
25993de2a12SLang Hames   IRBuilder<> Builder(EntryBlock);
26014359ef1SJames Y Knight   LoadInst *ImplAddr = Builder.CreateLoad(F.getType(), &ImplPointer);
26193de2a12SLang Hames   std::vector<Value*> CallArgs;
2622754714fSLang Hames   for (auto &A : F.args())
2632754714fSLang Hames     CallArgs.push_back(&A);
26414359ef1SJames Y Knight   CallInst *Call = Builder.CreateCall(F.getFunctionType(), ImplAddr, CallArgs);
26593de2a12SLang Hames   Call->setTailCall();
266dc4260dbSLang Hames   Call->setAttributes(F.getAttributes());
267cd68eba3SLang Hames   if (F.getReturnType()->isVoidTy())
268cd68eba3SLang Hames     Builder.CreateRetVoid();
269cd68eba3SLang Hames   else
27093de2a12SLang Hames     Builder.CreateRet(Call);
27193de2a12SLang Hames }
27293de2a12SLang Hames 
operator ()(Module & M)273bf6603e9SLang Hames std::vector<GlobalValue *> SymbolLinkagePromoter::operator()(Module &M) {
274bf6603e9SLang Hames   std::vector<GlobalValue *> PromotedGlobals;
275bf6603e9SLang Hames 
276c5192f75SLang Hames   for (auto &GV : M.global_values()) {
277bf6603e9SLang Hames     bool Promoted = true;
278c6de458fSLang Hames 
279c5192f75SLang Hames     // Rename if necessary.
280c5192f75SLang Hames     if (!GV.hasName())
281c5192f75SLang Hames       GV.setName("__orc_anon." + Twine(NextId++));
282c5192f75SLang Hames     else if (GV.getName().startswith("\01L"))
283c5192f75SLang Hames       GV.setName("__" + GV.getName().substr(1) + "." + Twine(NextId++));
284c5192f75SLang Hames     else if (GV.hasLocalLinkage())
285c5192f75SLang Hames       GV.setName("__orc_lcl." + GV.getName() + "." + Twine(NextId++));
286bf6603e9SLang Hames     else
287bf6603e9SLang Hames       Promoted = false;
288c5192f75SLang Hames 
289c5192f75SLang Hames     if (GV.hasLocalLinkage()) {
290c5192f75SLang Hames       GV.setLinkage(GlobalValue::ExternalLinkage);
291c5192f75SLang Hames       GV.setVisibility(GlobalValue::HiddenVisibility);
292bf6603e9SLang Hames       Promoted = true;
293c6de458fSLang Hames     }
294c5192f75SLang Hames     GV.setUnnamedAddr(GlobalValue::UnnamedAddr::None);
295bf6603e9SLang Hames 
296bf6603e9SLang Hames     if (Promoted)
297bf6603e9SLang Hames       PromotedGlobals.push_back(&GV);
298c6de458fSLang Hames   }
299bf6603e9SLang Hames 
300bf6603e9SLang Hames   return PromotedGlobals;
301cd68eba3SLang Hames }
302cd68eba3SLang Hames 
cloneFunctionDecl(Module & Dst,const Function & F,ValueToValueMapTy * VMap)303cd68eba3SLang Hames Function* cloneFunctionDecl(Module &Dst, const Function &F,
304cd68eba3SLang Hames                             ValueToValueMapTy *VMap) {
305cd68eba3SLang Hames   Function *NewF =
3065f6eaac6SManuel Jacob     Function::Create(cast<FunctionType>(F.getValueType()),
307cd68eba3SLang Hames                      F.getLinkage(), F.getName(), &Dst);
308cd68eba3SLang Hames   NewF->copyAttributesFrom(&F);
309cd68eba3SLang Hames 
310cd68eba3SLang Hames   if (VMap) {
311cd68eba3SLang Hames     (*VMap)[&F] = NewF;
312cd68eba3SLang Hames     auto NewArgI = NewF->arg_begin();
313cd68eba3SLang Hames     for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE;
314cd68eba3SLang Hames          ++ArgI, ++NewArgI)
3151275bffaSDuncan P. N. Exon Smith       (*VMap)[&*ArgI] = &*NewArgI;
316cd68eba3SLang Hames   }
317cd68eba3SLang Hames 
318cd68eba3SLang Hames   return NewF;
319cd68eba3SLang Hames }
320cd68eba3SLang Hames 
moveFunctionBody(Function & OrigF,ValueToValueMapTy & VMap,ValueMaterializer * Materializer,Function * NewF)321cd68eba3SLang Hames void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
322cd68eba3SLang Hames                       ValueMaterializer *Materializer,
323cd68eba3SLang Hames                       Function *NewF) {
324cd68eba3SLang Hames   assert(!OrigF.isDeclaration() && "Nothing to move");
325cd68eba3SLang Hames   if (!NewF)
326cd68eba3SLang Hames     NewF = cast<Function>(VMap[&OrigF]);
3272754714fSLang Hames   else
328cd68eba3SLang Hames     assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap.");
329cd68eba3SLang Hames   assert(NewF && "Function mapping missing from VMap.");
330cd68eba3SLang Hames   assert(NewF->getParent() != OrigF.getParent() &&
331cd68eba3SLang Hames          "moveFunctionBody should only be used to move bodies between "
332cd68eba3SLang Hames          "modules.");
3332754714fSLang Hames 
334cd68eba3SLang Hames   SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
33522a52dfdSDuncan P. N. Exon Smith   CloneFunctionInto(NewF, &OrigF, VMap,
33622a52dfdSDuncan P. N. Exon Smith                     CloneFunctionChangeType::DifferentModule, Returns, "",
33722a52dfdSDuncan P. N. Exon Smith                     nullptr, nullptr, Materializer);
338cd68eba3SLang Hames   OrigF.deleteBody();
339cd68eba3SLang Hames }
3402754714fSLang Hames 
cloneGlobalVariableDecl(Module & Dst,const GlobalVariable & GV,ValueToValueMapTy * VMap)341cd68eba3SLang Hames GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
342cd68eba3SLang Hames                                         ValueToValueMapTy *VMap) {
343cd68eba3SLang Hames   GlobalVariable *NewGV = new GlobalVariable(
3445f6eaac6SManuel Jacob       Dst, GV.getValueType(), GV.isConstant(),
345cd68eba3SLang Hames       GV.getLinkage(), nullptr, GV.getName(), nullptr,
346cd68eba3SLang Hames       GV.getThreadLocalMode(), GV.getType()->getAddressSpace());
347cd68eba3SLang Hames   NewGV->copyAttributesFrom(&GV);
348cd68eba3SLang Hames   if (VMap)
349cd68eba3SLang Hames     (*VMap)[&GV] = NewGV;
350cd68eba3SLang Hames   return NewGV;
351cd68eba3SLang Hames }
352cd68eba3SLang Hames 
moveGlobalVariableInitializer(GlobalVariable & OrigGV,ValueToValueMapTy & VMap,ValueMaterializer * Materializer,GlobalVariable * NewGV)353cd68eba3SLang Hames void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
354cd68eba3SLang Hames                                    ValueToValueMapTy &VMap,
355cd68eba3SLang Hames                                    ValueMaterializer *Materializer,
356cd68eba3SLang Hames                                    GlobalVariable *NewGV) {
357cd68eba3SLang Hames   assert(OrigGV.hasInitializer() && "Nothing to move");
358cd68eba3SLang Hames   if (!NewGV)
359cd68eba3SLang Hames     NewGV = cast<GlobalVariable>(VMap[&OrigGV]);
360cd68eba3SLang Hames   else
361cd68eba3SLang Hames     assert(VMap[&OrigGV] == NewGV &&
362cd68eba3SLang Hames            "Incorrect global variable mapping in VMap.");
363cd68eba3SLang Hames   assert(NewGV->getParent() != OrigGV.getParent() &&
364d3b69c6bSStefan Granitz          "moveGlobalVariableInitializer should only be used to move "
365d3b69c6bSStefan Granitz          "initializers between modules");
366cd68eba3SLang Hames 
367cd68eba3SLang Hames   NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None,
368cd68eba3SLang Hames                                  nullptr, Materializer));
36993de2a12SLang Hames }
37093de2a12SLang Hames 
cloneGlobalAliasDecl(Module & Dst,const GlobalAlias & OrigA,ValueToValueMapTy & VMap)37198c2ac13SLang Hames GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
37298c2ac13SLang Hames                                   ValueToValueMapTy &VMap) {
37344780acdSLang Hames   assert(OrigA.getAliasee() && "Original alias doesn't have an aliasee?");
37444780acdSLang Hames   auto *NewA = GlobalAlias::create(OrigA.getValueType(),
37544780acdSLang Hames                                    OrigA.getType()->getPointerAddressSpace(),
37644780acdSLang Hames                                    OrigA.getLinkage(), OrigA.getName(), &Dst);
37744780acdSLang Hames   NewA->copyAttributesFrom(&OrigA);
37844780acdSLang Hames   VMap[&OrigA] = NewA;
37944780acdSLang Hames   return NewA;
38044780acdSLang Hames }
38144780acdSLang Hames 
cloneModuleFlagsMetadata(Module & Dst,const Module & Src,ValueToValueMapTy & VMap)38238c7927bSLang Hames void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
38338c7927bSLang Hames                               ValueToValueMapTy &VMap) {
38438c7927bSLang Hames   auto *MFs = Src.getModuleFlagsMetadata();
38538c7927bSLang Hames   if (!MFs)
38638c7927bSLang Hames     return;
38738c7927bSLang Hames   for (auto *MF : MFs->operands())
38838c7927bSLang Hames     Dst.addModuleFlag(MapMetadata(MF, VMap));
38938c7927bSLang Hames }
39038c7927bSLang Hames 
addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol & Sym,jitlink::LinkGraph & G,MCDisassembler & Disassembler,MCInstrAnalysis & MIA)391a2639dcbSBen Langmuir Error addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol &Sym,
392a2639dcbSBen Langmuir                                                    jitlink::LinkGraph &G,
393a2639dcbSBen Langmuir                                                    MCDisassembler &Disassembler,
394a2639dcbSBen Langmuir                                                    MCInstrAnalysis &MIA) {
395a2639dcbSBen Langmuir   // AArch64 appears to already come with the necessary relocations. Among other
396a2639dcbSBen Langmuir   // architectures, only x86_64 is currently implemented here.
397a2639dcbSBen Langmuir   if (G.getTargetTriple().getArch() != Triple::x86_64)
398a2639dcbSBen Langmuir     return Error::success();
399a2639dcbSBen Langmuir 
400a2639dcbSBen Langmuir   raw_null_ostream CommentStream;
401a2639dcbSBen Langmuir   auto &STI = Disassembler.getSubtargetInfo();
402a2639dcbSBen Langmuir 
403a2639dcbSBen Langmuir   // Determine the function bounds
404a2639dcbSBen Langmuir   auto &B = Sym.getBlock();
405a2639dcbSBen Langmuir   assert(!B.isZeroFill() && "expected content block");
406a2639dcbSBen Langmuir   auto SymAddress = Sym.getAddress();
407a2639dcbSBen Langmuir   auto SymStartInBlock =
408a2639dcbSBen Langmuir       (const uint8_t *)B.getContent().data() + Sym.getOffset();
409a2639dcbSBen Langmuir   auto SymSize = Sym.getSize() ? Sym.getSize() : B.getSize() - Sym.getOffset();
410a2639dcbSBen Langmuir   auto Content = makeArrayRef(SymStartInBlock, SymSize);
411a2639dcbSBen Langmuir 
412a2639dcbSBen Langmuir   LLVM_DEBUG(dbgs() << "Adding self-relocations to " << Sym.getName() << "\n");
413a2639dcbSBen Langmuir 
414a2639dcbSBen Langmuir   SmallDenseSet<uintptr_t, 8> ExistingRelocations;
415a2639dcbSBen Langmuir   for (auto &E : B.edges()) {
416a2639dcbSBen Langmuir     if (E.isRelocation())
417a2639dcbSBen Langmuir       ExistingRelocations.insert(E.getOffset());
418a2639dcbSBen Langmuir   }
419a2639dcbSBen Langmuir 
420a2639dcbSBen Langmuir   size_t I = 0;
421a2639dcbSBen Langmuir   while (I < Content.size()) {
422a2639dcbSBen Langmuir     MCInst Instr;
423a2639dcbSBen Langmuir     uint64_t InstrSize = 0;
424118e953bSLang Hames     uint64_t InstrStart = SymAddress.getValue() + I;
425a2639dcbSBen Langmuir     auto DecodeStatus = Disassembler.getInstruction(
426a2639dcbSBen Langmuir         Instr, InstrSize, Content.drop_front(I), InstrStart, CommentStream);
427a2639dcbSBen Langmuir     if (DecodeStatus != MCDisassembler::Success) {
428a2639dcbSBen Langmuir       LLVM_DEBUG(dbgs() << "Aborting due to disassembly failure at address "
429a2639dcbSBen Langmuir                         << InstrStart);
430a2639dcbSBen Langmuir       return make_error<StringError>(
431a2639dcbSBen Langmuir           formatv("failed to disassemble at address {0:x16}", InstrStart),
432a2639dcbSBen Langmuir           inconvertibleErrorCode());
433a2639dcbSBen Langmuir     }
434a2639dcbSBen Langmuir     // Advance to the next instruction.
435a2639dcbSBen Langmuir     I += InstrSize;
436a2639dcbSBen Langmuir 
437a2639dcbSBen Langmuir     // Check for a PC-relative address equal to the symbol itself.
438a2639dcbSBen Langmuir     auto PCRelAddr =
439a2639dcbSBen Langmuir         MIA.evaluateMemoryOperandAddress(Instr, &STI, InstrStart, InstrSize);
440118e953bSLang Hames     if (!PCRelAddr || *PCRelAddr != SymAddress.getValue())
441a2639dcbSBen Langmuir       continue;
442a2639dcbSBen Langmuir 
443a2639dcbSBen Langmuir     auto RelocOffInInstr =
444a2639dcbSBen Langmuir         MIA.getMemoryOperandRelocationOffset(Instr, InstrSize);
445*ad7ce1e7SKazu Hirata     if (!RelocOffInInstr || InstrSize - *RelocOffInInstr != 4) {
446a2639dcbSBen Langmuir       LLVM_DEBUG(dbgs() << "Skipping unknown self-relocation at "
447a2639dcbSBen Langmuir                         << InstrStart);
448a2639dcbSBen Langmuir       continue;
449a2639dcbSBen Langmuir     }
450a2639dcbSBen Langmuir 
451118e953bSLang Hames     auto RelocOffInBlock = orc::ExecutorAddr(InstrStart) + *RelocOffInInstr -
452118e953bSLang Hames                            SymAddress + Sym.getOffset();
453a2639dcbSBen Langmuir     if (ExistingRelocations.contains(RelocOffInBlock))
454a2639dcbSBen Langmuir       continue;
455a2639dcbSBen Langmuir 
456a2639dcbSBen Langmuir     LLVM_DEBUG(dbgs() << "Adding delta32 self-relocation at " << InstrStart);
457a2639dcbSBen Langmuir     B.addEdge(jitlink::x86_64::Delta32, RelocOffInBlock, Sym, /*Addend=*/-4);
458a2639dcbSBen Langmuir   }
459a2639dcbSBen Langmuir   return Error::success();
460a2639dcbSBen Langmuir }
461a2639dcbSBen Langmuir 
462e738061cSLang Hames } // End namespace orc.
463e738061cSLang Hames } // End namespace llvm.
464