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,
71 E.setTarget(GOTEntry);
79 E.setTarget(PLTStubs);
82 bool isExternalBranchEdge(
Edge &
E)
const {
85 !
E.getTarget().isDefined();
89 Section &getGOTSection()
const {
95 Section &getStubsSection()
const {
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 gatherRISCVPairs(G); });
168 for (
Edge &E :
B->edges())
170 RelHi20[{
B, E.getOffset()}] = &E;
172 SetULEB128[{
B, E.getOffset()}] = &
E;
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");
184 const Symbol &Sym =
E.getTarget();
188 auto It = RelHi20.find({&
B,
Offset});
189 if (It != RelHi20.end())
193 "for LO12 PCREL relocation type");
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");
202 auto It = SetULEB128.find({&
B,
E.getOffset()});
203 if (It != SetULEB128.end())
207 "No RISCV_SET_ULEB128 relocation type be found");
211 using namespace riscv;
212 using namespace llvm::support;
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();
224 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
229 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
240 (RawInstr & 0x1FFF07F) | Imm12 | Imm10_5 | Imm4_1 | Imm11;
244 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
255 (RawInstr & 0xFFF) | Imm20 | Imm10_1 | Imm11 | Imm19_12;
262 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
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);
279 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
285 (RawInstr & 0xFFF) | (
static_cast<uint32_t
>(
Hi & 0xFFFFF000));
292 auto RelHI20 = getRISCVPCRelHi20(
E);
294 return RelHI20.takeError();
295 int64_t
Value = RelHI20->getTarget().getAddress() +
296 RelHI20->getAddend() -
E.getTarget().getAddress();
300 (RawInstr & 0xFFFFF) | (
static_cast<uint32_t
>(
Lo & 0xFFF) << 20);
307 auto RelHI20 = getRISCVPCRelHi20(
E);
309 return RelHI20.takeError();
310 int64_t
Value = RelHI20->getTarget().getAddress() +
311 RelHI20->getAddend() -
E.getTarget().getAddress();
317 *(
little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
321 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
327 (RawInstr & 0xFFF) | (
static_cast<uint32_t
>(
Hi & 0xFFFFF000));
333 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
337 (RawInstr & 0xFFFFF) | (
static_cast<uint32_t
>(
Lo & 0xFFF) << 20);
343 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
348 *(
little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
353 (
E.getTarget().getAddress() +
354 *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) +
E.getAddend())
356 *FixupPtr =
static_cast<uint8_t
>(
Value);
360 int64_t
Value = (
E.getTarget().getAddress() +
367 int64_t
Value = (
E.getTarget().getAddress() +
374 int64_t
Value = (
E.getTarget().getAddress() +
381 int64_t
Value = *(
reinterpret_cast<const uint8_t *
>(FixupPtr)) -
382 E.getTarget().getAddress().getValue() -
E.getAddend();
383 *FixupPtr =
static_cast<uint8_t
>(
Value);
388 E.getTarget().getAddress().getValue() -
E.getAddend();
394 E.getTarget().getAddress().getValue() -
E.getAddend();
400 E.getTarget().getAddress().getValue() -
E.getAddend();
405 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
417 (RawInstr & 0xE383) |
Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5;
421 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
435 *(
little16_t *)FixupPtr = (RawInstr & 0xE003) | Imm11 | Imm4 | Imm9_8 |
436 Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5;
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);
446 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
448 int64_t Word6 =
Value & 0x3f;
449 *(
little32_t *)FixupPtr = (RawData & 0xffffffc0) | Word6;
453 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
460 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
467 int64_t
Value = (
E.getTarget().getAddress() +
E.getAddend()).getValue();
473 int64_t
Value =
E.getTarget().getAddress() +
E.getAddend() - FixupAddress;
482 int64_t
Value = FixupAddress -
E.getTarget().getAddress() +
E.getAddend();
491 auto SetULEB128 = getRISCVSetULEB128(
B,
E);
493 return SetULEB128.takeError();
494 uint64_t
Value = SetULEB128->getTarget().getAddress() +
495 SetULEB128->getAddend() -
E.getTarget().getAddress() -
516struct BlockRelaxAux {
525 SmallVector<uint32_t, 0> RelocDeltas;
530 SmallVector<uint32_t, 0> Writes;
540 DenseMap<Block *, BlockRelaxAux> Blocks;
550 switch (E.getKind()) {
561 Aux.Config.IsRV32 =
G.getTargetTriple().isRISCV32();
562 const auto &Features =
G.getFeatures().getFeatures();
566 for (
auto &S :
G.sections()) {
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;
574 for (
auto &E :
B->edges())
576 BlockAux.RelaxEdges.push_back(&E);
578 if (BlockAux.RelaxEdges.empty()) {
579 Aux.Blocks.erase(BlockEmplaceResult.first);
583 const auto NumEdges = BlockAux.RelaxEdges.size();
584 BlockAux.RelocDeltas.resize(NumEdges, 0);
585 BlockAux.EdgeKinds.resize_for_overwrite(NumEdges);
588 for (
auto *Sym : S.symbols()) {
592 BlockAux.Anchors.push_back({Sym->
getOffset(), Sym,
false});
593 BlockAux.Anchors.push_back(
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);
613 Edge::Kind &NewEdgeKind) {
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");
629 Edge::Kind &NewEdgeKind) {
633 const auto Dest = E.getTarget().getAddress() + E.getAddend();
634 const auto Displace = Dest -
Loc;
636 if (Config.HasRVC &&
isInt<12>(Displace) && RD == 0) {
640 }
else if (Config.HasRVC && Config.IsRV32 &&
isInt<12>(Displace) && RD == 1) {
656 const RelaxConfig &Config) {
662 Aux.EdgeKinds.assign(Aux.EdgeKinds.size(), Edge::Invalid);
666 const auto Loc = BlockAddr + E->getOffset() - Delta;
667 auto &Cur = Aux.RelocDeltas[
I];
669 switch (E->getKind()) {
687 SA[0].Sym->setOffset(SA[0].
Offset - Delta);
697 for (
const SymbolAnchor &
A : SA) {
699 A.Sym->setSize(
A.Offset - Delta -
A.Sym->getOffset());
701 A.Sym->setOffset(
A.Offset - Delta);
710 for (
auto &[
B, BlockAux] : Aux.Blocks)
718 auto *Dest = Contents.
data();
719 auto NextWrite = Aux.Writes.
begin();
726 uint32_t Remove = Aux.RelocDeltas[
I] - Delta;
727 Delta = Aux.RelocDeltas[
I];
728 if (Remove == 0 && Aux.EdgeKinds[
I] == Edge::Invalid)
733 std::memmove(Dest, Contents.data() +
Offset,
Size);
737 switch (Aux.EdgeKinds[
I]) {
746 if (Remove % 4 || E->getAddend() % 4) {
747 Skip = E->getAddend() - Remove;
749 for (; J + 4 <= Skip; J += 4)
768 Offset = E->getOffset() + Skip + Remove;
771 std::memmove(Dest, Contents.data() +
Offset, Contents.size() -
Offset);
777 E.setOffset(E.getOffset() - Delta);
779 if (
I < Aux.RelaxEdges.size() && Aux.RelaxEdges[
I] == &E) {
780 if (Aux.EdgeKinds[
I] != Edge::Invalid)
781 E.setKind(Aux.EdgeKinds[
I]);
783 Delta = Aux.RelocDeltas[
I];
800 for (
auto &[
B, BlockAux] : Aux.Blocks)
812template <
typename ELFT>
817 using namespace riscv;
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:
886 "Unsupported riscv relocation:" +
formatv(
"{0:d}: ",
Type) +
906 for (
const auto &RelSect : Base::Sections)
907 if (
Error Err = Base::forEachRelaRelocation(RelSect,
this,
908 &Self::addSingleRelocation))
914 Error addSingleRelocation(
const typename ELFT::Rela &Rel,
915 const typename ELFT::Shdr &FixupSect,
920 int64_t Addend = Rel.r_addend;
922 if (
Type == ELF::R_RISCV_RELAX) {
925 "R_RISCV_RELAX without preceding relocation",
928 auto &PrevEdge = *std::prev(BlockToFix.
edges().end());
930 PrevEdge.setKind(getRelaxableRelocationKind(Kind));
936 return Kind.takeError();
938 uint32_t SymbolIndex = Rel.getSymbol(
false);
939 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
941 return ObjSymbol.takeError();
943 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
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()),
961 BlockToFix.
addEdge(std::move(GE));
968 std::shared_ptr<orc::SymbolStringPool> SSP,
977 std::shared_ptr<orc::SymbolStringPool> SSP) {
979 dbgs() <<
"Building jitlink graph for new input "
985 return ELFObj.takeError();
987 auto Features = (*ELFObj)->getFeatures();
989 return Features.takeError();
994 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
995 std::move(SSP), (*ELFObj)->makeTriple(), std::move(*Features))
999 "Invalid triple for RISCV ELF object file");
1002 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
1003 std::move(SSP), (*ELFObj)->makeTriple(), std::move(*Features))
1009 std::unique_ptr<JITLinkContext> Ctx) {
1011 const Triple &TT =
G->getTargetTriple();
1012 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
1016 ".eh_frame",
G->getPointerSize(), Edge::Invalid, Edge::Invalid,
1020 if (
auto MarkLive = Ctx->getMarkLivePass(TT))
1025 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::asPass);
1028 if (
auto Err = Ctx->modifyPassConfig(*
G, Config))
1029 return Ctx->notifyFailed(std::move(Err));
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)
ELFLinkGraphBuilder_riscv(StringRef FileName, const object::ELFFile< ELFT > &Obj, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, SubtargetFeatures Features)
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.
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)
LLVM_ABI 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)
LLVM_ABI 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.
LLVM_ABI 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)
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<X> - 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.