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

1

2

3

4

5

6

7

8

10

20#include

21

22#define DEBUG_TYPE "orc"

23

24using namespace llvm;

27

28namespace {

29

30template <typename SPSSerializer, typename... ArgTs>

32getArgDataBufferType(const ArgTs &...Args) {

34 ArgData.resize(SPSSerializer::size(Args...));

36 ArgData.size());

37 if (SPSSerializer::serialize(OB, Args...))

38 return ArgData;

39 return {};

40}

41

42std::unique_ptrjitlink::LinkGraph createPlatformGraph(ELFNixPlatform &MOP,

43 std::string Name) {

45 return std::make_uniquejitlink::LinkGraph(

46 std::move(Name), ES.getSymbolStringPool(), ES.getTargetTriple(),

48}

49

50

51class ELFNixPlatformCompleteBootstrapMaterializationUnit

53public:

54 ELFNixPlatformCompleteBootstrapMaterializationUnit(

62 MOP(MOP), PlatformJDName(PlatformJDName),

63 CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)),

64 DeferredAAsMap(std::move(DeferredAAs)),

65 ELFNixHeaderAddr(ELFNixHeaderAddr),

66 PlatformBootstrap(PlatformBootstrap),

67 PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib),

68 DeregisterJITDylib(DeregisterJITDylib) {}

69

71 return "ELFNixPlatformCompleteBootstrap";

72 }

73

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

76 auto G = createPlatformGraph(MOP, "");

77 auto &PlaceholderSection =

79 auto &PlaceholderBlock =

80 G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0);

81 G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1,

82 Linkage::Strong, Scope::Hidden, false, true);

83

84

85 G->allocActions().push_back(

87 PlatformBootstrap, ELFNixHeaderAddr)),

90

91

92 G->allocActions().push_back(

95 RegisterJITDylib, PlatformJDName, ELFNixHeaderAddr)),

97 DeregisterJITDylib, ELFNixHeaderAddr))});

98

99

100 for (auto &[Fn, CallDatas] : DeferredAAsMap) {

101 for (auto &CallData : CallDatas) {

102 G->allocActions().push_back(

105 }

106 }

107

109 }

110

112

113private:

123};

124

126public:

130 createDSOHandleSectionInterface(ENP, DSOHandleSymbol)),

131 ENP(ENP) {}

132

134

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

136

138

139 jitlink::Edge::Kind EdgeKind;

140

141 switch (ES.getTargetTriple().getArch()) {

144 break;

147 break;

150 break;

153 break;

156 break;

159 break;

160 default:

162 }

163

164

165 auto G = std::make_uniquejitlink::LinkGraph(

166 "", ES.getSymbolStringPool(), ES.getTargetTriple(),

168 auto &DSOHandleSection =

169 G->createSection(".data.__dso_handle", MemProt::Read);

170 auto &DSOHandleBlock = G->createContentBlock(

171 DSOHandleSection, getDSOHandleContent(G->getPointerSize()),

173 auto &DSOHandleSymbol = G->addDefinedSymbol(

174 DSOHandleBlock, 0, *R->getInitializerSymbol(), DSOHandleBlock.getSize(),

176 DSOHandleBlock.addEdge(EdgeKind, 0, DSOHandleSymbol, 0);

177

179 }

180

182

183private:

190 DSOHandleSymbol);

191 }

192

193 ArrayRef getDSOHandleContent(size_t PointerSize) {

194 static const char Content[8] = {0};

195 assert(PointerSize <= sizeof Content);

196 return {Content, PointerSize};

197 }

198

200};

201

202}

203

204namespace llvm {

205namespace orc {

206

207Expected<std::unique_ptr>

210 std::unique_ptr OrcRuntime,

211 std::optional RuntimeAliases) {

212

213 auto &ES = ObjLinkingLayer.getExecutionSession();

214

215

216 if (!supportedTarget(ES.getTargetTriple()))

218 ES.getTargetTriple().str(),

220

221 auto &EPC = ES.getExecutorProcessControl();

222

223

224 if (!RuntimeAliases) {

226 if (!StandardRuntimeAliases)

227 return StandardRuntimeAliases.takeError();

228 RuntimeAliases = std::move(*StandardRuntimeAliases);

229 }

230

231

232 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))

233 return std::move(Err);

234

235

