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/CallSite.h"
14 #include "llvm/IR/IRBuilder.h"
15 #include "llvm/Support/Format.h"
16 #include "llvm/Transforms/Utils/Cloning.h"
20 using namespace llvm::orc
;
24 class CompileCallbackMaterializationUnit
: public orc::MaterializationUnit
{
26 using CompileFunction
= JITCompileCallbackManager::CompileFunction
;
28 CompileCallbackMaterializationUnit(SymbolStringPtr Name
,
29 CompileFunction Compile
, VModuleKey K
)
30 : MaterializationUnit(SymbolFlagsMap({{Name
, JITSymbolFlags::Exported
}}),
32 Name(std::move(Name
)), Compile(std::move(Compile
)) {}
34 StringRef
getName() const override
{ return "<Compile Callbacks>"; }
37 void materialize(MaterializationResponsibility R
) override
{
39 Result
[Name
] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported
);
40 // No dependencies, so these calls cannot fail.
41 cantFail(R
.notifyResolved(Result
));
42 cantFail(R
.notifyEmitted());
45 void discard(const JITDylib
&JD
, const SymbolStringPtr
&Name
) override
{
46 llvm_unreachable("Discard should never occur on a LMU?");
50 CompileFunction Compile
;
58 void IndirectStubsManager::anchor() {}
59 void TrampolinePool::anchor() {}
61 Expected
<JITTargetAddress
>
62 JITCompileCallbackManager::getCompileCallback(CompileFunction Compile
) {
63 if (auto TrampolineAddr
= TP
->getTrampoline()) {
65 ES
.intern(std::string("cc") + std::to_string(++NextCallbackId
));
67 std::lock_guard
<std::mutex
> Lock(CCMgrMutex
);
68 AddrToSymbol
[*TrampolineAddr
] = CallbackName
;
69 cantFail(CallbacksJD
.define(
70 std::make_unique
<CompileCallbackMaterializationUnit
>(
71 std::move(CallbackName
), std::move(Compile
),
72 ES
.allocateVModule())));
73 return *TrampolineAddr
;
75 return TrampolineAddr
.takeError();
78 JITTargetAddress
JITCompileCallbackManager::executeCompileCallback(
79 JITTargetAddress TrampolineAddr
) {
83 std::unique_lock
<std::mutex
> Lock(CCMgrMutex
);
84 auto I
= AddrToSymbol
.find(TrampolineAddr
);
86 // If this address is not associated with a compile callback then report an
87 // error to the execution session and return ErrorHandlerAddress to the
89 if (I
== AddrToSymbol
.end()) {
93 raw_string_ostream
ErrMsgStream(ErrMsg
);
94 ErrMsgStream
<< "No compile callback for trampoline at "
95 << format("0x%016" PRIx64
, TrampolineAddr
);
98 make_error
<StringError
>(std::move(ErrMsg
), inconvertibleErrorCode()));
99 return ErrorHandlerAddress
;
104 if (auto Sym
= ES
.lookup(JITDylibSearchList({{&CallbacksJD
, true}}), Name
))
105 return Sym
->getAddress();
107 llvm::dbgs() << "Didn't find callback.\n";
108 // If anything goes wrong materializing Sym then report it to the session
109 // and return the ErrorHandlerAddress;
110 ES
.reportError(Sym
.takeError());
111 return ErrorHandlerAddress
;
115 Expected
<std::unique_ptr
<JITCompileCallbackManager
>>
116 createLocalCompileCallbackManager(const Triple
&T
, ExecutionSession
&ES
,
117 JITTargetAddress ErrorHandlerAddress
) {
118 switch (T
.getArch()) {
120 return make_error
<StringError
>(
121 std::string("No callback manager available for ") + T
.str(),
122 inconvertibleErrorCode());
123 case Triple::aarch64
:
124 case Triple::aarch64_32
: {
125 typedef orc::LocalJITCompileCallbackManager
<orc::OrcAArch64
> CCMgrT
;
126 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
130 typedef orc::LocalJITCompileCallbackManager
<orc::OrcI386
> CCMgrT
;
131 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
135 typedef orc::LocalJITCompileCallbackManager
<orc::OrcMips32Be
> CCMgrT
;
136 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
138 case Triple::mipsel
: {
139 typedef orc::LocalJITCompileCallbackManager
<orc::OrcMips32Le
> CCMgrT
;
140 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
144 case Triple::mips64el
: {
145 typedef orc::LocalJITCompileCallbackManager
<orc::OrcMips64
> CCMgrT
;
146 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
149 case Triple::x86_64
: {
150 if ( T
.getOS() == Triple::OSType::Win32
) {
151 typedef orc::LocalJITCompileCallbackManager
<orc::OrcX86_64_Win32
> CCMgrT
;
152 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
154 typedef orc::LocalJITCompileCallbackManager
<orc::OrcX86_64_SysV
> CCMgrT
;
155 return CCMgrT::Create(ES
, ErrorHandlerAddress
);
162 std::function
<std::unique_ptr
<IndirectStubsManager
>()>
163 createLocalIndirectStubsManagerBuilder(const Triple
&T
) {
164 switch (T
.getArch()) {
167 return std::make_unique
<
168 orc::LocalIndirectStubsManager
<orc::OrcGenericABI
>>();
171 case Triple::aarch64
:
172 case Triple::aarch64_32
:
174 return std::make_unique
<
175 orc::LocalIndirectStubsManager
<orc::OrcAArch64
>>();
180 return std::make_unique
<
181 orc::LocalIndirectStubsManager
<orc::OrcI386
>>();
186 return std::make_unique
<
187 orc::LocalIndirectStubsManager
<orc::OrcMips32Be
>>();
192 return std::make_unique
<
193 orc::LocalIndirectStubsManager
<orc::OrcMips32Le
>>();
197 case Triple::mips64el
:
199 return std::make_unique
<
200 orc::LocalIndirectStubsManager
<orc::OrcMips64
>>();
204 if (T
.getOS() == Triple::OSType::Win32
) {
206 return std::make_unique
<
207 orc::LocalIndirectStubsManager
<orc::OrcX86_64_Win32
>>();
211 return std::make_unique
<
212 orc::LocalIndirectStubsManager
<orc::OrcX86_64_SysV
>>();
219 Constant
* createIRTypedAddress(FunctionType
&FT
, JITTargetAddress Addr
) {
220 Constant
*AddrIntVal
=
221 ConstantInt::get(Type::getInt64Ty(FT
.getContext()), Addr
);
222 Constant
*AddrPtrVal
=
223 ConstantExpr::getCast(Instruction::IntToPtr
, AddrIntVal
,
224 PointerType::get(&FT
, 0));
228 GlobalVariable
* createImplPointer(PointerType
&PT
, Module
&M
,
229 const Twine
&Name
, Constant
*Initializer
) {
230 auto IP
= new GlobalVariable(M
, &PT
, false, GlobalValue::ExternalLinkage
,
231 Initializer
, Name
, nullptr,
232 GlobalValue::NotThreadLocal
, 0, true);
233 IP
->setVisibility(GlobalValue::HiddenVisibility
);
237 void makeStub(Function
&F
, Value
&ImplPointer
) {
238 assert(F
.isDeclaration() && "Can't turn a definition into a stub.");
239 assert(F
.getParent() && "Function isn't in a module.");
240 Module
&M
= *F
.getParent();
241 BasicBlock
*EntryBlock
= BasicBlock::Create(M
.getContext(), "entry", &F
);
242 IRBuilder
<> Builder(EntryBlock
);
243 LoadInst
*ImplAddr
= Builder
.CreateLoad(F
.getType(), &ImplPointer
);
244 std::vector
<Value
*> CallArgs
;
245 for (auto &A
: F
.args())
246 CallArgs
.push_back(&A
);
247 CallInst
*Call
= Builder
.CreateCall(F
.getFunctionType(), ImplAddr
, CallArgs
);
249 Call
->setAttributes(F
.getAttributes());
250 if (F
.getReturnType()->isVoidTy())
251 Builder
.CreateRetVoid();
253 Builder
.CreateRet(Call
);
256 std::vector
<GlobalValue
*> SymbolLinkagePromoter::operator()(Module
&M
) {
257 std::vector
<GlobalValue
*> PromotedGlobals
;
259 for (auto &GV
: M
.global_values()) {
260 bool Promoted
= true;
262 // Rename if necessary.
264 GV
.setName("__orc_anon." + Twine(NextId
++));
265 else if (GV
.getName().startswith("\01L"))
266 GV
.setName("__" + GV
.getName().substr(1) + "." + Twine(NextId
++));
267 else if (GV
.hasLocalLinkage())
268 GV
.setName("__orc_lcl." + GV
.getName() + "." + Twine(NextId
++));
272 if (GV
.hasLocalLinkage()) {
273 GV
.setLinkage(GlobalValue::ExternalLinkage
);
274 GV
.setVisibility(GlobalValue::HiddenVisibility
);
277 GV
.setUnnamedAddr(GlobalValue::UnnamedAddr::None
);
280 PromotedGlobals
.push_back(&GV
);
283 return PromotedGlobals
;
286 Function
* cloneFunctionDecl(Module
&Dst
, const Function
&F
,
287 ValueToValueMapTy
*VMap
) {
289 Function::Create(cast
<FunctionType
>(F
.getValueType()),
290 F
.getLinkage(), F
.getName(), &Dst
);
291 NewF
->copyAttributesFrom(&F
);
295 auto NewArgI
= NewF
->arg_begin();
296 for (auto ArgI
= F
.arg_begin(), ArgE
= F
.arg_end(); ArgI
!= ArgE
;
298 (*VMap
)[&*ArgI
] = &*NewArgI
;
304 void moveFunctionBody(Function
&OrigF
, ValueToValueMapTy
&VMap
,
305 ValueMaterializer
*Materializer
,
307 assert(!OrigF
.isDeclaration() && "Nothing to move");
309 NewF
= cast
<Function
>(VMap
[&OrigF
]);
311 assert(VMap
[&OrigF
] == NewF
&& "Incorrect function mapping in VMap.");
312 assert(NewF
&& "Function mapping missing from VMap.");
313 assert(NewF
->getParent() != OrigF
.getParent() &&
314 "moveFunctionBody should only be used to move bodies between "
317 SmallVector
<ReturnInst
*, 8> Returns
; // Ignore returns cloned.
318 CloneFunctionInto(NewF
, &OrigF
, VMap
, /*ModuleLevelChanges=*/true, Returns
,
319 "", nullptr, nullptr, Materializer
);
323 GlobalVariable
* cloneGlobalVariableDecl(Module
&Dst
, const GlobalVariable
&GV
,
324 ValueToValueMapTy
*VMap
) {
325 GlobalVariable
*NewGV
= new GlobalVariable(
326 Dst
, GV
.getValueType(), GV
.isConstant(),
327 GV
.getLinkage(), nullptr, GV
.getName(), nullptr,
328 GV
.getThreadLocalMode(), GV
.getType()->getAddressSpace());
329 NewGV
->copyAttributesFrom(&GV
);
331 (*VMap
)[&GV
] = NewGV
;
335 void moveGlobalVariableInitializer(GlobalVariable
&OrigGV
,
336 ValueToValueMapTy
&VMap
,
337 ValueMaterializer
*Materializer
,
338 GlobalVariable
*NewGV
) {
339 assert(OrigGV
.hasInitializer() && "Nothing to move");
341 NewGV
= cast
<GlobalVariable
>(VMap
[&OrigGV
]);
343 assert(VMap
[&OrigGV
] == NewGV
&&
344 "Incorrect global variable mapping in VMap.");
345 assert(NewGV
->getParent() != OrigGV
.getParent() &&
346 "moveGlobalVariableInitializer should only be used to move "
347 "initializers between modules");
349 NewGV
->setInitializer(MapValue(OrigGV
.getInitializer(), VMap
, RF_None
,
350 nullptr, Materializer
));
353 GlobalAlias
* cloneGlobalAliasDecl(Module
&Dst
, const GlobalAlias
&OrigA
,
354 ValueToValueMapTy
&VMap
) {
355 assert(OrigA
.getAliasee() && "Original alias doesn't have an aliasee?");
356 auto *NewA
= GlobalAlias::create(OrigA
.getValueType(),
357 OrigA
.getType()->getPointerAddressSpace(),
358 OrigA
.getLinkage(), OrigA
.getName(), &Dst
);
359 NewA
->copyAttributesFrom(&OrigA
);
364 void cloneModuleFlagsMetadata(Module
&Dst
, const Module
&Src
,
365 ValueToValueMapTy
&VMap
) {
366 auto *MFs
= Src
.getModuleFlagsMetadata();
369 for (auto *MF
: MFs
->operands())
370 Dst
.addModuleFlag(MapMetadata(MF
, VMap
));
373 } // End namespace orc.
374 } // End namespace llvm.