LLVM: lib/ExecutionEngine/Orc/LazyReexports.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

10

15

16#define DEBUG_TYPE "orc"

17

18namespace llvm {

19namespace orc {

20

24 : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(TP) {}

25

29 assert(TP && "TrampolinePool not set");

30

31 std::lock_guardstd::mutex Lock(LCTMMutex);

32 auto Trampoline = TP->getTrampoline();

33

34 if (!Trampoline)

35 return Trampoline.takeError();

36

37 Reexports[*Trampoline] = ReexportsEntry{&SourceJD, std::move(SymbolName)};

38 Notifiers[*Trampoline] = std::move(NotifyResolved);

39 return *Trampoline;

40}

41

43 ES.reportError(std::move(Err));

44 return ErrorHandlerAddr;

45}

46

49 std::lock_guardstd::mutex Lock(LCTMMutex);

50 auto I = Reexports.find(TrampolineAddr);

51 if (I == Reexports.end())

53 "Missing reexport for trampoline address %p" +

54 formatv("{0:x}", TrampolineAddr));

55 return I->second;

56}

57

61 {

62 std::lock_guardstd::mutex Lock(LCTMMutex);

63 auto I = Notifiers.find(TrampolineAddr);

64 if (I != Notifiers.end()) {

65 NotifyResolved = std::move(I->second);

66 Notifiers.erase(I);

67 }

68 }

69

70 return NotifyResolved ? NotifyResolved(ResolvedAddr) : Error::success();

71}

72

76

78 if (!Entry)

80

81

82

84 auto Callback = [this, TrampolineAddr, SymbolName = Entry->SymbolName,

85 NotifyLandingResolved = std::move(NotifyLandingResolved)](

88 assert(Result->size() == 1 && "Unexpected result size");

89 assert(Result->count(SymbolName) && "Unexpected result value");

90 ExecutorAddr LandingAddr = (*Result)[SymbolName].getAddress();

91

92 if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))

94 else

95 NotifyLandingResolved(LandingAddr);

96 } else {

98 }

99 };

100

106}

107

111 switch (T.getArch()) {

112 default:

114 std::string("No callback manager available for ") + T.str(),

116

120 ErrorHandlerAddr);

121

124

127 ES, ErrorHandlerAddr);

128

131 ErrorHandlerAddr);

132

135 ErrorHandlerAddr);

136

140

143 ErrorHandlerAddr);

144

148 ES, ErrorHandlerAddr);

149 else

151 ES, ErrorHandlerAddr);

152 }

153}

154

159 LCTManager(LCTManager), RSManager(RSManager), SourceJD(SourceJD),

160 CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}

161

163 return "";

164}

165

166void LazyReexportsMaterializationUnit::materialize(

167 std::unique_ptr R) {

168 auto RequestedSymbols = R->getRequestedSymbols();

169

171 for (auto &RequestedSymbol : RequestedSymbols) {

172 auto I = CallableAliases.find(RequestedSymbol);

173 assert(I != CallableAliases.end() && "Symbol not found in alias map?");

174 RequestedAliases[I->first] = std::move(I->second);

175 CallableAliases.erase(I);

176 }

177

178 if (!CallableAliases.empty())

179 if (auto Err = R->replace(lazyReexports(LCTManager, RSManager, SourceJD,

180 std::move(CallableAliases),

181 AliaseeTable))) {

182 R->getExecutionSession().reportError(std::move(Err));

183 R->failMaterialization();

184 return;

185 }

186

188 for (auto &Alias : RequestedAliases) {

190 SourceJD, Alias.second.Aliasee,

191 [&TargetJD = R->getTargetJITDylib(), &RSManager = this->RSManager,

192 StubSym = Alias.first](ExecutorAddr ResolvedAddr) -> Error {

193 return RSManager.redirect(TargetJD, StubSym,

194 ExecutorSymbolDef(ResolvedAddr, {}));

195 });

196

197 if (!CallThroughTrampoline) {

198 R->getExecutionSession().reportError(CallThroughTrampoline.takeError());

199 R->failMaterialization();

200 return;

201 }

202

203 Inits[Alias.first] = {*CallThroughTrampoline, Alias.second.AliasFlags};

204 }

205

206 if (AliaseeTable != nullptr && !RequestedAliases.empty())

207 AliaseeTable->trackImpls(RequestedAliases, &SourceJD);

208

209 if (auto Err = R->replace(std::make_unique(

210 RSManager, std::move(Inits)))) {

211 R->getExecutionSession().reportError(std::move(Err));

212 return R->failMaterialization();

213 }

214}

215

216void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,

