LLVM: lib/ExecutionEngine/JITLink/ELF_riscv.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

25

26#define DEBUG_TYPE "jitlink"

27using namespace llvm;

30

31namespace {

32

33class PerGraphGOTAndPLTStubsBuilder_ELF_riscv

35 PerGraphGOTAndPLTStubsBuilder_ELF_riscv> {

36public:

37 static constexpr size_t StubEntrySize = 16;

38 static const uint8_t NullGOTEntryContent[8];

39 static const uint8_t RV64StubContent[StubEntrySize];

40 static const uint8_t RV32StubContent[StubEntrySize];

41

44

45 bool isRV64() const { return G.getPointerSize() == 8; }

46

48

51 G.createContentBlock(getGOTSection(), getGOTEntryBlockContent(),

54 return G.addAnonymousSymbol(GOTBlock, 0, G.getPointerSize(), false, false);

55 }

56

58 Block &StubContentBlock = G.createContentBlock(

59 getStubsSection(), getStubBlockContent(), orc::ExecutorAddr(), 4, 0);

60 auto &GOTEntrySymbol = getGOTEntry(Target);

62 return G.addAnonymousSymbol(StubContentBlock, 0, StubEntrySize, true,

63 false);

64 }

65

66 void fixGOTEdge(Edge &E, Symbol &GOTEntry) {

67

68

69

71 E.setTarget(GOTEntry);

72 }

73

74 void fixPLTEdge(Edge &E, Symbol &PLTStubs) {

77 "Not a PLT edge?");

79 E.setTarget(PLTStubs);

80 }

81

82 bool isExternalBranchEdge(Edge &E) const {

85 E.getTarget().isDefined();

86 }

87

88private:

89 Section &getGOTSection() const {

90 if (!GOTSection)

92 return *GOTSection;

93 }

94

95 Section &getStubsSection() const {

96 if (!StubsSection)

97 StubsSection =

99 return *StubsSection;

100 }

101

103 return {reinterpret_cast<const char *>(NullGOTEntryContent),

104 G.getPointerSize()};

105 }

106

108 auto StubContent = isRV64() ? RV64StubContent : RV32StubContent;

109 return {reinterpret_cast<const char *>(StubContent), StubEntrySize};

110 }

111

112 mutable Section *GOTSection = nullptr;

113 mutable Section *StubsSection = nullptr;

114};

115

116const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_riscv::NullGOTEntryContent[8] =

117 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

118

120 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::RV64StubContent[StubEntrySize] = {

121 0x17, 0x0e, 0x00, 0x00,

122 0x03, 0x3e, 0x0e, 0x00,

123 0x67, 0x00, 0x0e, 0x00,

124 0x13, 0x00, 0x00, 0x00};

125

127 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::RV32StubContent[StubEntrySize] = {

128 0x17, 0x0e, 0x00, 0x00,

129 0x03, 0x2e, 0x0e, 0x00,

130 0x67, 0x00, 0x0e, 0x00,

131 0x13, 0x00, 0x00, 0x00};

132}

133namespace llvm {

135

137 return (Num & (((1ULL << Size) - 1) << Low)) >> Low;

138}

139

143

144

148

151

152public:

157 [this](LinkGraph &G) { return gatherRISCVPairs(G); });

158 }

159

160private:

162 RelHi20;

164 SetULEB128;

165

167 for (Block *B : G.blocks())

168 for (Edge &E : B->edges())

170 RelHi20[{B, E.getOffset()}] = &E;

172 SetULEB128[{B, E.getOffset()}] = &E;

173

175 }

176

177 Expected<const Edge &> getRISCVPCRelHi20(const Edge &E) const {

178 using namespace riscv;

181 "Can only have high relocation for R_RISCV_PCREL_LO12_I or "

182 "R_RISCV_PCREL_LO12_S");

183

184 const Symbol &Sym = E.getTarget();

187

188 auto It = RelHi20.find({&B, Offset});

