1 //===---- ExecutionUtils.cpp - Utilities for executing functions 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/ExecutionUtils.h"
11 #include "llvm/ExecutionEngine/Orc/Layer.h"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/Function.h"
14 #include "llvm/IR/GlobalVariable.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/Support/TargetRegistry.h"
17 #include "llvm/Target/TargetMachine.h"
22 CtorDtorIterator::CtorDtorIterator(const GlobalVariable
*GV
, bool End
)
24 GV
? dyn_cast_or_null
<ConstantArray
>(GV
->getInitializer()) : nullptr),
25 I((InitList
&& End
) ? InitList
->getNumOperands() : 0) {
28 bool CtorDtorIterator::operator==(const CtorDtorIterator
&Other
) const {
29 assert(InitList
== Other
.InitList
&& "Incomparable iterators.");
33 bool CtorDtorIterator::operator!=(const CtorDtorIterator
&Other
) const {
34 return !(*this == Other
);
37 CtorDtorIterator
& CtorDtorIterator::operator++() {
42 CtorDtorIterator
CtorDtorIterator::operator++(int) {
43 CtorDtorIterator Temp
= *this;
48 CtorDtorIterator::Element
CtorDtorIterator::operator*() const {
49 ConstantStruct
*CS
= dyn_cast
<ConstantStruct
>(InitList
->getOperand(I
));
50 assert(CS
&& "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
52 Constant
*FuncC
= CS
->getOperand(1);
53 Function
*Func
= nullptr;
55 // Extract function pointer, pulling off any casts.
57 if (Function
*F
= dyn_cast_or_null
<Function
>(FuncC
)) {
60 } else if (ConstantExpr
*CE
= dyn_cast_or_null
<ConstantExpr
>(FuncC
)) {
62 FuncC
= dyn_cast_or_null
<ConstantExpr
>(CE
->getOperand(0));
66 // This isn't anything we recognize. Bail out with Func left set to null.
71 ConstantInt
*Priority
= dyn_cast
<ConstantInt
>(CS
->getOperand(0));
72 Value
*Data
= CS
->getNumOperands() == 3 ? CS
->getOperand(2) : nullptr;
73 if (Data
&& !isa
<GlobalValue
>(Data
))
75 return Element(Priority
->getZExtValue(), Func
, Data
);
78 iterator_range
<CtorDtorIterator
> getConstructors(const Module
&M
) {
79 const GlobalVariable
*CtorsList
= M
.getNamedGlobal("llvm.global_ctors");
80 return make_range(CtorDtorIterator(CtorsList
, false),
81 CtorDtorIterator(CtorsList
, true));
84 iterator_range
<CtorDtorIterator
> getDestructors(const Module
&M
) {
85 const GlobalVariable
*DtorsList
= M
.getNamedGlobal("llvm.global_dtors");
86 return make_range(CtorDtorIterator(DtorsList
, false),
87 CtorDtorIterator(DtorsList
, true));
90 void CtorDtorRunner::add(iterator_range
<CtorDtorIterator
> CtorDtors
) {
94 MangleAndInterner
Mangle(
95 JD
.getExecutionSession(),
96 (*CtorDtors
.begin()).Func
->getParent()->getDataLayout());
98 for (const auto &CtorDtor
: CtorDtors
) {
99 assert(CtorDtor
.Func
&& CtorDtor
.Func
->hasName() &&
100 "Ctor/Dtor function must be named to be runnable under the JIT");
102 // FIXME: Maybe use a symbol promoter here instead.
103 if (CtorDtor
.Func
->hasLocalLinkage()) {
104 CtorDtor
.Func
->setLinkage(GlobalValue::ExternalLinkage
);
105 CtorDtor
.Func
->setVisibility(GlobalValue::HiddenVisibility
);
108 if (CtorDtor
.Data
&& cast
<GlobalValue
>(CtorDtor
.Data
)->isDeclaration()) {
109 dbgs() << " Skipping because why now?\n";
113 CtorDtorsByPriority
[CtorDtor
.Priority
].push_back(
114 Mangle(CtorDtor
.Func
->getName()));
118 Error
CtorDtorRunner::run() {
119 using CtorDtorTy
= void (*)();
123 for (auto &KV
: CtorDtorsByPriority
) {
124 for (auto &Name
: KV
.second
) {
125 auto Added
= Names
.insert(Name
).second
;
127 assert(Added
&& "Ctor/Dtor names clashed");
131 auto &ES
= JD
.getExecutionSession();
132 if (auto CtorDtorMap
=
133 ES
.lookup(JITDylibSearchList({{&JD
, true}}), std::move(Names
))) {
134 for (auto &KV
: CtorDtorsByPriority
) {
135 for (auto &Name
: KV
.second
) {
136 assert(CtorDtorMap
->count(Name
) && "No entry for Name");
137 auto CtorDtor
= reinterpret_cast<CtorDtorTy
>(
138 static_cast<uintptr_t>((*CtorDtorMap
)[Name
].getAddress()));
142 CtorDtorsByPriority
.clear();
143 return Error::success();
145 return CtorDtorMap
.takeError();
148 void LocalCXXRuntimeOverridesBase::runDestructors() {
149 auto& CXXDestructorDataPairs
= DSOHandleOverride
;
150 for (auto &P
: CXXDestructorDataPairs
)
152 CXXDestructorDataPairs
.clear();
155 int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor
,
158 auto& CXXDestructorDataPairs
=
159 *reinterpret_cast<CXXDestructorDataPairList
*>(DSOHandle
);
160 CXXDestructorDataPairs
.push_back(std::make_pair(Destructor
, Arg
));
164 Error
LocalCXXRuntimeOverrides::enable(JITDylib
&JD
,
165 MangleAndInterner
&Mangle
) {
166 SymbolMap RuntimeInterposes
;
167 RuntimeInterposes
[Mangle("__dso_handle")] =
168 JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride
),
169 JITSymbolFlags::Exported
);
170 RuntimeInterposes
[Mangle("__cxa_atexit")] =
171 JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride
),
172 JITSymbolFlags::Exported
);
174 return JD
.define(absoluteSymbols(std::move(RuntimeInterposes
)));
177 DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
178 sys::DynamicLibrary Dylib
, char GlobalPrefix
, SymbolPredicate Allow
)
179 : Dylib(std::move(Dylib
)), Allow(std::move(Allow
)),
180 GlobalPrefix(GlobalPrefix
) {}
182 Expected
<std::unique_ptr
<DynamicLibrarySearchGenerator
>>
183 DynamicLibrarySearchGenerator::Load(const char *FileName
, char GlobalPrefix
,
184 SymbolPredicate Allow
) {
186 auto Lib
= sys::DynamicLibrary::getPermanentLibrary(FileName
, &ErrMsg
);
188 return make_error
<StringError
>(std::move(ErrMsg
), inconvertibleErrorCode());
189 return std::make_unique
<DynamicLibrarySearchGenerator
>(
190 std::move(Lib
), GlobalPrefix
, std::move(Allow
));
193 Expected
<SymbolNameSet
>
194 DynamicLibrarySearchGenerator::tryToGenerate(JITDylib
&JD
,
195 const SymbolNameSet
&Names
) {
196 orc::SymbolNameSet Added
;
197 orc::SymbolMap NewSymbols
;
199 bool HasGlobalPrefix
= (GlobalPrefix
!= '\0');
201 for (auto &Name
: Names
) {
205 if (Allow
&& !Allow(Name
))
208 if (HasGlobalPrefix
&& (*Name
).front() != GlobalPrefix
)
211 std::string
Tmp((*Name
).data() + HasGlobalPrefix
,
212 (*Name
).size() - HasGlobalPrefix
);
213 if (void *Addr
= Dylib
.getAddressOfSymbol(Tmp
.c_str())) {
215 NewSymbols
[Name
] = JITEvaluatedSymbol(
216 static_cast<JITTargetAddress
>(reinterpret_cast<uintptr_t>(Addr
)),
217 JITSymbolFlags::Exported
);
221 // Add any new symbols to JD. Since the generator is only called for symbols
222 // that are not already defined, this will never trigger a duplicate
223 // definition error, so we can wrap this call in a 'cantFail'.
224 if (!NewSymbols
.empty())
225 cantFail(JD
.define(absoluteSymbols(std::move(NewSymbols
))));
230 Expected
<std::unique_ptr
<StaticLibraryDefinitionGenerator
>>
231 StaticLibraryDefinitionGenerator::Load(ObjectLayer
&L
, const char *FileName
) {
232 auto ArchiveBuffer
= errorOrToExpected(MemoryBuffer::getFile(FileName
));
235 return ArchiveBuffer
.takeError();
237 return Create(L
, std::move(*ArchiveBuffer
));
240 Expected
<std::unique_ptr
<StaticLibraryDefinitionGenerator
>>
241 StaticLibraryDefinitionGenerator::Create(
242 ObjectLayer
&L
, std::unique_ptr
<MemoryBuffer
> ArchiveBuffer
) {
243 Error Err
= Error::success();
245 std::unique_ptr
<StaticLibraryDefinitionGenerator
> ADG(
246 new StaticLibraryDefinitionGenerator(L
, std::move(ArchiveBuffer
), Err
));
249 return std::move(Err
);
251 return std::move(ADG
);
254 Expected
<SymbolNameSet
>
255 StaticLibraryDefinitionGenerator::tryToGenerate(JITDylib
&JD
,
256 const SymbolNameSet
&Names
) {
258 DenseSet
<std::pair
<StringRef
, StringRef
>> ChildBufferInfos
;
259 SymbolNameSet NewDefs
;
261 for (const auto &Name
: Names
) {
262 auto Child
= Archive
.findSym(*Name
);
264 return Child
.takeError();
267 auto ChildBuffer
= (*Child
)->getMemoryBufferRef();
269 return ChildBuffer
.takeError();
270 ChildBufferInfos
.insert(
271 {ChildBuffer
->getBuffer(), ChildBuffer
->getBufferIdentifier()});
272 NewDefs
.insert(Name
);
275 for (auto ChildBufferInfo
: ChildBufferInfos
) {
276 MemoryBufferRef
ChildBufferRef(ChildBufferInfo
.first
,
277 ChildBufferInfo
.second
);
280 L
.add(JD
, MemoryBuffer::getMemBuffer(ChildBufferRef
), VModuleKey()))
281 return std::move(Err
);
289 StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
290 ObjectLayer
&L
, std::unique_ptr
<MemoryBuffer
> ArchiveBuffer
, Error
&Err
)
291 : L(L
), ArchiveBuffer(std::move(ArchiveBuffer
)),
292 Archive(*this->ArchiveBuffer
, Err
) {
297 Error Err2
= Error::success();
298 for (auto _
: Archive
.children(Err2
)) {
303 // No need to check this: We will leave it to the caller.
304 Err
= std::move(Err2
);
307 } // End namespace orc.
308 } // End namespace llvm.