217 const SymbolStringPtr &Name) {

218 assert(CallableAliases.count(Name) &&

219 "Symbol not covered by this MaterializationUnit");

220 CallableAliases.erase(Name);

221}

222

223MaterializationUnit::Interface

224LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {

226 for (auto &KV : Aliases) {

227 assert(KV.second.AliasFlags.isCallable() &&

228 "Lazy re-exports must be callable symbols");

229 SymbolFlags[KV.first] = KV.second.AliasFlags;

230 }

231 return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);

232}

233

235public:

238 Reexports(std::move(Reexports)) {}

239

240private:

241 Interface getInterface(const SymbolAliasMap &Reexports) {

243 for (auto &[Alias, AI] : Reexports)

244 SF[Alias] = AI.AliasFlags;

245 return {std::move(SF), nullptr};

246 }

247

248 StringRef getName() const override { return "LazyReexportsManager::MU"; }

249

250 void materialize(std::unique_ptr R) override {

251 LRMgr.emitReentryTrampolines(std::move(R), std::move(Reexports));

252 }

253

254 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {

255 Reexports.erase(Name);

256 }

257

258 LazyReexportsManager &LRMgr;

260};

261

263public:

267

271

275

278

279private:

280 std::mutex M;

281};

282

284

291 std::move(EmitTrampolines), RSMgr, PlatformJD, L, Err));

292 if (Err)

293 return std::move(Err);

294 return std::move(LRM);

295}

296

299 auto I = KeyToReentryAddrs.find(K);

300 if (I == KeyToReentryAddrs.end())

302

303 auto &ReentryAddrs = I->second;

304 for (auto &ReentryAddr : ReentryAddrs) {

305 assert(CallThroughs.count(ReentryAddr) && "CallTrhough missing");

306 CallThroughs.erase(ReentryAddr);

307 }

308 KeyToReentryAddrs.erase(I);

309 return L ? L->onLazyReexportsRemoved(JD, K) : Error::success();

310 });

311}

312

316 auto I = KeyToReentryAddrs.find(SrcK);

317 if (I != KeyToReentryAddrs.end()) {

318 auto J = KeyToReentryAddrs.find(DstK);

319 if (J == KeyToReentryAddrs.end()) {

320 auto Tmp = std::move(I->second);

321 KeyToReentryAddrs.erase(I);

322 KeyToReentryAddrs[DstK] = std::move(Tmp);

323 } else {

324 auto &SrcAddrs = I->second;

325 auto &DstAddrs = J->second;

327 KeyToReentryAddrs.erase(I);

328 }

329 if (L)

330 L->onLazyReexportsTransfered(JD, DstK, SrcK);

331 }

332}

333

336 JITDylib &PlatformJD, Listener *L,

338 : ES(PlatformJD.getExecutionSession()),

339 EmitTrampolines(std::move(EmitTrampolines)), RSMgr(RSMgr), L(L) {

340

341 using namespace shared;

342

344

346

347 WFs[ES.intern("__orc_rt_resolve_tag")] =

348 ES.wrapAsyncWithSPS<SPSExpected(SPSExecutorAddr)>(

349 this, &LazyReexportsManager::resolve);

350

352}

353

354std::unique_ptr

355LazyReexportsManager::createLazyReexports(SymbolAliasMap Reexports) {

356 return std::make_unique(*this, std::move(Reexports));

357}

358

359void LazyReexportsManager::emitReentryTrampolines(

360 std::unique_ptr MR,

362 size_t NumTrampolines = Reexports.size();

363 auto RT = MR->getResourceTracker();

364 EmitTrampolines(

365 std::move(RT), NumTrampolines,

366 [this, MR = std::move(MR), Reexports = std::move(Reexports)](

367 Expected<std::vector> ReentryPoints) mutable {

368 emitRedirectableSymbols(std::move(MR), std::move(Reexports),

369 std::move(ReentryPoints));

370 });

371}

372