189 if (It != RelHi20.end())

190 return *It->second;

191

193 "for LO12 PCREL relocation type");

194 }

195

196 Expected<const Edge &> getRISCVSetULEB128(const Block &B,

197 const Edge &E) const {

198 using namespace riscv;

200 "Can only have pair relocation for R_RISCV_SUB_ULEB128");

201

202 auto It = SetULEB128.find({&B, E.getOffset()});

203 if (It != SetULEB128.end())

204 return *It->second;

205

207 "No RISCV_SET_ULEB128 relocation type be found");

208 }

209

210 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {

211 using namespace riscv;

212 using namespace llvm::support;

213

214 char *BlockWorkingMem = B.getAlreadyMutableContent().data();

215 char *FixupPtr = BlockWorkingMem + E.getOffset();

216 orc::ExecutorAddr FixupAddress = B.getAddress() + E.getOffset();

217 switch (E.getKind()) {

219 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();

221 break;

222 }

224 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();

226 break;

227 }

229 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;

238 uint32_t RawInstr = *(little32_t *)FixupPtr;

240 (RawInstr & 0x1FFF07F) | Imm12 | Imm10_5 | Imm4_1 | Imm11;

241 break;

242 }

244 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;

253 uint32_t RawInstr = *(little32_t *)FixupPtr;

255 (RawInstr & 0xFFF) | Imm20 | Imm10_1 | Imm11 | Imm19_12;

256 break;

257 }

259

262 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;

263 int64_t Hi = Value + 0x800;

266 int32_t Lo = Value & 0xFFF;

267 uint32_t RawInstrAuipc = *(little32_t *)FixupPtr;

268 uint32_t RawInstrJalr = *(little32_t *)(FixupPtr + 4);

270 RawInstrAuipc | (static_cast<uint32_t>(Hi & 0xFFFFF000));

272 RawInstrJalr | (static_cast<uint32_t>(Lo) << 20);

273 break;

274 }

275

276

277

279 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;

280 int64_t Hi = Value + 0x800;

283 uint32_t RawInstr = *(little32_t *)FixupPtr;

285 (RawInstr & 0xFFF) | (static_cast<uint32_t>(Hi & 0xFFFFF000));

286 break;

287 }

289

290

291

292 auto RelHI20 = getRISCVPCRelHi20(E);

293 if (!RelHI20)

294 return RelHI20.takeError();

295 int64_t Value = RelHI20->getTarget().getAddress() +

296 RelHI20->getAddend() - E.getTarget().getAddress();

297 int64_t Lo = Value & 0xFFF;

298 uint32_t RawInstr = *(little32_t *)FixupPtr;

300 (RawInstr & 0xFFFFF) | (static_cast<uint32_t>(Lo & 0xFFF) << 20);

301 break;

302 }

304

305

306

307 auto RelHI20 = getRISCVPCRelHi20(E);

308 if (!RelHI20)

309 return RelHI20.takeError();

310 int64_t Value = RelHI20->getTarget().getAddress() +

311 RelHI20->getAddend() - E.getTarget().getAddress();

312 int64_t Lo = Value & 0xFFF;

315 uint32_t RawInstr = *(little32_t *)FixupPtr;

316

317 *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;

318 break;

319 }

321 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();

322 int64_t Hi = Value + 0x800;

325 uint32_t RawInstr = *(little32_t *)FixupPtr;

327 (RawInstr & 0xFFF) | (static_cast<uint32_t>(Hi & 0xFFFFF000));

328 break;

329 }

331

332

333 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();

334 int32_t Lo = Value & 0xFFF;

335 uint32_t RawInstr = *(little32_t *)FixupPtr;

337 (RawInstr & 0xFFFFF) | (static_cast<uint32_t>(Lo & 0xFFF) << 20);

338 break;

339 }

341

342

343 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();

344 int64_t Lo = Value & 0xFFF;

347 uint32_t RawInstr = *(little32_t *)FixupPtr;

348 *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;