236 if (auto Err = PlatformJD.define(

238 {EPC.getJITDispatchInfo().JITDispatchFunction,

240 {ES.intern("__orc_rt_jit_dispatch_ctx"),

241 {EPC.getJITDispatchInfo().JITDispatchContext,

243 return std::move(Err);

244

245

247 auto P = std::unique_ptr(new ELFNixPlatform(

248 ObjLinkingLayer, PlatformJD, std::move(OrcRuntime), Err));

249 if (Err)

250 return std::move(Err);

251 return std::move(P);

252}

253

256 JITDylib &PlatformJD, const char *OrcRuntimePath,

257 std::optional RuntimeAliases) {

258

259

260 auto OrcRuntimeArchiveGenerator =

262 if (!OrcRuntimeArchiveGenerator)

263 return OrcRuntimeArchiveGenerator.takeError();

264

265 return Create(ObjLinkingLayer, PlatformJD,

266 std::move(*OrcRuntimeArchiveGenerator),

267 std::move(RuntimeAliases));

268}

269

271 if (auto Err = JD.define(std::make_unique(

272 *this, DSOHandleSymbol)))

273 return Err;

274

275 return ES.lookup({&JD}, DSOHandleSymbol).takeError();

276}

277

279 std::lock_guardstd::mutex Lock(PlatformMutex);

280 auto I = JITDylibToHandleAddr.find(&JD);

281 if (I != JITDylibToHandleAddr.end()) {

282 assert(HandleAddrToJITDylib.count(I->second) &&

283 "HandleAddrToJITDylib missing entry");

284 HandleAddrToJITDylib.erase(I->second);

285 JITDylibToHandleAddr.erase(I);

286 }

288}

289

292

295 if (!InitSym)

297

298 RegisteredInitSymbols[&JD].add(InitSym,

301 dbgs() << "ELFNixPlatform: Registered init symbol " << *InitSym

302 << " for MU " << MU.getName() << "\n";

303 });

305}

306

310

312 ArrayRef<std::pair<const char *, const char *>> AL) {

313 for (auto &KV : AL) {

314 auto AliasName = ES.intern(KV.first);

315 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");

316 Aliases[std::move(AliasName)] = {ES.intern(KV.second),

318 }

319}

320

330

333 static const std::pair<const char *, const char *> RequiredCXXAliases[] = {

334 {"__cxa_atexit", "__orc_rt_elfnix_cxa_atexit"},

335 {"atexit", "__orc_rt_elfnix_atexit"}};

336

338}

339

342 static const std::pair<const char *, const char *>

343 StandardRuntimeUtilityAliases[] = {

344 {"__orc_rt_run_program", "__orc_rt_elfnix_run_program"},

345 {"__orc_rt_jit_dlerror", "__orc_rt_elfnix_jit_dlerror"},

346 {"__orc_rt_jit_dlopen", "__orc_rt_elfnix_jit_dlopen"},

347 {"__orc_rt_jit_dlupdate", "__orc_rt_elfnix_jit_dlupdate"},

348 {"__orc_rt_jit_dlclose", "__orc_rt_elfnix_jit_dlclose"},

349 {"__orc_rt_jit_dlsym", "__orc_rt_elfnix_jit_dlsym"},

350 {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};

351

353 StandardRuntimeUtilityAliases);

354}

355

358 static const std::pair<const char *, const char *>

359 StandardLazyCompilationAliases[] = {

360 {"__orc_rt_reenter", "__orc_rt_sysv_reenter"}};

361

363 StandardLazyCompilationAliases);

364}

365

366bool ELFNixPlatform::supportedTarget(const Triple &TT) {

367 switch (TT.getArch()) {

370

371

375 return true;

376 default:

377 return false;

378 }

379}

380

381ELFNixPlatform::ELFNixPlatform(

383 std::unique_ptr OrcRuntimeGenerator, Error &Err)

384 : ES(ObjLinkingLayer.getExecutionSession()), PlatformJD(PlatformJD),

385 ObjLinkingLayer(ObjLinkingLayer),

386 DSOHandleSymbol(ES.intern("__dso_handle")) {

388 ObjLinkingLayer.addPlugin(std::make_unique(*this));

389

390 PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));

391

392 BootstrapInfo BI;

393 Bootstrap = &BI;

394

395

396

398 Err = std::move(E2);

399 return;

400 }

401

402

403

