LLVM 22.0.0git
ELFDebugObjectPlugin.cpp
Go to the documentation of this file.
1//===--------- ELFDebugObjectPlugin.cpp - JITLink debug objects -----------===//
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//===----------------------------------------------------------------------===//
8//
9// FIXME: Update Plugin to poke the debug object into a new JITLink section,
10// rather than creating a new allocation.
11//
12//===----------------------------------------------------------------------===//
13
15
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/StringMap.h"
18#include "llvm/ADT/StringRef.h"
24#include "llvm/Support/Errc.h"
29
30#include <set>
31
32#define DEBUG_TYPE "orc"
33
34using namespace llvm::jitlink;
35using namespace llvm::object;
36
37namespace llvm {
38namespace orc {
39
41public:
43 virtual void dump(raw_ostream &OS, StringRef Name) {}
44 virtual ~DebugObjectSection() = default;
45};
46
47template <typename ELFT>
49public:
50 // BinaryFormat ELF is not meant as a mutable format. We can only make changes
51 // that don't invalidate the file structure.
52 ELFDebugObjectSection(const typename ELFT::Shdr *Header)
53 : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
54
56 void dump(raw_ostream &OS, StringRef Name) override;
57
58 Error validateInBounds(StringRef Buffer, const char *Name) const;
59
60private:
61 typename ELFT::Shdr *Header;
62};
63
64template <typename ELFT>
66 // All recorded sections are candidates for load-address patching.
67 Header->sh_addr =
68 static_cast<typename ELFT::uint>(Range.getStart().getValue());
69}
70
71template <typename ELFT>
73 const char *Name) const {
74 const uint8_t *Start = Buffer.bytes_begin();
75 const uint8_t *End = Buffer.bytes_end();
76 const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
77 if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
79 formatv("{0} section header at {1:x16} not within bounds of the "
80 "given debug object buffer [{2:x16} - {3:x16}]",
81 Name, &Header->sh_addr, Start, End),
83 if (Header->sh_offset + Header->sh_size > Buffer.size())
85 formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
86 "the given debug object buffer [{3:x16} - {4:x16}]",
87 Name, Start + Header->sh_offset,
88 Start + Header->sh_offset + Header->sh_size, Start, End),
90 return Error::success();
91}
92
93template <typename ELFT>
95 if (uint64_t Addr = Header->sh_addr) {
96 OS << formatv(" {0:x16} {1}\n", Addr, Name);
97 } else {
98 OS << formatv(" {0}\n", Name);
99 }
100}
101
103 // Request final target memory load-addresses for all sections.
105
106 // We found sections with debug information when processing the input object.
108};
109
110/// The plugin creates a debug object from when JITLink starts processing the
111/// corresponding LinkGraph. It provides access to the pass configuration of
112/// the LinkGraph and calls the finalization function, once the resulting link
113/// artifact was emitted.
114///
116public:
122
123 bool hasFlags(DebugObjectFlags F) const { return Flags & F; }
125 Flags = static_cast<DebugObjectFlags>(Flags | F);
126 }
128 Flags = static_cast<DebugObjectFlags>(Flags & ~F);
129 }
130
133
135 FinalizePromise.set_value(std::move(Err));
136 }
137
139 FinalizePromise.set_value(TargetMem);
140 }
141
143
144 virtual ~DebugObject() {
145 if (Alloc) {
146 std::vector<FinalizedAlloc> Allocs;
147 Allocs.push_back(std::move(Alloc));
148 if (Error Err = MemMgr.deallocate(std::move(Allocs)))
149 ES.reportError(std::move(Err));
150 }
151 }
152
154 SectionRange TargetMem) {}
155
156protected:
159
161
163 const JITLinkDylib *JD = nullptr;
165
166 std::promise<MSVCPExpected<ExecutorAddrRange>> FinalizePromise;
167 std::future<MSVCPExpected<ExecutorAddrRange>> FinalizeFuture;
168
169private:
170 DebugObjectFlags Flags;
171 FinalizedAlloc Alloc;
172};
173
174// Finalize working memory and take ownership of the resulting allocation. Start
175// copying memory over to the target and pass on the result once we're done.
176// Ownership of the allocation remains with us for the rest of our lifetime.
178 assert(!this->Alloc && "Cannot finalize more than once");
179 if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
180 auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
181 ExecutorAddrRange DebugObjRange(ROSeg.Addr, ROSeg.WorkingMem.size());
182 SimpleSegAlloc->finalize(
183 [this, DebugObjRange,
184 OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
185 if (FA) {
186 // Note: FA->getAddress() is supposed to be the address of the
187 // memory range on the target, but InProcessMemoryManager returns
188 // the address of a FinalizedAllocInfo helper instead.
189 this->Alloc = std::move(*FA);
190 OnFinalize(DebugObjRange);
191 } else
192 OnFinalize(FA.takeError());
193 });
194 } else {
195 // We could report this error synchronously, but it's easier this way,
196 // because the FinalizePromise will be triggered unconditionally.
197 OnFinalize(SimpleSegAlloc.takeError());
198 }
199}
200
201/// The current implementation of ELFDebugObject replicates the approach used in
202/// RuntimeDyld: It patches executable and data section headers in the given
203/// object buffer with load-addresses of their corresponding sections in target
204/// memory.
205///
206class ELFDebugObject : public DebugObject {
207public:
210
212 SectionRange TargetMem) override;
213
214 StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
215
216protected:
218
219 template <typename ELFT>
221 std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
223
224private:
225 template <typename ELFT>
227 CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr,
229
230 static std::unique_ptr<WritableMemoryBuffer>
231 CopyBuffer(MemoryBufferRef Buffer, Error &Err);
232
233 ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
236 : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) {
238 }
239
240 std::unique_ptr<WritableMemoryBuffer> Buffer;
242};
243
244static const std::set<StringRef> DwarfSectionNames = {
245#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
246 ELF_NAME,
247#include "llvm/BinaryFormat/Dwarf.def"
248#undef HANDLE_DWARF_SECTION
249};
250
252 return DwarfSectionNames.count(SectionName) == 1;
253}
254
255std::unique_ptr<WritableMemoryBuffer>
256ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
258 size_t Size = Buffer.getBufferSize();
259 StringRef Name = Buffer.getBufferIdentifier();
260 if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
261 memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
262 return Copy;
263 }
264
266 return nullptr;
267}
268
269template <typename ELFT>
270Expected<std::unique_ptr<ELFDebugObject>>
271ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
272 JITLinkMemoryManager &MemMgr,
273 const JITLinkDylib *JD, ExecutionSession &ES) {
274 using SectionHeader = typename ELFT::Shdr;
275
276 Error Err = Error::success();
277 std::unique_ptr<ELFDebugObject> DebugObj(
278 new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES));
279 if (Err)
280 return std::move(Err);
281
282 Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
283 if (!ObjRef)
284 return ObjRef.takeError();
285
286 Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
287 if (!Sections)
288 return Sections.takeError();
289
290 for (const SectionHeader &Header : *Sections) {
291 Expected<StringRef> Name = ObjRef->getSectionName(Header);
292 if (!Name)
293 return Name.takeError();
294 if (Name->empty())
295 continue;
296 if (isDwarfSection(*Name))
297 DebugObj->setFlags(HasDebugSections);
298
299 // Only record text and data sections (i.e. no bss, comments, rel, etc.)
300 if (Header.sh_type != ELF::SHT_PROGBITS &&
301 Header.sh_type != ELF::SHT_X86_64_UNWIND)
302 continue;
303 if (!(Header.sh_flags & ELF::SHF_ALLOC))
304 continue;
305
306 auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
307 if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
308 return std::move(Err);
309 }
310
311 return std::move(DebugObj);
312}
313
314Expected<std::unique_ptr<DebugObject>>
317 unsigned char Class, Endian;
318 std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
319
320 if (Class == ELF::ELFCLASS32) {
321 if (Endian == ELF::ELFDATA2LSB)
322 return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
323 Ctx.getJITLinkDylib(), ES);
324 if (Endian == ELF::ELFDATA2MSB)
325 return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
326 Ctx.getJITLinkDylib(), ES);
327 return nullptr;
328 }
329 if (Class == ELF::ELFCLASS64) {
330 if (Endian == ELF::ELFDATA2LSB)
331 return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
332 Ctx.getJITLinkDylib(), ES);
333 if (Endian == ELF::ELFDATA2MSB)
334 return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
335 Ctx.getJITLinkDylib(), ES);
336 return nullptr;
337 }
338 return nullptr;
339}
340
342 LLVM_DEBUG({
343 dbgs() << "Section load-addresses in debug object for \""
344 << Buffer->getBufferIdentifier() << "\":\n";
345 for (const auto &KV : Sections)
346 KV.second->dump(dbgs(), KV.first());
347 });
348
349 // TODO: This works, but what actual alignment requirements do we have?
351 size_t Size = Buffer->getBufferSize();
352
353 // Allocate working memory for debug object in read-only segment.
354 auto Alloc = SimpleSegmentAlloc::Create(
355 MemMgr, ES.getSymbolStringPool(), ES.getTargetTriple(), JD,
356 {{MemProt::Read, {Size, Align(PageSize)}}});
357 if (!Alloc)
358 return Alloc;
359
360 // Initialize working memory with a copy of our object buffer.
361 auto SegInfo = Alloc->getSegInfo(MemProt::Read);
362 memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size);
363 Buffer.reset();
364
365 return Alloc;
366}
367
369 SectionRange TargetMem) {
370 if (auto *DebugObjSection = getSection(Name))
371 DebugObjSection->setTargetMemoryRange(TargetMem);
372}
373
374template <typename ELFT>
376 StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
377 if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
378 return Err;
379 bool Inserted = Sections.try_emplace(Name, std::move(Section)).second;
380 if (!Inserted)
381 LLVM_DEBUG(dbgs() << "Skipping debug registration for section '" << Name
382 << "' in object " << Buffer->getBufferIdentifier()
383 << " (duplicate name)\n");
384 return Error::success();
385}
386
388 auto It = Sections.find(Name);
389 return It == Sections.end() ? nullptr : It->second.get();
390}
391
392/// Creates a debug object based on the input object file from
393/// ObjectLinkingLayerJITLinkContext.
394///
397 JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
398 switch (G.getTargetTriple().getObjectFormat()) {
399 case Triple::ELF:
400 return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
401
402 default:
403 // TODO: Once we add support for other formats, we might want to split this
404 // into multiple files.
405 return nullptr;
406 }
407}
408
410 bool RequireDebugSections,
411 bool AutoRegisterCode, Error &Err)
412 : ES(ES), RequireDebugSections(RequireDebugSections),
413 AutoRegisterCode(AutoRegisterCode) {
414 // Pass bootstrap symbol for registration function to enable debugging
416 Err = ES.getExecutorProcessControl().getBootstrapSymbols(
417 {{RegistrationAction, rt::RegisterJITLoaderGDBAllocActionName}});
418}
419
421
424 MemoryBufferRef ObjBuffer) {
425 std::lock_guard<std::mutex> Lock(PendingObjsLock);
426 assert(PendingObjs.count(&MR) == 0 &&
427 "Cannot have more than one pending debug object per "
428 "MaterializationResponsibility");
429
430 if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
431 // Not all link artifacts allow debugging.
432 if (*DebugObj == nullptr)
433 return;
434 if (RequireDebugSections && !(**DebugObj).hasFlags(HasDebugSections)) {
435 LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
436 << G.getName() << "': no debug info\n");
437 return;
438 }
439 PendingObjs[&MR] = std::move(*DebugObj);
440 } else {
441 ES.reportError(DebugObj.takeError());
442 }
443}
444
446 LinkGraph &G,
447 PassConfiguration &PassConfig) {
448 // Not all link artifacts have associated debug objects.
449 std::lock_guard<std::mutex> Lock(PendingObjsLock);
450 auto It = PendingObjs.find(&MR);
451 if (It == PendingObjs.end())
452 return;
453
454 DebugObject &DebugObj = *It->second;
456 PassConfig.PostAllocationPasses.push_back(
457 [&DebugObj](LinkGraph &Graph) -> Error {
458 for (const Section &GraphSection : Graph.sections())
459 DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
460 SectionRange(GraphSection));
461 return Error::success();
462 });
463
464 PassConfig.PreFixupPasses.push_back(
465 [this, &DebugObj, &MR](LinkGraph &G) -> Error {
466 DebugObj.finalizeAsync([this, &DebugObj,
467 &MR](Expected<ExecutorAddrRange> TargetMem) {
468 if (!TargetMem) {
469 DebugObj.failMaterialization(TargetMem.takeError());
470 return;
471 }
472 // Update tracking info
473 Error Err = MR.withResourceKeyDo([&](ResourceKey K) {
474 std::lock_guard<std::mutex> LockPending(PendingObjsLock);
475 std::lock_guard<std::mutex> LockRegistered(RegisteredObjsLock);
476 auto It = PendingObjs.find(&MR);
477 RegisteredObjs[K].push_back(std::move(It->second));
478 PendingObjs.erase(It);
479 });
480
481 if (Err)
482 DebugObj.failMaterialization(std::move(Err));
483
484 // Unblock post-fixup pass
485 DebugObj.reportTargetMem(*TargetMem);
486 });
487 return Error::success();
488 });
489
490 PassConfig.PostFixupPasses.push_back(
491 [this, &DebugObj](LinkGraph &G) -> Error {
493 if (!R)
494 return R.takeError();
495 if (R->empty())
496 return Error::success();
497
498 using namespace shared;
499 G.allocActions().push_back(
500 {cantFail(WrapperFunctionCall::Create<
501 SPSArgList<SPSExecutorAddrRange, bool>>(
502 RegistrationAction, *R, AutoRegisterCode)),
503 {/* no deregistration */}});
504 return Error::success();
505 });
506 }
507}
508
510 std::lock_guard<std::mutex> Lock(PendingObjsLock);
511 PendingObjs.erase(&MR);
512 return Error::success();
513}
514
516 ResourceKey DstKey,
517 ResourceKey SrcKey) {
518 // Debug objects are stored by ResourceKey only after registration.
519 // Thus, pending objects don't need to be updated here.
520 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
521 auto SrcIt = RegisteredObjs.find(SrcKey);
522 if (SrcIt != RegisteredObjs.end()) {
523 // Resources from distinct MaterializationResponsibilitys can get merged
524 // after emission, so we can have multiple debug objects per resource key.
525 for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
526 RegisteredObjs[DstKey].push_back(std::move(DebugObj));
527 RegisteredObjs.erase(SrcIt);
528 }
529}
530
533 // Removing the resource for a pending object fails materialization, so they
534 // get cleaned up in the notifyFailed() handler.
535 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
536 RegisteredObjs.erase(Key);
537
538 // TODO: Implement unregister notifications.
539 return Error::success();
540}
541
542} // namespace orc
543} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
#define _
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
#define F(x, y, z)
Definition MD5.cpp:54
#define G(x, y, z)
Definition MD5.cpp:55
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
Provides a library for accessing information about this process and other processes on the operating ...
#define LLVM_DEBUG(...)
Definition Debug.h:114
Helper for Errors used as out-parameters.
Definition Error.h:1144
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
size_t getBufferSize() const
StringRef getBufferIdentifier() const
const char * getBufferStart() const
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:133
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
const unsigned char * bytes_end() const
Definition StringRef.h:127
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:146
const unsigned char * bytes_begin() const
Definition StringRef.h:124
static LLVM_ABI std::unique_ptr< WritableMemoryBuffer > getNewUninitMemBuffer(size_t Size, const Twine &BufferName="", std::optional< Align > Alignment=std::nullopt)
Allocate a new MemoryBuffer of the specified size that is not initialized.
static Expected< ELFFile > create(StringRef Object)
Definition ELF.h:965
virtual void setTargetMemoryRange(SectionRange Range)=0
virtual void dump(raw_ostream &OS, StringRef Name)
virtual ~DebugObjectSection()=default
The plugin creates a debug object from when JITLink starts processing the corresponding LinkGraph.
JITLinkMemoryManager & MemMgr
Expected< ExecutorAddrRange > awaitTargetMem()
void reportTargetMem(ExecutorAddrRange TargetMem)
void finalizeAsync(FinalizeContinuation OnAsync)
bool hasFlags(DebugObjectFlags F) const
virtual Expected< SimpleSegmentAlloc > finalizeWorkingMemory()=0
std::function< void(Expected< ExecutorAddrRange >)> FinalizeContinuation
void clearFlags(DebugObjectFlags F)
std::future< MSVCPExpected< ExecutorAddrRange > > FinalizeFuture
virtual void reportSectionTargetMemoryRange(StringRef Name, SectionRange TargetMem)
void setFlags(DebugObjectFlags F)
JITLinkMemoryManager::FinalizedAlloc FinalizedAlloc
JITLinkMemoryManager::InFlightAlloc InFlightAlloc
std::promise< MSVCPExpected< ExecutorAddrRange > > FinalizePromise
DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD, ExecutionSession &ES)
Error notifyFailed(MaterializationResponsibility &MR) override
void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override
ELFDebugObjectPlugin(ExecutionSession &ES, bool RequireDebugSections, bool AutoRegisterCode, Error &Err)
Create the plugin to submit DebugObjects for JITLink artifacts.
Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &LG, jitlink::PassConfiguration &PassConfig) override
void notifyMaterializing(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::JITLinkContext &Ctx, MemoryBufferRef InputObject) override
Error validateInBounds(StringRef Buffer, const char *Name) const
void setTargetMemoryRange(SectionRange Range) override
void dump(raw_ostream &OS, StringRef Name) override
ELFDebugObjectSection(const typename ELFT::Shdr *Header)
The current implementation of ELFDebugObject replicates the approach used in RuntimeDyld: It patches ...
Error recordSection(StringRef Name, std::unique_ptr< ELFDebugObjectSection< ELFT > > Section)
DebugObjectSection * getSection(StringRef Name)
Expected< SimpleSegmentAlloc > finalizeWorkingMemory() override
void reportSectionTargetMemoryRange(StringRef Name, SectionRange TargetMem) override
static Expected< std::unique_ptr< DebugObject > > Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES)
An ExecutionSession represents a running JIT program.
Definition Core.h:1342
Represents a JIT'd dynamic library.
Definition Core.h:906
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition Core.h:580
Error withResourceKeyDo(Func &&F) const
Runs the given callback under the session lock, passing in the associated ResourceKey.
Definition Core.h:599
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
static unsigned getPageSizeEstimate()
Get the process's estimated page size.
Definition Process.h:62
@ SHF_ALLOC
Definition ELF.h:1248
@ SHT_PROGBITS
Definition ELF.h:1147
@ SHT_X86_64_UNWIND
Definition ELF.h:1222
@ ELFDATA2MSB
Definition ELF.h:341
@ ELFDATA2LSB
Definition ELF.h:340
@ ELFCLASS64
Definition ELF.h:334
@ ELFCLASS32
Definition ELF.h:333
Expected< const typename ELFT::Shdr * > getSection(typename ELFT::ShdrRange Sections, uint32_t Index)
Definition ELF.h:586
std::pair< unsigned char, unsigned char > getElfArchType(StringRef Object)
Definition ELF.h:82
LLVM_ABI const char * RegisterJITLoaderGDBAllocActionName
static const std::set< StringRef > DwarfSectionNames
static Expected< std::unique_ptr< DebugObject > > createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G, JITLinkContext &Ctx, MemoryBufferRef ObjBuffer)
Creates a debug object based on the input object file from ObjectLinkingLayerJITLinkContext.
uintptr_t ResourceKey
Definition Core.h:79
static bool isDwarfSection(StringRef SectionName)
This is an optimization pass for GlobalISel generic memory operations.
std::error_code make_error_code(BitcodeError E)
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:98
@ not_enough_memory
Definition Errc.h:68
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1867
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition Error.cpp:111
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:867
Represents an address range in the exceutor process.