349 break;

350 }

353 (E.getTarget().getAddress() +

354 *(reinterpret_cast<const uint8_t *>(FixupPtr)) + E.getAddend())

355 .getValue();

356 *FixupPtr = static_cast<uint8_t>(Value);

357 break;

358 }

360 int64_t Value = (E.getTarget().getAddress() +

362 .getValue();

364 break;

365 }

367 int64_t Value = (E.getTarget().getAddress() +

369 .getValue();

371 break;

372 }

374 int64_t Value = (E.getTarget().getAddress() +

376 .getValue();

378 break;

379 }

381 int64_t Value = *(reinterpret_cast<const uint8_t *>(FixupPtr)) -

382 E.getTarget().getAddress().getValue() - E.getAddend();

383 *FixupPtr = static_cast<uint8_t>(Value);

384 break;

385 }

388 E.getTarget().getAddress().getValue() - E.getAddend();

390 break;

391 }

394 E.getTarget().getAddress().getValue() - E.getAddend();

396 break;

397 }

400 E.getTarget().getAddress().getValue() - E.getAddend();

402 break;

403 }

405 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;

415 uint16_t RawInstr = *(little16_t *)FixupPtr;

417 (RawInstr & 0xE383) | Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5;

418 break;

419 }

421 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;

434 uint16_t RawInstr = *(little16_t *)FixupPtr;

435 *(little16_t *)FixupPtr = (RawInstr & 0xE003) | Imm11 | Imm4 | Imm9_8 |

436 Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5;

437 break;

438 }

440 int64_t Value = *(reinterpret_cast<const uint8_t *>(FixupPtr)) & 0x3f;

441 Value -= E.getTarget().getAddress().getValue() - E.getAddend();

442 *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<uint8_t>(Value) & 0x3f);

443 break;

444 }

446 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();

447 uint32_t RawData = *(little32_t *)FixupPtr;

448 int64_t Word6 = Value & 0x3f;

449 *(little32_t *)FixupPtr = (RawData & 0xffffffc0) | Word6;

450 break;

451 }

453 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();

454 uint32_t RawData = *(little32_t *)FixupPtr;

456 *(little32_t *)FixupPtr = (RawData & 0xffffff00) | Word8;

457 break;

458 }

460 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();

461 uint32_t RawData = *(little32_t *)FixupPtr;

464 break;

465 }

467 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();

470 break;

471 }

473 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;

476 break;

477 }

479

480 break;

482 int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();

486 break;

487 }

489 break;

491 auto SetULEB128 = getRISCVSetULEB128(B, E);

492 if (!SetULEB128)

493 return SetULEB128.takeError();

494 uint64_t Value = SetULEB128->getTarget().getAddress() +

495 SetULEB128->getAddend() - E.getTarget().getAddress() -

496 E.getAddend();

498 0x80)

501 break;

502 }

503 }

505 }

506};

507

508namespace {

509

510struct SymbolAnchor {

513 bool End;

514};

515

516struct BlockRelaxAux {

517

518

520

521

523

524

525 SmallVector<uint32_t, 0> RelocDeltas;

526

528

529

530 SmallVector<uint32_t, 0> Writes;

531};

532

533struct RelaxConfig {

534 bool IsRV32;

535 bool HasRVC;

536};

537

538struct RelaxAux {

539 RelaxConfig Config;

540 DenseMap<Block *, BlockRelaxAux> Blocks;

541};

542

543}

544

548

550 switch (E.getKind()) {

551 default:

552 return false;

555 return true;

556 }

557}

558

560 RelaxAux Aux;

561 Aux.Config.IsRV32 = G.getTargetTriple().isRISCV32();

562 const auto &Features = G.getFeatures().getFeatures();

565

