LLVM  11.0.0git
MachOPlatform.cpp
Go to the documentation of this file.
1 //===------ MachOPlatform.cpp - Utilities for executing MachO 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 //===----------------------------------------------------------------------===//
8 
10 
14 #include "llvm/Support/Debug.h"
15 
16 #define DEBUG_TYPE "orc"
17 
18 namespace {
19 
20 struct objc_class;
21 struct objc_image_info;
22 struct objc_object;
23 struct objc_selector;
24 
25 using Class = objc_class *;
26 using id = objc_object *;
27 using SEL = objc_selector *;
28 
29 using ObjCMsgSendTy = id (*)(id, SEL, ...);
30 using ObjCReadClassPairTy = Class (*)(Class, const objc_image_info *);
31 using SelRegisterNameTy = SEL (*)(const char *);
32 
33 enum class ObjCRegistrationAPI { Uninitialized, Unavailable, Initialized };
34 
35 ObjCRegistrationAPI ObjCRegistrationAPIState =
36  ObjCRegistrationAPI::Uninitialized;
37 ObjCMsgSendTy objc_msgSend = nullptr;
38 ObjCReadClassPairTy objc_readClassPair = nullptr;
39 SelRegisterNameTy sel_registerName = nullptr;
40 
41 } // end anonymous namespace
42 
43 namespace llvm {
44 namespace orc {
45 
46 template <typename FnTy>
48  const char *Name) {
49  if (void *Addr = LibObjC.getAddressOfSymbol(Name))
50  Target = reinterpret_cast<FnTy>(Addr);
51  else
52  return make_error<StringError>(
53  (Twine("Could not find address for ") + Name).str(),
55  return Error::success();
56 }
57 
58 Error enableObjCRegistration(const char *PathToLibObjC) {
59  // If we've already tried to initialize then just bail out.
60  if (ObjCRegistrationAPIState != ObjCRegistrationAPI::Uninitialized)
61  return Error::success();
62 
63  ObjCRegistrationAPIState = ObjCRegistrationAPI::Unavailable;
64 
65  std::string ErrMsg;
66  auto LibObjC =
67  sys::DynamicLibrary::getPermanentLibrary(PathToLibObjC, &ErrMsg);
68 
69  if (!LibObjC.isValid())
70  return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
71 
72  if (auto Err = setUpObjCRegAPIFunc(objc_msgSend, LibObjC, "objc_msgSend"))
73  return Err;
74  if (auto Err = setUpObjCRegAPIFunc(objc_readClassPair, LibObjC,
75  "objc_readClassPair"))
76  return Err;
77  if (auto Err =
78  setUpObjCRegAPIFunc(sel_registerName, LibObjC, "sel_registerName"))
79  return Err;
80 
81  ObjCRegistrationAPIState = ObjCRegistrationAPI::Initialized;
82  return Error::success();
83 }
84 
86  return ObjCRegistrationAPIState == ObjCRegistrationAPI::Initialized;
87 }
88 
89 void MachOJITDylibInitializers::runModInits() const {
90  for (const auto &ModInit : ModInitSections) {
91  for (uint64_t I = 0; I != ModInit.NumPtrs; ++I) {
92  auto *InitializerAddr = jitTargetAddressToPointer<uintptr_t *>(
93  ModInit.Address + (I * sizeof(uintptr_t)));
94  auto *Initializer =
95  jitTargetAddressToFunction<void (*)()>(*InitializerAddr);
96  Initializer();
97  }
98  }
99 }
100 
101 void MachOJITDylibInitializers::registerObjCSelectors() const {
102  assert(objCRegistrationEnabled() && "ObjC registration not enabled.");
103 
104  for (const auto &ObjCSelRefs : ObjCSelRefsSections) {
105  for (uint64_t I = 0; I != ObjCSelRefs.NumPtrs; ++I) {
106  auto SelEntryAddr = ObjCSelRefs.Address + (I * sizeof(uintptr_t));
107  const auto *SelName =
108  *jitTargetAddressToPointer<const char **>(SelEntryAddr);
109  auto Sel = sel_registerName(SelName);
110  *jitTargetAddressToPointer<SEL *>(SelEntryAddr) = Sel;
111  }
112  }
113 }
114 
115 Error MachOJITDylibInitializers::registerObjCClasses() const {
116  assert(objCRegistrationEnabled() && "ObjC registration not enabled.");
117 
118  struct ObjCClassCompiled {
119  void *Metaclass;
120  void *Parent;
121  void *Cache1;
122  void *Cache2;
123  void *Data;
124  };
125 
126  auto *ImageInfo =
127  jitTargetAddressToPointer<const objc_image_info *>(ObjCImageInfoAddr);
128  auto ClassSelector = sel_registerName("class");
129 
130  for (const auto &ObjCClassList : ObjCClassListSections) {
131  for (uint64_t I = 0; I != ObjCClassList.NumPtrs; ++I) {
132  auto ClassPtrAddr = ObjCClassList.Address + (I * sizeof(uintptr_t));
133  auto Cls = *jitTargetAddressToPointer<Class *>(ClassPtrAddr);
134  auto *ClassCompiled =
135  *jitTargetAddressToPointer<ObjCClassCompiled **>(ClassPtrAddr);
136  objc_msgSend(reinterpret_cast<id>(ClassCompiled->Parent), ClassSelector);
137  auto Registered = objc_readClassPair(Cls, ImageInfo);
138 
139  // FIXME: Improve diagnostic by reporting the failed class's name.
140  if (Registered != Cls)
141  return make_error<StringError>("Unable to register Objective-C class",
143  }
144  }
145  return Error::success();
146 }
147 
148 MachOPlatform::MachOPlatform(
149  ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
150  std::unique_ptr<MemoryBuffer> StandardSymbolsObject)
151  : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
152  StandardSymbolsObject(std::move(StandardSymbolsObject)) {
153  ObjLinkingLayer.addPlugin(std::make_unique<InitScraperPlugin>(*this));
154 }
155 
157  auto ObjBuffer = MemoryBuffer::getMemBuffer(
158  StandardSymbolsObject->getMemBufferRef(), false);
159  return ObjLinkingLayer.add(JD, std::move(ObjBuffer));
160 }
161 
163  const auto &InitSym = MU.getInitializerSymbol();
164  if (!InitSym)
165  return Error::success();
166 
167  RegisteredInitSymbols[&JD].add(InitSym,
169  LLVM_DEBUG({
170  dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "
171  << MU.getName() << "\n";
172  });
173  return Error::success();
174 }
175 
177  llvm_unreachable("Not supported yet");
178 }
179 
182 
183  LLVM_DEBUG({
184  dbgs() << "MachOPlatform: Building initializer sequence for "
185  << JD.getName() << "\n";
186  });
187 
188  std::vector<JITDylib *> DFSLinkOrder;
189 
190  while (true) {
191 
193 
194  ES.runSessionLocked([&]() {
195  DFSLinkOrder = getDFSLinkOrder(JD);
196 
197  for (auto *InitJD : DFSLinkOrder) {
198  auto RISItr = RegisteredInitSymbols.find(InitJD);
199  if (RISItr != RegisteredInitSymbols.end()) {
200  NewInitSymbols[InitJD] = std::move(RISItr->second);
201  RegisteredInitSymbols.erase(RISItr);
202  }
203  }
204  });
205 
206  if (NewInitSymbols.empty())
207  break;
208 
209  LLVM_DEBUG({
210  dbgs() << "MachOPlatform: Issuing lookups for new init symbols: "
211  "(lookup may require multiple rounds)\n";
212  for (auto &KV : NewInitSymbols)
213  dbgs() << " \"" << KV.first->getName() << "\": " << KV.second << "\n";
214  });
215 
216  // Outside the lock, issue the lookup.
217  if (auto R = lookupInitSymbols(JD.getExecutionSession(), NewInitSymbols))
218  ; // Nothing to do in the success case.
219  else
220  return R.takeError();
221  }
222 
223  LLVM_DEBUG({
224  dbgs() << "MachOPlatform: Init symbol lookup complete, building init "
225  "sequence\n";
226  });
227 
228  // Lock again to collect the initializers.
229  InitializerSequence FullInitSeq;
230  {
231  std::lock_guard<std::mutex> Lock(InitSeqsMutex);
232  for (auto *InitJD : reverse(DFSLinkOrder)) {
233  LLVM_DEBUG({
234  dbgs() << "MachOPlatform: Appending inits for \"" << InitJD->getName()
235  << "\" to sequence\n";
236  });
237  auto ISItr = InitSeqs.find(InitJD);
238  if (ISItr != InitSeqs.end()) {
239  FullInitSeq.emplace_back(InitJD, std::move(ISItr->second));
240  InitSeqs.erase(ISItr);
241  }
242  }
243  }
244 
245  return FullInitSeq;
246 }
247 
250  std::vector<JITDylib *> DFSLinkOrder = getDFSLinkOrder(JD);
251 
252  DeinitializerSequence FullDeinitSeq;
253  {
254  std::lock_guard<std::mutex> Lock(InitSeqsMutex);
255  for (auto *DeinitJD : DFSLinkOrder) {
256  FullDeinitSeq.emplace_back(DeinitJD, MachOJITDylibDeinitializers());
257  }
258  }
259 
260  return FullDeinitSeq;
261 }
262 
263 std::vector<JITDylib *> MachOPlatform::getDFSLinkOrder(JITDylib &JD) {
264  std::vector<JITDylib *> Result, WorkStack({&JD});
265  DenseSet<JITDylib *> Visited;
266 
267  while (!WorkStack.empty()) {
268  auto *NextJD = WorkStack.back();
269  WorkStack.pop_back();
270  if (Visited.count(NextJD))
271  continue;
272  Visited.insert(NextJD);
273  Result.push_back(NextJD);
274  NextJD->withLinkOrderDo([&](const JITDylibSearchOrder &LO) {
275  for (auto &KV : LO)
276  WorkStack.push_back(KV.first);
277  });
278  }
279 
280  return Result;
281 }
282 
283 void MachOPlatform::registerInitInfo(
284  JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,
288  std::lock_guard<std::mutex> Lock(InitSeqsMutex);
289 
290  auto &InitSeq = InitSeqs[&JD];
291 
292  InitSeq.setObjCImageInfoAddr(ObjCImageInfoAddr);
293 
294  if (ModInits.Address)
295  InitSeq.addModInitsSection(std::move(ModInits));
296 
297  if (ObjCSelRefs.Address)
298  InitSeq.addObjCSelRefsSection(std::move(ObjCSelRefs));
299 
300  if (ObjCClassList.Address)
301  InitSeq.addObjCClassListSection(std::move(ObjCClassList));
302 }
303 
306  auto *Sec = G.findSectionByName(SectionName);
307  if (!Sec)
309  jitlink::SectionRange R(*Sec);
310  if (R.getSize() % G.getPointerSize() != 0)
311  return make_error<StringError>(SectionName + " section size is not a "
312  "multiple of the pointer size",
315  R.getStart(), R.getSize() / G.getPointerSize());
316 }
317 
318 void MachOPlatform::InitScraperPlugin::modifyPassConfig(
319  MaterializationResponsibility &MR, const Triple &TT,
320  jitlink::PassConfiguration &Config) {
321 
322  Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) -> Error {
323  JITLinkSymbolVector InitSectionSymbols;
324  preserveInitSectionIfPresent(InitSectionSymbols, G, "__mod_init_func");
325  preserveInitSectionIfPresent(InitSectionSymbols, G, "__objc_selrefs");
326  preserveInitSectionIfPresent(InitSectionSymbols, G, "__objc_classlist");
327 
328  if (!InitSymbolDeps.empty()) {
329  std::lock_guard<std::mutex> Lock(InitScraperMutex);
330  InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
331  }
332 
333  if (auto Err = processObjCImageInfo(G, MR))
334  return Err;
335 
336  return Error::success();
337  });
338 
339  Config.PostFixupPasses.push_back([this, &JD = MR.getTargetJITDylib()](
340  jitlink::LinkGraph &G) -> Error {
341  MachOJITDylibInitializers::SectionExtent ModInits, ObjCSelRefs,
342  ObjCClassList;
343 
344  JITTargetAddress ObjCImageInfoAddr = 0;
345  if (auto *ObjCImageInfoSec = G.findSectionByName("__objc_image_info")) {
346  if (auto Addr = jitlink::SectionRange(*ObjCImageInfoSec).getStart()) {
347  ObjCImageInfoAddr = Addr;
348  dbgs() << "Recorded __objc_imageinfo @ " << formatv("{0:x16}", Addr);
349  }
350  }
351 
352  // Record __mod_init_func.
353  if (auto ModInitsOrErr = getSectionExtent(G, "__mod_init_func"))
354  ModInits = std::move(*ModInitsOrErr);
355  else
356  return ModInitsOrErr.takeError();
357 
358  // Record __objc_selrefs.
359  if (auto ObjCSelRefsOrErr = getSectionExtent(G, "__objc_selrefs"))
360  ObjCSelRefs = std::move(*ObjCSelRefsOrErr);
361  else
362  return ObjCSelRefsOrErr.takeError();
363 
364  // Record __objc_classlist.
365  if (auto ObjCClassListOrErr = getSectionExtent(G, "__objc_classlist"))
366  ObjCClassList = std::move(*ObjCClassListOrErr);
367  else
368  return ObjCClassListOrErr.takeError();
369 
370  // Dump the scraped inits.
371  LLVM_DEBUG({
372  dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
373  dbgs() << " __objc_selrefs: ";
374  if (ObjCSelRefs.NumPtrs)
375  dbgs() << ObjCSelRefs.NumPtrs << " pointer(s) at "
376  << formatv("{0:x16}", ObjCSelRefs.Address) << "\n";
377  else
378  dbgs() << "none\n";
379 
380  dbgs() << " __objc_classlist: ";
381  if (ObjCClassList.NumPtrs)
382  dbgs() << ObjCClassList.NumPtrs << " pointer(s) at "
383  << formatv("{0:x16}", ObjCClassList.Address) << "\n";
384  else
385  dbgs() << "none\n";
386 
387  dbgs() << " __mod_init_func: ";
388  if (ModInits.NumPtrs)
389  dbgs() << ModInits.NumPtrs << " pointer(s) at "
390  << formatv("{0:x16}", ModInits.Address) << "\n";
391  else
392  dbgs() << "none\n";
393  });
394 
395  MP.registerInitInfo(JD, ObjCImageInfoAddr, std::move(ModInits),
396  std::move(ObjCSelRefs), std::move(ObjCClassList));
397 
398  return Error::success();
399  });
400 }
401 
403 MachOPlatform::InitScraperPlugin::getSyntheticSymbolLocalDependencies(
405  std::lock_guard<std::mutex> Lock(InitScraperMutex);
406  auto I = InitSymbolDeps.find(&MR);
407  if (I != InitSymbolDeps.end()) {
408  LocalDependenciesMap Result;
409  Result[MR.getInitializerSymbol()] = std::move(I->second);
410  InitSymbolDeps.erase(&MR);
411  return Result;
412  }
413  return LocalDependenciesMap();
414 }
415 
416 void MachOPlatform::InitScraperPlugin::preserveInitSectionIfPresent(
417  JITLinkSymbolVector &Symbols, jitlink::LinkGraph &G,
419  if (auto *Sec = G.findSectionByName(SectionName)) {
420  auto SecBlocks = Sec->blocks();
421  if (!llvm::empty(SecBlocks))
422  Symbols.push_back(
423  &G.addAnonymousSymbol(**SecBlocks.begin(), 0, 0, false, true));
424  }
425 }
426 
427 Error MachOPlatform::InitScraperPlugin::processObjCImageInfo(
429 
430  // If there's an ObjC imagine info then either
431  // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In
432  // this case we name and record it.
433  // OR
434  // (2) We already have a recorded __objc_imageinfo for this JITDylib,
435  // in which case we just verify it.
436  auto *ObjCImageInfo = G.findSectionByName("__objc_imageinfo");
437  if (!ObjCImageInfo)
438  return Error::success();
439 
440  auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
441 
442  // Check that the section is not empty if present.
443  if (llvm::empty(ObjCImageInfoBlocks))
444  return make_error<StringError>("Empty __objc_imageinfo section in " +
445  G.getName(),
447 
448  // Check that there's only one block in the section.
449  if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
450  return make_error<StringError>("Multiple blocks in __objc_imageinfo "
451  "section in " +
452  G.getName(),
454 
455  // Check that the __objc_imageinfo section is unreferenced.
456  // FIXME: We could optimize this check if Symbols had a ref-count.
457  for (auto &Sec : G.sections()) {
458  if (&Sec != ObjCImageInfo)
459  for (auto *B : Sec.blocks())
460  for (auto &E : B->edges())
461  if (E.getTarget().isDefined() &&
462  &E.getTarget().getBlock().getSection() == ObjCImageInfo)
463  return make_error<StringError>("__objc_imageinfo is referenced "
464  "within file " +
465  G.getName(),
467  }
468 
469  auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();
470  auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();
471  auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness());
472  auto Flags =
473  support::endian::read32(ObjCImageInfoData + 4, G.getEndianness());
474 
475  // Lock the mutex while we verify / update the ObjCImageInfos map.
476  std::lock_guard<std::mutex> Lock(InitScraperMutex);
477 
478  auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());
479  if (ObjCImageInfoItr != ObjCImageInfos.end()) {
480  // We've already registered an __objc_imageinfo section. Verify the
481  // content of this new section matches, then delete it.
482  if (ObjCImageInfoItr->second.first != Version)
483  return make_error<StringError>(
484  "ObjC version in " + G.getName() +
485  " does not match first registered version",
487  if (ObjCImageInfoItr->second.second != Flags)
488  return make_error<StringError>("ObjC flags in " + G.getName() +
489  " do not match first registered flags",
491 
492  // __objc_imageinfo is valid. Delete the block.
493  for (auto *S : ObjCImageInfo->symbols())
494  G.removeDefinedSymbol(*S);
495  G.removeBlock(ObjCImageInfoBlock);
496  } else {
497  // We haven't registered an __objc_imageinfo section yet. Register and
498  // move on. The section should already be marked no-dead-strip.
499  ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags);
500  }
501 
502  return Error::success();
503 }
504 
505 } // End namespace orc.
506 } // End namespace llvm.
std::vector< std::pair< JITDylib *, MachOJITDylibInitializers > > InitializerSequence
Definition: MachOPlatform.h:90
This class represents lattice values for constants.
Definition: AllocatorList.h:23
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
Implements a dense probed hash-table based set.
Definition: DenseSet.h:255
Error enableObjCRegistration(const char *PathToLibObjC)
Enable registration of JIT&#39;d ObjC classes and selectors.
uint32_t read32(const void *P, endianness E)
Definition: Endian.h:363
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
static sys::Mutex Lock
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup...
Definition: Core.h:92
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: BitVector.h:959
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
void * getAddressOfSymbol(const char *symbolName)
Searches through the library for the symbol symbolName.
An ObjectLayer implementation built on JITLink.
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:410
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
Error setupJITDylib(JITDylib &JD) override
This method will be called outside the session lock each time a JITDylib is created (unless it is cre...
Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) override
This method will be called under the ExecutionSession lock each time a MaterializationUnit is added t...
JITDylib & getTargetJITDylib() const
Returns the target JITDylib that these symbols are being materialized into.
Definition: Core.h:424
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:42
ExecutionSession & getExecutionSession() const
Get a reference to the ExecutionSession for this JITDylib.
Definition: Core.h:814
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Expected< DeinitializerSequence > getDeinitializerSequence(JITDylib &JD)
Expected< InitializerSequence > getInitializerSequence(JITDylib &JD)
static Error setUpObjCRegAPIFunc(FnTy &Target, sys::DynamicLibrary &LibObjC, const char *Name)
static Expected< DenseMap< JITDylib *, SymbolMap > > lookupInitSymbols(ExecutionSession &ES, const DenseMap< JITDylib *, SymbolLookupSet > &InitSyms)
A utility function for looking up initializer symbols.
Definition: Core.cpp:1726
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const SymbolStringPtr & getInitializerSymbol() const
Returns the initialization symbol for this MaterializationUnit (if any).
Definition: Core.h:575
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
virtual Error add(JITDylib &JD, std::unique_ptr< MemoryBuffer > O, VModuleKey K=VModuleKey())
Adds a MaterializationUnit representing the given IR to the given JITDylib.
Definition: Layer.cpp:166
const SymbolStringPtr & getInitializerSymbol() const
Returns the initialization pseudo-symbol, if any.
Definition: Core.h:438
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Definition: STLExtras.h:266
std::vector< std::pair< JITDylib *, MachOJITDylibDeinitializers > > DeinitializerSequence
Definition: MachOPlatform.h:93
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group...
Definition: Core.h:552
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
An ExecutionSession represents a running JIT program.
Definition: Core.h:1088
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
ObjCRegistrationAPI
Target - Wrapper for Target specific information.
Error notifyRemoving(JITDylib &JD, VModuleKey K) override
This method will be called under the ExecutionSession lock when a VModuleKey is removed.
success
Parameters (see the expansion example below): (the builder, addr, loaded, new_val, ordering, /* OUT.
uint8_t uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:40
static Expected< MachOJITDylibInitializers::SectionExtent > getSectionExtent(jitlink::LinkGraph &G, StringRef SectionName)
ObjectLinkingLayer & addPlugin(std::unique_ptr< Plugin > P)
Add a pass-config modifier.
#define I(x, y, z)
Definition: MD5.cpp:59
bool objCRegistrationEnabled()
const std::string & getName() const
Get the name for this JITDylib.
Definition: Core.h:811
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Definition: Core.h:1120
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
Definition: STLExtras.h:341
#define LLVM_DEBUG(X)
Definition: Debug.h:122
const uint64_t Version
Definition: InstrProf.h:988
A symbol table that supports asynchoronous symbol queries.
Definition: Core.h:779
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:77
virtual StringRef getName() const =0
Return the name of this materialization unit.