Skip to content

Commit 03f8e79

Browse files
committed
1 parent 89f09a8 commit 03f8e79

File tree

56 files changed

+1827
-943
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1827
-943
lines changed

lld/ELF/Arch/LoongArch.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ static uint32_t setJ5(uint32_t insn, uint32_t imm) {
168168
return (insn & 0xfffffc1f) | (extractBits(imm, 4, 0) << 5);
169169
}
170170

171+
static uint32_t setK10(uint32_t insn, uint32_t imm) {
172+
return (insn & 0xffc003ff) | (extractBits(imm, 9, 0) << 10);
173+
}
174+
171175
static uint32_t setK12(uint32_t insn, uint32_t imm) {
172176
return (insn & 0xffc003ff) | (extractBits(imm, 11, 0) << 10);
173177
}
@@ -423,6 +427,8 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
423427
// [1]: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=9f482b73f41a9a1bbfb173aad0733d1c824c788a
424428
// [2]: https://github.com/loongson/la-abi-specs/pull/3
425429
return isJirl(read32le(loc)) ? R_PLT : R_ABS;
430+
case R_LARCH_PCADD_LO12_I:
431+
return RE_LOONGARCH_PC_INDIRECT;
426432
case R_LARCH_TLS_DTPREL32:
427433
case R_LARCH_TLS_DTPREL64:
428434
return R_DTPREL;
@@ -453,10 +459,12 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
453459
case R_LARCH_32_PCREL:
454460
case R_LARCH_64_PCREL:
455461
case R_LARCH_PCREL20_S2:
462+
case R_LARCH_PCADD_HI20:
456463
return R_PC;
457464
case R_LARCH_B16:
458465
case R_LARCH_B21:
459466
case R_LARCH_B26:
467+
case R_LARCH_CALL30:
460468
case R_LARCH_CALL36:
461469
return R_PLT_PC;
462470
case R_LARCH_GOT_PC_HI20:
@@ -466,6 +474,9 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
466474
case R_LARCH_TLS_IE64_PC_LO20:
467475
case R_LARCH_TLS_IE64_PC_HI12:
468476
return RE_LOONGARCH_GOT_PAGE_PC;
477+
case R_LARCH_PCADD_GOT_HI20:
478+
case R_LARCH_PCADD_TLS_IE_HI20:
479+
return R_GOT_PC;
469480
case R_LARCH_GOT_PC_LO12:
470481
case R_LARCH_TLS_IE_PC_LO12:
471482
return RE_LOONGARCH_GOT;
@@ -529,6 +540,7 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
529540
case R_LARCH_TLS_DESC_LO12:
530541
case R_LARCH_TLS_DESC64_LO20:
531542
case R_LARCH_TLS_DESC64_HI12:
543+
case R_LARCH_PCADD_TLS_DESC_HI20:
532544
return R_TLSDESC;
533545
case R_LARCH_TLS_DESC_CALL:
534546
return R_TLSDESC_CALL;
@@ -612,6 +624,22 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
612624
write32le(loc, setD10k16(read32le(loc), val >> 2));
613625
return;
614626