566 for (auto &S : G.sections()) {

568 continue;

569 for (auto *B : S.blocks()) {

570 auto BlockEmplaceResult = Aux.Blocks.try_emplace(B);

571 assert(BlockEmplaceResult.second && "Block encountered twice");

572 auto &BlockAux = BlockEmplaceResult.first->second;

573

574 for (auto &E : B->edges())

576 BlockAux.RelaxEdges.push_back(&E);

577

578 if (BlockAux.RelaxEdges.empty()) {

579 Aux.Blocks.erase(BlockEmplaceResult.first);

580 continue;

581 }

582

583 const auto NumEdges = BlockAux.RelaxEdges.size();

584 BlockAux.RelocDeltas.resize(NumEdges, 0);

585 BlockAux.EdgeKinds.resize_for_overwrite(NumEdges);

586

587

588 for (auto *Sym : S.symbols()) {

590 continue;

591

592 BlockAux.Anchors.push_back({Sym->getOffset(), Sym, false});

593 BlockAux.Anchors.push_back(

595 }

596 }

597 }

598

599

600

601

602

603 for (auto &BlockAuxIter : Aux.Blocks) {

604 llvm::sort(BlockAuxIter.second.Anchors, [](auto &A, auto &B) {

605 return std::make_pair(A.Offset, A.End) < std::make_pair(B.Offset, B.End);

606 });

607 }

608

609 return Aux;

610}

611

613 Edge::Kind &NewEdgeKind) {

614

615

616

619 const auto SrcLoc = Loc.getValue() + E.getAddend();

620 Remove = SrcLoc - DestLoc;

621 assert(static_cast<int32_t>(Remove) >= 0 &&

622 "R_RISCV_ALIGN needs expanding the content");

624}

625

629 Edge::Kind &NewEdgeKind) {

630 const auto JALR =

633 const auto Dest = E.getTarget().getAddress() + E.getAddend();

634 const auto Displace = Dest - Loc;

635

636 if (Config.HasRVC && isInt<12>(Displace) && RD == 0) {

638 Aux.Writes.push_back(0xa001);

639 Remove = 6;

640 } else if (Config.HasRVC && Config.IsRV32 && isInt<12>(Displace) && RD == 1) {

642 Aux.Writes.push_back(0x2001);

643 Remove = 6;

644 } else if (isInt<21>(Displace)) {

646 Aux.Writes.push_back(0x6f | RD << 7);

647 Remove = 4;

648 } else {

649

651 Remove = 0;

652 }

653}

654

656 const RelaxConfig &Config) {

661

662 Aux.EdgeKinds.assign(Aux.EdgeKinds.size(), Edge::Invalid);

663 Aux.Writes.clear();

664

666 const auto Loc = BlockAddr + E->getOffset() - Delta;

667 auto &Cur = Aux.RelocDeltas[I];

669 switch (E->getKind()) {

672 break;

675 break;

676 default:

678 }

679

680

681

682

684 if (SA[0].End)

685 SA[0].Sym->setSize(SA[0].Offset - Delta - SA[0].Sym->getOffset());

686 else

687 SA[0].Sym->setOffset(SA[0].Offset - Delta);

688 }

689

690 Delta += Remove;

691 if (Delta != Cur) {

692 Cur = Delta;

694 }

695 }

696

697 for (const SymbolAnchor &A : SA) {

698 if (A.End)

699 A.Sym->setSize(A.Offset - Delta - A.Sym->getOffset());

700 else

701 A.Sym->setOffset(A.Offset - Delta);

702 }

703

705}

706

709

710 for (auto &[B, BlockAux] : Aux.Blocks)

712

714}

715

718 auto *Dest = Contents.data();

719 auto NextWrite = Aux.Writes.begin();

722

723

724

726 uint32_t Remove = Aux.RelocDeltas[I] - Delta;

727 Delta = Aux.RelocDeltas[I];

728 if (Remove == 0 && Aux.EdgeKinds[I] == Edge::Invalid)

729 continue;

730

731

732 const auto Size = E->getOffset() - Offset;

733 std::memmove(Dest, Contents.data() + Offset, Size);

734 Dest += Size;

735

