Skip to content

Commit ee5b76c

Browse files
committed
[𝘀𝗽𝗿] changes to main this commit is based on
Created using spr 1.3.5-bogner [skip ci]
1 parent 390300d commit ee5b76c

File tree

5 files changed

+346
-0
lines changed

5 files changed

+346
-0
lines changed

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,18 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
990990
// and stubs for branches Thumb - ARM and ARM - Thumb.
991991
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc, [pc, #-4]
992992
return Addr + 4;
993+
} else if (Arch == Triple::loongarch64) {
994+
// lu12i.w $t0, %abs_hi20(addr)
995+
// ori $t0, $t0, %abs_lo12(addr)
996+
// lu32i.d $t0, %abs64_lo20(addr)
997+
// lu52i.d $t0, $t0, %abs64_lo12(addr)
998+
// jr $t0
999+
writeBytesUnaligned(0x1400000c, Addr, 4);
1000+
writeBytesUnaligned(0x0380018c, Addr + 4, 4);
1001+
writeBytesUnaligned(0x1600000c, Addr + 8, 4);
1002+
writeBytesUnaligned(0x0300018c, Addr + 12, 4);
1003+
writeBytesUnaligned(0x4c000180, Addr + 16, 4);
1004+
return Addr;
9931005
} else if (IsMipsO32ABI || IsMipsN32ABI) {
9941006
// 0: 3c190000 lui t9,%hi(addr).
9951007
// 4: 27390000 addiu t9,t9,%lo(addr).

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,203 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
645645
}
646646
}
647647

