[AMDGPU] prevent shrinking udiv/urem if either operand is in (SignedMax,UnsignedMax...
[llvm-project.git] / llvm / lib / ExecutionEngine / Orc / ExecutionUtils.cpp
blobedb49a41ecd120eb9fbbda27ef08a5ec8f311f29
1 //===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
10 #include "llvm/ExecutionEngine/JITLink/x86_64.h"
11 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
12 #include "llvm/ExecutionEngine/Orc/Layer.h"
13 #include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h"
14 #include "llvm/ExecutionEngine/Orc/MachO.h"
15 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/Function.h"
18 #include "llvm/IR/GlobalVariable.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/MC/TargetRegistry.h"
21 #include "llvm/Object/MachOUniversal.h"
22 #include "llvm/Support/StringSaver.h"
23 #include "llvm/Target/TargetMachine.h"
24 #include <string>
26 namespace llvm {
27 namespace orc {
29 CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
30 : InitList(
31 GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
32 I((InitList && End) ? InitList->getNumOperands() : 0) {
35 bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const {
36 assert(InitList == Other.InitList && "Incomparable iterators.");
37 return I == Other.I;
40 bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const {
41 return !(*this == Other);
44 CtorDtorIterator& CtorDtorIterator::operator++() {
45 ++I;
46 return *this;
49 CtorDtorIterator CtorDtorIterator::operator++(int) {
50 CtorDtorIterator Temp = *this;
51 ++I;
52 return Temp;
55 CtorDtorIterator::Element CtorDtorIterator::operator*() const {
56 ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
57 assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
59 Constant *FuncC = CS->getOperand(1);
60 Function *Func = nullptr;
62 // Extract function pointer, pulling off any casts.
63 while (FuncC) {
64 if (Function *F = dyn_cast_or_null<Function>(FuncC)) {
65 Func = F;
66 break;
67 } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
68 if (CE->isCast())
69 FuncC = CE->getOperand(0);
70 else
71 break;
72 } else {
73 // This isn't anything we recognize. Bail out with Func left set to null.
74 break;
78 auto *Priority = cast<ConstantInt>(CS->getOperand(0));
79 Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
80 if (Data && !isa<GlobalValue>(Data))
81 Data = nullptr;
82 return Element(Priority->getZExtValue(), Func, Data);
85 iterator_range<CtorDtorIterator> getConstructors(const Module &M) {
86 const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors");
87 return make_range(CtorDtorIterator(CtorsList, false),
88 CtorDtorIterator(CtorsList, true));
91 iterator_range<CtorDtorIterator> getDestructors(const Module &M) {
92 const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors");
93 return make_range(CtorDtorIterator(DtorsList, false),
94 CtorDtorIterator(DtorsList, true));
97 bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) {
98 if (GV.isDeclaration())
99 return false;
101 if (GV.hasName() && (GV.getName() == "llvm.global_ctors" ||
102 GV.getName() == "llvm.global_dtors"))
103 return true;
105 if (ObjFmt == Triple::MachO) {
106 // FIXME: These section checks are too strict: We should match first and
107 // second word split by comma.
108 if (GV.hasSection() &&
109 (GV.getSection().starts_with("__DATA,__objc_classlist") ||
110 GV.getSection().starts_with("__DATA,__objc_selrefs")))
111 return true;
114 return false;
117 void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) {
118 if (CtorDtors.empty())
119 return;
121 MangleAndInterner Mangle(
122 JD.getExecutionSession(),
123 (*CtorDtors.begin()).Func->getDataLayout());
125 for (auto CtorDtor : CtorDtors) {
126 assert(CtorDtor.Func && CtorDtor.Func->hasName() &&
127 "Ctor/Dtor function must be named to be runnable under the JIT");
129 // FIXME: Maybe use a symbol promoter here instead.
130 if (CtorDtor.Func->hasLocalLinkage()) {
131 CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage);
132 CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility);
135 if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) {
136 dbgs() << " Skipping because why now?\n";
137 continue;
140 CtorDtorsByPriority[CtorDtor.Priority].push_back(
141 Mangle(CtorDtor.Func->getName()));
145 Error CtorDtorRunner::run() {
146 using CtorDtorTy = void (*)();
148 SymbolLookupSet LookupSet;
149 for (auto &KV : CtorDtorsByPriority)
150 for (auto &Name : KV.second)
151 LookupSet.add(Name);
152 assert(!LookupSet.containsDuplicates() &&
153 "Ctor/Dtor list contains duplicates");
155 auto &ES = JD.getExecutionSession();
156 if (auto CtorDtorMap = ES.lookup(
157 makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols),
158 std::move(LookupSet))) {
159 for (auto &KV : CtorDtorsByPriority) {
160 for (auto &Name : KV.second) {
161 assert(CtorDtorMap->count(Name) && "No entry for Name");
162 auto CtorDtor = (*CtorDtorMap)[Name].getAddress().toPtr<CtorDtorTy>();
163 CtorDtor();
166 CtorDtorsByPriority.clear();
167 return Error::success();
168 } else
169 return CtorDtorMap.takeError();
172 void LocalCXXRuntimeOverridesBase::runDestructors() {
173 auto& CXXDestructorDataPairs = DSOHandleOverride;
174 for (auto &P : CXXDestructorDataPairs)
175 P.first(P.second);
176 CXXDestructorDataPairs.clear();
179 int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
180 void *Arg,
181 void *DSOHandle) {
182 auto& CXXDestructorDataPairs =
183 *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
184 CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
185 return 0;
188 Error LocalCXXRuntimeOverrides::enable(JITDylib &JD,
189 MangleAndInterner &Mangle) {
190 SymbolMap RuntimeInterposes;
191 RuntimeInterposes[Mangle("__dso_handle")] = {
192 ExecutorAddr::fromPtr(&DSOHandleOverride), JITSymbolFlags::Exported};
193 RuntimeInterposes[Mangle("__cxa_atexit")] = {
194 ExecutorAddr::fromPtr(&CXAAtExitOverride), JITSymbolFlags::Exported};
196 return JD.define(absoluteSymbols(std::move(RuntimeInterposes)));
199 void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx,
200 void *DSOHandle) {
201 std::lock_guard<std::mutex> Lock(AtExitsMutex);
202 AtExitRecords[DSOHandle].push_back({F, Ctx});
205 void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) {
206 std::vector<AtExitRecord> AtExitsToRun;
209 std::lock_guard<std::mutex> Lock(AtExitsMutex);
210 auto I = AtExitRecords.find(DSOHandle);
211 if (I != AtExitRecords.end()) {
212 AtExitsToRun = std::move(I->second);
213 AtExitRecords.erase(I);
217 while (!AtExitsToRun.empty()) {
218 AtExitsToRun.back().F(AtExitsToRun.back().Ctx);
219 AtExitsToRun.pop_back();
223 DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
224 sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow,
225 AddAbsoluteSymbolsFn AddAbsoluteSymbols)
226 : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
227 AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)),
228 GlobalPrefix(GlobalPrefix) {}
230 Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
231 DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
232 SymbolPredicate Allow,
233 AddAbsoluteSymbolsFn AddAbsoluteSymbols) {
234 std::string ErrMsg;
235 auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
236 if (!Lib.isValid())
237 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
238 return std::make_unique<DynamicLibrarySearchGenerator>(
239 std::move(Lib), GlobalPrefix, std::move(Allow),
240 std::move(AddAbsoluteSymbols));
243 Error DynamicLibrarySearchGenerator::tryToGenerate(
244 LookupState &LS, LookupKind K, JITDylib &JD,
245 JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
246 orc::SymbolMap NewSymbols;
248 bool HasGlobalPrefix = (GlobalPrefix != '\0');
250 for (auto &KV : Symbols) {
251 auto &Name = KV.first;
253 if ((*Name).empty())
254 continue;
256 if (Allow && !Allow(Name))
257 continue;
259 if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
260 continue;
262 std::string Tmp((*Name).data() + HasGlobalPrefix,
263 (*Name).size() - HasGlobalPrefix);
264 if (void *P = Dylib.getAddressOfSymbol(Tmp.c_str()))
265 NewSymbols[Name] = {ExecutorAddr::fromPtr(P), JITSymbolFlags::Exported};
268 if (NewSymbols.empty())
269 return Error::success();
271 if (AddAbsoluteSymbols)
272 return AddAbsoluteSymbols(JD, std::move(NewSymbols));
273 return JD.define(absoluteSymbols(std::move(NewSymbols)));
276 StaticLibraryDefinitionGenerator::VisitMembersFunction
277 StaticLibraryDefinitionGenerator::loadAllObjectFileMembers(ObjectLayer &L,
278 JITDylib &JD) {
279 return [&](MemoryBufferRef Buf) -> Error {
280 switch (identify_magic(Buf.getBuffer())) {
281 case file_magic::elf_relocatable:
282 case file_magic::macho_object:
283 case file_magic::coff_object:
284 return L.add(JD, MemoryBuffer::getMemBuffer(Buf));
285 default:
286 return Error::success();
291 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
292 StaticLibraryDefinitionGenerator::Load(
293 ObjectLayer &L, const char *FileName, VisitMembersFunction VisitMembers,
294 GetObjectFileInterface GetObjFileInterface) {
296 const auto &TT = L.getExecutionSession().getTargetTriple();
297 auto Linkable = loadLinkableFile(FileName, TT, LoadArchives::Required);
298 if (!Linkable)
299 return Linkable.takeError();
301 return Create(L, std::move(Linkable->first), std::move(VisitMembers),
302 std::move(GetObjFileInterface));
305 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
306 StaticLibraryDefinitionGenerator::Create(
307 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
308 std::unique_ptr<object::Archive> Archive, VisitMembersFunction VisitMembers,
309 GetObjectFileInterface GetObjFileInterface) {
311 Error Err = Error::success();
313 if (VisitMembers) {
314 for (auto Child : Archive->children(Err)) {
315 if (auto ChildBuf = Child.getMemoryBufferRef()) {
316 if (auto Err2 = VisitMembers(*ChildBuf))
317 return std::move(Err2);
318 } else {
319 // We silently allow non-object archive members. This matches the
320 // behavior of ld.
321 consumeError(ChildBuf.takeError());
324 if (Err)
325 return std::move(Err);
328 std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
329 new StaticLibraryDefinitionGenerator(
330 L, std::move(ArchiveBuffer), std::move(Archive),
331 std::move(GetObjFileInterface), Err));
333 if (Err)
334 return std::move(Err);
336 return std::move(ADG);
339 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
340 StaticLibraryDefinitionGenerator::Create(
341 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
342 VisitMembersFunction VisitMembers,
343 GetObjectFileInterface GetObjFileInterface) {
345 auto B = object::createBinary(ArchiveBuffer->getMemBufferRef());
346 if (!B)
347 return B.takeError();
349 // If this is a regular archive then create an instance from it.
350 if (isa<object::Archive>(*B))
351 return Create(L, std::move(ArchiveBuffer),
352 std::unique_ptr<object::Archive>(
353 static_cast<object::Archive *>(B->release())),
354 std::move(VisitMembers), std::move(GetObjFileInterface));
356 // If this is a universal binary then search for a slice matching the given
357 // Triple.
358 if (auto *UB = dyn_cast<object::MachOUniversalBinary>(B->get())) {
360 const auto &TT = L.getExecutionSession().getTargetTriple();
362 auto SliceRange = getMachOSliceRangeForTriple(*UB, TT);
363 if (!SliceRange)
364 return SliceRange.takeError();
366 MemoryBufferRef SliceRef(
367 StringRef(ArchiveBuffer->getBufferStart() + SliceRange->first,
368 SliceRange->second),
369 ArchiveBuffer->getBufferIdentifier());
371 auto Archive = object::Archive::create(SliceRef);
372 if (!Archive)
373 return Archive.takeError();
375 return Create(L, std::move(ArchiveBuffer), std::move(*Archive),
376 std::move(VisitMembers), std::move(GetObjFileInterface));
379 return make_error<StringError>(Twine("Unrecognized file type for ") +
380 ArchiveBuffer->getBufferIdentifier(),
381 inconvertibleErrorCode());
384 Error StaticLibraryDefinitionGenerator::tryToGenerate(
385 LookupState &LS, LookupKind K, JITDylib &JD,
386 JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
387 // Don't materialize symbols from static archives unless this is a static
388 // lookup.
389 if (K != LookupKind::Static)
390 return Error::success();
392 // Bail out early if we've already freed the archive.
393 if (!Archive)
394 return Error::success();
396 DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos;
398 for (const auto &KV : Symbols) {
399 const auto &Name = KV.first;
400 if (!ObjectFilesMap.count(Name))
401 continue;
402 auto ChildBuffer = ObjectFilesMap[Name];
403 ChildBufferInfos.insert(
404 {ChildBuffer.getBuffer(), ChildBuffer.getBufferIdentifier()});
407 for (auto ChildBufferInfo : ChildBufferInfos) {
408 MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
409 ChildBufferInfo.second);
411 auto I = GetObjFileInterface(L.getExecutionSession(), ChildBufferRef);
412 if (!I)
413 return I.takeError();
415 if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false),
416 std::move(*I)))
417 return Err;
420 return Error::success();
423 Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() {
424 DenseMap<uint64_t, MemoryBufferRef> MemoryBuffers;
425 DenseSet<uint64_t> Visited;
426 DenseSet<uint64_t> Excluded;
427 StringSaver FileNames(ObjFileNameStorage);
428 for (auto &S : Archive->symbols()) {
429 StringRef SymName = S.getName();
430 auto Member = S.getMember();
431 if (!Member)
432 return Member.takeError();
433 auto DataOffset = Member->getDataOffset();
434 if (!Visited.count(DataOffset)) {
435 Visited.insert(DataOffset);
436 auto Child = Member->getAsBinary();
437 if (!Child)
438 return Child.takeError();
439 if ((*Child)->isCOFFImportFile()) {
440 ImportedDynamicLibraries.insert((*Child)->getFileName().str());
441 Excluded.insert(DataOffset);
442 continue;
445 // Give members of the archive a name that contains the archive path so
446 // that they can be differentiated from a member with the same name in a
447 // different archive. This also ensure initializer symbols names will be
448 // unique within a JITDylib.
449 StringRef FullName = FileNames.save(Archive->getFileName() + "(" +
450 (*Child)->getFileName() + ")");
451 MemoryBufferRef MemBuffer((*Child)->getMemoryBufferRef().getBuffer(),
452 FullName);
454 MemoryBuffers[DataOffset] = MemBuffer;
456 if (!Excluded.count(DataOffset))
457 ObjectFilesMap[L.getExecutionSession().intern(SymName)] =
458 MemoryBuffers[DataOffset];
461 return Error::success();
464 StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
465 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
466 std::unique_ptr<object::Archive> Archive,
467 GetObjectFileInterface GetObjFileInterface, Error &Err)
468 : L(L), GetObjFileInterface(std::move(GetObjFileInterface)),
469 ArchiveBuffer(std::move(ArchiveBuffer)), Archive(std::move(Archive)) {
470 ErrorAsOutParameter _(&Err);
471 if (!this->GetObjFileInterface)
472 this->GetObjFileInterface = getObjectFileInterface;
473 if (!Err)
474 Err = buildObjectFilesMap();
477 std::unique_ptr<DLLImportDefinitionGenerator>
478 DLLImportDefinitionGenerator::Create(ExecutionSession &ES,
479 ObjectLinkingLayer &L) {
480 return std::unique_ptr<DLLImportDefinitionGenerator>(
481 new DLLImportDefinitionGenerator(ES, L));
484 Error DLLImportDefinitionGenerator::tryToGenerate(
485 LookupState &LS, LookupKind K, JITDylib &JD,
486 JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
487 JITDylibSearchOrder LinkOrder;
488 JD.withLinkOrderDo([&](const JITDylibSearchOrder &LO) {
489 LinkOrder.reserve(LO.size());
490 for (auto &KV : LO) {
491 if (KV.first == &JD)
492 continue;
493 LinkOrder.push_back(KV);
497 // FIXME: if regular symbol name start with __imp_ we have to issue lookup of
498 // both __imp_ and stripped name and use the lookup information to resolve the
499 // real symbol name.
500 SymbolLookupSet LookupSet;
501 DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols;
502 for (auto &KV : Symbols) {
503 StringRef Deinterned = *KV.first;
504 if (Deinterned.starts_with(getImpPrefix()))
505 Deinterned = Deinterned.drop_front(StringRef(getImpPrefix()).size());
506 // Don't degrade the required state
507 if (ToLookUpSymbols.count(Deinterned) &&
508 ToLookUpSymbols[Deinterned] == SymbolLookupFlags::RequiredSymbol)
509 continue;
510 ToLookUpSymbols[Deinterned] = KV.second;
513 for (auto &KV : ToLookUpSymbols)
514 LookupSet.add(ES.intern(KV.first), KV.second);
516 auto Resolved =
517 ES.lookup(LinkOrder, LookupSet, LookupKind::DLSym, SymbolState::Resolved);
518 if (!Resolved)
519 return Resolved.takeError();
521 auto G = createStubsGraph(*Resolved);
522 if (!G)
523 return G.takeError();
524 return L.add(JD, std::move(*G));
527 Expected<unsigned>
528 DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) {
529 switch (TT.getArch()) {
530 case Triple::x86_64:
531 return 8;
532 default:
533 return make_error<StringError>(
534 "architecture unsupported by DLLImportDefinitionGenerator",
535 inconvertibleErrorCode());
539 Expected<llvm::endianness>
540 DLLImportDefinitionGenerator::getEndianness(const Triple &TT) {
541 switch (TT.getArch()) {
542 case Triple::x86_64:
543 return llvm::endianness::little;
544 default:
545 return make_error<StringError>(
546 "architecture unsupported by DLLImportDefinitionGenerator",
547 inconvertibleErrorCode());
551 Expected<std::unique_ptr<jitlink::LinkGraph>>
552 DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) {
553 Triple TT = ES.getTargetTriple();
554 auto PointerSize = getTargetPointerSize(TT);
555 if (!PointerSize)
556 return PointerSize.takeError();
557 auto Endianness = getEndianness(TT);
558 if (!Endianness)
559 return Endianness.takeError();
561 auto G = std::make_unique<jitlink::LinkGraph>(
562 "<DLLIMPORT_STUBS>", TT, *PointerSize, *Endianness,
563 jitlink::getGenericEdgeKindName);
564 jitlink::Section &Sec =
565 G->createSection(getSectionName(), MemProt::Read | MemProt::Exec);
567 for (auto &KV : Resolved) {
568 jitlink::Symbol &Target = G->addAbsoluteSymbol(
569 *KV.first, KV.second.getAddress(), *PointerSize,
570 jitlink::Linkage::Strong, jitlink::Scope::Local, false);
572 // Create __imp_ symbol
573 jitlink::Symbol &Ptr =
574 jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target);
575 auto NameCopy = G->allocateContent(Twine(getImpPrefix()) + *KV.first);
576 StringRef NameCopyRef = StringRef(NameCopy.data(), NameCopy.size());
577 Ptr.setName(NameCopyRef);
578 Ptr.setLinkage(jitlink::Linkage::Strong);
579 Ptr.setScope(jitlink::Scope::Default);
581 // Create PLT stub
582 // FIXME: check PLT stub of data symbol is not accessed
583 jitlink::Block &StubBlock =
584 jitlink::x86_64::createPointerJumpStubBlock(*G, Sec, Ptr);
585 G->addDefinedSymbol(StubBlock, 0, *KV.first, StubBlock.getSize(),
586 jitlink::Linkage::Strong, jitlink::Scope::Default, true,
587 false);
590 return std::move(G);
593 } // End namespace orc.
594 } // End namespace llvm.