Skip to content

Commit bb00736

Browse files
Ami-zhangSixWeining
authored andcommitted
[RuntimeDyld][LoongArch] Support large code model (llvm#148584)
Co-authored-by: Weining Lu <[email protected]> (cherry picked from commit 4e35ae1)
1 parent 23779f7 commit bb00736

File tree

2 files changed

+93
-6
lines changed

2 files changed

+93
-6
lines changed

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,32 @@ static inline uint32_t extractBits(uint64_t Val, uint32_t Hi, uint32_t Lo) {
728728
return Hi == 63 ? Val >> Lo : (Val & (((1ULL << (Hi + 1)) - 1))) >> Lo;
729729
}
730730

731+
// Calculate the adjusted page delta between dest and PC. The code is copied
732+
// from lld and see comments there for more details.
733+
static uint64_t getLoongArchPageDelta(uint64_t dest, uint64_t pc,
734+
uint32_t type) {
735+
uint64_t pcalau12i_pc;
736+
switch (type) {
737+
case ELF::R_LARCH_PCALA64_LO20:
738+
case ELF::R_LARCH_GOT64_PC_LO20:
739+
pcalau12i_pc = pc - 8;
740+
break;
741+
case ELF::R_LARCH_PCALA64_HI12:
742+
case ELF::R_LARCH_GOT64_PC_HI12:
743+
pcalau12i_pc = pc - 12;
744+
break;
745+
default:
746+
pcalau12i_pc = pc;
747+
break;
748+
}
749+
uint64_t result = (dest & ~0xfffULL) - (pcalau12i_pc & ~0xfffULL);
750+
if (dest & 0x800)
751+
result += 0x1000 - 0x1'0000'0000;
752+
if (result & 0x8000'0000)
753+
result += 0x1'0000'0000;
754+
return result;
755+
}
756+
731757
void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section,
732758
uint64_t Offset,
733759
uint64_t Value, uint32_t Type,
@@ -779,10 +805,7 @@ void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section,
779805
case ELF::R_LARCH_GOT_PC_HI20:
780806
case ELF::R_LARCH_PCALA_HI20: {
781807
uint64_t Target = Value + Addend;
782-
uint64_t TargetPage =
783-
(Target + (Target & 0x800)) & ~static_cast<uint64_t>(0xfff);
784-
uint64_t PCPage = FinalAddress & ~static_cast<uint64_t>(0xfff);
785-
int64_t PageDelta = TargetPage - PCPage;
808+
int64_t PageDelta = getLoongArchPageDelta(Target, FinalAddress, Type);
786809
auto Instr = support::ulittle32_t::ref(TargetPtr);
787810
uint32_t Imm31_12 = extractBits(PageDelta, /*Hi=*/31, /*Lo=*/12) << 5;
788811
Instr = (Instr & 0xfe00001f) | Imm31_12;
@@ -796,6 +819,24 @@ void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section,
796819
Instr = (Instr & 0xffc003ff) | Imm11_0;
797820
break;
798821
}
822+
case ELF::R_LARCH_GOT64_PC_LO20:
823+
case ELF::R_LARCH_PCALA64_LO20: {
824+
uint64_t Target = Value + Addend;
825+
int64_t PageDelta = getLoongArchPageDelta(Target, FinalAddress, Type);
826+
auto Instr = support::ulittle32_t::ref(TargetPtr);
827+
uint32_t Imm51_32 = extractBits(PageDelta, /*Hi=*/51, /*Lo=*/32) << 5;
828+
Instr = (Instr & 0xfe00001f) | Imm51_32;
829+
break;
830+
}
831+
case ELF::R_LARCH_GOT64_PC_HI12:
832+
case ELF::R_LARCH_PCALA64_HI12: {
833+
uint64_t Target = Value + Addend;
834+
int64_t PageDelta = getLoongArchPageDelta(Target, FinalAddress, Type);
835+
auto Instr = support::ulittle32_t::ref(TargetPtr);
836+
uint32_t Imm63_52 = extractBits(PageDelta, /*Hi=*/63, /*Lo=*/52) << 10;
837+
Instr = (Instr & 0xffc003ff) | Imm63_52;
838+
break;
839+
}
799840
case ELF::R_LARCH_ABS_HI20: {
800841
uint64_t Target = Value + Addend;
801842
auto Instr = support::ulittle32_t::ref(TargetPtr);
@@ -1581,7 +1622,9 @@ RuntimeDyldELF::processRelocationRef(
15811622
if (RelType == ELF::R_LARCH_B26 && MemMgr.allowStubAllocation()) {
15821623
resolveLoongArch64Branch(SectionID, Value, RelI, Stubs);
15831624
} else if (RelType == ELF::R_LARCH_GOT_PC_HI20 ||
1584-
RelType == ELF::R_LARCH_GOT_PC_LO12) {
1625+
RelType == ELF::R_LARCH_GOT_PC_LO12 ||
1626+
RelType == ELF::R_LARCH_GOT64_PC_HI12 ||
1627+
RelType == ELF::R_LARCH_GOT64_PC_LO20) {
15851628
uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_LARCH_64);
15861629
resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend,
15871630
RelType);
@@ -2748,7 +2791,9 @@ bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const {
27482791

27492792
if (Arch == Triple::loongarch64)
27502793
return RelTy == ELF::R_LARCH_GOT_PC_HI20 ||
2751-
RelTy == ELF::R_LARCH_GOT_PC_LO12;
2794+
RelTy == ELF::R_LARCH_GOT_PC_LO12 ||
2795+
RelTy == ELF::R_LARCH_GOT64_PC_HI12 ||
2796+
RelTy == ELF::R_LARCH_GOT64_PC_LO20;
27522797

27532798
if (Arch == Triple::x86_64)
27542799
return RelTy == ELF::R_X86_64_GOTPCREL ||

llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/ELF_LoongArch_relocations.s

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
# RUN: llvm-mc --triple=loongarch64 --filetype=obj -o %t/reloc.o %s
33
# RUN: llvm-rtdyld --triple=loongarch64 --verify --check=%s %t/reloc.o \
44
# RUN: --map-section reloc.o,.got=0x21f00 \
5+
# RUN: --map-section reloc.o,.sec.large.pc=0x0000000012345000 \
6+
# RUN: --map-section reloc.o,.sec.large.got=0x44433333abcde000 \
7+
# RUN: --map-section reloc.o,.sec.dummy=0x4443333334567111 \
58
# RUN: --dummy-extern abs=0x0123456789abcdef \
69
# RUN: --dummy-extern external_data=0x1234
710

@@ -100,3 +103,42 @@ named_data:
100103
.quad 0x2222222222222222
101104
.quad 0x3333333333333333
102105
.size named_data, .-named_data
106+
107+
.section .sec.large.pc,"ax"
108+
.globl test_large_pc
109+
test_large_pc:
110+
## Code after link should be:
111+
## 1a44444d pcalau12i $t1, 139810
112+
## 02c4440c addi.d $t0, $zero, 273
113+
## 1666666c lu32i.d $t0, 209715
114+
## 0311118c lu52i.d $t0, $t0, 1092
115+
116+
# rtdyld-check: *{4}(test_large_pc) = 0x1a44444d
117+
pcalau12i $t1, %pc_hi20(.sec.dummy)
118+
# rtdyld-check: *{4}(test_large_pc + 4) = 0x02c4440c
119+
addi.d $t0, $zero, %pc_lo12(.sec.dummy)
120+
# rtdyld-check: *{4}(test_large_pc + 8) = 0x1666666c
121+
lu32i.d $t0, %pc64_lo20(.sec.dummy)
122+
# rtdyld-check: *{4}(test_large_pc + 12) = 0x0311118c
123+
lu52i.d $t0, $t0, %pc64_hi12(.sec.dummy)
124+
125+
.section .sec.large.got,"ax"
126+
.globl test_large_got
127+
test_large_got:
128+
## Code after link should be:
129+
## 1aa8688d pcalau12i $t1, 344900
130+
## 02fc000c addi.d $t0, $zero, -256
131+
## 1799996c lu32i.d $t0, -209717
132+
## 032eed8c lu52i.d $t0, $t0, -1093
133+
134+
# rtdyld-check: *{4}(test_large_got) = 0x1aa8688d
135+
pcalau12i $t1, %got_pc_hi20(external_data)
136+
# rtdyld-check: *{4}(test_large_got + 4) = 0x02fc000c
137+
addi.d $t0, $zero, %got_pc_lo12(external_data)
138+
# rtdyld-check: *{4}(test_large_got + 8) = 0x1799996c
139+
lu32i.d $t0, %got64_pc_lo20(external_data)
140+
# rtdyld-check: *{4}(test_large_got + 12) = 0x032eed8c
141+
lu52i.d $t0, $t0, %got64_pc_hi12(external_data)
142+
143+
.section .sec.dummy,"a"
144+
.word 0

0 commit comments

Comments
 (0)