373void LazyReexportsManager::emitRedirectableSymbols(

374 std::unique_ptr MR, SymbolAliasMap Reexports,

375 Expected<std::vector> ReentryPoints) {

376

377 if (!ReentryPoints) {

378 MR->getExecutionSession().reportError(ReentryPoints.takeError());

379 MR->failMaterialization();

380 return;

381 }

382

383 assert(Reexports.size() == ReentryPoints->size() &&

384 "Number of reentry points doesn't match number of reexports");

385

386

388 size_t I = 0;

389 for (auto &[Name, AI] : Reexports)

390 Redirs[Name] = {(*ReentryPoints)[I++].getAddress(), AI.AliasFlags};

391

392 I = 0;

393 if (!Reexports.empty()) {

394 if (auto Err = MR->withResourceKeyDo([&](ResourceKey K) {

395 auto &JD = MR->getTargetJITDylib();

396 auto &ReentryAddrsForK = KeyToReentryAddrs[K];

397 for (auto &[Name, AI] : Reexports) {

398 const auto &ReentryPoint = (*ReentryPoints)[I++];

399 CallThroughs[ReentryPoint.getAddress()] = {&JD, Name, AI.Aliasee};

400 ReentryAddrsForK.push_back(ReentryPoint.getAddress());

401 }

402 if (L)

403 L->onLazyReexportsCreated(JD, K, Reexports);

404 })) {

405 MR->getExecutionSession().reportError(std::move(Err));

406 MR->failMaterialization();

407 return;

408 }

409 }

410

412}

413

414void LazyReexportsManager::resolve(ResolveSendResultFn SendResult,

415 ExecutorAddr ReentryStubAddr) {

416

417 CallThroughInfo LandingInfo;

418

419 ES.runSessionLocked([&]() {

420 auto I = CallThroughs.find(ReentryStubAddr);

421 if (I == CallThroughs.end())

423 "Reentry address " + formatv("{0:x}", ReentryStubAddr) +

424 " not registered",

426 LandingInfo = I->second;

427 });

428

429 if (L)

430 L->onLazyReexportCalled(LandingInfo);

431

432 SymbolInstance LandingSym(LandingInfo.JD, std::move(LandingInfo.BodyName));

433 LandingSym.lookupAsync([this, JD = std::move(LandingInfo.JD),

434 ReentryName = std::move(LandingInfo.Name),

435 SendResult = std::move(SendResult)](

437 if (Result) {

438

439

440 if (auto Err = RSMgr.redirect(*JD, ReentryName, *Result))

441 SendResult(std::move(Err));

442 else

443 SendResult(std::move(Result));

444 } else

445 SendResult(std::move(Result));

446 });

447}

448

450public:

451 SpeculateTask(std::weak_ptr Speculator)

452 : Speculator(std::move(Speculator)) {}

453

455 OS << "Speculative Lookup Task";

456 }

457

458 void run() override {

459 if (auto S = Speculator.lock())

460 S->doNextSpeculativeLookup();

461 }

462

463private:

464 std::weak_ptr Speculator;

465};

466

468 for (auto &[JD, _] : LazyReexports)

470}

471

474 if (!LazyReexports.count(&JD))

476 auto &BodiesVec = LazyReexports[&JD][K];

477 for (auto &[Name, AI] : Reexports)

478 BodiesVec.push_back(AI.Aliasee);

479 if (!SpeculateTaskActive) {

480 SpeculateTaskActive = true;

481 ES.dispatchTask(std::make_unique(WeakThis));

482 }

483}

484

487

488 auto I = LazyReexports.find(&JD);

489 if (I == LazyReexports.end())

490 return;

491

492 auto &MapForJD = I->second;

493 auto J = MapForJD.find(SrcK);

494 if (J == MapForJD.end())

495 return;

496

497

498 auto K = MapForJD.find(DstK);

499 if (K == MapForJD.end()) {

500 auto Tmp = std::move(J->second);

501 MapForJD.erase(J);

502 MapForJD[DstK] = std::move(Tmp);

503 } else {

504 auto &SrcNames = J->second;

505 auto &DstNames = K->second;

507 MapForJD.erase(J);

508 }

509}

510

513

514 auto I = LazyReexports.find(&JD);

515 if (I == LazyReexports.end())

517

518 auto &MapForJD = I->second;

519 MapForJD.erase(K);

520

521 if (MapForJD.empty()) {

522 LazyReexports.erase(I);

524 }

525

527}

528

531 if (RecordExec)

532 RecordExec(CTI);

533}

534

536 std::vector<std::pair<std::string, SymbolStringPtr>> NewSuggestions) {

537 ES.runSessionLocked([&]() {

538 for (auto &[JDName, SymbolName] : NewSuggestions)

539 SpeculateSuggestions.push_back(

540 {std::move(JDName), std::move(SymbolName)});

541 });

542}

543