627+
case R_LARCH_CALL30: {
628+
// This relocation is designed for adjacent pcaddu12i+jirl pairs that
629+
// are patched in one time.
630+
// The relocation range is [-4G, +4G) (of course must be 4-byte aligned).
631+
if ((int64_t)val != llvm::SignExtend64(val, 32))
632+
reportRangeError(ctx, loc, rel, Twine(val), llvm::minIntN(32),
633+
llvm::maxIntN(32));
634+
checkAlignment(ctx, loc, val, 4, rel);
635+
uint32_t hi20 = extractBits(val, 31, 12);
636+
// Despite the name, the lower part is actually 12 bits with 4-byte aligned.
637+
uint32_t lo10 = extractBits(val, 11, 2);
638+
write32le(loc, setJ20(read32le(loc), hi20));
639+
write32le(loc + 4, setK10(read32le(loc + 4), lo10));
640+
return;
641+
}
642+
615643
case R_LARCH_CALL36: {
616644
// This relocation is designed for adjacent pcaddu18i+jirl pairs that
617645
// are patched in one time. Because of sign extension of these insns'
@@ -655,6 +683,7 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
655683
case R_LARCH_TLS_LE_LO12_R:
656684
case R_LARCH_TLS_DESC_PC_LO12:
657685
case R_LARCH_TLS_DESC_LO12:
686+
case R_LARCH_PCADD_LO12_I:
658687
write32le(loc, setK12(read32le(loc), extractBits(val, 11, 0)));
659688
return;
660689

@@ -674,6 +703,15 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
674703
case R_LARCH_TLS_DESC_HI20:
675704
write32le(loc, setJ20(read32le(loc), extractBits(val, 31, 12)));
676705
return;
706+
case R_LARCH_PCADD_HI20:
707+
case R_LARCH_PCADD_GOT_HI20:
708+
case R_LARCH_PCADD_TLS_IE_HI20:
709+
case R_LARCH_PCADD_TLS_DESC_HI20: {
710+
uint64_t hi = val + 0x800;
711+
checkInt(ctx, loc, SignExtend64(hi, 32) >> 12, 20, rel);
712+
write32le(loc, setJ20(read32le(loc), extractBits(hi, 31, 12)));
713+
return;
714+
}
677715
case R_LARCH_TLS_LE_HI20_R:
678716
write32le(loc, setJ20(read32le(loc), extractBits(val + 0x800, 31, 12)));
679717
return;

lld/ELF/InputSection.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,61 @@ static Relocation *getRISCVPCRelHi20(Ctx &ctx, const InputSectionBase *loSec,
713713
return nullptr;
714714
}
715715

716+
// For RE_LARCH_PC_INDIRECT (R_LARCH_PCADD_LO12_I), the symbol actually
717+
// points the corresponding R_LARCH_PCADD_*_HI20 relocation, and the target VA
718+
// is calculated using PCADD_HI20's symbol.
719+
//
720+
// This function returns the R_LARCH_PCADD_*_HI20 relocation from the
721+
// R_LARCH_PCADD_LO12 relocation.
722+
static Relocation *getLoongArchPCAddHi20(Ctx &ctx,
723+
const InputSectionBase *loSec,
724+
const Relocation &loReloc) {
725+
int64_t addend = loReloc.addend;
726+
Symbol *sym = loReloc.sym;
727+
728+
const Defined *d = cast<Defined>(sym);
729+
if (!d->section) {
730+
Err(ctx) << loSec->getLocation(loReloc.offset)
731+
<< ": R_LARCH_PCADD_LO12 relocation points to an absolute symbol: "
732+
<< sym->getName();
733+
return nullptr;
734+
}
735+
InputSection *hiSec = cast<InputSection>(d->section);
736+
737+
if (hiSec != loSec)
738+
Err(ctx) << loSec->getLocation(loReloc.offset)
739+
<< ": R_LARCH_PCADD_LO12 relocation points to a symbol '"
740+
<< sym->getName() << "' in a different section '" << hiSec->name
741+
<< "'";
742+
743+
if (addend != 0)
744+
Warn(ctx) << loSec->getLocation(loReloc.offset)
745+
<< ": non-zero addend in R_LARCH_PCADD_LO12 relocation to "
746+
<< hiSec->getObjMsg(d->value) << " is ignored";
747+
748+
// Relocations are sorted by offset, so we can use std::equal_range to do
749+
// binary search.
750+
Relocation hiReloc;
751+
hiReloc.offset = d->value + addend;
752+
auto range =
753+
std::equal_range(hiSec->relocs().begin(), hiSec->relocs().end(), hiReloc,
754+
[](const Relocation &lhs, const Relocation &rhs) {
755+
return lhs.offset < rhs.offset;
756+
});
757+
758+
for (auto it = range.first; it != range.second; ++it)
759+
if (it->type == R_LARCH_PCADD_HI20 || it->type == R_LARCH_PCADD_GOT_HI20 ||
760+
it->type == R_LARCH_PCADD_TLS_IE_HI20 ||
761+
it->type == R_LARCH_PCADD_TLS_DESC_HI20)
762+
return &*it;
763+
764+
Err(ctx) << loSec->getLocation(loReloc.offset)
765+
<< ": R_LARCH_PCADD_LO12 relocation points to "
766+
<< hiSec->getObjMsg(d->value)
767+
<< " without an associated R_LARCH_PCADD_HI20 relocation";
768+
return nullptr;
769+
}
770+
716771
// A TLS symbol's virtual address is relative to the TLS segment. Add a
717772
// target-specific adjustment to produce a thread-pointer-relative offset.
718773
static int64_t getTlsTpOffset(Ctx &ctx, const Symbol &s) {
@@ -885,6 +940,11 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
885940
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx));
886941
return 0;
887942
}
943+
case RE_LOONGARCH_PC_INDIRECT: {
944+
if (const Relocation *hiRel = getLoongArchPCAddHi20(ctx, this, r))
945+
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx, a));
946+
return 0;
947+
}
888948
case RE_LOONGARCH_PAGE_PC:
889949
return getLoongArchPageDelta(r.sym->getVA(ctx, a), p, r.type);
890950
case R_PC:

lld/ELF/Relocations.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ static bool isRelExpr(RelExpr expr) {
210210
return oneof<R_PC, R_GOTREL, R_GOTPLTREL, RE_ARM_PCA, RE_MIPS_GOTREL,
211211
RE_PPC64_CALL, RE_PPC64_RELAX_TOC, RE_AARCH64_PAGE_PC,
212212
R_RELAX_GOT_PC, RE_RISCV_PC_INDIRECT, RE_PPC64_RELAX_GOT_PC,
213-
RE_LOONGARCH_PAGE_PC>(expr);
213+
RE_LOONGARCH_PAGE_PC, RE_LOONGARCH_PC_INDIRECT>(expr);
214214
}
215215

216216
static RelExpr toPlt(RelExpr expr) {

lld/ELF/Relocations.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ enum RelExpr {
129129
// also reused for TLS, making the semantics differ from other architectures.
130130
RE_LOONGARCH_GOT,
131131
RE_LOONGARCH_GOT_PAGE_PC,
132+
RE_LOONGARCH_PC_INDIRECT,
132133
RE_LOONGARCH_TLSGD_PAGE_PC,
133134
RE_LOONGARCH_TLSDESC_PAGE_PC,
134135
RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC,

lld/test/ELF/loongarch-call30.s

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# REQUIRES: loongarch
2+
3+
# RUN: rm -rf %t && split-file %s %t
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch32-unknown-elf %t/a.s -o %t/a.o
5+
6+
# RUN: ld.lld %t/a.o --section-start=.text=0x20010 --section-start=.sec.foo=0x21020 -o %t/exe1
7+
# RUN: llvm-objdump --no-show-raw-insn -d %t/exe1 | FileCheck --match-full-lines %s --check-prefix=EXE1
8+
## hi20 = target - pc >> 12 = 0x21020 - 0x20010 >> 12 = 1
9+
## lo12 = target - pc & (1 << 12) - 1 = 0x21020 - 0x20010 & 0xfff = 16
10+
# EXE1: 20010: pcaddu12i $t0, 1
11+
# EXE1-NEXT: 20014: jirl $zero, $t0, 16
12+
13+
# RUN: ld.lld %t/a.o --section-start=.text=0x20010 --section-start=.sec.foo=0x21820 -o %t/exe2
14+
# RUN: llvm-objdump --no-show-raw-insn -d %t/exe2 | FileCheck --match-full-lines %s --check-prefix=EXE2
15+
## hi20 = target - pc >> 12 = 0x21820 - 0x20010 >> 12 = 1
16+
## lo12 = target - pc & (1 << 12) - 1 = 0x21820 - 0x20010 & 0xfff = 2064
17+
# EXE2: 20010: pcaddu12i $t0, 1
18+
# EXE2-NEXT: 20014: jirl $zero, $t0, 2064
19+
20+
# RUN: ld.lld %t/a.o -shared -T %t/a.t -o %t/a.so
21+
# RUN: llvm-readelf -x .got.plt %t/a.so | FileCheck --check-prefix=GOTPLT %s
22+
# RUN: llvm-objdump -d --no-show-raw-insn %t/a.so | FileCheck --check-prefix=SO %s
23+
## PLT should be present in this case.
24+
# SO: Disassembly of section .plt:
25+
# SO: <.plt>:
26+
## foo@plt:
27+
# SO: 1234520: pcaddu12i $t3, 64{{$}}
28+
# SO-NEXT: ld.w $t3, $t3, 444{{$}}
29+
# SO-NEXT: jirl $t1, $t3, 0
30+
# SO-NEXT: nop
31+
32+
# SO: Disassembly of section .text:
33+
# SO: <_start>:
34+
## hi20 = foo@plt - pc >> 12 = 0x1234520 - 0x1274670 >> 12 = -65
35+
## lo18 = foo@plt - pc & (1 << 12) - 1 = 0x1234520 - 0x1274670 & 0xfff = 3760
36+
# SO-NEXT: pcaddu12i $t0, -65{{$}}
37+
# SO-NEXT: jirl $zero, $t0, 3760{{$}}
38+
39+
# GOTPLT: section '.got.plt':
40+
# GOTPLT-NEXT: 0x012746d4 00000000 00000000 00452301
41+
42+
## Impossible case in reality becasue all LoongArch instructions are fixed 4-bytes long.
43+
# RUN: not ld.lld %t/a.o --section-start=.text=0x20000 --section-start=.sec.foo=0x40001 -o /dev/null 2>&1 | \
44+
# RUN: FileCheck -DFILE=%t/a.o --check-prefix=ERROR-ALIGN %s
45+
# ERROR-ALIGN: error: [[FILE]]:(.text+0x0): improper alignment for relocation R_LARCH_CALL30: 0x20001 is not aligned to 4 bytes
46+
47+
#--- a.t
48+
SECTIONS {
49+
.plt 0x1234500: { *(.plt) }
50+
.text 0x1274670: { *(.text) }
51+
}
52+
53+
#--- a.s
54+
.text
55+
.global _start
56+
_start:
57+
.reloc ., R_LARCH_CALL30, foo
58+
pcaddu12i $t0, 0
59+
jirl $zero, $t0, 0
60+
61+
.section .sec.foo,"awx"
62+
.global foo
63+
foo:
64+
ret

lld/test/ELF/loongarch-relax-align.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# REQUIRES: loongarch
22

3-
# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o
4-
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o
3+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s,+relax %s -o %t.32.o
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+32s,+relax %s -o %t.64.o
55
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o -o %t.32
66
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o -o %t.64
77
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.32.o -o %t.32n

lld/test/ELF/loongarch-relax-emit-relocs.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# REQUIRES: loongarch
22
## Test that we can handle --emit-relocs while relaxing.
33

4-
# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s,+relax %s -o %t.32.o
55
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax --defsym ELF64=1 %s -o %t.64.o
66
# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.32.o -o %t.32
77
# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.64.o -o %t.64

lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
# REQUIRES: loongarch
55
# RUN: rm -rf %t && split-file %s %t && cd %t
66

7-
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax symbols.s -o symbols.32.o
7+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax symbols.s -o symbols.32.o
88
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax symbols.s -o symbols.64.o
9-
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax abs.s -o abs.32.o
9+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax abs.s -o abs.32.o
1010
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax abs.s -o abs.64.o
1111

1212
# RUN: ld.lld --shared -Tlinker.t symbols.32.o abs.32.o -o symbols.32.so

lld/test/ELF/loongarch-relax-pc-hi20-lo12.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# REQUIRES: loongarch
22

3-
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %s -o %t.32.o
3+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax %s -o %t.32.o
44
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.64.o
55

66
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -o %t.32

lld/test/ELF/loongarch-tls-gd-edge-case.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
# LA64-REL-NEXT: 00000000000203a8 0000000200000009 R_LARCH_TLS_DTPREL64 0000000000000000 y + 0
2525
# LA64-REL-NEXT: 00000000000203b0 000000020000000b R_LARCH_TLS_TPREL64 0000000000000000 y + 0
2626

27-
# LA32: 101d4: pcalau12i $a0, 16
28-
# LA32-NEXT: ld.w $a0, $a0, 580
27+
# LA32: 101d4: pcaddu12i $a0, 16
28+
# LA32-NEXT: ld.w $a0, $a0, 112
2929
# LA32-NEXT: pcalau12i $a1, 16
3030
# LA32-NEXT: addi.w $a1, $a1, 572
3131

0 commit comments

Comments
 (0)