1 //===---- IndirectionUtils.cpp - Utilities for call indirection in Orc ----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/Triple.h"
12 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
13 #include "llvm/IR/IRBuilder.h"
14 #include "llvm/Support/Format.h"
15 #include "llvm/Transforms/Utils/Cloning.h"
19 using namespace llvm::orc
;
23 class CompileCallbackMaterializationUnit
: public orc::MaterializationUnit
{
25 using CompileFunction
= JITCompileCallbackManager::CompileFunction
;
27 CompileCallbackMaterializationUnit(SymbolStringPtr Name
,
28 CompileFunction Compile
)
29 : MaterializationUnit(SymbolFlagsMap({{Name
, JITSymbolFlags::Exported
}}),
31 Name(std::move(Name
)), Compile(std::move(Compile
)) {}
33 StringRef
getName() const override
{ return "<Compile Callbacks>"; }
36 void materialize(std::unique_ptr
<MaterializationResponsibility
> R
) override
{
38 Result
[Name
] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported
);
39 // No dependencies, so these calls cannot fail.
40 cantFail(R
->notifyResolved(Result
));
41 cantFail(R
->notifyEmitted());
44 void discard(const JITDylib
&JD
, const SymbolStringPtr
&Name
) override
{
45 llvm_unreachable("Discard should never occur on a LMU?");
49 CompileFunction Compile
;
57 TrampolinePool::~TrampolinePool() {}
58 void IndirectStubsManager::anchor() {}
60 Expected
<JITTargetAddress
>
61 JITCompileCallbackManager::getCompileCallback(CompileFunction Compile
) {
62 if (auto TrampolineAddr
= TP
->getTrampoline()) {
64 ES
.intern(std::string("cc") + std::to_string(++NextCallbackId
));
66 std::lock_guard
<std::mutex
> Lock(CCMgrMutex
);
67 AddrToSymbol
[*TrampolineAddr
] = CallbackName
;
69 CallbacksJD
.define(std::make_unique
<CompileCallbackMaterializationUnit
>(
70 std::move(CallbackName
), std::move(Compile
))));
71 return *TrampolineAddr
;
73 return TrampolineAddr
.takeError();
76 JITTargetAddress
JITCompileCallbackManager::executeCompileCallback(
77 JITTargetAddress TrampolineAddr
) {
81 std::unique_lock
<std::mutex
> Lock(CCMgrMutex
);
82 auto I
= AddrToSymbol
.find(TrampolineAddr
);
84 // If this address is not associated with a compile callback then report an
85 // error to the execution session and return ErrorHandlerAddress to the
87 if (I
== AddrToSymbol
.end()) {
91 raw_string_ostream
ErrMsgStream(ErrMsg
);
92 ErrMsgStream
<< "No compile callback for trampoline at "
93 << format("0x%016" PRIx64
, TrampolineAddr
);
96 make_error
<StringError
>(std::move(ErrMsg
), inconvertibleErrorCode()));
97 return ErrorHandlerAddress
;
103 ES
.lookup(makeJITDylibSearchOrder(
104 &CallbacksJD
, JITDylibLookupFlags::MatchAllSymbols
),
106 return Sym
->getAddress();
108 llvm::dbgs() << "Didn't find callback.\n";
109 // If anything goes wrong materializing Sym then report it to the session
110 // and return the ErrorHandlerAddress;
111 ES
.reportError(Sym
.takeError());
112 return ErrorHandlerAddress
;
116 Expected
<std::unique_ptr
<JITCompileCallbackManager
>>
117 createLocalCompileCallbackManager(const Triple
&T
, ExecutionSession
&ES
,
118 JITTargetAddress ErrorHandlerAddress
) {
119 switch (T
.getArch()) {
121 return make_error
<StringError
>(
122 std::string("No callback manager available for ") + T
.str(),
123 inconvertibleErrorCode());
124 case Triple::aarch64
:
125 case Triple::aarch64_32
: {
126 typedef orc::LocalJITCompileCallbackManager
<orc::OrcAArch64
> CCMgrT
;
127 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
131 typedef orc::LocalJITCompileCallbackManager
<orc::OrcI386
> CCMgrT
;
132 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
136 typedef orc::LocalJITCompileCallbackManager
<orc::OrcMips32Be
> CCMgrT
;
137 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
139 case Triple::mipsel
: {
140 typedef orc::LocalJITCompileCallbackManager
<orc::OrcMips32Le
> CCMgrT
;
141 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
145 case Triple::mips64el
: {
146 typedef orc::LocalJITCompileCallbackManager
<orc::OrcMips64
> CCMgrT
;
147 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
150 case Triple::x86_64
: {
151 if (T
.getOS() == Triple::OSType::Win32
) {
152 typedef orc::LocalJITCompileCallbackManager
<orc::OrcX86_64_Win32
> CCMgrT
;
153 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
155 typedef orc::LocalJITCompileCallbackManager
<orc::OrcX86_64_SysV
> CCMgrT
;
156 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
163 std::function
<std::unique_ptr
<IndirectStubsManager
>()>
164 createLocalIndirectStubsManagerBuilder(const Triple
&T
) {
165 switch (T
.getArch()) {
168 return std::make_unique
<
169 orc::LocalIndirectStubsManager
<orc::OrcGenericABI
>>();
172 case Triple::aarch64
:
173 case Triple::aarch64_32
:
175 return std::make_unique
<
176 orc::LocalIndirectStubsManager
<orc::OrcAArch64
>>();
181 return std::make_unique
<
182 orc::LocalIndirectStubsManager
<orc::OrcI386
>>();
187 return std::make_unique
<
188 orc::LocalIndirectStubsManager
<orc::OrcMips32Be
>>();
193 return std::make_unique
<
194 orc::LocalIndirectStubsManager
<orc::OrcMips32Le
>>();
198 case Triple::mips64el
:
200 return std::make_unique
<
201 orc::LocalIndirectStubsManager
<orc::OrcMips64
>>();
205 if (T
.getOS() == Triple::OSType::Win32
) {
207 return std::make_unique
<
208 orc::LocalIndirectStubsManager
<orc::OrcX86_64_Win32
>>();
212 return std::make_unique
<
213 orc::LocalIndirectStubsManager
<orc::OrcX86_64_SysV
>>();
220 Constant
* createIRTypedAddress(FunctionType
&FT
, JITTargetAddress Addr
) {
221 Constant
*AddrIntVal
=
222 ConstantInt::get(Type::getInt64Ty(FT
.getContext()), Addr
);
223 Constant
*AddrPtrVal
=
224 ConstantExpr::getCast(Instruction::IntToPtr
, AddrIntVal
,
225 PointerType::get(&FT
, 0));
229 GlobalVariable
* createImplPointer(PointerType
&PT
, Module
&M
,
230 const Twine
&Name
, Constant
*Initializer
) {
231 auto IP
= new GlobalVariable(M
, &PT
, false, GlobalValue::ExternalLinkage
,
232 Initializer
, Name
, nullptr,
233 GlobalValue::NotThreadLocal
, 0, true);
234 IP
->setVisibility(GlobalValue::HiddenVisibility
);
238 void makeStub(Function
&F
, Value
&ImplPointer
) {
239 assert(F
.isDeclaration() && "Can't turn a definition into a stub.");
240 assert(F
.getParent() && "Function isn't in a module.");
241 Module
&M
= *F
.getParent();
242 BasicBlock
*EntryBlock
= BasicBlock::Create(M
.getContext(), "entry", &F
);
243 IRBuilder
<> Builder(EntryBlock
);
244 LoadInst
*ImplAddr
= Builder
.CreateLoad(F
.getType(), &ImplPointer
);
245 std::vector
<Value
*> CallArgs
;
246 for (auto &A
: F
.args())
247 CallArgs
.push_back(&A
);
248 CallInst
*Call
= Builder
.CreateCall(F
.getFunctionType(), ImplAddr
, CallArgs
);
250 Call
->setAttributes(F
.getAttributes());
251 if (F
.getReturnType()->isVoidTy())
252 Builder
.CreateRetVoid();
254 Builder
.CreateRet(Call
);
257 std::vector
<GlobalValue
*> SymbolLinkagePromoter::operator()(Module
&M
) {
258 std::vector
<GlobalValue
*> PromotedGlobals
;
260 for (auto &GV
: M
.global_values()) {
261 bool Promoted
= true;
263 // Rename if necessary.
265 GV
.setName("__orc_anon." + Twine(NextId
++));
266 else if (GV
.getName().startswith("\01L"))
267 GV
.setName("__" + GV
.getName().substr(1) + "." + Twine(NextId
++));
268 else if (GV
.hasLocalLinkage())
269 GV
.setName("__orc_lcl." + GV
.getName() + "." + Twine(NextId
++));
273 if (GV
.hasLocalLinkage()) {
274 GV
.setLinkage(GlobalValue::ExternalLinkage
);
275 GV
.setVisibility(GlobalValue::HiddenVisibility
);
278 GV
.setUnnamedAddr(GlobalValue::UnnamedAddr::None
);
281 PromotedGlobals
.push_back(&GV
);
284 return PromotedGlobals
;
287 Function
* cloneFunctionDecl(Module
&Dst
, const Function
&F
,
288 ValueToValueMapTy
*VMap
) {
290 Function::Create(cast
<FunctionType
>(F
.getValueType()),
291 F
.getLinkage(), F
.getName(), &Dst
);
292 NewF
->copyAttributesFrom(&F
);
296 auto NewArgI
= NewF
->arg_begin();
297 for (auto ArgI
= F
.arg_begin(), ArgE
= F
.arg_end(); ArgI
!= ArgE
;
299 (*VMap
)[&*ArgI
] = &*NewArgI
;
305 void moveFunctionBody(Function
&OrigF
, ValueToValueMapTy
&VMap
,
306 ValueMaterializer
*Materializer
,
308 assert(!OrigF
.isDeclaration() && "Nothing to move");
310 NewF
= cast
<Function
>(VMap
[&OrigF
]);
312 assert(VMap
[&OrigF
] == NewF
&& "Incorrect function mapping in VMap.");
313 assert(NewF
&& "Function mapping missing from VMap.");
314 assert(NewF
->getParent() != OrigF
.getParent() &&
315 "moveFunctionBody should only be used to move bodies between "
318 SmallVector
<ReturnInst
*, 8> Returns
; // Ignore returns cloned.
319 CloneFunctionInto(NewF
, &OrigF
, VMap
,
320 CloneFunctionChangeType::DifferentModule
, Returns
, "",
321 nullptr, nullptr, Materializer
);
325 GlobalVariable
* cloneGlobalVariableDecl(Module
&Dst
, const GlobalVariable
&GV
,
326 ValueToValueMapTy
*VMap
) {
327 GlobalVariable
*NewGV
= new GlobalVariable(
328 Dst
, GV
.getValueType(), GV
.isConstant(),
329 GV
.getLinkage(), nullptr, GV
.getName(), nullptr,
330 GV
.getThreadLocalMode(), GV
.getType()->getAddressSpace());
331 NewGV
->copyAttributesFrom(&GV
);
333 (*VMap
)[&GV
] = NewGV
;
337 void moveGlobalVariableInitializer(GlobalVariable
&OrigGV
,
338 ValueToValueMapTy
&VMap
,
339 ValueMaterializer
*Materializer
,
340 GlobalVariable
*NewGV
) {
341 assert(OrigGV
.hasInitializer() && "Nothing to move");
343 NewGV
= cast
<GlobalVariable
>(VMap
[&OrigGV
]);
345 assert(VMap
[&OrigGV
] == NewGV
&&
346 "Incorrect global variable mapping in VMap.");
347 assert(NewGV
->getParent() != OrigGV
.getParent() &&
348 "moveGlobalVariableInitializer should only be used to move "
349 "initializers between modules");
351 NewGV
->setInitializer(MapValue(OrigGV
.getInitializer(), VMap
, RF_None
,
352 nullptr, Materializer
));
355 GlobalAlias
* cloneGlobalAliasDecl(Module
&Dst
, const GlobalAlias
&OrigA
,
356 ValueToValueMapTy
&VMap
) {
357 assert(OrigA
.getAliasee() && "Original alias doesn't have an aliasee?");
358 auto *NewA
= GlobalAlias::create(OrigA
.getValueType(),
359 OrigA
.getType()->getPointerAddressSpace(),
360 OrigA
.getLinkage(), OrigA
.getName(), &Dst
);
361 NewA
->copyAttributesFrom(&OrigA
);
366 void cloneModuleFlagsMetadata(Module
&Dst
, const Module
&Src
,
367 ValueToValueMapTy
&VMap
) {
368 auto *MFs
= Src
.getModuleFlagsMetadata();
371 for (auto *MF
: MFs
->operands())
372 Dst
.addModuleFlag(MapMetadata(MF
, VMap
));
375 } // End namespace orc.
376 } // End namespace llvm.