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;
240 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
248 RawInstrAuipc | (
static_cast<uint32_t>(
Hi & 0xFFFFF000));
250 RawInstrJalr | (
static_cast<uint32_t>(
Lo) << 20);
257 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
263 (RawInstr & 0xFFF) | (
static_cast<uint32_t>(
Hi & 0xFFFFF000));
272 return RelHI20.takeError();
273 int64_t
Value = RelHI20->getTarget().getAddress() +
274 RelHI20->getAddend() -
E.getTarget().getAddress();
278 (RawInstr & 0xFFFFF) | (
static_cast<uint32_t>(
Lo & 0xFFF) << 20);
287 return RelHI20.takeError();
288 int64_t
Value = RelHI20->getTarget().getAddress() +
289 RelHI20->getAddend() -
E.getTarget().getAddress();
295 *(
little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
299 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
305 (RawInstr & 0xFFF) | (
static_cast<uint32_t>(
Hi & 0xFFFFF000));
311 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
315 (RawInstr & 0xFFFFF) | (
static_cast<uint32_t>(
Lo & 0xFFF) << 20);
321 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
326 *(
little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
331 (
E.getTarget().getAddress() +
332 *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) +
E.getAddend())
334 *FixupPtr =
static_cast<uint8_t
>(
Value);
338 int64_t
Value = (
E.getTarget().getAddress() +
345 int64_t
Value = (
E.getTarget().getAddress() +
352 int64_t
Value = (
E.getTarget().getAddress() +
359 int64_t
Value = *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) -
360 E.getTarget().getAddress().getValue() -
E.getAddend();
361 *FixupPtr =
static_cast<uint8_t
>(
Value);
366 E.getTarget().getAddress().getValue() -
E.getAddend();
372 E.getTarget().getAddress().getValue() -
E.getAddend();
378 E.getTarget().getAddress().getValue() -
E.getAddend();
383 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
395 (RawInstr & 0xE383) |
Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5;
399 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
413 *(
little16_t *)FixupPtr = (RawInstr & 0xE003) | Imm11 | Imm4 | Imm9_8 |
414 Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5;
418 int64_t
Value = *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) & 0x3f;
419 Value -=
E.getTarget().getAddress().getValue() -
E.getAddend();
420 *FixupPtr = (*FixupPtr & 0xc0) | (
static_cast<uint8_t
>(
Value) & 0x3f);
424 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
426 int64_t Word6 =
Value & 0x3f;
427 *(
little32_t *)FixupPtr = (RawData & 0xffffffc0) | Word6;
431 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
438 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
445 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
451 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
472struct BlockRelaxAux {
506 switch (
E.getKind()) {
517 Aux.Config.IsRV32 =
G.getTargetTriple().isRISCV32();
518 const auto &Features =
G.getFeatures().getFeatures();
521 for (
auto &S :
G.sections()) {
524 for (
auto *
B : S.blocks()) {
525 auto BlockEmplaceResult = Aux.Blocks.try_emplace(
B);
526 assert(BlockEmplaceResult.second &&
"Block encountered twice");
527 auto &BlockAux = BlockEmplaceResult.first->second;
529 for (
auto &
E :
B->edges())
531 BlockAux.RelaxEdges.push_back(&
E);
533 if (BlockAux.RelaxEdges.empty()) {
534 Aux.Blocks.erase(BlockEmplaceResult.first);
538 const auto NumEdges = BlockAux.RelaxEdges.size();
539 BlockAux.RelocDeltas.resize(NumEdges, 0);
540 BlockAux.EdgeKinds.resize_for_overwrite(NumEdges);
543 for (
auto *
Sym : S.symbols()) {
548 BlockAux.Anchors.push_back(
558 for (
auto &BlockAuxIter : Aux.Blocks) {
559 llvm::sort(BlockAuxIter.second.Anchors, [](
auto &
A,
auto &
B) {
560 return std::make_pair(A.Offset, A.End) < std::make_pair(B.Offset, B.End);
574 const auto SrcLoc = Loc.
getValue() +
E.getAddend();
575 Remove = SrcLoc - DestLoc;
576 assert(
static_cast<int32_t
>(Remove) >= 0 &&
577 "R_RISCV_ALIGN needs expanding the content");
588 const auto Dest =
E.getTarget().getAddress() +
E.getAddend();
589 const auto Displace = Dest - Loc;
591 if (
Config.HasRVC && isInt<12>(Displace) && RD == 0) {
593 Aux.Writes.push_back(0xa001);
595 }
else if (
Config.HasRVC &&
Config.IsRV32 && isInt<12>(Displace) && RD == 1) {
597 Aux.Writes.push_back(0x2001);
599 }
else if (isInt<21>(Displace)) {
601 Aux.Writes.push_back(0x6f | RD << 7);
611 const RelaxConfig &
Config) {
613 bool Changed =
false;
621 const auto Loc = BlockAddr +
E->getOffset() - Delta;
622 auto &Cur = Aux.RelocDeltas[
I];
624 switch (
E->getKind()) {
642 SA[0].Sym->setOffset(SA[0].
Offset - Delta);
652 for (
const SymbolAnchor &
A : SA) {
654 A.Sym->setSize(
A.Offset - Delta -
A.Sym->getOffset());
656 A.Sym->setOffset(
A.Offset - Delta);
663 bool Changed =
false;
665 for (
auto &[
B, BlockAux] : Aux.Blocks)
673 auto *Dest = Contents.
data();
674 auto NextWrite = Aux.Writes.begin();
681 uint32_t Remove = Aux.RelocDeltas[
I] - Delta;
682 Delta = Aux.RelocDeltas[
I];
688 std::memmove(Dest, Contents.data() +
Offset,
Size);
692 switch (Aux.EdgeKinds[
I]) {
701 if (Remove % 4 ||
E->getAddend() % 4) {
702 Skip =
E->getAddend() - Remove;
704 for (; J + 4 <= Skip; J += 4)
723 Offset =
E->getOffset() + Skip + Remove;
726 std::memmove(Dest, Contents.data() +
Offset, Contents.size() -
Offset);
732 E.setOffset(
E.getOffset() - Delta);
734 if (
I < Aux.RelaxEdges.size() && Aux.RelaxEdges[
I] == &
E) {
736 E.setKind(Aux.EdgeKinds[
I]);
738 Delta = Aux.RelocDeltas[
I];
755 for (
auto &[
B, BlockAux] : Aux.Blocks)
767template <
typename ELFT>
772 using namespace riscv;
774 case ELF::R_RISCV_32:
775 return EdgeKind_riscv::R_RISCV_32;
776 case ELF::R_RISCV_64:
777 return EdgeKind_riscv::R_RISCV_64;
778 case ELF::R_RISCV_BRANCH:
779 return EdgeKind_riscv::R_RISCV_BRANCH;
780 case ELF::R_RISCV_JAL:
781 return EdgeKind_riscv::R_RISCV_JAL;
782 case ELF::R_RISCV_CALL:
783 return EdgeKind_riscv::R_RISCV_CALL;
784 case ELF::R_RISCV_CALL_PLT:
785 return EdgeKind_riscv::R_RISCV_CALL_PLT;
786 case ELF::R_RISCV_GOT_HI20:
787 return EdgeKind_riscv::R_RISCV_GOT_HI20;
788 case ELF::R_RISCV_PCREL_HI20:
789 return EdgeKind_riscv::R_RISCV_PCREL_HI20;
790 case ELF::R_RISCV_PCREL_LO12_I:
791 return EdgeKind_riscv::R_RISCV_PCREL_LO12_I;
792 case ELF::R_RISCV_PCREL_LO12_S:
793 return EdgeKind_riscv::R_RISCV_PCREL_LO12_S;
794 case ELF::R_RISCV_HI20:
795 return EdgeKind_riscv::R_RISCV_HI20;
796 case ELF::R_RISCV_LO12_I:
797 return EdgeKind_riscv::R_RISCV_LO12_I;
798 case ELF::R_RISCV_LO12_S:
799 return EdgeKind_riscv::R_RISCV_LO12_S;
800 case ELF::R_RISCV_ADD8:
801 return EdgeKind_riscv::R_RISCV_ADD8;
802 case ELF::R_RISCV_ADD16:
803 return EdgeKind_riscv::R_RISCV_ADD16;
804 case ELF::R_RISCV_ADD32:
805 return EdgeKind_riscv::R_RISCV_ADD32;
806 case ELF::R_RISCV_ADD64:
807 return EdgeKind_riscv::R_RISCV_ADD64;
808 case ELF::R_RISCV_SUB8:
809 return EdgeKind_riscv::R_RISCV_SUB8;
810 case ELF::R_RISCV_SUB16:
811 return EdgeKind_riscv::R_RISCV_SUB16;
812 case ELF::R_RISCV_SUB32:
813 return EdgeKind_riscv::R_RISCV_SUB32;
814 case ELF::R_RISCV_SUB64:
815 return EdgeKind_riscv::R_RISCV_SUB64;
816 case ELF::R_RISCV_RVC_BRANCH:
817 return EdgeKind_riscv::R_RISCV_RVC_BRANCH;
818 case ELF::R_RISCV_RVC_JUMP:
819 return EdgeKind_riscv::R_RISCV_RVC_JUMP;
820 case ELF::R_RISCV_SUB6:
821 return EdgeKind_riscv::R_RISCV_SUB6;
822 case ELF::R_RISCV_SET6:
823 return EdgeKind_riscv::R_RISCV_SET6;
824 case ELF::R_RISCV_SET8:
825 return EdgeKind_riscv::R_RISCV_SET8;
826 case ELF::R_RISCV_SET16:
827 return EdgeKind_riscv::R_RISCV_SET16;
828 case ELF::R_RISCV_SET32:
829 return EdgeKind_riscv::R_RISCV_SET32;
830 case ELF::R_RISCV_32_PCREL:
831 return EdgeKind_riscv::R_RISCV_32_PCREL;
832 case ELF::R_RISCV_ALIGN:
833 return EdgeKind_riscv::AlignRelaxable;
836 return make_error<JITLinkError>(
837 "Unsupported riscv relocation:" +
formatv(
"{0:d}: ",
Type) +
852 Error addRelocations()
override {
857 for (
const auto &RelSect : Base::Sections)
858 if (
Error Err = Base::forEachRelaRelocation(RelSect,
this,
859 &Self::addSingleRelocation))
865 Error addSingleRelocation(
const typename ELFT::Rela &Rel,
866 const typename ELFT::Shdr &FixupSect,
871 int64_t Addend = Rel.r_addend;
873 if (
Type == ELF::R_RISCV_RELAX) {
875 return make_error<StringError>(
876 "R_RISCV_RELAX without preceding relocation",
879 auto &PrevEdge = *std::prev(BlockToFix.
edges().end());
881 PrevEdge.setKind(getRelaxableRelocationKind(Kind));
887 return Kind.takeError();
889 uint32_t SymbolIndex = Rel.getSymbol(
false);
890 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
892 return ObjSymbol.takeError();
894 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
896 return make_error<StringError>(
897 formatv(
"Could not find symbol at given index, did you add it to "
898 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
899 SymbolIndex, (*ObjSymbol)->st_shndx,
900 Base::GraphSymbols.size()),
912 BlockToFix.
addEdge(std::move(GE));
927 dbgs() <<
"Building jitlink graph for new input "
933 return ELFObj.takeError();
935 auto Features = (*ELFObj)->getFeatures();
937 return Features.takeError();
940 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
942 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
943 (*ELFObj)->makeTriple(), std::move(*Features))
947 "Invalid triple for RISCV ELF object file");
948 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
950 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
951 (*ELFObj)->makeTriple(), std::move(*Features))
957 std::unique_ptr<JITLinkContext> Ctx) {
959 const Triple &TT =
G->getTargetTriple();
960 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
961 if (
auto MarkLive = Ctx->getMarkLivePass(TT))
962 Config.PrePrunePasses.push_back(std::move(MarkLive));
965 Config.PostPrunePasses.push_back(
966 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::asPass);
969 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
970 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.
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.
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, SubtargetFeatures Features)
LinkGraph 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.
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
unique_function is a type-erasing functor similar to std::function.
#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)
LinkGraphPassFunction createRelaxationPass_ELF_riscv()
Returns a pass that performs linker relaxation.
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.
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...