404 if ((Err = ES.lookup(

406 SymbolLookupSet(

407 {PlatformBootstrap.Name, PlatformShutdown.Name,

408 RegisterJITDylib.Name, DeregisterJITDylib.Name,

409 RegisterInitSections.Name, DeregisterInitSections.Name,

410 RegisterObjectSections.Name,

411 DeregisterObjectSections.Name, CreatePThreadKey.Name}))

412 .takeError()))

413 return;

414

415

416 {

417 std::unique_lockstd::mutex Lock(BI.Mutex);

418 BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; });

419 Bootstrap = nullptr;

420 }

421

422

423 auto BootstrapCompleteSymbol =

424 ES.intern("__orc_rt_elfnix_complete_bootstrap");

425 if ((Err = PlatformJD.define(

426 std::make_unique(

427 *this, PlatformJD.getName(), BootstrapCompleteSymbol,

428 std::move(BI.DeferredRTFnMap), BI.ELFNixHeaderAddr,

429 PlatformBootstrap.Addr, PlatformShutdown.Addr,

430 RegisterJITDylib.Addr, DeregisterJITDylib.Addr))))

431 return;

434 std::move(BootstrapCompleteSymbol))

435 .takeError()))

436 return;

437

438

439 if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {

440 Err = std::move(E2);

441 return;

442 }

443}

444

445Error ELFNixPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {

447

448 using RecordInitializersSPSSig =

449 SPSExpected(SPSExecutorAddr);

450 WFs[ES.intern("__orc_rt_elfnix_push_initializers_tag")] =

451 ES.wrapAsyncWithSPS(

452 this, &ELFNixPlatform::rt_recordInitializers);

453

454 using LookupSymbolSPSSig =

455 SPSExpected(SPSExecutorAddr, SPSString);

456 WFs[ES.intern("__orc_rt_elfnix_symbol_lookup_tag")] =

457 ES.wrapAsyncWithSPS(this,

458 &ELFNixPlatform::rt_lookupSymbol);

459

460 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));

461}

462

463void ELFNixPlatform::pushInitializersLoop(

464 PushInitializersSendResultFn SendResult, JITDylibSP JD) {

465 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;

466 DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap;

468

469 ES.runSessionLocked([&]() {

470 while (!Worklist.empty()) {

471

472

473 auto DepJD = Worklist.back();

474 Worklist.pop_back();

475

476

478 if (!Inserted)

479 continue;

480

481

482 auto &DM = It->second;

484 for (auto &KV : O) {

485 if (KV.first == DepJD)

486 continue;

487 DM.push_back(KV.first);

488 Worklist.push_back(KV.first);

489 }

490 });

491

492

493 auto RISItr = RegisteredInitSymbols.find(DepJD);

494 if (RISItr != RegisteredInitSymbols.end()) {

495 NewInitSymbols[DepJD] = std::move(RISItr->second);

496 RegisteredInitSymbols.erase(RISItr);

497 }

498 }

499 });

500

501

502

503 if (NewInitSymbols.empty()) {

504

505

506

507

508

509 DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;

511 {

512 std::lock_guardstd::mutex Lock(PlatformMutex);

513 for (auto &KV : JDDepMap) {

514 auto I = JITDylibToHandleAddr.find(KV.first);

515 if (I != JITDylibToHandleAddr.end())

516 HeaderAddrs[KV.first] = I->second;

517 }

518 }

519

520

522 DIM.reserve(JDDepMap.size());

523 for (auto &KV : JDDepMap) {

524 auto HI = HeaderAddrs.find(KV.first);

525

526 if (HI == HeaderAddrs.end())

527 continue;

528 auto H = HI->second;

530 for (auto &Dep : KV.second) {

531 auto HJ = HeaderAddrs.find(Dep);

532 if (HJ != HeaderAddrs.end())

533 DepInfo.push_back(HJ->second);

534 }

535 DIM.push_back(std::make_pair(H, std::move(DepInfo)));

536 }

537 SendResult(DIM);

538 return;

539 }

540

541

543 [this, SendResult = std::move(SendResult), JD](Error Err) mutable {

544 if (Err)

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

546 else

547 pushInitializersLoop(std::move(SendResult), JD);

548 },

549 ES, std::move(NewInitSymbols));

550}

551