544bool SimpleLazyReexportsSpeculator::doNextSpeculativeLookup() {

545

546

549

550 auto SpeculateAgain = ES.runSessionLocked([&]() {

551 while (!SpeculateSuggestions.empty()) {

552 auto [JDName, SymbolName] = std::move(SpeculateSuggestions.front());

553 SpeculateSuggestions.pop_front();

554

555 if (auto *JD = ES.getJITDylibByName(JDName)) {

556 SpeculateJD = JD;

557 SpeculateFn = std::move(SymbolName);

558 break;

559 }

560 }

561

562 if (!SpeculateJD) {

563 assert(!LazyReexports.empty() && "LazyReexports map is empty");

564 auto LRItr =

565 std::next(LazyReexports.begin(), rand() % LazyReexports.size());

566 auto &[JD, KeyToFnBodies] = *LRItr;

567

568 assert(!KeyToFnBodies.empty() && "Key to function bodies map empty");

569 auto KeyToFnBodiesItr =

570 std::next(KeyToFnBodies.begin(), rand() % KeyToFnBodies.size());

571 auto &[Key, FnBodies] = *KeyToFnBodiesItr;

572

573 assert(!FnBodies.empty() && "Function bodies list empty");

574 auto FnBodyItr = std::next(FnBodies.begin(), rand() % FnBodies.size());

575

576 SpeculateJD = JITDylibSP(JD);

577 SpeculateFn = std::move(*FnBodyItr);

578

579 FnBodies.erase(FnBodyItr);

580 if (FnBodies.empty()) {

581 KeyToFnBodies.erase(KeyToFnBodiesItr);

582 if (KeyToFnBodies.empty()) {

583 LRItr->first->Release();

584 LazyReexports.erase(LRItr);

585 }

586 }

587 }

588

589 SpeculateTaskActive =

590 !SpeculateSuggestions.empty() || !LazyReexports.empty();

591 return SpeculateTaskActive;

592 });

593

595 dbgs() << "Issuing speculative lookup for ( " << SpeculateJD->getName()

596 << ", " << SpeculateFn << " )...\n";

597 });

598

599 ES.lookup(

601 {{std::move(SpeculateFn), SymbolLookupFlags::WeaklyReferencedSymbol}},

602 SymbolState::Ready,

605

606 if (SpeculateAgain)

607 ES.dispatchTask(std::make_unique(WeakThis));

608

609 return false;

610}

611

612}

613}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static StringRef getName(Value *V)

iterator find(const_arg_type_t< KeyT > Val)

bool erase(const KeyT &Val)

Helper for Errors used as out-parameters.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

StringRef - Represent a constant reference to a string, i.e.

Triple - Helper class for working with autoconf configuration names.

An ExecutionSession represents a running JIT program.

SymbolStringPtr intern(StringRef SymName)

Add a symbol name to the SymbolStringPool and return a pointer to it.

static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H)

Wrap a handler that takes concrete argument types (and a sender for a concrete return type) to produc...

LLVM_ABI Error registerJITDispatchHandlers(JITDylib &JD, JITDispatchHandlerAssociationMap WFs)

For each tag symbol name, associate the corresponding AsyncHandlerWrapperFunction with the address of...

decltype(auto) runSessionLocked(Func &&F)

Run the given lambda with the session mutex locked.

DenseMap< SymbolStringPtr, JITDispatchHandlerFunction > JITDispatchHandlerAssociationMap

A map associating tag names with asynchronous wrapper function implementations in the JIT.

Represents an address in the executor process.

IdleTask can be used as the basis for low-priority tasks, e.g.

Represents a JIT'd dynamic library.

ExecutionSession & getExecutionSession() const

Get a reference to the ExecutionSession for this JITDylib.

Manages a set of 'lazy call-through' trampolines.

LLVM_ABI ExecutorAddr reportCallThroughError(Error Err)

Definition LazyReexports.cpp:42

TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolvedFunction

LLVM_ABI Expected< ReexportsEntry > findReexport(ExecutorAddr TrampolineAddr)

Definition LazyReexports.cpp:48

LLVM_ABI Error notifyResolved(ExecutorAddr TrampolineAddr, ExecutorAddr ResolvedAddr)

Definition LazyReexports.cpp:58

LLVM_ABI void resolveTrampolineLandingAddress(ExecutorAddr TrampolineAddr, TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved)

Definition LazyReexports.cpp:73

unique_function< Error(ExecutorAddr ResolvedAddr)> NotifyResolvedFunction

LLVM_ABI LazyCallThroughManager(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr, TrampolinePool *TP)

Definition LazyReexports.cpp:21

LLVM_ABI Expected< ExecutorAddr > getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName, NotifyResolvedFunction NotifyResolved)

Definition LazyReexports.cpp:26

LazyReexportsManager::CallThroughInfo CallThroughInfo

Definition LazyReexports.cpp:234

MU(LazyReexportsManager &LRMgr, SymbolAliasMap Reexports)

Definition LazyReexports.cpp:236

Definition LazyReexports.cpp:262