737 switch (Aux.EdgeKinds[I]) {

738 case Edge::Invalid:

739 break;

741

742

743

744

745

746 if (Remove % 4 || E->getAddend() % 4) {

747 Skip = E->getAddend() - Remove;

749 for (; J + 4 <= Skip; J += 4)

751 if (J != Skip) {

752 assert(J + 2 == Skip);

754 }

755 }

756 break;

758 Skip = 2;

760 break;

762 Skip = 4;

764 break;

765 }

766

767 Dest += Skip;

768 Offset = E->getOffset() + Skip + Remove;

769 }

770

771 std::memmove(Dest, Contents.data() + Offset, Contents.size() - Offset);

772

773

774 Delta = 0;

775 size_t I = 0;

777 E.setOffset(E.getOffset() - Delta);

778

779 if (I < Aux.RelaxEdges.size() && Aux.RelaxEdges[I] == &E) {

780 if (Aux.EdgeKinds[I] != Edge::Invalid)

781 E.setKind(Aux.EdgeKinds[I]);

782

783 Delta = Aux.RelocDeltas[I];

784 ++I;

785 }

786 }

787

788

789

790

794 else

795 ++IE;

796 }

797}

798

800 for (auto &[B, BlockAux] : Aux.Blocks)

802}

803

811

812template

814private:

817 using namespace riscv;

818 switch (Type) {

819 case ELF::R_RISCV_32:

821 case ELF::R_RISCV_64:

823 case ELF::R_RISCV_BRANCH:

825 case ELF::R_RISCV_JAL:

827 case ELF::R_RISCV_CALL:

829 case ELF::R_RISCV_CALL_PLT:

831 case ELF::R_RISCV_GOT_HI20:

833 case ELF::R_RISCV_PCREL_HI20:

835 case ELF::R_RISCV_PCREL_LO12_I:

837 case ELF::R_RISCV_PCREL_LO12_S:

839 case ELF::R_RISCV_HI20:

841 case ELF::R_RISCV_LO12_I:

843 case ELF::R_RISCV_LO12_S:

845 case ELF::R_RISCV_ADD8:

847 case ELF::R_RISCV_ADD16:

849 case ELF::R_RISCV_ADD32:

851 case ELF::R_RISCV_ADD64:

853 case ELF::R_RISCV_SUB8:

855 case ELF::R_RISCV_SUB16:

857 case ELF::R_RISCV_SUB32:

859 case ELF::R_RISCV_SUB64:

861 case ELF::R_RISCV_RVC_BRANCH:

863 case ELF::R_RISCV_RVC_JUMP:

865 case ELF::R_RISCV_SUB6:

867 case ELF::R_RISCV_SET6:

869 case ELF::R_RISCV_SET8:

871 case ELF::R_RISCV_SET16:

873 case ELF::R_RISCV_SET32:

875 case ELF::R_RISCV_32_PCREL:

877 case ELF::R_RISCV_ALIGN:

879 case ELF::R_RISCV_SET_ULEB128:

881 case ELF::R_RISCV_SUB_ULEB128:

883 }

884

886 "Unsupported riscv relocation:" + formatv("{0:d}: ", Type) +

888 }

889

891 switch (Kind) {

892 default:

893

894 return Kind;

898 }

899 }

900

903

906 for (const auto &RelSect : Base::Sections)

907 if (Error Err = Base::forEachRelaRelocation(RelSect, this,

908 &Self::addSingleRelocation))

909 return Err;

910

912 }

913

914 Error addSingleRelocation(const typename ELFT::Rela &Rel,

915 const typename ELFT::Shdr &FixupSect,

916 Block &BlockToFix) {

918

920 int64_t Addend = Rel.r_addend;

921

922 if (Type == ELF::R_RISCV_RELAX) {

925 "R_RISCV_RELAX without preceding relocation",

927

928 auto &PrevEdge = *std::prev(BlockToFix.edges().end());

929 auto Kind = static_cast<EdgeKind_riscv>(PrevEdge.getKind());

930 PrevEdge.setKind(getRelaxableRelocationKind(Kind));

932 }

933

935 if (!Kind)

936 return Kind.takeError();

937

938 uint32_t SymbolIndex = Rel.getSymbol(false);

939 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);