552void ELFNixPlatform::rt_recordInitializers(

553 PushInitializersSendResultFn SendResult, ExecutorAddr JDHeaderAddr) {

555 {

556 std::lock_guardstd::mutex Lock(PlatformMutex);

557 auto I = HandleAddrToJITDylib.find(JDHeaderAddr);

558 if (I != HandleAddrToJITDylib.end())

559 JD = I->second;

560 }

561

563 dbgs() << "ELFNixPlatform::rt_recordInitializers(" << JDHeaderAddr << ") ";

564 if (JD)

565 dbgs() << "pushing initializers for " << JD->getName() << "\n";

566 else

567 dbgs() << "No JITDylib for header address.\n";

568 });

569

570 if (!JD) {

572 formatv("{0:x}", JDHeaderAddr),

574 return;

575 }

576

577 pushInitializersLoop(std::move(SendResult), JD);

578}

579

580void ELFNixPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,

582 StringRef SymbolName) {

584 dbgs() << "ELFNixPlatform::rt_lookupSymbol(\"" << Handle << "\")\n";

585 });

586

587 JITDylib *JD = nullptr;

588

589 {

590 std::lock_guardstd::mutex Lock(PlatformMutex);

591 auto I = HandleAddrToJITDylib.find(Handle);

592 if (I != HandleAddrToJITDylib.end())

593 JD = I->second;

594 }

595

596 if (!JD) {

597 LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n");

599 formatv("{0:x}", Handle),

601 return;

602 }

603

604

605 class RtLookupNotifyComplete {

606 public:

607 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)

608 : SendResult(std::move(SendResult)) {}

609 void operator()(Expected Result) {

611 assert(Result->size() == 1 && "Unexpected result map count");

612 SendResult(Result->begin()->second.getAddress());

613 } else {

614 SendResult(Result.takeError());

615 }

616 }

617

618 private:

619 SendSymbolAddressFn SendResult;

620 };

621

622 ES.lookup(

626}

627

628Error ELFNixPlatform::ELFNixPlatformPlugin::bootstrapPipelineStart(

629 jitlink::LinkGraph &G) {

630

631 std::lock_guardstd::mutex Lock(MP.Bootstrap.load()->Mutex);

632 ++MP.Bootstrap.load()->ActiveGraphs;

634}

635

636Error ELFNixPlatform::ELFNixPlatformPlugin::

637 bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) {

638

639 std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = {

640 {*MP.DSOHandleSymbol, &MP.Bootstrap.load()->ELFNixHeaderAddr},

641 {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr},

642 {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},

643 {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},

644 {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr},

645 {*MP.RegisterObjectSections.Name, &MP.RegisterObjectSections.Addr},

646 {*MP.DeregisterObjectSections.Name, &MP.DeregisterObjectSections.Addr},

647 {*MP.RegisterInitSections.Name, &MP.RegisterInitSections.Addr},

648 {*MP.DeregisterInitSections.Name, &MP.DeregisterInitSections.Addr},

649 {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr}};

650

651 bool RegisterELFNixHeader = false;

652

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

654 for (auto &RTSym : RuntimeSymbols) {

655 if (Sym->hasName() && *Sym->getName() == RTSym.first) {

656 if (*RTSym.second)

658 "Duplicate " + RTSym.first +

659 " detected during ELFNixPlatform bootstrap",

661

662 if (*Sym->getName() == *MP.DSOHandleSymbol)

663 RegisterELFNixHeader = true;

664

665 *RTSym.second = Sym->getAddress();

666 }

667 }

668 }

669

670 if (RegisterELFNixHeader) {

671

672

673 std::lock_guardstd::mutex Lock(MP.PlatformMutex);

674 MP.JITDylibToHandleAddr[&MP.PlatformJD] =

675 MP.Bootstrap.load()->ELFNixHeaderAddr;

676 MP.HandleAddrToJITDylib[MP.Bootstrap.load()->ELFNixHeaderAddr] =

677 &MP.PlatformJD;

678 }

679

681}

682

683Error ELFNixPlatform::ELFNixPlatformPlugin::bootstrapPipelineEnd(

684 jitlink::LinkGraph &G) {

685 std::lock_guardstd::mutex Lock(MP.Bootstrap.load()->Mutex);

686 assert(MP.Bootstrap && "DeferredAAs reset before bootstrap completed");

687 --MP.Bootstrap.load()->ActiveGraphs;

688

689

690 if (MP.Bootstrap.load()->ActiveGraphs == 0)

691 MP.Bootstrap.load()->CV.notify_all();

693}

694

