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

1

2

3

4

5

6

7

8

15

16#define DEBUG_TYPE "orc"

17

18using namespace llvm;

21

22namespace {

23

25 switch (TT.getArch()) {

31

32 assert(Sym.isCallable() && "Only callable symbols can have thumb flag");

35 }

37 default:

39 }

40}

41

42}

43

44namespace llvm {

45namespace orc {

46

48public:

50 std::unique_ptr MR,

51 std::unique_ptr ObjBuffer)

52 : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),

54 std::lock_guardstd::mutex Lock(Layer.LayerMutex);

55 Plugins = Layer.Plugins;

56 }

57

59

60

61 if (Layer.ReturnObjectBuffer && ObjBuffer)

62 Layer.ReturnObjectBuffer(std::move(ObjBuffer));

63 }

64

66

68 for (auto &P : Plugins)

69 P->notifyMaterializing(*MR, G, *this,

70 ObjBuffer ? ObjBuffer->getMemBufferRef()

72 }

73

75 for (auto &P : Plugins)

76 Err = joinErrors(std::move(Err), P->notifyFailed(*MR));

77 Layer.getExecutionSession().reportError(std::move(Err));

78 MR->failMaterialization();

79 }

80

82 std::unique_ptr LC) override {

83

85 MR->getTargetJITDylib().withLinkOrderDo(

87

88 auto &ES = Layer.getExecutionSession();

89

91 for (auto &KV : Symbols) {

93 switch (KV.second) {

96 break;

99 break;

100 }

101 LookupSet.add(KV.first, LookupFlags);

102 }

103

104

105 auto OnResolve = [LookupContinuation =

108 LookupContinuation->run(Result.takeError());

109 else {

112 LookupContinuation->run(std::move(LR));

113 }

114 };

115

119

120 for (auto &[DepJD, Deps] : Deps)

121 for (auto &DepSym : Deps)

123 });

124 }

125

127

129 bool AutoClaim = Layer.AutoClaimObjectSymbols;

130

132 for (auto *Sym : G.defined_symbols())

134 auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());

136 InternedResult[Sym->getName()] = {Ptr, Flags};

137 if (AutoClaim && !MR->getSymbols().count(Sym->getName())) {

138 assert(!ExtraSymbolsToClaim.count(Sym->getName()) &&

139 "Duplicate symbol to claim?");

140 ExtraSymbolsToClaim[Sym->getName()] = Flags;

141 }

142 }

143

144 for (auto *Sym : G.absolute_symbols())

146 auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());

148 InternedResult[Sym->getName()] = {Ptr, Flags};

149 if (AutoClaim && !MR->getSymbols().count(Sym->getName())) {

150 assert(!ExtraSymbolsToClaim.count(Sym->getName()) &&

151 "Duplicate symbol to claim?");

152 ExtraSymbolsToClaim[Sym->getName()] = Flags;

153 }

154 }

155

156 if (!ExtraSymbolsToClaim.empty())

157 if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))

158 return Err;

159

160 {

161

162

163

164

165

166

167 size_t NumMaterializationSideEffectsOnlySymbols = 0;

169 for (auto &[Sym, Flags] : MR->getSymbols()) {

170

171 auto I = InternedResult.find(Sym);

172

173

174

175

176 if (Flags.hasMaterializationSideEffectsOnly())

177 ++NumMaterializationSideEffectsOnlySymbols;

178 else if (I == InternedResult.end())

179 MissingSymbols.push_back(Sym);

180 else if (Layer.OverrideObjectFlags)

181 I->second.setFlags(Flags);

182 }

183

184

185 if (!MissingSymbols.empty())

187 Layer.getExecutionSession().getSymbolStringPool(), G.getName(),

188 std::move(MissingSymbols));

189

190

191

193 if (InternedResult.size() >

194 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {

195 for (auto &KV : InternedResult)

196 if (!MR->getSymbols().count(KV.first))

197 ExtraSymbols.push_back(KV.first);

198 }

199

200

201 if (!ExtraSymbols.empty())

203 Layer.getExecutionSession().getSymbolStringPool(), G.getName(),

204 std::move(ExtraSymbols));

205 }

206

207 if (auto Err = MR->notifyResolved(InternedResult))

208 return Err;

209

211 }

212

215 Layer.getExecutionSession().reportError(std::move(Err));

216 MR->failMaterialization();

217 return;

218 }

219

220 if (auto Err = MR->notifyEmitted(SymbolDepGroups)) {

221 Layer.getExecutionSession().reportError(std::move(Err));

222 MR->failMaterialization();

223 }

224 }

225

227 return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };

228 }

229

231

232

234 return claimOrExternalizeWeakAndCommonSymbols(G);

235 });

236