940 if (!ObjSymbol)

941 return ObjSymbol.takeError();

942

943 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);

944 if (!GraphSymbol)

946 formatv("Could not find symbol at given index, did you add it to "

947 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",

948 SymbolIndex, (*ObjSymbol)->st_shndx,

949 Base::GraphSymbols.size()),

951

952 auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;

953 Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();

954 Edge GE(*Kind, Offset, *GraphSymbol, Addend);

956 dbgs() << " ";

958 dbgs() << "\n";

959 });

960

961 BlockToFix.addEdge(std::move(GE));

963 }

964

965public:

968 std::shared_ptrorc::SymbolStringPool SSP,

971 std::move(Features), FileName,

973};

974

977 std::shared_ptrorc::SymbolStringPool SSP) {

979 dbgs() << "Building jitlink graph for new input "

981 });

982

984 if (!ELFObj)

985 return ELFObj.takeError();

986

987 auto Features = (*ELFObj)->getFeatures();

988 if (!Features)

989 return Features.takeError();

990

994 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),

995 std::move(SSP), (*ELFObj)->makeTriple(), std::move(*Features))

997 } else {

999 "Invalid triple for RISCV ELF object file");

1002 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),

1003 std::move(SSP), (*ELFObj)->makeTriple(), std::move(*Features))

1005 }

1006}

1007

1009 std::unique_ptr Ctx) {

1011 const Triple &TT = G->getTargetTriple();

1012 if (Ctx->shouldAddDefaultTargetPasses(TT)) {

1013

1016 ".eh_frame", G->getPointerSize(), Edge::Invalid, Edge::Invalid,

1017 Edge::Invalid, Edge::Invalid, NegDelta32));

1019

1020 if (auto MarkLive = Ctx->getMarkLivePass(TT))

1021 Config.PrePrunePasses.push_back(std::move(MarkLive));

1022 else

1025 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::asPass);

1027 }

1028 if (auto Err = Ctx->modifyPassConfig(*G, Config))

1029 return Ctx->notifyFailed(std::move(Err));

1030

1032}

1033

1035

1036}

1037}

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")

#define LLVM_UNLIKELY(EXPR)

std::pair< BasicBlock *, BasicBlock * > Edge

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

size_t size() const

size - Get the array size.

ArrayRef< T > slice(size_t N, size_t M) const

slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.

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 getBufferIdentifier() const

void push_back(const T &Elt)

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

Manages the enabling and disabling of subtarget specific features.

Target - Wrapper for Target specific information.

Triple - Helper class for working with autoconf configuration names.

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM Value Representation.

orc::ExecutorAddr getAddress() const

An Addressable with content and edges.

edge_iterator removeEdge(edge_iterator I)

Remove the edge pointed to by the given iterator.

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

Add an edge to this block.

iterator_range< edge_iterator > edges()

Return the list of edges attached to this content.

MutableArrayRef< char > getAlreadyMutableContent()

Get mutable content for this block.

bool edges_empty() const

Returns true if the list of edges is empty.

A LinkGraph pass that splits blocks in a section that follows the DWARF Record format into sub-blocks...

A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA edges.

ELFJITLinker_riscv(std::unique_ptr< JITLinkContext > Ctx, std::unique_ptr< LinkGraph > G, PassConfiguration PassConfig)

Definition ELF_riscv.cpp:153

Definition ELF_riscv.cpp:813

ELFLinkGraphBuilder_riscv(StringRef FileName, const object::ELFFile< ELFT > &Obj, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, SubtargetFeatures Features)

Definition ELF_riscv.cpp:966

virtual Error addRelocations()=0

Call to derived class to handle relocations.