695Error ELFNixPlatform::registerPerObjectSections(

696 jitlink::LinkGraph &G, const ELFPerObjectSectionsToRegister &POSR,

697 bool IsBootstrapping) {

698 using SPSRegisterPerObjSectionsArgs =

699 SPSArgList;

700

702 Bootstrap.load()->addArgumentsToRTFnMap(

703 &RegisterObjectSections, &DeregisterObjectSections,

704 getArgDataBufferType(POSR),

705 getArgDataBufferType(POSR));

707 }

708

709 G.allocActions().push_back(

711 RegisterObjectSections.Addr, POSR)),

713 DeregisterObjectSections.Addr, POSR))});

714

716}

717

718Expected<uint64_t> ELFNixPlatform::createPThreadKey() {

719 if (!CreatePThreadKey.Addr)

721 "Attempting to create pthread key in target, but runtime support has "

722 "not been loaded yet",

724

725 Expected<uint64_t> Result(0);

726 if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(

727 CreatePThreadKey.Addr, Result))

728 return std::move(Err);

730}

731

732void ELFNixPlatform::ELFNixPlatformPlugin::modifyPassConfig(

733 MaterializationResponsibility &MR, jitlink::LinkGraph &LG,

734 jitlink::PassConfiguration &Config) {

735 using namespace jitlink;

736

737 bool InBootstrapPhase =

739

740

741 if (InBootstrapPhase) {

743 [this](LinkGraph &G) { return bootstrapPipelineStart(G); });

745 return bootstrapPipelineRecordRuntimeFunctions(G);

746 });

747 }

748

749

750

752 if (InitSymbol == MP.DSOHandleSymbol && !InBootstrapPhase) {

753 addDSOHandleSupportPasses(MR, Config);

754

755

756 return;

757 }

758

759

761 [this, &MR](jitlink::LinkGraph &G) -> Error {

762 if (auto Err = preserveInitSections(G, MR))

763 return Err;

765 });

766 }

767

768

769 addEHAndTLVSupportPasses(MR, Config, InBootstrapPhase);

770

771

773 InBootstrapPhase](jitlink::LinkGraph &G) {

774 return registerInitSections(G, JD, InBootstrapPhase);

775 });

776

777

778

779 if (InBootstrapPhase)

781 [this](LinkGraph &G) { return bootstrapPipelineEnd(G); });

782}

783

784void ELFNixPlatform::ELFNixPlatformPlugin::addDSOHandleSupportPasses(

785 MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {

786

788 jitlink::LinkGraph &G) -> Error {

789 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {

790 return Sym->getName() == MP.DSOHandleSymbol;

791 });

792 assert(I != G.defined_symbols().end() && "Missing DSO handle symbol");

793 {

794 std::lock_guardstd::mutex Lock(MP.PlatformMutex);

795 auto HandleAddr = (*I)->getAddress();

796 MP.HandleAddrToJITDylib[HandleAddr] = &JD;

797 MP.JITDylibToHandleAddr[&JD] = HandleAddr;

798

799 G.allocActions().push_back(

801 SPSArgList<SPSString, SPSExecutorAddr>>(

802 MP.RegisterJITDylib.Addr, JD.getName(), HandleAddr)),

804 MP.DeregisterJITDylib.Addr, HandleAddr))});

805 }

807 });

808}

809

810void ELFNixPlatform::ELFNixPlatformPlugin::addEHAndTLVSupportPasses(

812 bool IsBootstrapping) {

813

814

815

816

817

818

821 return fixTLVSectionsAndEdges(G, JD);

822 });

823

824

825

826 Config.PostFixupPasses.push_back([this, IsBootstrapping](

827 jitlink::LinkGraph &G) -> Error {

828 ELFPerObjectSectionsToRegister POSR;

829

831 jitlink::SectionRange R(*EHFrameSection);

832 if (R.empty())

834 }

835

836

837

838 jitlink::Section *ThreadDataSection =

840

841

843

844

845

846 if (ThreadDataSection)

847 G.mergeSections(*ThreadDataSection, *ThreadBSSSection);

848 else

849 ThreadDataSection = ThreadBSSSection;

850 }

851

852

853

854 if (ThreadDataSection) {

855 jitlink::SectionRange R(*ThreadDataSection);

856 if (R.empty())

858 }

859

861 if (auto Err = MP.registerPerObjectSections(G, POSR, IsBootstrapping))

862 return Err;

863 }

864

866 });

867}

868