237 for (auto &P : Plugins)

238 P->modifyPassConfig(*MR, LG, Config);

239

241 [this](LinkGraph &G) { return registerDependencies(G); });

242

244 }

245

248 for (auto &P : Plugins)

249 Err = joinErrors(std::move(Err), P->notifyEmitted(*MR));

250

251 if (Err) {

252 if (FA)

253 Err =

254 joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA)));

255 return Err;

256 }

257

258 if (FA)

259 return Layer.recordFinalizedAlloc(*MR, std::move(FA));

260

262 }

263

264private:

265 Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {

267 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;

268

269 auto ProcessSymbol = [&](Symbol *Sym) {

270 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&

272 if (!MR->getSymbols().count(Sym->getName())) {

273 NewSymbolsToClaim[Sym->getName()] =

275 NameToSym.push_back(std::make_pair(Sym->getName(), Sym));

276 }

277 }

278 };

279

280 for (auto *Sym : G.defined_symbols())

281 ProcessSymbol(Sym);

282 for (auto *Sym : G.absolute_symbols())

283 ProcessSymbol(Sym);

284

285

286

287

288 if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))

289 return Err;

290

291

292

293

294 for (auto &KV : NameToSym) {

295 if (MR->getSymbols().count(KV.first))

296 KV.second->setLive(true);

297 else

298 G.makeExternal(*KV.second);

299 }

300

302 }

303

304 Error markResponsibilitySymbolsLive(LinkGraph &G) const {

305 for (auto *Sym : G.defined_symbols())

306 if (Sym->hasName() && MR->getSymbols().count(Sym->getName()))

307 Sym->setLive(true);

309 }

310

311 Error registerDependencies(LinkGraph &G) {

312

313 struct BlockInfo {

314 bool InWorklist = false;

315 DenseSet<Symbol *> Defs;

316 DenseSet<Symbol *> SymbolDeps;

317 DenseSet<Block *> AnonEdges, AnonBackEdges;

318 };

319

320 DenseMap<Block *, BlockInfo> BlockInfos;

321

322

323

324 {

325 size_t NumBlocks = 0;

326 for (auto &Sec : G.sections())

327 NumBlocks += Sec.blocks_size();

328 BlockInfos.reserve(NumBlocks);

329 }

330

331

332 for (auto *Sym : G.defined_symbols()) {

333 if (Sym->getScope() != Scope::Local)

334 BlockInfos[&Sym->getBlock()].Defs.insert(Sym);

335 }

336

337

338 for (auto *B : G.blocks()) {

339 auto &BI = BlockInfos[B];

340

341 for (auto &E : B->edges()) {

342

343

344 if (E.getTarget().isExternal()) {

345 BI.SymbolDeps.insert(&E.getTarget());

346 continue;

347 }

348

349

350

351 if (E.getTarget().isAbsolute())

352 continue;

353

354

355

356 auto &TgtBI = BlockInfos[&E.getTarget().getBlock()];

357

358

359

360

361

362 if (!TgtBI.Defs.empty()) {

363 BI.SymbolDeps.insert(*TgtBI.Defs.begin());

364 continue;

365 }

366

367

368

369 BI.AnonEdges.insert(&E.getTarget().getBlock());

370 TgtBI.AnonBackEdges.insert(B);

371 }

372 }

373

374

375 {

376 std::vector<Block *> BlocksToRemove;

377 for (auto &[B, BI] : BlockInfos) {

378

379 if (!BI.Defs.empty())

380 continue;

381

382 BlocksToRemove.push_back(B);

383

384 for (auto *FB : BI.AnonEdges)

385 BlockInfos[FB].AnonBackEdges.erase(B);

386

387 for (auto *BB : BI.AnonBackEdges)

388 BlockInfos[BB].AnonEdges.erase(B);

389

390 for (auto *FB : BI.AnonEdges) {

391 auto &FBI = BlockInfos[FB];

392 FBI.AnonBackEdges.insert_range(BI.AnonBackEdges);

393 }

394

395 for (auto *BB : BI.AnonBackEdges) {

396 auto &BBI = BlockInfos[BB];

397 BBI.SymbolDeps.insert_range(BI.SymbolDeps);

398 BBI.AnonEdges.insert_range(BI.AnonEdges);

399 }

400 }

401

402 for (auto *B : BlocksToRemove)

403 BlockInfos.erase(B);

404 }

405

406

407 std::deque<Block *> Worklist;

408 for (auto &[B, BI] : BlockInfos) {

409 if (!BI.SymbolDeps.empty() && !BI.AnonBackEdges.empty()) {

410 Worklist.push_back(B);

411 BI.InWorklist = true;

412 }

413 }

414

415

416 while (!Worklist.empty()) {

417 auto *B = Worklist.front();

418 Worklist.pop_front();

419

420 auto &BI = BlockInfos[B];

421 BI.InWorklist = false;

422

423 for (auto *DB : BI.AnonBackEdges) {

424 auto &DBI = BlockInfos[DB];

425 for (auto *Sym : BI.SymbolDeps) {

426 if (DBI.SymbolDeps.insert(Sym).second && !DBI.InWorklist) {

427 Worklist.push_back(DB);

428 DBI.InWorklist = true;

429 }

430 }

431 }

432 }

433

434

435

436

437 auto &TargetJD = MR->getTargetJITDylib();

438

439 for (auto &[B, BI] : BlockInfos) {

440 if (!BI.Defs.empty()) {

441 SymbolDepGroups.push_back(SymbolDependenceGroup());

442 auto &SDG = SymbolDepGroups.back();

443

444 for (auto *Def : BI.Defs)

445 SDG.Symbols.insert(Def->getName());

446

447 for (auto *Dep : BI.SymbolDeps) {

448 auto DepName = Dep->getName();

449 if (Dep->isDefined())

450 SDG.Dependencies[&TargetJD].insert(std::move(DepName));

451 else {

452 auto SourceJDItr =

453 SymbolSourceJDs.find(NonOwningSymbolStringPtr(DepName));

454 if (SourceJDItr != SymbolSourceJDs.end())

455 SDG.Dependencies[SourceJDItr->second].insert(std::move(DepName));

456 }

457 }

458 }

459 }

460

462 }