ELFLinkGraphBuilder(const object::ELFFile< ELFT > &Obj, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, SubtargetFeatures Features, StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)

Expected< std::unique_ptr< LinkGraph > > buildGraph()

Attempt to construct and return the LinkGraph.

Represents fixups and constraints in the LinkGraph.

PassConfiguration & getPassConfig()

static void link(ArgTs &&... Args)

Per-object GOT and PLT Stub builder.

Represents an object file section.

orc::MemProt getMemProt() const

Returns the protection flags for this section.

bool isDefined() const

Returns true if this Symbol has content (potentially) defined within this object file (i....

Block & getBlock()

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

orc::ExecutorAddrDiff getSize() const

Returns the size of this symbol.

orc::ExecutorAddrDiff getOffset() const

Returns the offset for this symbol within the underlying addressable.

static Expected< std::unique_ptr< ObjectFile > > createELFObjectFile(MemoryBufferRef Object, bool InitContent=true)

Represents an address in the executor process.

#define llvm_unreachable(msg)

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

EdgeKind_riscv

Represents riscv fixups.

@ R_RISCV_SUB32

32 bits label subtraction

@ R_RISCV_LO12_S

Low 12 bits of 32-bit pointer value relocation, used by S type instruction format.

@ R_RISCV_JAL

High 20 bits of PC-relative jump pointer value relocation.

@ R_RISCV_ADD8

8 bits label addition

@ R_RISCV_HI20

High 20 bits of 32-bit pointer value relocation.

@ R_RISCV_PCREL_LO12_I

Low 12 bits of PC relative relocation, used by I type instruction format.

@ R_RISCV_SUB8

8 bits label subtraction

@ R_RISCV_SET6

Local label assignment.

@ R_RISCV_CALL_PLT

PC relative call by PLT.

@ R_RISCV_SET_ULEB128

Set ULEB128-encoded value.

@ R_RISCV_SET32

Local label assignment.

@ R_RISCV_RVC_JUMP

11-bit PC-relative jump offset

@ R_RISCV_SUB6

6 bits label subtraction

@ R_RISCV_CALL

PC relative call.

@ CallRelaxable

An auipc/jalr pair eligible for linker relaxation.

@ R_RISCV_BRANCH

PC-relative branch pointer value relocation.

@ R_RISCV_PCREL_LO12_S

Low 12 bits of PC relative relocation, used by S type instruction format.

@ R_RISCV_SUB_ULEB128

Subtract from ULEB128-encoded value.

@ R_RISCV_32

A plain 32-bit pointer value relocation.

@ R_RISCV_RVC_BRANCH

8-bit PC-relative branch offset

@ R_RISCV_64

A plain 64-bit pointer value relocation.

@ R_RISCV_LO12_I

Low 12 bits of 32-bit pointer value relocation.

@ NegDelta32

32-bit negative delta.

@ R_RISCV_32_PCREL

32 bits PC relative relocation

@ R_RISCV_SET16

Local label assignment.

@ AlignRelaxable

Alignment requirement used by linker relaxation.

@ R_RISCV_PCREL_HI20

High 20 bits of PC relative relocation.

@ R_RISCV_ADD64

64 bits label addition

@ R_RISCV_ADD32

32 bits label addition

@ R_RISCV_GOT_HI20

PC relative GOT offset.

@ R_RISCV_SUB16

16 bits label subtraction

@ R_RISCV_SET8

Local label assignment.

@ R_RISCV_ADD16

16 bits label addition

@ R_RISCV_SUB64

64 bits label subtraction

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

Returns a string name for the given riscv edge.

unique_function< Error(LinkGraph &)> LinkGraphPassFunction

A function for mutating LinkGraphs.

LLVM_ABI Error makeTargetOutOfRangeError(const LinkGraph &G, const Block &B, const Edge &E)

Create an out of range error for the given edge in the given block.

Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject_riscv(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)

Create a LinkGraph from an ELF/riscv relocatable object.

Definition ELF_riscv.cpp:976

static void relaxCall(const Block &B, BlockRelaxAux &Aux, const RelaxConfig &Config, orc::ExecutorAddr Loc, const Edge &E, uint32_t &Remove, Edge::Kind &NewEdgeKind)

Definition ELF_riscv.cpp:626

static bool shouldRelax(const Section &S)

Definition ELF_riscv.cpp:545

static void finalizeBlockRelax(LinkGraph &G, Block &Block, BlockRelaxAux &Aux)

Definition ELF_riscv.cpp:716

static void relaxAlign(orc::ExecutorAddr Loc, const Edge &E, uint32_t &Remove, Edge::Kind &NewEdgeKind)

Definition ELF_riscv.cpp:612

static bool relaxOnce(LinkGraph &G, RelaxAux &Aux)

Definition ELF_riscv.cpp:707

LLVM_ABI Error makeAlignmentError(llvm::orc::ExecutorAddr Loc, uint64_t Value, int N, const Edge &E)

static Error relax(LinkGraph &G)

Definition ELF_riscv.cpp:804

static bool isRelaxable(const Edge &E)

Definition ELF_riscv.cpp:549

LLVM_ABI Error markAllSymbolsLive(LinkGraph &G)

Marks all symbols in a graph live.

static bool isAlignmentCorrect(uint64_t Value, int N)

Definition ELF_riscv.cpp:140

static RelaxAux initRelaxAux(LinkGraph &G)

Definition ELF_riscv.cpp:559

LinkGraphPassFunction createRelaxationPass_ELF_riscv()

Returns a pass that performs linker relaxation.

Definition ELF_riscv.cpp:1034

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

jit-link the given object buffer, which must be a ELF riscv object file.

Definition ELF_riscv.cpp:1008

LLVM_ABI void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)