869Error ELFNixPlatform::ELFNixPlatformPlugin::preserveInitSections(

870 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {

871

873

874 jitlink::Symbol *InitSym = nullptr;

875

876 for (auto &InitSection : G.sections()) {

877

879 InitSection.empty())

880 continue;

881

882

883

884 if (!InitSym) {

885 auto &B = **InitSection.blocks().begin();

886 InitSym = &G.addDefinedSymbol(

889 }

890

891

892 for (auto *B : InitSection.blocks()) {

894 continue;

895

896 auto &S = G.addAnonymousSymbol(*B, 0, B->getSize(), false, true);

897 InitSym->getBlock().addEdge(jitlink::Edge::KeepAlive, 0, S, 0);

898 }

899 }

900 }

901

903}

904

905Error ELFNixPlatform::ELFNixPlatformPlugin::registerInitSections(

906 jitlink::LinkGraph &G, JITDylib &JD, bool IsBootstrapping) {

908 LLVM_DEBUG(dbgs() << "ELFNixPlatform::registerInitSections\n");

909

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

913 OrderedInitSections.push_back(&Sec);

914

915

916

917

918 llvm::sort(OrderedInitSections, [](const jitlink::Section *LHS,

919 const jitlink::Section *RHS) {

922 StringRef LHSPrioStr(LHS->getName());

923 StringRef RHSPrioStr(RHS->getName());

924 uint64_t LHSPriority;

925 bool LHSHasPriority = LHSPrioStr.consume_front(".init_array.") &&

926 !LHSPrioStr.getAsInteger(10, LHSPriority);

927 uint64_t RHSPriority;

928 bool RHSHasPriority = RHSPrioStr.consume_front(".init_array.") &&

929 !RHSPrioStr.getAsInteger(10, RHSPriority);

930 if (LHSHasPriority)

931 return RHSHasPriority ? LHSPriority < RHSPriority : true;

932 else if (RHSHasPriority)

933 return false;

934

935

936 } else {

937

938 return true;

939 }

940 }

942 });

943

944 for (auto &Sec : OrderedInitSections)

945 ELFNixPlatformSecs.push_back(jitlink::SectionRange(*Sec).getRange());

946

947

949 dbgs() << "ELFNixPlatform: Scraped " << G.getName() << " init sections:\n";

950 for (auto &Sec : G.sections()) {

951 jitlink::SectionRange R(Sec);

952 dbgs() << " " << Sec.getName() << ": " << R.getRange() << "\n";

953 }

954 });

955

956 ExecutorAddr HeaderAddr;

957 {

958 std::lock_guardstd::mutex Lock(MP.PlatformMutex);

959 auto I = MP.JITDylibToHandleAddr.find(&JD);

960 assert(I != MP.JITDylibToHandleAddr.end() && "No header registered for JD");

961 assert(I->second && "Null header registered for JD");

962 HeaderAddr = I->second;

963 }

964

965 using SPSRegisterInitSectionsArgs =

966 SPSArgList<SPSExecutorAddr, SPSSequence>;

967

969 MP.Bootstrap.load()->addArgumentsToRTFnMap(

970 &MP.RegisterInitSections, &MP.DeregisterInitSections,

971 getArgDataBufferType(HeaderAddr,

972 ELFNixPlatformSecs),

973 getArgDataBufferType(HeaderAddr,

974 ELFNixPlatformSecs));

976 }

977

978 G.allocActions().push_back(

980 MP.RegisterInitSections.Addr, HeaderAddr, ELFNixPlatformSecs)),

982 MP.DeregisterInitSections.Addr, HeaderAddr, ELFNixPlatformSecs))});

983

985}

986

