30#define DEBUG_TYPE "jitlink"
38constexpr StringRef GOTSectionName =
"$__GOT";
39constexpr StringRef StubsSectionName =
"$__STUBS";
40constexpr StringRef TLSInfoSectionName =
"$__TLSINFO";
41constexpr StringRef TLSBaseName =
"__jitlink_mips_tls_base";
42constexpr StringRef GOTSymbolName =
"_GLOBAL_OFFSET_TABLE_";
44constexpr StringRef GPDispName =
"_gp_disp";
45constexpr StringRef LocalGPName =
"__gnu_local_gp";
46constexpr unsigned RelocationTypeBits = 8;
47constexpr unsigned MaxRelocationOperations = 3;
50constexpr uint64_t GPAnchorOffset = 0x7ff0;
52enum class MipsABI { O32, N32, N64 };
54static Edge::Kind getPagePointerEdgeKind(
const LinkGraph &
G) {
58template <
unsigned Bits,
unsigned Shift>
60 static_assert(Bits + Shift <= 32);
65static uint8_t getPackedRelocationField(
uint32_t Packed,
unsigned Index) {
66 return static_cast<uint8_t>((Packed >> (Index * RelocationTypeBits)) &
81static unsigned getFixupSize(Edge::Kind
K) {
133class ELFJITLinker_mips :
public JITLinker<ELFJITLinker_mips> {
134 friend class JITLinker<ELFJITLinker_mips>;
137 ELFJITLinker_mips(std::unique_ptr<JITLinkContext> Ctx,
139 :
JITLinker(std::move(Ctx), std::move(
G), std::move(PassConfig)) {
140 getPassConfig().PreFixupPasses.push_back([
this](
LinkGraph &
G) {
141 GPSymbol =
G.findDefinedSymbolByName(
G.intern(GPName));
142 TLSBaseSymbol =
G.findDefinedSymbolByName(
G.intern(TLSBaseName));
148 Symbol *GPSymbol =
nullptr;
149 Symbol *TLSBaseSymbol =
nullptr;
156template <
typename ELFT>
159 using Rel =
typename ELFT::Rel;
160 using Rela =
typename ELFT::Rela;
171 std::shared_ptr<orc::SymbolStringPool> SSP,
173 :
Base(Obj, std::move(SSP), std::move(TT), std::move(Features), FileName,
180 bool excludeSection(
const typename ELFT::Shdr &Sec)
const override {
187 const Twine &Message)
const {
190 return Name.takeError();
198 if (
Type == ELF::R_MIPS_NONE ||
Type == ELF::R_MIPS_JALR)
201 unsigned FixupSize =
Type == ELF::R_MIPS_16 ?
sizeof(
uint16_t)
206 "relocation fixup extends past the end of its block");
208 const char *
P =
B.getContent().data() +
Offset;
209 if (
Type == ELF::R_MIPS_16)
212 if (
Type == ELF::R_MIPS_64)
218 case ELF::R_MIPS_GPREL32:
219 case ELF::R_MIPS_PC32:
220 case ELF::R_MIPS_TLS_DTPREL32:
223 return decodeInstructionImmediate<26, 2>(W);
224 case ELF::R_MIPS_HI16:
225 case ELF::R_MIPS_PCHI16:
226 case ELF::R_MIPS_GOT16:
227 case ELF::R_MIPS_GOT_HI16:
228 case ELF::R_MIPS_CALL_HI16:
229 return decodeInstructionImmediate<16, 16>(W);
230 case ELF::R_MIPS_PC16:
231 return decodeInstructionImmediate<16, 2>(W);
232 case ELF::R_MIPS_PC18_S3:
233 return decodeInstructionImmediate<18, 3>(W);
234 case ELF::R_MIPS_PC19_S2:
235 return decodeInstructionImmediate<19, 2>(W);
236 case ELF::R_MIPS_PC21_S2:
237 return decodeInstructionImmediate<21, 2>(W);
238 case ELF::R_MIPS_PC26_S2:
239 return decodeInstructionImmediate<26, 2>(W);
241 return decodeInstructionImmediate<16, 0>(W);
247 case ELF::R_MIPS_HI16:
248 return ELF::R_MIPS_LO16;
249 case ELF::R_MIPS_PCHI16:
250 return ELF::R_MIPS_PCLO16;
251 case ELF::R_MIPS_GOT16:
252 return IsLocal ? ELF::R_MIPS_LO16 : ELF::R_MIPS_NONE;
254 return ELF::R_MIPS_NONE;
258 Error validateSymbols() {
263 return Symbols.takeError();
264 for (
const auto &Sym : *Symbols)
269 ": compact-mode MIPS16/microMIPS symbols are unsupported");
273 Error collectRelocs(
const typename ELFT::Shdr &RelSect,
Block &
B,
278 return Rs.takeError();
279 for (
auto I = Rs->begin(),
E = Rs->end();
I !=
E;) {
280 const Rela &R = *
I++;
281 if (ABI == MipsABI::N32) {
282 Reloc RR{R.r_offset, R.getSymbol(
false), {}, R.r_addend};
283 RR.Types.push_back(R.getType(
false));
284 while (
I !=
E &&
I->r_offset == R.r_offset) {
285 if (RR.Types.size() == MaxRelocationOperations)
286 return error(RelSect, R.r_offset,
287 "more than three N32 relocation operations");
288 if (
I->getSymbol(
false) != 0)
289 return error(RelSect, R.r_offset,
290 "non-zero symbol in a secondary N32 relocation");
291 RR.Types.push_back(
I->getType(
false));
294 Out.push_back(std::move(RR));
299 uint8_t T2 = getPackedRelocationField(PackedType, 1);
300 uint8_t T3 = getPackedRelocationField(PackedType, 2);
301 RR.Types.push_back(getPackedRelocationField(PackedType, 0));
303 RR.Types.push_back(T2);
305 RR.Types.push_back(T3);
306 uint8_t SSym = getPackedRelocationField(PackedType, 3);
308 return error(RelSect, R.r_offset,
309 "unsupported packed relocation special symbol " +
311 Out.push_back(std::move(RR));
319 return Rs.takeError();
320 for (
auto I = Rs->begin(),
E = Rs->end();
I !=
E;) {
322 Reloc RR{R.r_offset, R.getSymbol(
false), {}, 0};
323 RR.Types.push_back(R.getType(
false));
324 if (ABI == MipsABI::N32) {
325 while (
I !=
E &&
I->r_offset == R.r_offset) {
326 if (RR.Types.size() == MaxRelocationOperations)
327 return error(RelSect, R.r_offset,
328 "more than three N32 relocation operations");
329 if (
I->getSymbol(
false) != 0)
330 return error(RelSect, R.r_offset,
331 "non-zero symbol in a secondary N32 relocation");
332 RR.Types.push_back(
I->getType(
false));
336 Out.push_back(std::move(RR));
339 for (
size_t I = 0;
I != Out.size(); ++
I) {
341 uint8_t FinalType = R.Types.back();
342 auto Addend = implicitAddend(RelSect, FinalType,
B, R.Offset);
344 return Addend.takeError();
346 bool IsLocal =
false;
349 uint8_t LowType = matchingLow(R.Types.front(), IsLocal);
350 if (LowType == ELF::R_MIPS_NONE)
353 for (
size_t J =
I + 1; J != Out.size(); ++J)
354 if (Out[J].Types.front() == LowType && Out[J].Symbol == R.Symbol) {
355 auto LowAddend = implicitAddend(RelSect, LowType,
B, Out[J].
Offset);
357 return LowAddend.takeError();
358 R.Addend += *LowAddend;
363 return error(RelSect, R.Offset,
373 if (R.Types.size() > 1) {
374 if (R.Types.size() == 2 && R.Types[1] == ELF::R_MIPS_64) {
375 switch (R.Types[0]) {
379 case ELF::R_MIPS_PC32:
381 case ELF::R_MIPS_GPREL32:
387 if (R.Types.size() == 3 && R.Types[0] == ELF::R_MIPS_GPREL16 &&
388 R.Types[1] == ELF::R_MIPS_SUB && R.Types[2] == ELF::R_MIPS_HI16)
390 if (R.Types.size() == 3 && R.Types[0] == ELF::R_MIPS_GPREL16 &&
391 R.Types[1] == ELF::R_MIPS_SUB && R.Types[2] == ELF::R_MIPS_LO16)
394 getRelocationChainName(R.Types));
398 switch (R.Types.front()) {
405 case ELF::R_MIPS_HI16:
407 case ELF::R_MIPS_LO16:
409 case ELF::R_MIPS_HIGHER:
411 case ELF::R_MIPS_HIGHEST:
415 case ELF::R_MIPS_PC16:
417 case ELF::R_MIPS_PC32:
419 case ELF::R_MIPS_PC18_S3:
421 case ELF::R_MIPS_PC19_S2:
423 case ELF::R_MIPS_PC21_S2:
425 case ELF::R_MIPS_PC26_S2:
427 case ELF::R_MIPS_PCHI16:
429 case ELF::R_MIPS_PCLO16:
431 case ELF::R_MIPS_GPREL16:
433 case ELF::R_MIPS_GPREL32:
435 case ELF::R_MIPS_GOT16:
439 case ELF::R_MIPS_CALL16:
440 case ELF::R_MIPS_GOT_DISP:
442 case ELF::R_MIPS_GOT_PAGE:
444 case ELF::R_MIPS_GOT_OFST:
446 case ELF::R_MIPS_GOT_HI16:
447 case ELF::R_MIPS_CALL_HI16:
449 case ELF::R_MIPS_GOT_LO16:
450 case ELF::R_MIPS_CALL_LO16:
452 case ELF::R_MIPS_TLS_GD:
454 case ELF::R_MIPS_TLS_LDM:
456 case ELF::R_MIPS_TLS_DTPREL_HI16:
458 case ELF::R_MIPS_TLS_DTPREL_LO16:
460 case ELF::R_MIPS_TLS_DTPREL32:
462 case ELF::R_MIPS_TLS_DTPREL64:
464 case ELF::R_MIPS_TLS_GOTTPREL:
465 case ELF::R_MIPS_TLS_TPREL32:
466 case ELF::R_MIPS_TLS_TPREL64:
467 case ELF::R_MIPS_TLS_TPREL_HI16:
468 case ELF::R_MIPS_TLS_TPREL_LO16:
470 "initial/local-exec MIPS TLS relocations are unsupported");
478 Error addRelocations()
override {
479 if (
auto Err = validateSymbols())
484 if ((ABI != MipsABI::O32) != (RelSect.sh_type ==
ELF::SHT_RELA))
487 ": invalid MIPS relocation-section format for ABI");
490 return FixupSect.takeError();
495 if (
auto Err = collectRelocs(RelSect, *
B, Rs))
497 for (
const Reloc &R : Rs) {
498 uint8_t Primary = R.Types.front();
499 if (Primary == ELF::R_MIPS_NONE || Primary == ELF::R_MIPS_JALR)
503 return error(**FixupSect, R.Offset,
504 "relocation references missing symbol index " +
506 auto Kind = edgeKind(R, *
Target);
509 error(**FixupSect, R.Offset,
"cannot lower relocation"),
512 Edge::OffsetT
Offset = FixupAddress -
B->getAddress();
513 unsigned FixupSize = getFixupSize(*Kind);
515 return error(**FixupSect, R.Offset,
516 "relocation fixup extends past the end of its block");
525 auto Name =
G.intern(TLSBaseName);
526 if (
auto *S =
G.findDefinedSymbolByName(Name))
528 Section *TLS =
G.findSectionByName(
".tdata");
529 if (!TLS || TLS->empty())
530 TLS =
G.findSectionByName(
".tbss");
531 if (!TLS || TLS->empty()) {
538 auto &
B = **TLS->blocks().begin();
543class MipsTableManager {
548 switch (
E.getKind()) {
562 rewriteTLS(
E, TLSDescriptorKind::GeneralDynamic);
565 rewriteTLS(
E, TLSDescriptorKind::LocalDynamic);
568 if (!
E.getTarget().isDefined()) {
569 rewriteBranchToStub(
E);
575 rewriteBranchToStub(
E);
585 enum class GOTEntryKind { Exact, Page };
586 enum class TLSDescriptorKind { GeneralDynamic, LocalDynamic };
588 using GOTKey = std::tuple<Symbol *, int64_t, GOTEntryKind>;
589 using StubKey = std::tuple<Symbol *, int64_t>;
594 Symbol *TLSLDMEntry =
nullptr;
597 if (
auto *S =
G.findSectionByName(Name))
599 return G.createSection(Name, Prot);
605 if (
I != GOTEntries.
end())
610 Edge::Kind PointerKind = Kind == GOTEntryKind::Page
611 ? getPagePointerEdgeKind(
G)
613 Entry.getBlock().addEdge(PointerKind, 0,
Target, Addend);
614 GOTEntries[
Key] = &Entry;
618 void rewriteGOT(
Edge &
E, GOTEntryKind EntryKind, Edge::Kind NewKind) {
619 Symbol &Entry = getGOT(
E.getTarget(),
E.getAddend(), EntryKind);
626 auto &Sec = getSection(TLSInfoSectionName,
629 G.createMutableContentBlock(Sec, 2 *
G.getPointerSize(),
632 return G.addAnonymousSymbol(
B, 0,
B.getSize(),
false,
false);
635 void rewriteTLS(
Edge &
E, TLSDescriptorKind Kind) {
637 if (Kind == TLSDescriptorKind::LocalDynamic) {
639 TLSLDMEntry = &createTLSInfo(getOrCreateTLSBase(
G), 0);
642 auto Key = std::make_pair(&
E.getTarget(),
E.getAddend());
644 if (
I == TLSGDEntries.
end())
655 void rewriteBranchToStub(
Edge &
E) {
657 int64_t PointerAddend =
E.getAddend();
658 int64_t BranchAddend = 0;
660 PointerAddend += CompactBranchPCBias;
661 BranchAddend = -CompactBranchPCBias;
664 StubKey
Key{&
E.getTarget(), PointerAddend};
666 if (
I == Stubs.
end()) {
667 auto &Ptr = getGOT(
E.getTarget(), PointerAddend, GOTEntryKind::Exact);
675 E.setTarget(*
I->second);
676 E.setAddend(BranchAddend);
681 MipsTableManager Tables(
G);
688 auto N =
G.intern(Name);
689 if (
auto *S =
G.findDefinedSymbolByName(
N)) {
693 if (
auto *S =
G.findExternalSymbolByName(
N)) {
703 Section *GOT =
G.findSectionByName(GOTSectionName);
705 GOT = &
G.createSection(GOTSectionName,
708 auto &Anchor =
G.createMutableContentBlock(
710 defineMagic(
G, Anchor, GOTSymbolName, 0);
711 defineMagic(
G, Anchor, GPName, GPAnchorOffset);
712 defineMagic(
G, Anchor, GPDispName, GPAnchorOffset);
713 defineMagic(
G, Anchor, LocalGPName, GPAnchorOffset);
715 for (
const std::string &Name : GPRelSectionNames)
716 if (
auto *S =
G.findSectionByName(Name)) {
718 for (
auto *
B : Blocks)
719 G.transferBlock(*
B, *GOT);
724 auto *GOT =
G.findSectionByName(GOTSectionName);
728 if (
auto *TLSInfo =
G.findSectionByName(TLSInfoSectionName))
729 G.mergeSections(*GOT, *TLSInfo);
731 auto *GOTBase =
G.findDefinedSymbolByName(
G.intern(GOTSymbolName));
732 assert(GOTBase && &GOTBase->getBlock().getSection() == GOT &&
733 GOTBase->getOffset() == 0 &&
"invalid MIPS GOT base");
737 Block &Anchor = GOTBase->getBlock();
739 for (
auto *
B : GOT->blocks())
746template <
typename ELFT>
749 auto Sections = Obj.sections();
751 return Sections.takeError();
752 const typename ELFT::Shdr *ABIFlagsSec =
nullptr;
753 for (
const auto &Sec : *Sections)
757 ": multiple .MIPS.abiflags sections");
762 auto Contents = Obj.template getSectionContentsAsArray<char>(*ABIFlagsSec);
764 return Contents.takeError();
767 ": invalid .MIPS.abiflags size");
772 ": unsupported .MIPS.abiflags version");
773 if ((ABI == MipsABI::N32 || ABI == MipsABI::N64) &&
776 FileName.
str() +
": N32/N64 requires 64-bit general registers");
777 if (
static_cast<uint32_t>(AF.ases) &
781 ": MIPS16 and microMIPS ABI flags are unsupported by JITLink");
785template <
typename ELFT>
788 std::shared_ptr<orc::SymbolStringPool> SSP, MipsABI ABI,
Triple TT,
791 if (
auto Err = validateABIFlags(Obj, ABI, ObjFile.
getFileName()))
792 return std::move(Err);
793 ELFLinkGraphBuilder_mips<ELFT> Builder(ObjFile.
getFileName(), Obj,
794 std::move(SSP), std::move(TT),
795 std::move(Features), ABI);
796 auto G = Builder.buildGraph();
798 return G.takeError();
801 auto Sections = Obj.sections();
803 return Sections.takeError();
804 for (
const auto &Sec : *Sections)
806 auto Name = Obj.getSectionName(Sec);
808 return Name.takeError();
811 prepareGPRegion(**
G, GPRelSections);
817 uint32_t Flags = Obj.getPlatformFlags();
821 ": MIPS16 and microMIPS objects are unsupported by JITLink");
827 FileName.
str() +
": inconsistent MIPS N64 ELF class/ABI flags");
833 FileName.
str() +
": inconsistent MIPS N32 ELF class/ABI flags");
838 ": unsupported 32-bit MIPS ABI flags");
847Expected<std::unique_ptr<LinkGraph>>
849 std::shared_ptr<orc::SymbolStringPool> SSP) {
853 return ELFObj.takeError();
860 auto ABI = validateHeader(
Base, Class, FileName);
862 return ABI.takeError();
863 auto Features =
Base.getFeatures();
865 return Features.takeError();
868 if (*ABI == MipsABI::N32) {
875 std::move(SSP), *ABI, TT, std::move(*Features));
878 std::move(SSP), *ABI, TT, std::move(*Features));
881 std::move(SSP), *ABI, TT, std::move(*Features));
884 std::move(SSP), *ABI, TT, std::move(*Features));
889 std::unique_ptr<JITLinkContext> Ctx) {
891 const Triple &TT =
G->getTargetTriple();
892 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
898 if (
auto MarkLive = Ctx->getMarkLivePass(TT))
904 if (
auto Err = Ctx->modifyPassConfig(*
G, Config))
905 return Ctx->notifyFailed(std::move(Err));
906 if (Ctx->shouldAddDefaultTargetPasses(TT))
908 ELFJITLinker_mips::link(std::move(Ctx), std::move(
G), std::move(Config));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
static bool isMips64EL(const ELFYAML::Object &Obj)
static StringRef getName(Value *V)
This file defines the SmallVector class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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
StringRef getBuffer() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
Manages the enabling and disabling of subtarget specific features.
Target - Wrapper for Target specific information.
const char * getName() const
getName - Get the target name.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
void setAddress(orc::ExecutorAddr Address)
An Addressable with content and edges.
size_t getSize() const
Returns the size of this defined addressable.
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.
std::unique_ptr< LinkGraph > G
LinkGraph building code that's specific to the given ELFT, but common across all architectures.
const ELFFile::Elf_Shdr * SymTabSec
Block * getGraphBlock(ELFSectionIndex SecIndex)
ELFFile::Elf_Shdr_Range Sections
Symbol * getGraphSymbol(ELFSymbolIndex SymIndex)
Represents fixups and constraints in the LinkGraph.
Represents an object file section.
StringRef getFileName() const
Expected< Elf_Sym_Range > symbols(const Elf_Shdr *Sec) const
Expected< Elf_Rela_Range > relas(const Elf_Shdr &Sec) const
Expected< StringRef > getSectionName(const Elf_Shdr &Section, WarningHandler WarnHandler=&defaultWarningHandler) const
Expected< Elf_Rel_Range > rels(const Elf_Shdr &Sec) const
Expected< const Elf_Shdr * > getSection(const Elf_Sym &Sym, const Elf_Shdr *SymTab, DataRegion< Elf_Word > ShndxTable) const
const ELFFile< ELFT > & getELFFile() const
static Expected< std::unique_ptr< ObjectFile > > createELFObjectFile(MemoryBufferRef Object, bool InitContent=true)
Represents an address in the executor process.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ RequestGOTAndTransformToOffsetHi16
Create an exact-address GOT entry and rewrite to its high/low GP offset.
@ Higher16
Fixup[15:0] <- (Target + Addend + 0x80008000) >> 32.
@ RequestGOTAndTransformToOffsetLo16
@ Lo16
Fixup[15:0] <- Target + Addend.
@ Jump26
J/JAL target. The target must be aligned and in the same 256-MiB region.
@ RequestTLSGDAndTransformToOffset16
Create a two-word general/local-dynamic TLS descriptor.
@ DTPRelHi16
Fixup <- Target + Addend - start-of-ORC-TLS-template.
@ Delta32
Fixup <- Target - Fixup + Addend : int32.
@ Abs16
Fixup[15:0] <- Target + Addend : int16.
@ PCHi16
Paired PC-relative high and low halves.
@ PC32
Fixup <- Target - Fixup + Addend : int32.
@ GPRel16
Fixup <- Target + Addend - _gp.
@ Highest16
Fixup[15:0] <- (Target + Addend + 0x800080008000) >> 48.
@ Pointer64
Fixup <- Target + Addend : uint64.
@ GOTPageOffset16
Low offset complementary to a rounded 64-KiB GOT page entry.
@ RequestGOTAndTransformToOffset16
Create an exact-address GOT entry and rewrite to GOTOffset16.
@ RequestTLSLDMAndTransformToOffset16
@ Pointer32
Fixup <- Target + Addend, checked as an unsigned 32-bit pointer.
@ NegGPRelHi16
Compound N32/N64 neg(gp_rel(Target + Addend)) fixups.
@ Delta64
Fixup <- Target - Fixup + Addend : int64.
@ PC18S3
Release-6 compact branch immediate fields.
@ PC16
Fixup[15:0] <- (Target - Fixup + Addend) >> 2 : int16.
@ PagePointer32
Pointer containing the rounded 64-KiB page of Target + Addend.
@ NegDelta32
Fixup <- Fixup - Target + Addend : int32 (used by .eh_frame).
@ GOTOffset16
Fixup <- address of GOT entry - _gp.
@ RequestGOTPageAndTransformToOffset16
Create a rounded 64-KiB page GOT entry and rewrite to GOTOffset16.
@ Hi16
Fixup[15:0] <- (Target + Addend + 0x8000) >> 16.
@ GPDispHi16
_gp_disp high/low expressions. The O32 low half uses Fixup - 4 as P.
LLVM_ABI Symbol & createAnonymousPointer(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget=nullptr, Edge::AddendT InitialAddend=0)
Creates an anonymous pointer, optionally initialized to InitialTarget.
LLVM_ABI Edge::Kind getPointerEdgeKind(const LinkGraph &G)
Returns Pointer32 or Pointer64, according to G's pointer ABI.
LLVM_ABI Symbol & createAnonymousPointerJumpStub(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol)
Creates a stub that materializes PointerSymbol, loads its value into $t9, and jumps to $t9.
LLVM_ABI const char * getEdgeKindName(Edge::Kind K)
constexpr unsigned InstructionSize
LLVM_ABI bool isR6(const LinkGraph &G)
Returns true if G uses the MIPS release-6 ISA.
Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const Symbol *GPSymbol, const Symbol *TLSBaseSymbol)
Apply fixup expression for edge to block content.
void visitExistingEdges(LinkGraph &G, VisitorTs &&...Vs)
For each edge in the given graph, apply a list of visitors to the edge, stopping when the first visit...
LLVM_ABI Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
LLVM_ABI void link_ELF_mips(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
JIT-link an ELF/MIPS graph.
LLVM_ABI Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject_mips(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from an O32, N32, or N64 ELF/MIPS relocatable object.
void visitEdge(LinkGraph &G, Block *B, Edge &E)
Base case for edge-visitors where the visitor-list is empty.
LLVM_ABI StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
MemProt
Describes Read/Write/Exec permissions for memory.
uint32_t read32(const void *P, endianness E)
uint64_t read64(const void *P, endianness E)
uint16_t read16(const void *P, endianness E)
This is an optimization pass for GlobalISel generic memory operations.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PostPrunePasses
Post-prune passes.
LinkGraphPassList PrePrunePasses
Pre-prune passes.