static bool isInRangeForImm(int64_t Value, int N)

Definition ELF_riscv.cpp:145

static uint32_t extractBits(uint32_t Num, unsigned Low, unsigned Size)

Definition ELF_riscv.cpp:136

static bool relaxBlock(LinkGraph &G, Block &Block, BlockRelaxAux &Aux, const RelaxConfig &Config)

Definition ELF_riscv.cpp:655

static void finalizeRelax(LinkGraph &G, RelaxAux &Aux)

Definition ELF_riscv.cpp:799

LLVM_ABI StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)

uint64_t ExecutorAddrDiff

uint64_t read64le(const void *P)

uint16_t read16le(const void *P)

void write32le(void *P, uint32_t V)

void write16le(void *P, uint16_t V)

uint32_t read32le(const void *P)

detail::packed_endian_specific_integral< int16_t, llvm::endianness::little, unaligned > little16_t

detail::packed_endian_specific_integral< int32_t, llvm::endianness::little, unaligned > little32_t

detail::packed_endian_specific_integral< int64_t, llvm::endianness::little, unaligned > little64_t

This is an optimization pass for GlobalISel generic memory operations.

@ Low

Lower the current thread's priority such that it does not affect foreground tasks significantly.

FunctionAddr VTableAddr Value

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

LLVM_ABI std::error_code inconvertibleErrorCode()

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

static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)

uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val)

Overwrite a ULEB128 value and keep the original length.

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

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

ArrayRef(const T &OneElt) -> ArrayRef< T >

OutputIt move(R &&Range, OutputIt Out)

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

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

constexpr int64_t SignExtend64(uint64_t x)

Sign-extend the number in the bottom B bits of X to a 64-bit integer.

constexpr uint64_t NextPowerOf2(uint64_t A)

Returns the next power of two (in 64-bits) that is strictly greater than A.

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

This struct is a compact representation of a valid (non-zero power of two) alignment.

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

LinkGraphPassList PostAllocationPasses

Post-allocation passes.

LinkGraphPassList PostPrunePasses

Post-prune passes.

LinkGraphPassList PrePrunePasses

Pre-prune passes.