987Error ELFNixPlatform::ELFNixPlatformPlugin::fixTLVSectionsAndEdges(

988 jitlink::LinkGraph &G, JITDylib &JD) {

989 auto TLSGetAddrSymbolName = G.intern("__tls_get_addr");

990 auto TLSDescResolveSymbolName = G.intern("__tlsdesc_resolver");

991 auto TLSGetOffsetSymbolName = G.intern("__tls_get_offset");

992 for (auto *Sym : G.external_symbols()) {

993 if (Sym->getName() == TLSGetAddrSymbolName) {

994 auto TLSGetAddr =

995 MP.getExecutionSession().intern("___orc_rt_elfnix_tls_get_addr");

996 Sym->setName(std::move(TLSGetAddr));

997 } else if (Sym->getName() == TLSDescResolveSymbolName) {

998 auto TLSGetAddr =

999 MP.getExecutionSession().intern("___orc_rt_elfnix_tlsdesc_resolver");

1000 Sym->setName(std::move(TLSGetAddr));

1001 } else if (Sym->getName() == TLSGetOffsetSymbolName) {

1002 auto TLSGetAddr =

1003 MP.getExecutionSession().intern("___orc_rt_elfnix_tls_get_offset");

1004 Sym->setName(std::move(TLSGetAddr));

1005 }

1006 }

1007

1008 auto *TLSInfoEntrySection = G.findSectionByName("$__TLSINFO");

1009

1010 if (TLSInfoEntrySection) {

1011 std::optional<uint64_t> Key;

1012 {

1013 std::lock_guardstd::mutex Lock(MP.PlatformMutex);

1014 auto I = MP.JITDylibToPThreadKey.find(&JD);

1015 if (I != MP.JITDylibToPThreadKey.end())

1016 Key = I->second;

1017 }

1018 if (Key) {

1019 if (auto KeyOrErr = MP.createPThreadKey())

1020 Key = *KeyOrErr;

1021 else

1022 return KeyOrErr.takeError();

1023 }

1024

1025 uint64_t PlatformKeyBits =

1027

1028 for (auto *B : TLSInfoEntrySection->blocks()) {

1029

1030

1031 assert(B->getSize() == (G.getPointerSize() * 2) &&

1032 "TLS descriptor must be 2 words length");

1033 auto TLSInfoEntryContent = B->getMutableContent(G);

1034 memcpy(TLSInfoEntryContent.data(), &PlatformKeyBits, G.getPointerSize());

1035 }

1036 }

1037

1039}

1040

1041}

1042}

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

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

#define LLVM_UNLIKELY(EXPR)

static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")

static StringRef getName(Value *V)

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

iterator find(const_arg_type_t< KeyT > Val)

std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)

size_type count(const_arg_type_t< KeyT > Val) const

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

void reserve(size_type NumEntries)

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

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.

void push_back(const T &Elt)

pointer data()

Return a pointer to the vector's buffer, even if empty().

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

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

Manages the enabling and disabling of subtarget specific features.

Triple - Helper class for working with autoconf configuration names.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, Edge::AddendT Addend)

Add an edge to this block.

const std::string & getName() const

Get the name for this JITLinkDylib.

Block & getBlock()

Return the Block for this Symbol (Symbol must be defined).

Mediates between ELFNix initialization and ExecutionSession state.

ObjectLinkingLayer & getObjectLinkingLayer() const

static Expected< SymbolAliasMap > standardPlatformAliases(ExecutionSession &ES, JITDylib &PlatformJD)

Returns an AliasMap containing the default aliases for the ELFNixPlatform.

Definition ELFNixPlatform.cpp:322

Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) override

This method will be called under the ExecutionSession lock each time a MaterializationUnit is added t...

Definition ELFNixPlatform.cpp:290

Error notifyRemoving(ResourceTracker &RT) override

This method will be called under the ExecutionSession lock when a ResourceTracker is removed.

Definition ELFNixPlatform.cpp:307

Error setupJITDylib(JITDylib &JD) override

This method will be called outside the session lock each time a JITDylib is created (unless it is cre...

Definition ELFNixPlatform.cpp:270

ExecutionSession & getExecutionSession() const

static ArrayRef< std::pair< const char *, const char * > > standardRuntimeUtilityAliases()

Returns the array of standard runtime utility aliases for ELF.

Definition ELFNixPlatform.cpp:341

static Expected< std::unique_ptr< ELFNixPlatform > > Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, std::unique_ptr< DefinitionGenerator > OrcRuntime, std::optional< SymbolAliasMap > RuntimeAliases=std::nullopt)

Try to create a ELFNixPlatform instance, adding the ORC runtime to the given JITDylib.

Definition ELFNixPlatform.cpp:208

static ArrayRef< std::pair< const char *, const char * > > standardLazyCompilationAliases()

Returns a list of aliases required to enable lazy compilation via the ORC runtime.

Definition ELFNixPlatform.cpp:357

static ArrayRef< std::pair< const char *, const char * > > requiredCXXAliases()

Returns the array of required CXX aliases.

Definition ELFNixPlatform.cpp:332

Error teardownJITDylib(JITDylib &JD) override

This method will be called outside the session lock each time a JITDylib is removed to allow the Plat...

Definition ELFNixPlatform.cpp:278