648+
bool RuntimeDyldELF::resolveLoongArch64ShortBranch(
649+
unsigned SectionID, relocation_iterator RelI,
650+
const RelocationValueRef &Value) {
651+
uint64_t Address;
652+
if (Value.SymbolName) {
653+
auto Loc = GlobalSymbolTable.find(Value.SymbolName);
654+
// Don't create direct branch for external symbols.
655+
if (Loc == GlobalSymbolTable.end())
656+
return false;
657+
const auto &SymInfo = Loc->second;
658+
Address =
659+
uint64_t(Sections[SymInfo.getSectionID()].getLoadAddressWithOffset(
660+
SymInfo.getOffset()));
661+
} else {
662+
Address = uint64_t(Sections[Value.SectionID].getLoadAddress());
663+
}
664+
uint64_t Offset = RelI->getOffset();
665+
uint64_t SourceAddress = Sections[SectionID].getLoadAddressWithOffset(Offset);
666+
if (!isInt<28>(Address + Value.Addend - SourceAddress))
667+
return false;
668+
resolveRelocation(Sections[SectionID], Offset, Address, RelI->getType(),
669+
Value.Addend);
670+
return true;
671+
}
672+
673+
void RuntimeDyldELF::resolveLoongArch64Branch(unsigned SectionID,
674+
const RelocationValueRef &Value,
675+
relocation_iterator RelI,
676+
StubMap &Stubs) {
677+
LLVM_DEBUG(dbgs() << "\t\tThis is an LoongArch64 branch relocation.\n");
678+
SectionEntry &Section = Sections[SectionID];
679+
uint64_t Offset = RelI->getOffset();
680+
unsigned RelType = RelI->getType();
681+
// Look for an existing stub.
682+
StubMap::const_iterator i = Stubs.find(Value);
683+
if (i != Stubs.end()) {
684+
resolveRelocation(Section, Offset,
685+
(uint64_t)Section.getAddressWithOffset(i->second),
686+
RelType, 0);
687+
LLVM_DEBUG(dbgs() << " Stub function found\n");
688+
} else if (!resolveLoongArch64ShortBranch(SectionID, RelI, Value)) {
689+
// Create a new stub function.
690+
LLVM_DEBUG(dbgs() << " Create a new stub function\n");
691+
Stubs[Value] = Section.getStubOffset();
692+
uint8_t *StubTargetAddr = createStubFunction(
693+
Section.getAddressWithOffset(Section.getStubOffset()));
694+
RelocationEntry LU12I_W(SectionID, StubTargetAddr - Section.getAddress(),
695+
ELF::R_LARCH_ABS_HI20, Value.Addend);
696+
RelocationEntry ORI(SectionID, StubTargetAddr - Section.getAddress() + 4,
697+
ELF::R_LARCH_ABS_LO12, Value.Addend);
698+
RelocationEntry LU32I_D(SectionID,
699+
StubTargetAddr - Section.getAddress() + 8,
700+
ELF::R_LARCH_ABS64_LO20, Value.Addend);
701+
RelocationEntry LU52I_D(SectionID,
702+
StubTargetAddr - Section.getAddress() + 12,
703+
ELF::R_LARCH_ABS64_HI12, Value.Addend);
704+
if (Value.SymbolName) {
705+
addRelocationForSymbol(LU12I_W, Value.SymbolName);
706+
addRelocationForSymbol(ORI, Value.SymbolName);
707+
addRelocationForSymbol(LU32I_D, Value.SymbolName);
708+
addRelocationForSymbol(LU52I_D, Value.SymbolName);
709+
} else {
710+
addRelocationForSection(LU12I_W, Value.SectionID);
711+
addRelocationForSection(ORI, Value.SectionID);
712+
addRelocationForSection(LU32I_D, Value.SectionID);
713+
addRelocationForSection(LU52I_D, Value.SectionID);
714+
}
715+
resolveRelocation(Section, Offset,
716+
reinterpret_cast<uint64_t>(Section.getAddressWithOffset(
717+
Section.getStubOffset())),
718+
RelType, 0);
719+
Section.advanceStubOffset(getMaxStubSize());
720+
}
721+
}
722+
723+
// Returns extract bits Val[Hi:Lo].
724+
static inline uint32_t extractBits(uint64_t Val, uint32_t Hi, uint32_t Lo) {
725+
return Hi == 63 ? Val >> Lo : (Val & (((1ULL << (Hi + 1)) - 1))) >> Lo;
726+
}
727+
728+
void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section,
729+
uint64_t Offset,
730+
uint64_t Value, uint32_t Type,
731+
int64_t Addend) {
732+
auto *TargetPtr = Section.getAddressWithOffset(Offset);
733+
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
734+
735+
LLVM_DEBUG(dbgs() << "resolveLoongArch64Relocation, LocalAddress: 0x"
736+
<< format("%llx", Section.getAddressWithOffset(Offset))
737+
<< " FinalAddress: 0x" << format("%llx", FinalAddress)
738+
<< " Value: 0x" << format("%llx", Value) << " Type: 0x"
739+
<< format("%x", Type) << " Addend: 0x"
740+
<< format("%llx", Addend) << "\n");
741+
742+
switch (Type) {
743+
default:
744+
report_fatal_error("Relocation type not implemented yet!");
745+
break;
746+
case ELF::R_LARCH_32:
747+
support::ulittle32_t::ref{TargetPtr} =
748+
static_cast<uint32_t>(Value + Addend);
749+
break;
750+
case ELF::R_LARCH_64:
751+
support::ulittle64_t::ref{TargetPtr} = Value + Addend;
752+
break;
753+
case ELF::R_LARCH_32_PCREL:
754+
support::ulittle32_t::ref{TargetPtr} =
755+
static_cast<uint32_t>(Value + Addend - FinalAddress);
756+
break;
757+
case ELF::R_LARCH_B26: {
758+
uint64_t B26 = (Value + Addend - FinalAddress) >> 2;
759+
auto Instr = support::ulittle32_t::ref(TargetPtr);
760+
uint32_t Imm15_0 = extractBits(B26, /*Hi=*/15, /*Lo=*/0) << 10;
761+
uint32_t Imm25_16 = extractBits(B26, /*Hi=*/25, /*Lo=*/16);
762+
Instr = (Instr & 0xfc000000) | Imm15_0 | Imm25_16;
763+
break;
764+
}
765+
case ELF::R_LARCH_CALL36: {
766+
uint64_t Call36 = (Value + Addend - FinalAddress) >> 2;
767+
auto Pcaddu18i = support::ulittle32_t::ref(TargetPtr);
768+
uint32_t Imm35_16 =
769+
extractBits((Call36 + (1UL << 15)), /*Hi=*/35, /*Lo=*/16) << 5;
770+
Pcaddu18i = (Pcaddu18i & 0xfe00001f) | Imm35_16;
771+
auto Jirl = support::ulittle32_t::ref(TargetPtr + 4);
772+
uint32_t Imm15_0 = extractBits(Call36, /*Hi=*/15, /*Lo=*/0) << 10;
773+
Jirl = (Jirl & 0xfc0003ff) | Imm15_0;
774+
break;
775+
}
776+
case ELF::R_LARCH_GOT_PC_HI20:
777+
case ELF::R_LARCH_PCALA_HI20: {
778+
uint64_t Target = Value + Addend;
779+
uint64_t TargetPage =
780+
(Target + (Target & 0x800)) & ~static_cast<uint64_t>(0xfff);
781+
uint64_t PCPage = FinalAddress & ~static_cast<uint64_t>(0xfff);
782+
int64_t PageDelta = TargetPage - PCPage;
783+
auto Instr = support::ulittle32_t::ref(TargetPtr);
784+
uint32_t Imm31_12 = extractBits(PageDelta, /*Hi=*/31, /*Lo=*/12) << 5;
785+
Instr = (Instr & 0xfe00001f) | Imm31_12;
786+
break;
787+
}
788+
case ELF::R_LARCH_GOT_PC_LO12:
789+
case ELF::R_LARCH_PCALA_LO12: {
790+
uint64_t TargetOffset = (Value + Addend) & 0xfff;
791+
auto Instr = support::ulittle32_t::ref(TargetPtr);
792+
uint32_t Imm11_0 = TargetOffset << 10;
793+
Instr = (Instr & 0xffc003ff) | Imm11_0;
794+
break;
795+
}
796+
case ELF::R_LARCH_ABS_HI20: {
797+
uint64_t Target = Value + Addend;
798+
auto Instr = support::ulittle32_t::ref(TargetPtr);
799+
uint32_t Imm31_12 = extractBits(Target, /*Hi=*/31, /*Lo=*/12) << 5;
800+
Instr = (Instr & 0xfe00001f) | Imm31_12;
801+
break;
802+
}
803+
case ELF::R_LARCH_ABS_LO12: {
804+
uint64_t Target = Value + Addend;
805+
auto Instr = support::ulittle32_t::ref(TargetPtr);
806+
uint32_t Imm11_0 = extractBits(Target, /*Hi=*/11, /*Lo=*/0) << 10;
807+
Instr = (Instr & 0xffc003ff) | Imm11_0;
808+
break;
809+
}
810+
case ELF::R_LARCH_ABS64_LO20: {
811+
uint64_t Target = Value + Addend;
812+
auto Instr = support::ulittle32_t::ref(TargetPtr);
813+
uint32_t Imm51_32 = extractBits(Target, /*Hi=*/51, /*Lo=*/32) << 5;
814+
Instr = (Instr & 0xfe00001f) | Imm51_32;
815+
break;
816+
}
817+
case ELF::R_LARCH_ABS64_HI12: {
818+
uint64_t Target = Value + Addend;
819+
auto Instr = support::ulittle32_t::ref(TargetPtr);
820+
uint32_t Imm63_52 = extractBits(Target, /*Hi=*/63, /*Lo=*/52) << 10;
821+
Instr = (Instr & 0xffc003ff) | Imm63_52;
822+
break;
823+
}
824+
case ELF::R_LARCH_ADD32:
825+
support::ulittle32_t::ref{TargetPtr} =
826+
(support::ulittle32_t::ref{TargetPtr} +
827+
static_cast<uint32_t>(Value + Addend));
828+
break;
829+
case ELF::R_LARCH_SUB32:
830+
support::ulittle32_t::ref{TargetPtr} =
831+
(support::ulittle32_t::ref{TargetPtr} -
832+
static_cast<uint32_t>(Value + Addend));
833+
break;
834+
case ELF::R_LARCH_ADD64:
835+
support::ulittle64_t::ref{TargetPtr} =
836+
(support::ulittle64_t::ref{TargetPtr} + Value + Addend);
837+
break;
838+
case ELF::R_LARCH_SUB64:
839+
support::ulittle64_t::ref{TargetPtr} =
840+
(support::ulittle64_t::ref{TargetPtr} - Value - Addend);
841+
break;
842+
}
843+
}
844+
648845
void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) {
649846
if (Arch == Triple::UnknownArch ||
650847
Triple::getArchTypePrefix(Arch) != "mips") {
@@ -1190,6 +1387,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
11901387
resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type,
11911388
(uint32_t)(Addend & 0xffffffffL));
11921389
break;
1390+
case Triple::loongarch64:
1391+
resolveLoongArch64Relocation(Section, Offset, Value, Type, Addend);
1392+
break;
11931393
case Triple::ppc: // Fall through.
11941394
case Triple::ppcle:
11951395
resolvePPC32Relocation(Section, Offset, Value, Type, Addend);
@@ -1515,6 +1715,17 @@ RuntimeDyldELF::processRelocationRef(
15151715
}
15161716
processSimpleRelocation(SectionID, Offset, RelType, Value);
15171717
}
1718+
} else if (Arch == Triple::loongarch64) {
1719+
if (RelType == ELF::R_LARCH_B26 && MemMgr.allowStubAllocation()) {
1720+
resolveLoongArch64Branch(SectionID, Value, RelI, Stubs);
1721+
} else if (RelType == ELF::R_LARCH_GOT_PC_HI20 ||
1722+
RelType == ELF::R_LARCH_GOT_PC_LO12) {
1723+
uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_LARCH_64);
1724+
resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend,
1725+
RelType);
1726+
} else {
1727+
processSimpleRelocation(SectionID, Offset, RelType, Value);
1728+
}
15181729
} else if (IsMipsO32ABI) {
15191730
uint8_t *Placeholder = reinterpret_cast<uint8_t *>(
15201731
computePlaceholderAddress(SectionID, Offset));
@@ -2371,6 +2582,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() {
23712582
case Triple::x86_64:
23722583
case Triple::aarch64:
23732584
case Triple::aarch64_be:
2585+
case Triple::loongarch64:
23742586
case Triple::ppc64:
23752587
case Triple::ppc64le:
23762588
case Triple::systemz:
@@ -2683,6 +2895,10 @@ bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const {
26832895
return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE ||
26842896
RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC;
26852897

2898+
if (Arch == Triple::loongarch64)
2899+
return RelTy == ELF::R_LARCH_GOT_PC_HI20 ||
2900+
RelTy == ELF::R_LARCH_GOT_PC_LO12;
2901+
26862902
if (Arch == Triple::x86_64)
26872903
return RelTy == ELF::R_X86_64_GOTPCREL ||
26882904
RelTy == ELF::R_X86_64_GOTPCRELX ||

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
4646
void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset,
4747
uint32_t Value, uint32_t Type, int32_t Addend);
4848

49+
void resolveLoongArch64Relocation(const SectionEntry &Section,
50+
uint64_t Offset, uint64_t Value,
51+
uint32_t Type, int64_t Addend);
52+
53+
bool resolveLoongArch64ShortBranch(unsigned SectionID,
54+
relocation_iterator RelI,
55+
const RelocationValueRef &Value);
56+
57+
void resolveLoongArch64Branch(unsigned SectionID,
58+
const RelocationValueRef &Value,
59+
relocation_iterator RelI, StubMap &Stubs);
60+
4961
void resolvePPC32Relocation(const SectionEntry &Section, uint64_t Offset,
5062
uint64_t Value, uint32_t Type, int64_t Addend);
5163

@@ -71,6 +83,8 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
7183
return 16;
7284
else if (IsMipsN64ABI)
7385
return 32;
86+
if (Arch == Triple::loongarch64)
87+
return 20; // lu12i.w; ori; lu32i.d; lu52i.d; jr
7488
else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le)
7589
return 44;
7690
else if (Arch == Triple::x86_64)

0 commit comments

Comments
 (0)