463

465 std::vector<std::shared_ptrLinkGraphLinkingLayer::Plugin> Plugins;

466 std::unique_ptr MR;

467 std::unique_ptr ObjBuffer;

468 DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs;

469 std::vector SymbolDepGroups;

470};

471

473

475 : LinkGraphLayer(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {

476 ES.registerResourceManager(*this);

477}

478

482 ES.registerResourceManager(*this);

483}

484

486 ExecutionSession &ES, std::unique_ptr MemMgr)

489}

490

492 assert(Allocs.empty() &&

493 "Layer destroyed with resources still attached "

494 "(ExecutionSession::endSession() must be called prior to "

495 "destruction)");

497}

498

500 std::unique_ptr R,

501 std::unique_ptr G) {

502 assert(R && "R must not be null");

503 assert(G && "G must not be null");

504 auto Ctx = std::make_unique(*this, std::move(R), nullptr);

505 Ctx->notifyMaterializing(*G);

506 link(std::move(G), std::move(Ctx));

507}

508

510 std::unique_ptr R,

511 std::unique_ptr G, std::unique_ptr ObjBuf) {

512 assert(R && "R must not be null");

513 assert(G && "G must not be null");

514 assert(ObjBuf && "Object must not be null");

515 auto Ctx =

516 std::make_unique(*this, std::move(R), std::move(ObjBuf));

517 Ctx->notifyMaterializing(*G);

518 link(std::move(G), std::move(Ctx));

519}

520

521Error LinkGraphLinkingLayer::recordFinalizedAlloc(

524 [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });

525

526 if (Err)

527 Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));

528

529 return Err;

530}

531

532Error LinkGraphLinkingLayer::handleRemoveResources(JITDylib &JD,

534

535 {

537 for (auto &P : Plugins)

538 Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K));

539 if (Err)

540 return Err;

541 }

542

543 std::vector AllocsToRemove;

545 auto I = Allocs.find(K);

546 if (I != Allocs.end()) {

547 std::swap(AllocsToRemove, I->second);

548 Allocs.erase(I);

549 }

550 });

551

552 if (AllocsToRemove.empty())

554

555 return MemMgr.deallocate(std::move(AllocsToRemove));

556}

557

558void LinkGraphLinkingLayer::handleTransferResources(JITDylib &JD,

561 if (Allocs.contains(SrcKey)) {

562

563

564 auto &DstAllocs = Allocs[DstKey];

565 auto &SrcAllocs = Allocs[SrcKey];

566 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());

567 for (auto &Alloc : SrcAllocs)

568 DstAllocs.push_back(std::move(Alloc));

569

570 Allocs.erase(SrcKey);

571 }

572

573 for (auto &P : Plugins)

574 P->notifyTransferringResources(JD, DstKey, SrcKey);

575}

576

577}

578}

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

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

iterator find(const_arg_type_t< KeyT > Val)

size_type count(const_arg_type_t< KeyT > Val) const

Return 1 if the specified key is in the map, 0 otherwise.

void insert_range(Range &&R)

Inserts range of 'std::pair<KeyT, ValueT>' values into the map.

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

void reserve(size_type NumEntries)

Grow the densemap so that it can contain at least NumEntries items before resizing again.

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.

