26#define DEBUG_TYPE "jitlink"
33class PerGraphGOTAndPLTStubsBuilder_ELF_riscv
35 PerGraphGOTAndPLTStubsBuilder_ELF_riscv> {
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];
45 bool isRV64()
const {
return G.getPointerSize() == 8; }
51 G.createContentBlock(getGOTSection(), getGOTEntryBlockContent(),
54 return G.addAnonymousSymbol(GOTBlock, 0,
G.getPointerSize(),
false,
false);
58 Block &StubContentBlock =
G.createContentBlock(
60 auto &GOTEntrySymbol = getGOTEntry(
Target);
62 return G.addAnonymousSymbol(StubContentBlock, 0, StubEntrySize,
true,
82 bool isExternalBranchEdge(
Edge &E)
const {
89 Section &getGOTSection()
const {
91 GOTSection = &
G.createSection(
"$__GOT", orc::MemProt::Read);
95 Section &getStubsSection()
const {
98 &
G.createSection(
"$__STUBS", orc::MemProt::Read | orc::MemProt::Exec);
103 return {
reinterpret_cast<const char *
>(NullGOTEntryContent),
108 auto StubContent = isRV64() ? RV64StubContent : RV32StubContent;
109 return {
reinterpret_cast<const char *
>(StubContent), StubEntrySize};
112 mutable Section *GOTSection =
nullptr;
113 mutable Section *StubsSection =
nullptr;
116const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_riscv::NullGOTEntryContent[8] =
117 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
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};
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};
137 return (Num & (((1ULL <<
Size) - 1) <<
Low)) >>
Low;
157 [
this](
LinkGraph &
G) {
return gatherRISCVPCRelHi20(
G); });
166 for (
Edge &
E :
B->edges())
168 RelHi20[{
B,
E.getOffset()}] = &
E;
174 using namespace riscv;
177 "Can only have high relocation for R_RISCV_PCREL_LO12_I or "
178 "R_RISCV_PCREL_LO12_S");
185 if (It != RelHi20.
end())
188 return make_error<JITLinkError>(
"No HI20 PCREL relocation type be found "
189 "for LO12 PCREL relocation type");
193 using namespace riscv;
196 char *BlockWorkingMem =
B.getAlreadyMutableContent().data();
197 char *FixupPtr = BlockWorkingMem +
E.getOffset();
199 switch (
E.getKind()) {
201 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
206 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
211 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
222 (RawInstr & 0x1FFF07F) | Imm12 | Imm10_5 | Imm4_1 | Imm11;
226 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
237 (RawInstr & 0xFFF) | Imm20 | Imm10_1 | Imm11 | Imm19_12;
244 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
252 RawInstrAuipc | (
static_cast<uint32_t>(
Hi & 0xFFFFF000));
254 RawInstrJalr | (
static_cast<uint32_t>(
Lo) << 20);
261 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
267 (RawInstr & 0xFFF) | (
static_cast<uint32_t>(
Hi & 0xFFFFF000));
274 auto RelHI20 = getRISCVPCRelHi20(
E);
276 return RelHI20.takeError();
277 int64_t
Value = RelHI20->getTarget().getAddress() +
278 RelHI20->getAddend() -
E.getTarget().getAddress();
282 (RawInstr & 0xFFFFF) | (
static_cast<uint32_t>(
Lo & 0xFFF) << 20);
289 auto RelHI20 = getRISCVPCRelHi20(
E);
291 return RelHI20.takeError();
292 int64_t
Value = RelHI20->getTarget().getAddress() +
293 RelHI20->getAddend() -
E.getTarget().getAddress();
299 *(
little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
303 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
309 (RawInstr & 0xFFF) | (
static_cast<uint32_t>(
Hi & 0xFFFFF000));
315 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
319 (RawInstr & 0xFFFFF) | (
static_cast<uint32_t>(
Lo & 0xFFF) << 20);
325 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
330 *(
little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
335 (
E.getTarget().getAddress() +
336 *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) +
E.getAddend())
338 *FixupPtr =
static_cast<uint8_t
>(
Value);
342 int64_t
Value = (
E.getTarget().getAddress() +
349 int64_t
Value = (
E.getTarget().getAddress() +
356 int64_t
Value = (
E.getTarget().getAddress() +
363 int64_t
Value = *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) -
364 E.getTarget().getAddress().getValue() -
E.getAddend();
365 *FixupPtr =
static_cast<uint8_t
>(
Value);
370 E.getTarget().getAddress().getValue() -
E.getAddend();
376 E.getTarget().getAddress().getValue() -
E.getAddend();
382 E.getTarget().getAddress().getValue() -
E.getAddend();
387 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
399 (RawInstr & 0xE383) |
Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5;
403 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
417 *(
little16_t *)FixupPtr = (RawInstr & 0xE003) | Imm11 | Imm4 | Imm9_8 |
418 Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5;
422 int64_t
Value = *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) & 0x3f;
423 Value -=
E.getTarget().getAddress().getValue() -
E.getAddend();
424 *FixupPtr = (*FixupPtr & 0xc0) | (
static_cast<uint8_t
>(
Value) & 0x3f);
428 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
430 int64_t Word6 =
Value & 0x3f;
431 *(
little32_t *)FixupPtr = (RawData & 0xffffffc0) | Word6;
435 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
442 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
449 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
455 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
464 int64_t
Value = FixupAddress -
E.getTarget().getAddress() +
E.getAddend();
483struct BlockRelaxAux {
528 Aux.Config.IsRV32 =
G.getTargetTriple().isRISCV32();
529 const auto &Features =
G.getFeatures().getFeatures();
533 for (
auto &S :
G.sections()) {
536 for (
auto *
B : S.blocks()) {
537 auto BlockEmplaceResult = Aux.Blocks.try_emplace(
B);
538 assert(BlockEmplaceResult.second &&
"Block encountered twice");
539 auto &BlockAux = BlockEmplaceResult.first->second;
541 for (
auto &E :
B->edges())
543 BlockAux.RelaxEdges.push_back(&E);
545 if (BlockAux.RelaxEdges.empty()) {
546 Aux.Blocks.erase(BlockEmplaceResult.first);
550 const auto NumEdges = BlockAux.RelaxEdges.size();
551 BlockAux.RelocDeltas.resize(NumEdges, 0);
552 BlockAux.EdgeKinds.resize_for_overwrite(NumEdges);
555 for (
auto *
Sym : S.symbols()) {
560 BlockAux.Anchors.push_back(
570 for (
auto &BlockAuxIter : Aux.Blocks) {
571 llvm::sort(BlockAuxIter.second.Anchors, [](
auto &
A,
auto &
B) {
572 return std::make_pair(A.Offset, A.End) < std::make_pair(B.Offset, B.End);
587 Remove = SrcLoc - DestLoc;
588 assert(
static_cast<int32_t
>(Remove) >= 0 &&
589 "R_RISCV_ALIGN needs expanding the content");
601 const auto Displace = Dest - Loc;
603 if (
Config.HasRVC && isInt<12>(Displace) && RD == 0) {
605 Aux.Writes.push_back(0xa001);
607 }
else if (
Config.HasRVC &&
Config.IsRV32 && isInt<12>(Displace) && RD == 1) {
609 Aux.Writes.push_back(0x2001);
611 }
else if (isInt<21>(Displace)) {
613 Aux.Writes.push_back(0x6f | RD << 7);
623 const RelaxConfig &
Config) {
625 bool Changed =
false;
633 const auto Loc = BlockAddr + E->
getOffset() - Delta;
634 auto &Cur = Aux.RelocDeltas[
I];
654 SA[0].Sym->setOffset(SA[0].
Offset - Delta);
664 for (
const SymbolAnchor &
A : SA) {
666 A.Sym->setSize(
A.Offset - Delta -
A.Sym->getOffset());
668 A.Sym->setOffset(
A.Offset - Delta);
675 bool Changed =
false;
677 for (
auto &[
B, BlockAux] : Aux.Blocks)
685 auto *Dest = Contents.
data();
686 auto NextWrite = Aux.Writes.begin();
693 uint32_t Remove = Aux.RelocDeltas[
I] - Delta;
694 Delta = Aux.RelocDeltas[
I];
700 std::memmove(Dest, Contents.data() +
Offset,
Size);
704 switch (Aux.EdgeKinds[
I]) {
716 for (; J + 4 <= Skip; J += 4)
738 std::memmove(Dest, Contents.data() +
Offset, Contents.size() -
Offset);
746 if (
I < Aux.RelaxEdges.size() && Aux.RelaxEdges[
I] == &E) {
750 Delta = Aux.RelocDeltas[
I];
767 for (
auto &[
B, BlockAux] : Aux.Blocks)
779template <
typename ELFT>
784 using namespace riscv;
786 case ELF::R_RISCV_32:
787 return EdgeKind_riscv::R_RISCV_32;
788 case ELF::R_RISCV_64:
789 return EdgeKind_riscv::R_RISCV_64;
790 case ELF::R_RISCV_BRANCH:
791 return EdgeKind_riscv::R_RISCV_BRANCH;
792 case ELF::R_RISCV_JAL:
793 return EdgeKind_riscv::R_RISCV_JAL;
794 case ELF::R_RISCV_CALL:
795 return EdgeKind_riscv::R_RISCV_CALL;
796 case ELF::R_RISCV_CALL_PLT:
797 return EdgeKind_riscv::R_RISCV_CALL_PLT;
798 case ELF::R_RISCV_GOT_HI20:
799 return EdgeKind_riscv::R_RISCV_GOT_HI20;
800 case ELF::R_RISCV_PCREL_HI20:
801 return EdgeKind_riscv::R_RISCV_PCREL_HI20;
802 case ELF::R_RISCV_PCREL_LO12_I:
803 return EdgeKind_riscv::R_RISCV_PCREL_LO12_I;
804 case ELF::R_RISCV_PCREL_LO12_S:
805 return EdgeKind_riscv::R_RISCV_PCREL_LO12_S;
806 case ELF::R_RISCV_HI20:
807 return EdgeKind_riscv::R_RISCV_HI20;
808 case ELF::R_RISCV_LO12_I:
809 return EdgeKind_riscv::R_RISCV_LO12_I;
810 case ELF::R_RISCV_LO12_S:
811 return EdgeKind_riscv::R_RISCV_LO12_S;
812 case ELF::R_RISCV_ADD8:
813 return EdgeKind_riscv::R_RISCV_ADD8;
814 case ELF::R_RISCV_ADD16:
815 return EdgeKind_riscv::R_RISCV_ADD16;
816 case ELF::R_RISCV_ADD32:
817 return EdgeKind_riscv::R_RISCV_ADD32;
818 case ELF::R_RISCV_ADD64:
819 return EdgeKind_riscv::R_RISCV_ADD64;
820 case ELF::R_RISCV_SUB8:
821 return EdgeKind_riscv::R_RISCV_SUB8;
822 case ELF::R_RISCV_SUB16:
823 return EdgeKind_riscv::R_RISCV_SUB16;
824 case ELF::R_RISCV_SUB32:
825 return EdgeKind_riscv::R_RISCV_SUB32;
826 case ELF::R_RISCV_SUB64:
827 return EdgeKind_riscv::R_RISCV_SUB64;
828 case ELF::R_RISCV_RVC_BRANCH:
829 return EdgeKind_riscv::R_RISCV_RVC_BRANCH;
830 case ELF::R_RISCV_RVC_JUMP:
831 return EdgeKind_riscv::R_RISCV_RVC_JUMP;
832 case ELF::R_RISCV_SUB6:
833 return EdgeKind_riscv::R_RISCV_SUB6;
834 case ELF::R_RISCV_SET6:
835 return EdgeKind_riscv::R_RISCV_SET6;
836 case ELF::R_RISCV_SET8:
837 return EdgeKind_riscv::R_RISCV_SET8;
838 case ELF::R_RISCV_SET16:
839 return EdgeKind_riscv::R_RISCV_SET16;
840 case ELF::R_RISCV_SET32:
841 return EdgeKind_riscv::R_RISCV_SET32;
842 case ELF::R_RISCV_32_PCREL:
843 return EdgeKind_riscv::R_RISCV_32_PCREL;
844 case ELF::R_RISCV_ALIGN:
845 return EdgeKind_riscv::AlignRelaxable;
848 return make_error<JITLinkError>(
849 "Unsupported riscv relocation:" +
formatv(
"{0:d}: ",
Type) +
864 Error addRelocations()
override {
869 for (
const auto &RelSect : Base::Sections)
870 if (
Error Err = Base::forEachRelaRelocation(RelSect,
this,
871 &Self::addSingleRelocation))
877 Error addSingleRelocation(
const typename ELFT::Rela &Rel,
878 const typename ELFT::Shdr &FixupSect,
883 int64_t Addend = Rel.r_addend;
885 if (
Type == ELF::R_RISCV_RELAX) {
887 return make_error<StringError>(
888 "R_RISCV_RELAX without preceding relocation",
891 auto &PrevEdge = *std::prev(BlockToFix.
edges().end());
893 PrevEdge.setKind(getRelaxableRelocationKind(Kind));
899 return Kind.takeError();
901 uint32_t SymbolIndex = Rel.getSymbol(
false);
902 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
904 return ObjSymbol.takeError();
906 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
908 return make_error<StringError>(
909 formatv(
"Could not find symbol at given index, did you add it to "
910 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
911 SymbolIndex, (*ObjSymbol)->st_shndx,
912 Base::GraphSymbols.size()),
924 BlockToFix.
addEdge(std::move(GE));
939 dbgs() <<
"Building jitlink graph for new input "
945 return ELFObj.takeError();
947 auto Features = (*ELFObj)->getFeatures();
949 return Features.takeError();
952 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
954 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
955 (*ELFObj)->makeTriple(), std::move(*Features))
959 "Invalid triple for RISCV ELF object file");
960 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
962 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
963 (*ELFObj)->makeTriple(), std::move(*Features))
969 std::unique_ptr<JITLinkContext> Ctx) {
971 const Triple &TT =
G->getTargetTriple();
972 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
980 if (
auto MarkLive = Ctx->getMarkLivePass(TT))
981 Config.PrePrunePasses.push_back(std::move(MarkLive));
984 Config.PostPrunePasses.push_back(
985 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::asPass);
988 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
989 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.
iterator find(const_arg_type_t< KeyT > Val)
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.
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)
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.
Symbol & getTarget() const
AddendT getAddend() const
OffsetT getOffset() const
void setTarget(Symbol &Target)
void setOffset(OffsetT Offset)
PassConfiguration & getPassConfig()
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....
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
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.
@ 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
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 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 enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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...
LinkGraphPassList PostAllocationPasses
Post-allocation passes.