void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::PassConfiguration &Config) override

Definition LazyReexports.cpp:264

void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override

Definition LazyReexports.cpp:276

Error notifyFailed(MaterializationResponsibility &MR) override

Definition LazyReexports.cpp:268

Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override

Definition LazyReexports.cpp:272

void handleTransferResources(JITDylib &JD, ResourceKey DstK, ResourceKey SrcK) override

This function will be called inside the session lock.

Definition LazyReexports.cpp:313

Error handleRemoveResources(JITDylib &JD, ResourceKey K) override

This function will be called outside the session lock.

Definition LazyReexports.cpp:297

unique_function< void(ResourceTrackerSP RT, size_t NumTrampolines, OnTrampolinesReadyFn OnTrampolinesReady)> EmitTrampolinesFn

LazyReexportsManager(LazyReexportsManager &&)=delete

static Expected< std::unique_ptr< LazyReexportsManager > > Create(EmitTrampolinesFn EmitTrampolines, RedirectableSymbolManager &RSMgr, JITDylib &PlatformJD, Listener *L=nullptr)

Create a LazyReexportsManager that uses the ORC runtime for reentry.

Definition LazyReexports.cpp:286

LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager, RedirectableSymbolManager &RSManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)

Definition LazyReexports.cpp:155

StringRef getName() const override

Return the name of this materialization unit.

Definition LazyReexports.cpp:162

Plugin instances can be added to the ObjectLinkingLayer to receive callbacks when code is loaded or e...

static Expected< std::unique_ptr< LocalLazyCallThroughManager > > Create(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr)

Create a LocalLazyCallThroughManager using the given ABI.

Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...

MaterializationUnit(Interface I)

Base class for managing redirectable symbols in which a call gets redirected to another symbol in run...

virtual void emitRedirectableSymbols(std::unique_ptr< MaterializationResponsibility > MR, SymbolMap InitialDests)=0

Emit redirectable symbol.

Definition LazyReexports.cpp:449

SpeculateTask(std::weak_ptr< SimpleLazyReexportsSpeculator > Speculator)

Definition LazyReexports.cpp:451

void printDescription(raw_ostream &OS) override

Definition LazyReexports.cpp:454

void run() override

Definition LazyReexports.cpp:458

Error onLazyReexportsRemoved(JITDylib &JD, ResourceKey K) override

Called under the session lock when lazy reexports are removed.

Definition LazyReexports.cpp:511

~SimpleLazyReexportsSpeculator() override

Definition LazyReexports.cpp:467

void onLazyReexportsCreated(JITDylib &JD, ResourceKey K, const SymbolAliasMap &Reexports) override

Called under the session lock when new lazy reexports are created.

Definition LazyReexports.cpp:472

void onLazyReexportCalled(const CallThroughInfo &CTI) override

Called outside the session lock when a lazy reexport is called.

Definition LazyReexports.cpp:529

void onLazyReexportsTransfered(JITDylib &JD, ResourceKey DstK, ResourceKey SrcK) override

Called under the session lock when lazy reexports have their ownership transferred to a new ResourceK...

Definition LazyReexports.cpp:485

void addSpeculationSuggestions(std::vector< std::pair< std::string, SymbolStringPtr > > NewSuggestions)

Definition LazyReexports.cpp:535

A set of symbols to look up, each associated with a SymbolLookupFlags value.

Pointer to a pooled string representing a symbol name.

Base class for pools of compiler re-entry trampolines.

This class implements an extremely fast bulk output stream that can only output to a stream.

JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)

Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...

IntrusiveRefCntPtr< JITDylib > JITDylibSP

DenseMap< SymbolStringPtr, ExecutorSymbolDef > SymbolMap

A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).

LLVM_ABI Expected< std::unique_ptr< LazyCallThroughManager > > createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr)

Create a LocalLazyCallThroughManager from the given triple and execution session.

Definition LazyReexports.cpp:109

std::unique_ptr< LazyReexportsMaterializationUnit > lazyReexports(LazyCallThroughManager &LCTManager, RedirectableSymbolManager &RSManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc=nullptr)

Define lazy-reexports based on the given SymbolAliasMap.

LLVM_ABI RegisterDependenciesFunction NoDependenciesToRegister

This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...

@ Ready

Emitted to memory, but waiting on transitive dependencies.

DenseMap< SymbolStringPtr, SymbolAliasMapEntry > SymbolAliasMap

A map of Symbols to (Symbol, Flags) pairs.

DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap

A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

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.

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.

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

void consumeError(Error Err)

Consume a Error without doing anything.

Implement std::hash so that hash_code can be used in STL containers.

An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...