Triple - Helper class for working with autoconf configuration names.

JITLinkContext(const JITLinkDylib *JD)

Create a JITLinkContext.

DenseMap< orc::SymbolStringPtr, SymbolLookupFlags > LookupMap

Represents a finalized allocation.

Manages allocations of JIT memory.

bool isCallable() const

Returns true is this symbol is callable.

orc::ExecutorAddr getAddress() const

Returns the address of this symbol.

An ExecutionSession represents a running JIT program.

LLVM_ABI void registerResourceManager(ResourceManager &RM)

Register the given ResourceManager with this ExecutionSession.

LLVM_ABI void deregisterResourceManager(ResourceManager &RM)

Deregister the given ResourceManager with this ExecutionSession.

decltype(auto) runSessionLocked(Func &&F)

Run the given lambda with the session mutex locked.

Represents an address in the executor process.

uint64_t getValue() const

Represents a JIT'd dynamic library.

LinkGraphLayer(ExecutionSession &ES)

ExecutionSession & getExecutionSession()

static JITSymbolFlags getJITSymbolFlagsForSymbol(jitlink::Symbol &Sym)

Get the JITSymbolFlags for the given symbol.

JITLinkCtx(LinkGraphLinkingLayer &Layer, std::unique_ptr< MaterializationResponsibility > MR, std::unique_ptr< MemoryBuffer > ObjBuffer)

Definition LinkGraphLinkingLayer.cpp:49

void notifyFailed(Error Err) override

Notify this context that linking failed.

Definition LinkGraphLinkingLayer.cpp:74

void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override

Called by JITLink to notify the context that the object has been finalized (i.e.

Definition LinkGraphLinkingLayer.cpp:213

JITLinkMemoryManager & getMemoryManager() override

Return the MemoryManager to be used for this link.

Definition LinkGraphLinkingLayer.cpp:65

Error notifyResolved(LinkGraph &G) override

Called by JITLink once all defined symbols in the graph have been assigned their final memory locatio...

Definition LinkGraphLinkingLayer.cpp:126

void lookup(const LookupMap &Symbols, std::unique_ptr< JITLinkAsyncLookupContinuation > LC) override

Called by JITLink to resolve external symbols.

Definition LinkGraphLinkingLayer.cpp:81

LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override

Returns the mark-live pass to be used for this link.

Definition LinkGraphLinkingLayer.cpp:226

Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override

Called by JITLink to modify the pass pipeline prior to linking.

Definition LinkGraphLinkingLayer.cpp:230

~JITLinkCtx() override

Definition LinkGraphLinkingLayer.cpp:58

void notifyMaterializing(LinkGraph &G)

Definition LinkGraphLinkingLayer.cpp:67

Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA)

Definition LinkGraphLinkingLayer.cpp:246

~LinkGraphLinkingLayer() override

Destroy the LinkGraphLinkingLayer.

Definition LinkGraphLinkingLayer.cpp:491

void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< jitlink::LinkGraph > G) override

Emit a LinkGraph.

LinkGraphLinkingLayer(ExecutionSession &ES)

Construct a LinkGraphLinkingLayer using the ExecutorProcessControl instance's memory manager.

Definition LinkGraphLinkingLayer.cpp:474

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

Error withResourceKeyDo(Func &&F) const

Runs the given callback under the session lock, passing in the associated ResourceKey.

Non-owning SymbolStringPool entry pointer.

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

SymbolLookupSet & add(SymbolStringPtr Name, SymbolLookupFlags Flags=SymbolLookupFlags::RequiredSymbol)

Add an element to the set.

unique_function< Error(LinkGraph &)> LinkGraphPassFunction

A function for mutating LinkGraphs.

LLVM_ABI void link(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)

Link the given graph.

DenseMap< orc::SymbolStringPtr, orc::ExecutorSymbolDef > AsyncLookupResult

A map of symbol names to resolved addresses.

std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder

A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.

SymbolLookupFlags

Lookup flags that apply to each symbol in a lookup.

DenseMap< SymbolStringPtr, ExecutorSymbolDef > SymbolMap

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

std::vector< SymbolStringPtr > SymbolNameVector

A vector of symbol names.

DenseMap< JITDylib *, SymbolNameSet > SymbolDependenceMap

A map from JITDylibs to sets of symbols.

@ Resolved

Queried, materialization begun.

DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap

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

NodeAddr< DefNode * > Def

This is an optimization pass for GlobalISel generic memory operations.

Error joinErrors(Error E1, Error E2)

Concatenate errors.

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.

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

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

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

LinkGraphPassList PreFixupPasses

Pre-fixup passes.

LinkGraphPassList PrePrunePasses

Pre-prune passes.