24#define DEBUG_TYPE "jitlink"
31class PerGraphGOTAndPLTStubsBuilder_ELF_riscv
33 PerGraphGOTAndPLTStubsBuilder_ELF_riscv> {
35 static constexpr size_t StubEntrySize = 16;
36 static const uint8_t NullGOTEntryContent[8];
37 static const uint8_t RV64StubContent[StubEntrySize];
38 static const uint8_t RV32StubContent[StubEntrySize];
43 bool isRV64()
const {
return G.getPointerSize() == 8; }
49 G.createContentBlock(getGOTSection(), getGOTEntryBlockContent(),
52 return G.addAnonymousSymbol(GOTBlock, 0,
G.getPointerSize(),
false,
false);
56 Block &StubContentBlock =
G.createContentBlock(
58 auto &GOTEntrySymbol = getGOTEntry(
Target);
60 return G.addAnonymousSymbol(StubContentBlock, 0, StubEntrySize,
true,
69 E.setTarget(GOTEntry);
77 E.setTarget(PLTStubs);
80 bool isExternalBranchEdge(
Edge &
E)
const {
83 !
E.getTarget().isDefined();
87 Section &getGOTSection()
const {
89 GOTSection = &
G.createSection(
"$__GOT", orc::MemProt::Read);
93 Section &getStubsSection()
const {
96 &
G.createSection(
"$__STUBS", orc::MemProt::Read | orc::MemProt::Exec);
101 return {
reinterpret_cast<const char *
>(NullGOTEntryContent),
106 auto StubContent = isRV64() ? RV64StubContent : RV32StubContent;
107 return {
reinterpret_cast<const char *
>(StubContent), StubEntrySize};
110 mutable Section *GOTSection =
nullptr;
111 mutable Section *StubsSection =
nullptr;
114const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_riscv::NullGOTEntryContent[8] =
115 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
118 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::RV64StubContent[StubEntrySize] = {
119 0x17, 0x0e, 0x00, 0x00,
120 0x03, 0x3e, 0x0e, 0x00,
121 0x67, 0x00, 0x0e, 0x00,
122 0x13, 0x00, 0x00, 0x00};
125 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::RV32StubContent[StubEntrySize] = {
126 0x17, 0x0e, 0x00, 0x00,
127 0x03, 0x2e, 0x0e, 0x00,
128 0x67, 0x00, 0x0e, 0x00,
129 0x13, 0x00, 0x00, 0x00};
135 using namespace riscv;
138 "Can only have high relocation for R_RISCV_PCREL_LO12_I or "
139 "R_RISCV_PCREL_LO12_S");
155 std::equal_range(
B.edges().begin(),
B.edges().end(),
Offset, Comp{});
157 for (
auto It = Bound.first; It != Bound.second; ++It) {
162 return make_error<JITLinkError>(
163 "No HI20 PCREL relocation type be found for LO12 PCREL relocation type");
167 return (Num & (((1ULL <<
Size) - 1) <<
Low)) >>
Low;
189 using namespace riscv;
192 char *BlockWorkingMem =
B.getAlreadyMutableContent().data();
193 char *FixupPtr = BlockWorkingMem +
E.getOffset();
195 switch (
E.getKind()) {
197 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
202 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
207 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
218 (RawInstr & 0x1FFF07F) | Imm12 | Imm10_5 | Imm4_1 | Imm11;
222 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
233 (RawInstr & 0xFFF) | Imm20 | Imm10_1 | Imm11 | Imm19_12;
238 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
246 RawInstrAuipc | (
static_cast<uint32_t>(
Hi & 0xFFFFF000));
248 RawInstrJalr | (
static_cast<uint32_t>(
Lo) << 20);
255 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
261 (RawInstr & 0xFFF) | (
static_cast<uint32_t>(
Hi & 0xFFFFF000));
270 return RelHI20.takeError();
271 int64_t
Value = RelHI20->getTarget().getAddress() +
272 RelHI20->getAddend() -
E.getTarget().getAddress();
276 (RawInstr & 0xFFFFF) | (
static_cast<uint32_t>(
Lo & 0xFFF) << 20);
285 return RelHI20.takeError();
286 int64_t
Value = RelHI20->getTarget().getAddress() +
287 RelHI20->getAddend() -
E.getTarget().getAddress();
293 *(
little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
297 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
303 (RawInstr & 0xFFF) | (
static_cast<uint32_t>(
Hi & 0xFFFFF000));
309 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
313 (RawInstr & 0xFFFFF) | (
static_cast<uint32_t>(
Lo & 0xFFF) << 20);
319 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
324 *(
little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
329 (
E.getTarget().getAddress() +
330 *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) +
E.getAddend())
332 *FixupPtr =
static_cast<uint8_t
>(
Value);
336 int64_t
Value = (
E.getTarget().getAddress() +
343 int64_t
Value = (
E.getTarget().getAddress() +
350 int64_t
Value = (
E.getTarget().getAddress() +
357 int64_t
Value = *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) -
358 E.getTarget().getAddress().getValue() -
E.getAddend();
359 *FixupPtr =
static_cast<uint8_t
>(
Value);
364 E.getTarget().getAddress().getValue() -
E.getAddend();
370 E.getTarget().getAddress().getValue() -
E.getAddend();
376 E.getTarget().getAddress().getValue() -
E.getAddend();
381 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
393 (RawInstr & 0xE383) |
Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5;
397 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
411 *(
little16_t *)FixupPtr = (RawInstr & 0xE003) | Imm11 | Imm4 | Imm9_8 |
412 Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5;
416 int64_t
Value = *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) & 0x3f;
417 Value -=
E.getTarget().getAddress().getValue() -
E.getAddend();
418 *FixupPtr = (*FixupPtr & 0xc0) | (
static_cast<uint8_t
>(
Value) & 0x3f);
422 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
424 int64_t Word6 =
Value & 0x3f;
425 *(
little32_t *)FixupPtr = (RawData & 0xffffffc0) | Word6;
429 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
436 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
443 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
449 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
467struct BlockRelaxAux {
501 switch (
E.getKind()) {
512 Aux.Config.IsRV32 =
G.getTargetTriple().isRISCV32();
513 const auto &Features =
G.getFeatures();
515 std::find(Features.begin(), Features.end(),
"+c") != Features.end();
517 for (
auto &S :
G.sections()) {
520 for (
auto *
B : S.blocks()) {
521 auto BlockEmplaceResult = Aux.Blocks.try_emplace(
B);
522 assert(BlockEmplaceResult.second &&
"Block encountered twice");
523 auto &BlockAux = BlockEmplaceResult.first->second;
525 for (
auto &
E :
B->edges())
527 BlockAux.RelaxEdges.push_back(&
E);
529 if (BlockAux.RelaxEdges.empty()) {
530 Aux.Blocks.erase(BlockEmplaceResult.first);
534 const auto NumEdges = BlockAux.RelaxEdges.size();
535 BlockAux.RelocDeltas.resize(NumEdges, 0);
536 BlockAux.EdgeKinds.resize_for_overwrite(NumEdges);
539 for (
auto *
Sym : S.symbols()) {
544 BlockAux.Anchors.push_back(
554 for (
auto &BlockAuxIter : Aux.Blocks) {
555 llvm::sort(BlockAuxIter.second.Anchors, [](
auto &
A,
auto &
B) {
556 return std::make_pair(A.Offset, A.End) < std::make_pair(B.Offset, B.End);
570 const auto SrcLoc = Loc.
getValue() +
E.getAddend();
571 Remove = SrcLoc - DestLoc;
572 assert(
static_cast<int32_t
>(Remove) >= 0 &&
573 "R_RISCV_ALIGN needs expanding the content");
584 const auto Dest =
E.getTarget().getAddress() +
E.getAddend();
585 const auto Displace = Dest - Loc;
587 if (
Config.HasRVC && isInt<12>(Displace) && RD == 0) {
589 Aux.Writes.push_back(0xa001);
591 }
else if (
Config.HasRVC &&
Config.IsRV32 && isInt<12>(Displace) && RD == 1) {
593 Aux.Writes.push_back(0x2001);
595 }
else if (isInt<21>(Displace)) {
597 Aux.Writes.push_back(0x6f | RD << 7);
607 const RelaxConfig &
Config) {
609 bool Changed =
false;
617 const auto Loc = BlockAddr +
E->getOffset() - Delta;
618 auto &Cur = Aux.RelocDeltas[
I];
620 switch (
E->getKind()) {
638 SA[0].Sym->setOffset(SA[0].
Offset - Delta);
648 for (
const SymbolAnchor &
A : SA) {
650 A.Sym->setSize(
A.Offset - Delta -
A.Sym->getOffset());
652 A.Sym->setOffset(
A.Offset - Delta);
659 bool Changed =
false;
661 for (
auto &[
B, BlockAux] : Aux.Blocks)
669 auto *Dest = Contents.
data();
670 auto NextWrite = Aux.Writes.begin();
677 uint32_t Remove = Aux.RelocDeltas[
I] - Delta;
678 Delta = Aux.RelocDeltas[
I];
684 std::memmove(Dest, Contents.data() +
Offset,
Size);
688 switch (Aux.EdgeKinds[
I]) {
697 if (Remove % 4 ||
E->getAddend() % 4) {
698 Skip =
E->getAddend() - Remove;
700 for (; J + 4 <= Skip; J += 4)
719 Offset =
E->getOffset() + Skip + Remove;
722 std::memmove(Dest, Contents.data() +
Offset, Contents.size() -
Offset);
727 E->setOffset(
E->getOffset() - Delta);
730 E->setKind(Aux.EdgeKinds[
I]);
732 Delta = Aux.RelocDeltas[
I];
738 for (
auto *
B :
G.blocks()) {
739 for (
auto IE =
B->edges().begin(); IE !=
B->edges().end();) {
741 IE =
B->removeEdge(IE);
749 for (
auto &[
B, BlockAux] : Aux.Blocks)
761template <
typename ELFT>
766 using namespace riscv;
768 case ELF::R_RISCV_32:
769 return EdgeKind_riscv::R_RISCV_32;
770 case ELF::R_RISCV_64:
771 return EdgeKind_riscv::R_RISCV_64;
772 case ELF::R_RISCV_BRANCH:
773 return EdgeKind_riscv::R_RISCV_BRANCH;
774 case ELF::R_RISCV_JAL:
775 return EdgeKind_riscv::R_RISCV_JAL;
776 case ELF::R_RISCV_CALL:
777 return EdgeKind_riscv::R_RISCV_CALL;
778 case ELF::R_RISCV_CALL_PLT:
779 return EdgeKind_riscv::R_RISCV_CALL_PLT;
780 case ELF::R_RISCV_GOT_HI20:
781 return EdgeKind_riscv::R_RISCV_GOT_HI20;
782 case ELF::R_RISCV_PCREL_HI20:
783 return EdgeKind_riscv::R_RISCV_PCREL_HI20;
784 case ELF::R_RISCV_PCREL_LO12_I:
785 return EdgeKind_riscv::R_RISCV_PCREL_LO12_I;
786 case ELF::R_RISCV_PCREL_LO12_S:
787 return EdgeKind_riscv::R_RISCV_PCREL_LO12_S;
788 case ELF::R_RISCV_HI20:
789 return EdgeKind_riscv::R_RISCV_HI20;
790 case ELF::R_RISCV_LO12_I:
791 return EdgeKind_riscv::R_RISCV_LO12_I;
792 case ELF::R_RISCV_LO12_S:
793 return EdgeKind_riscv::R_RISCV_LO12_S;
794 case ELF::R_RISCV_ADD8:
795 return EdgeKind_riscv::R_RISCV_ADD8;
796 case ELF::R_RISCV_ADD16:
797 return EdgeKind_riscv::R_RISCV_ADD16;
798 case ELF::R_RISCV_ADD32:
799 return EdgeKind_riscv::R_RISCV_ADD32;
800 case ELF::R_RISCV_ADD64:
801 return EdgeKind_riscv::R_RISCV_ADD64;
802 case ELF::R_RISCV_SUB8:
803 return EdgeKind_riscv::R_RISCV_SUB8;
804 case ELF::R_RISCV_SUB16:
805 return EdgeKind_riscv::R_RISCV_SUB16;
806 case ELF::R_RISCV_SUB32:
807 return EdgeKind_riscv::R_RISCV_SUB32;
808 case ELF::R_RISCV_SUB64:
809 return EdgeKind_riscv::R_RISCV_SUB64;
810 case ELF::R_RISCV_RVC_BRANCH:
811 return EdgeKind_riscv::R_RISCV_RVC_BRANCH;
812 case ELF::R_RISCV_RVC_JUMP:
813 return EdgeKind_riscv::R_RISCV_RVC_JUMP;
814 case ELF::R_RISCV_SUB6:
815 return EdgeKind_riscv::R_RISCV_SUB6;
816 case ELF::R_RISCV_SET6:
817 return EdgeKind_riscv::R_RISCV_SET6;
818 case ELF::R_RISCV_SET8:
819 return EdgeKind_riscv::R_RISCV_SET8;
820 case ELF::R_RISCV_SET16:
821 return EdgeKind_riscv::R_RISCV_SET16;
822 case ELF::R_RISCV_SET32:
823 return EdgeKind_riscv::R_RISCV_SET32;
824 case ELF::R_RISCV_32_PCREL:
825 return EdgeKind_riscv::R_RISCV_32_PCREL;
826 case ELF::R_RISCV_ALIGN:
827 return EdgeKind_riscv::AlignRelaxable;
830 return make_error<JITLinkError>(
831 "Unsupported riscv relocation:" +
formatv(
"{0:d}: ",
Type) +
846 Error addRelocations()
override {
851 for (
const auto &RelSect : Base::Sections)
852 if (
Error Err = Base::forEachRelaRelocation(RelSect,
this,
853 &Self::addSingleRelocation))
859 Error addSingleRelocation(
const typename ELFT::Rela &Rel,
860 const typename ELFT::Shdr &FixupSect,
865 int64_t Addend = Rel.r_addend;
867 if (
Type == ELF::R_RISCV_RELAX) {
869 return make_error<StringError>(
870 "R_RISCV_RELAX without preceding relocation",
873 auto &PrevEdge = *std::prev(BlockToFix.
edges().end());
875 PrevEdge.setKind(getRelaxableRelocationKind(Kind));
881 return Kind.takeError();
883 uint32_t SymbolIndex = Rel.getSymbol(
false);
884 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
886 return ObjSymbol.takeError();
888 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
890 return make_error<StringError>(
891 formatv(
"Could not find symbol at given index, did you add it to "
892 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
893 SymbolIndex, (*ObjSymbol)->st_shndx,
894 Base::GraphSymbols.size()),
906 BlockToFix.
addEdge(std::move(GE));
921 dbgs() <<
"Building jitlink graph for new input "
927 return ELFObj.takeError();
929 auto Features = (*ELFObj)->getFeatures();
931 return Features.takeError();
934 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
936 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
937 (*ELFObj)->makeTriple(), Features->getFeatures())
941 "Invalid triple for RISCV ELF object file");
942 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
944 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
945 (*ELFObj)->makeTriple(), Features->getFeatures())
951 std::unique_ptr<JITLinkContext> Ctx) {
953 const Triple &TT =
G->getTargetTriple();
954 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
955 if (
auto MarkLive = Ctx->getMarkLivePass(TT))
956 Config.PrePrunePasses.push_back(std::move(MarkLive));
959 Config.PostPrunePasses.push_back(
960 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::asPass);
963 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
964 return Ctx->notifyFailed(std::move(Err));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
DenseMap< Block *, BlockRelaxAux > Blocks
SmallVector< uint32_t, 0 > Writes
SmallVector< uint32_t, 0 > RelocDeltas
SmallVector< Edge *, 0 > RelaxEdges
SmallVector< Edge::Kind, 0 > EdgeKinds
SmallVector< SymbolAnchor, 0 > Anchors
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
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.
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.
ELFJITLinker_riscv(std::unique_ptr< JITLinkContext > Ctx, std::unique_ptr< LinkGraph > G, PassConfiguration PassConfig)
ELFLinkGraphBuilder_riscv(StringRef FileName, const object::ELFFile< ELFT > &Obj, Triple TT, LinkGraph::FeatureVector Features)
Ling-graph building code that's specific to the given ELFT, but common across all architectures.
Expected< std::unique_ptr< LinkGraph > > buildGraph()
Attempt to construct and return the LinkGraph.
Represents fixups and constraints in the LinkGraph.
OffsetT getOffset() const
static void link(ArgTs &&... Args)
Link constructs a LinkerImpl instance and calls linkPhase1.
std::vector< std::string > FeatureVector
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.
uint64_t getValue() const
#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_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_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.
@ 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
const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given riscv edge.
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.
static void relaxCall(const Block &B, BlockRelaxAux &Aux, const RelaxConfig &Config, orc::ExecutorAddr Loc, const Edge &E, uint32_t &Remove, Edge::Kind &NewEdgeKind)
static Expected< const Edge & > getRISCVPCRelHi20(const Edge &E)
static bool shouldRelax(const Section &S)
static void finalizeBlockRelax(LinkGraph &G, Block &Block, BlockRelaxAux &Aux)
static void relaxAlign(orc::ExecutorAddr Loc, const Edge &E, uint32_t &Remove, Edge::Kind &NewEdgeKind)
static bool relaxOnce(LinkGraph &G, RelaxAux &Aux)
Error makeAlignmentError(llvm::orc::ExecutorAddr Loc, uint64_t Value, int N, const Edge &E)
static Error relax(LinkGraph &G)
static bool isRelaxable(const Edge &E)
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject_riscv(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from an ELF/riscv relocatable object.
Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
static bool isAlignmentCorrect(uint64_t Value, int N)
static RelaxAux initRelaxAux(LinkGraph &G)
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.
void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
static bool isInRangeForImm(int64_t Value, int N)
static uint32_t extractBits(uint32_t Num, unsigned Low, unsigned Size)
static bool relaxBlock(LinkGraph &G, Block &Block, BlockRelaxAux &Aux, const RelaxConfig &Config)
static void finalizeRelax(LinkGraph &G, RelaxAux &Aux)
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
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)
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.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are are tuples (A,...
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)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
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.
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...