An ExecutionSession represents a running JIT program.

SymbolStringPtr intern(StringRef SymName)

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

DenseMap< SymbolStringPtr, JITDispatchHandlerFunction > JITDispatchHandlerAssociationMap

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

Represents an address in the executor process.

Represents a JIT'd dynamic library.

Error define(std::unique_ptr< MaterializationUnitType > &&MU, ResourceTrackerSP RT=nullptr)

Define all symbols provided by the materialization unit to be part of this JITDylib.

GeneratorT & addGenerator(std::unique_ptr< GeneratorT > DefGenerator)

Adds a definition generator to this JITDylib and returns a referenece to it.

LinkGraphLinkingLayer & addPlugin(std::shared_ptr< Plugin > P)

Add a plugin.

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

const SymbolStringPtr & getInitializerSymbol() const

Returns the initialization pseudo-symbol, if any.

JITDylib & getTargetJITDylib() const

Returns the target JITDylib that these symbols are being materialized into.

A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...

virtual StringRef getName() const =0

Return the name of this materialization unit.

const SymbolStringPtr & getInitializerSymbol() const

Returns the initialization symbol for this MaterializationUnit (if any).

An ObjectLayer implementation built on JITLink.

void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< MemoryBuffer > O) override

Emit an object file.

static void lookupInitSymbolsAsync(unique_function< void(Error)> OnComplete, ExecutionSession &ES, const DenseMap< JITDylib *, SymbolLookupSet > &InitSyms)

Performs an async lookup for the given symbols in each of the given JITDylibs, calling the given hand...

API to remove / transfer ownership of JIT resources.

JITDylib & getJITDylib() const

Return the JITDylib targeted by this tracker.

static Expected< std::unique_ptr< StaticLibraryDefinitionGenerator > > Load(ObjectLayer &L, const char *FileName, VisitMembersFunction VisitMembers=VisitMembersFunction(), GetObjectFileInterface GetObjFileInterface=GetObjectFileInterface())

Try to create a StaticLibraryDefinitionGenerator from the given path.

Pointer to a pooled string representing a symbol name.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ Pointer64

A plain 64-bit pointer value relocation.

@ Pointer64

A plain 64-bit pointer value relocation.

@ Pointer64

A plain 64-bit pointer value relocation.

@ Pointer64

A plain 64-bit pointer value relocation.

LLVM_ABI const char * getGenericEdgeKindName(Edge::Kind K)

Returns the string name of the given generic edge kind, or "unknown" otherwise.

LLVM_ABI StringRef ELFThreadBSSSectionName

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...

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

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

IntrusiveRefCntPtr< JITDylib > JITDylibSP

std::vector< std::pair< ExecutorAddr, ELFNixJITDylibDepInfo > > ELFNixJITDylibDepInfoMap

std::unique_ptr< ReExportsMaterializationUnit > symbolAliases(SymbolAliasMap Aliases)

Create a ReExportsMaterializationUnit with the given aliases.

std::vector< ExecutorAddr > ELFNixJITDylibDepInfo

std::unique_ptr< AbsoluteSymbolsMaterializationUnit > absoluteSymbols(SymbolMap Symbols)

Create an AbsoluteSymbolsMaterializationUnit with the given symbols.

LLVM_ABI StringRef ELFEHFrameSectionName

@ MatchExportedSymbolsOnly

static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, ArrayRef< std::pair< const char *, const char * > > AL)

std::unordered_map< std::pair< RuntimeFunction *, RuntimeFunction * >, SmallVector< std::pair< shared::WrapperFunctionCall::ArgDataBufferType, shared::WrapperFunctionCall::ArgDataBufferType > >, FunctionPairKeyHash, FunctionPairKeyEqual > DeferredRuntimeFnMap

LLVM_ABI StringRef ELFThreadDataSectionName

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.

LLVM_ABI bool isELFInitializerSection(StringRef SecName)

DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap

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

value_type byte_swap(value_type value, endianness endian)

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...

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

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.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

OutputIt move(R &&Range, OutputIt Out)

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

LinkGraphPassList PostAllocationPasses

Post-allocation passes.

LinkGraphPassList PostFixupPasses

Post-fixup passes.

LinkGraphPassList PostPrunePasses

Post-prune passes.

LinkGraphPassList PrePrunePasses

Pre-prune passes.

ExecutorAddrRange EHFrameSection

ExecutorAddrRange ThreadDataSection