Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6084ee7

Browse files
xen0nSixWeining
authored andcommittedJul 25, 2023
[lld][ELF] Support LoongArch
This adds support for the LoongArch ELF psABI v2.00 [1] relocation model to LLD. The deprecated stack-machine-based psABI v1 relocs are not supported. The code is tested by successfully bootstrapping a Gentoo/LoongArch stage3, complete with common GNU userland tools and both the LLVM and GNU toolchains (GNU toolchain is present only for building glibc, LLVM+Clang+LLD are used for the rest). Large programs like QEMU are tested to work as well. [1]: https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html Reviewed By: MaskRay, SixWeining Differential Revision: https://reviews.llvm.org/D138135
1 parent 4cf11d8 commit 6084ee7

29 files changed

+2064
-26
lines changed
 

‎lld/ELF/Arch/LoongArch.cpp

Lines changed: 687 additions & 0 deletions
Large diffs are not rendered by default.

‎lld/ELF/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ add_lld_library(lldELF
2525
Arch/ARM.cpp
2626
Arch/AVR.cpp
2727
Arch/Hexagon.cpp
28+
Arch/LoongArch.cpp
2829
Arch/Mips.cpp
2930
Arch/MipsArchTree.cpp
3031
Arch/MSP430.cpp

‎lld/ELF/Driver.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef emul) {
180180
.Case("elf32lriscv", {ELF32LEKind, EM_RISCV})
181181
.Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC})
182182
.Cases("elf32lppc", "elf32lppclinux", {ELF32LEKind, EM_PPC})
183+
.Case("elf32loongarch", {ELF32LEKind, EM_LOONGARCH})
183184
.Case("elf64btsmip", {ELF64BEKind, EM_MIPS})
184185
.Case("elf64ltsmip", {ELF64LEKind, EM_MIPS})
185186
.Case("elf64lriscv", {ELF64LEKind, EM_RISCV})
@@ -191,6 +192,7 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef emul) {
191192
.Case("elf64_sparc", {ELF64BEKind, EM_SPARCV9})
192193
.Case("msp430elf", {ELF32LEKind, EM_MSP430})
193194
.Case("elf64_amdgpu", {ELF64LEKind, EM_AMDGPU})
195+
.Case("elf64loongarch", {ELF64LEKind, EM_LOONGARCH})
194196
.Default({ELFNoneKind, EM_NONE});
195197

196198
if (ret.first == ELFNoneKind)
@@ -1085,8 +1087,9 @@ static bool getIsRela(opt::InputArgList &args) {
10851087

10861088
// Otherwise use the psABI defined relocation entry format.
10871089
uint16_t m = config->emachine;
1088-
return m == EM_AARCH64 || m == EM_AMDGPU || m == EM_HEXAGON || m == EM_PPC ||
1089-
m == EM_PPC64 || m == EM_RISCV || m == EM_X86_64;
1090+
return m == EM_AARCH64 || m == EM_AMDGPU || m == EM_HEXAGON ||
1091+
m == EM_LOONGARCH || m == EM_PPC || m == EM_PPC64 || m == EM_RISCV ||
1092+
m == EM_X86_64;
10901093
}
10911094

10921095
static void parseClangOption(StringRef opt, const Twine &msg) {
@@ -1693,8 +1696,9 @@ static void setConfigs(opt::InputArgList &args) {
16931696
// have support for reading Elf_Rel addends, so we only enable for a subset.
16941697
#ifndef NDEBUG
16951698
bool checkDynamicRelocsDefault = m == EM_AARCH64 || m == EM_ARM ||
1696-
m == EM_386 || m == EM_MIPS ||
1697-
m == EM_X86_64 || m == EM_RISCV;
1699+
m == EM_386 || m == EM_LOONGARCH ||
1700+
m == EM_MIPS || m == EM_RISCV ||
1701+
m == EM_X86_64;
16981702
#else
16991703
bool checkDynamicRelocsDefault = false;
17001704
#endif

‎lld/ELF/InputFiles.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,9 @@ static uint16_t getBitcodeMachineKind(StringRef path, const Triple &t) {
15751575
return EM_AVR;
15761576
case Triple::hexagon:
15771577
return EM_HEXAGON;
1578+
case Triple::loongarch32:
1579+
case Triple::loongarch64:
1580+
return EM_LOONGARCH;
15781581
case Triple::mips:
15791582
case Triple::mipsel:
15801583
case Triple::mips64:

‎lld/ELF/InputSection.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ static int64_t getTlsTpOffset(const Symbol &s) {
610610
// to allow a signed 16-bit offset to reach 0x1000 of TCB/thread-library
611611
// data and 0xf000 of the program's TLS segment.
612612
return s.getVA(0) + (tls->p_vaddr & (tls->p_align - 1)) - 0x7000;
613+
case EM_LOONGARCH:
613614
case EM_RISCV:
614615
return s.getVA(0) + (tls->p_vaddr & (tls->p_align - 1));
615616

@@ -644,6 +645,14 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
644645
case R_GOT:
645646
case R_RELAX_TLS_GD_TO_IE_ABS:
646647
return sym.getGotVA() + a;
648+
case R_LOONGARCH_GOT:
649+
// The LoongArch TLS GD relocs reuse the R_LARCH_GOT_PC_LO12 reloc type
650+
// for their page offsets. The arithmetics are different in the TLS case
651+
// so we have to duplicate some logic here.
652+
if (sym.hasFlag(NEEDS_TLSGD) && type != R_LARCH_TLS_IE_PC_LO12)
653+
// Like R_LOONGARCH_TLSGD_PAGE_PC but taking the absolute value.
654+
return in.got->getGlobalDynAddr(sym) + a;
655+
return getRelocTargetVA(file, type, a, p, sym, R_GOT);
647656
case R_GOTONLY_PC:
648657
return in.got->getVA() + a - p;
649658
case R_GOTPLTONLY_PC:
@@ -668,6 +677,10 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
668677
case R_GOT_PC:
669678
case R_RELAX_TLS_GD_TO_IE:
670679
return sym.getGotVA() + a - p;
680+
case R_LOONGARCH_GOT_PAGE_PC:
681+
if (sym.hasFlag(NEEDS_TLSGD))
682+
return getLoongArchPageDelta(in.got->getGlobalDynAddr(sym) + a, p);
683+
return getLoongArchPageDelta(sym.getGotVA() + a, p);
671684
case R_MIPS_GOTREL:
672685
return sym.getVA(a) - in.mipsGot->getGp(file);
673686
case R_MIPS_GOT_GP:
@@ -716,6 +729,8 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
716729
*hiRel->sym, hiRel->expr);
717730
return 0;
718731
}
732+
case R_LOONGARCH_PAGE_PC:
733+
return getLoongArchPageDelta(sym.getVA(a), p);
719734
case R_PC:
720735
case R_ARM_PCA: {
721736
uint64_t dest;
@@ -749,6 +764,8 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
749764
case R_PLT_PC:
750765
case R_PPC64_CALL_PLT:
751766
return sym.getPltVA() + a - p;
767+
case R_LOONGARCH_PLT_PAGE_PC:
768+
return getLoongArchPageDelta(sym.getPltVA() + a, p);
752769
case R_PLT_GOTPLT:
753770
return sym.getPltVA() + a - in.gotPlt->getVA();
754771
case R_PPC32_PLTREL:
@@ -809,6 +826,8 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
809826
return in.got->getGlobalDynAddr(sym) + a - in.gotPlt->getVA();
810827
case R_TLSGD_PC:
811828
return in.got->getGlobalDynAddr(sym) + a - p;
829+
case R_LOONGARCH_TLSGD_PAGE_PC:
830+
return getLoongArchPageDelta(in.got->getGlobalDynAddr(sym) + a, p);
812831
case R_TLSLD_GOTPLT:
813832
return in.got->getVA() + in.got->getTlsIndexOff() + a - in.gotPlt->getVA();
814833
case R_TLSLD_GOT:

‎lld/ELF/Relocations.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,8 @@ static bool isAbsoluteValue(const Symbol &sym) {
195195

196196
// Returns true if Expr refers a PLT entry.
197197
static bool needsPlt(RelExpr expr) {
198-
return oneof<R_PLT, R_PLT_PC, R_PLT_GOTPLT, R_PPC32_PLTREL, R_PPC64_CALL_PLT>(
199-
expr);
198+
return oneof<R_PLT, R_PLT_PC, R_PLT_GOTPLT, R_LOONGARCH_PLT_PAGE_PC,
199+
R_PPC32_PLTREL, R_PPC64_CALL_PLT>(expr);
200200
}
201201

202202
// Returns true if Expr refers a GOT entry. Note that this function
@@ -205,20 +205,23 @@ static bool needsPlt(RelExpr expr) {
205205
static bool needsGot(RelExpr expr) {
206206
return oneof<R_GOT, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF,
207207
R_MIPS_GOT_OFF32, R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTPLT,
208-
R_AARCH64_GOT_PAGE>(expr);
208+
R_AARCH64_GOT_PAGE, R_LOONGARCH_GOT, R_LOONGARCH_GOT_PAGE_PC>(
209+
expr);
209210
}
210211

211212
// True if this expression is of the form Sym - X, where X is a position in the
212213
// file (PC, or GOT for example).
213214
static bool isRelExpr(RelExpr expr) {
214215
return oneof<R_PC, R_GOTREL, R_GOTPLTREL, R_MIPS_GOTREL, R_PPC64_CALL,
215216
R_PPC64_RELAX_TOC, R_AARCH64_PAGE_PC, R_RELAX_GOT_PC,
216-
R_RISCV_PC_INDIRECT, R_PPC64_RELAX_GOT_PC>(expr);
217+
R_RISCV_PC_INDIRECT, R_PPC64_RELAX_GOT_PC, R_LOONGARCH_PAGE_PC>(
218+
expr);
217219
}
218220

219-
220221
static RelExpr toPlt(RelExpr expr) {
221222
switch (expr) {
223+
case R_LOONGARCH_PAGE_PC:
224+
return R_LOONGARCH_PLT_PAGE_PC;
222225
case R_PPC64_CALL:
223226
return R_PPC64_CALL_PLT;
224227
case R_PC:
@@ -237,6 +240,8 @@ static RelExpr fromPlt(RelExpr expr) {
237240
case R_PLT_PC:
238241
case R_PPC32_PLTREL:
239242
return R_PC;
243+
case R_LOONGARCH_PLT_PAGE_PC:
244+
return R_LOONGARCH_PAGE_PC;
240245
case R_PPC64_CALL_PLT:
241246
return R_PPC64_CALL;
242247
case R_PLT:
@@ -951,7 +956,9 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
951956
R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
952957
R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTPLTONLY_PC,
953958
R_PLT_PC, R_PLT_GOTPLT, R_PPC32_PLTREL, R_PPC64_CALL_PLT,
954-
R_PPC64_RELAX_TOC, R_RISCV_ADD, R_AARCH64_GOT_PAGE>(e))
959+
R_PPC64_RELAX_TOC, R_RISCV_ADD, R_AARCH64_GOT_PAGE,
960+
R_LOONGARCH_PLT_PAGE_PC, R_LOONGARCH_GOT, R_LOONGARCH_GOT_PAGE_PC>(
961+
e))
955962
return true;
956963

957964
// These never do, except if the entire file is position dependent or if
@@ -1055,7 +1062,9 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
10551062
// for detailed description:
10561063
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
10571064
in.mipsGot->addEntry(*sec->file, sym, addend, expr);
1058-
} else {
1065+
} else if (!sym.isTls() || config->emachine != EM_LOONGARCH) {
1066+
// Many LoongArch TLS relocs reuse the R_LOONGARCH_GOT type, in which
1067+
// case the NEEDS_GOT flag shouldn't get set.
10591068
sym.setFlags(NEEDS_GOT);
10601069
}
10611070
} else if (needsPlt(expr)) {
@@ -1095,7 +1104,8 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
10951104
(isa<EhInputSection>(sec) && config->emachine != EM_MIPS));
10961105
if (canWrite) {
10971106
RelType rel = target->getDynRel(type);
1098-
if (expr == R_GOT || (rel == target->symbolicRel && !sym.isPreemptible)) {
1107+
if (oneof<R_GOT, R_LOONGARCH_GOT>(expr) ||
1108+
(rel == target->symbolicRel && !sym.isPreemptible)) {
10991109
addRelativeReloc<true>(*sec, offset, sym, addend, expr, type);
11001110
return;
11011111
} else if (rel != 0) {
@@ -1247,11 +1257,13 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
12471257
return 1;
12481258
}
12491259

1250-
// ARM, Hexagon and RISC-V do not support GD/LD to IE/LE relaxation. For
1251-
// PPC64, if the file has missing R_PPC64_TLSGD/R_PPC64_TLSLD, disable
1260+
// ARM, Hexagon, LoongArch and RISC-V do not support GD/LD to IE/LE
1261+
// relaxation.
1262+
// For PPC64, if the file has missing R_PPC64_TLSGD/R_PPC64_TLSLD, disable
12521263
// relaxation as well.
12531264
bool toExecRelax = !config->shared && config->emachine != EM_ARM &&
12541265
config->emachine != EM_HEXAGON &&
1266+
config->emachine != EM_LOONGARCH &&
12551267
config->emachine != EM_RISCV &&
12561268
!c.file->ppc64DisableTLSRelax;
12571269

@@ -1268,8 +1280,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
12681280
// being suitable for being dynamically loaded via dlopen. GOT[e0] is the
12691281
// module index, with a special value of 0 for the current module. GOT[e1] is
12701282
// unused. There only needs to be one module index entry.
1271-
if (oneof<R_TLSLD_GOT, R_TLSLD_GOTPLT, R_TLSLD_PC, R_TLSLD_HINT>(
1272-
expr)) {
1283+
if (oneof<R_TLSLD_GOT, R_TLSLD_GOTPLT, R_TLSLD_PC, R_TLSLD_HINT>(expr)) {
12731284
// Local-Dynamic relocs can be relaxed to Local-Exec.
12741285
if (toExecRelax) {
12751286
c.addReloc({target->adjustTlsExpr(type, R_RELAX_TLS_LD_TO_LE), type,
@@ -1300,7 +1311,8 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
13001311
}
13011312

13021313
if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
1303-
R_TLSDESC_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC>(expr)) {
1314+
R_TLSDESC_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC,
1315+
R_LOONGARCH_TLSGD_PAGE_PC>(expr)) {
13041316
if (!toExecRelax) {
13051317
sym.setFlags(NEEDS_TLSGD);
13061318
c.addReloc({expr, type, offset, addend, &sym});
@@ -1320,8 +1332,8 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
13201332
return target->getTlsGdRelaxSkip(type);
13211333
}
13221334

1323-
if (oneof<R_GOT, R_GOTPLT, R_GOT_PC, R_AARCH64_GOT_PAGE_PC, R_GOT_OFF,
1324-
R_TLSIE_HINT>(expr)) {
1335+
if (oneof<R_GOT, R_GOTPLT, R_GOT_PC, R_AARCH64_GOT_PAGE_PC,
1336+
R_LOONGARCH_GOT_PAGE_PC, R_GOT_OFF, R_TLSIE_HINT>(expr)) {
13251337
ctx.hasTlsIe.store(true, std::memory_order_relaxed);
13261338
// Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
13271339
// defined.

‎lld/ELF/Relocations.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@ enum RelExpr {
102102
R_PPC64_RELAX_GOT_PC,
103103
R_RISCV_ADD,
104104
R_RISCV_PC_INDIRECT,
105+
// Same as R_PC but with page-aligned semantics.
106+
R_LOONGARCH_PAGE_PC,
107+
// Same as R_PLT_PC but with page-aligned semantics.
108+
R_LOONGARCH_PLT_PAGE_PC,
109+
// In addition to having page-aligned semantics, LoongArch GOT relocs are
110+
// also reused for TLS, making the semantics differ from other architectures.
111+
R_LOONGARCH_GOT,
112+
R_LOONGARCH_GOT_PAGE_PC,
113+
R_LOONGARCH_TLSGD_PAGE_PC,
105114
};
106115

107116
// Architecture-neutral representation of relocation.

‎lld/ELF/ScriptParser.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,8 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
445445
.Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV})
446446
.Case("elf64-sparc", {ELF64BEKind, EM_SPARCV9})
447447
.Case("elf32-msp430", {ELF32LEKind, EM_MSP430})
448+
.Case("elf32-loongarch", {ELF32LEKind, EM_LOONGARCH})
449+
.Case("elf64-loongarch", {ELF64LEKind, EM_LOONGARCH})
448450
.Default({ELFNoneKind, EM_NONE});
449451
}
450452

‎lld/ELF/Target.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ TargetInfo *elf::getTarget() {
6262
return getAVRTargetInfo();
6363
case EM_HEXAGON:
6464
return getHexagonTargetInfo();
65+
case EM_LOONGARCH:
66+
return getLoongArchTargetInfo();
6567
case EM_MIPS:
6668
switch (config->ekind) {
6769
case ELF32LEKind:

‎lld/ELF/Target.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ TargetInfo *getAMDGPUTargetInfo();
179179
TargetInfo *getARMTargetInfo();
180180
TargetInfo *getAVRTargetInfo();
181181
TargetInfo *getHexagonTargetInfo();
182+
TargetInfo *getLoongArchTargetInfo();
182183
TargetInfo *getMSP430TargetInfo();
183184
TargetInfo *getPPC64TargetInfo();
184185
TargetInfo *getPPCTargetInfo();
@@ -225,6 +226,7 @@ void addPPC64SaveRestore();
225226
uint64_t getPPC64TocBase();
226227
uint64_t getAArch64Page(uint64_t expr);
227228
template <typename ELFT> void writeARMCmseImportLib();
229+
uint64_t getLoongArchPageDelta(uint64_t dest, uint64_t pc);
228230
void riscvFinalizeRelax(int passes);
229231
void mergeRISCVAttributesSections();
230232
void addArmInputSectionMappingSymbols();

‎lld/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ ELF Improvements
5151
* Program header assignment can now be used within ``OVERLAY``. This functionality was accidentally lost in 2020.
5252
(`D150445 <https://reviews.llvm.org/D150445>`_)
5353
* Operators ``^`` and ``^=`` can now be used in linker scripts.
54+
* LoongArch is now supported.
5455
* ``DT_AARCH64_MEMTAG_*`` dynamic tags are now supported.
5556
(`D143769 <https://reviews.llvm.org/D143769>`_)
5657
* AArch32 port now supports BE-8 and BE-32 modes for big-endian.

‎lld/docs/index.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ Features
2222
machine, you can expect that LLD runs more than twice as fast as the GNU
2323
gold linker. Your mileage may vary, though.
2424

25-
- It supports various CPUs/ABIs including AArch64, AMDGPU, ARM, Hexagon, MIPS
26-
32/64 big/little-endian, PowerPC, PowerPC64, RISC-V, SPARC V9, x86-32 and
27-
x86-64. Among these, AArch64, ARM (>= v4), PowerPC, PowerPC64, RISC-V, x86-32
28-
and x86-64 have production quality. MIPS seems decent too.
25+
- It supports various CPUs/ABIs including AArch64, AMDGPU, ARM, Hexagon,
26+
LoongArch, MIPS 32/64 big/little-endian, PowerPC, PowerPC64, RISC-V,
27+
SPARC V9, x86-32 and x86-64. Among these, AArch64, ARM (>= v4), LoongArch,
28+
PowerPC, PowerPC64, RISC-V, x86-32 and x86-64 have production quality.
29+
MIPS seems decent too.
2930

3031
- It is always a cross-linker, meaning that it always supports all the
3132
above targets however it was built. In fact, we don't provide a

‎lld/docs/ld.lld.1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
.\"
55
.\" This man page documents only lld's ELF linking support, obtained originally
66
.\" from FreeBSD.
7-
.Dd Feb 9, 2023
7+
.Dd Jul 25, 2023
88
.Dt LD.LLD 1
99
.Os
1010
.Sh NAME
@@ -27,8 +27,8 @@ It accepts most of the same command line arguments and linker scripts
2727
as GNU linkers.
2828
.Pp
2929
.Nm
30-
currently supports i386, x86-64, ARM, AArch64, PowerPC32, PowerPC64,
31-
MIPS32, MIPS64, RISC-V, AMDGPU, Hexagon and SPARC V9 targets.
30+
currently supports i386, x86-64, ARM, AArch64, LoongArch, PowerPC32,
31+
PowerPC64, MIPS32, MIPS64, RISC-V, AMDGPU, Hexagon and SPARC V9 targets.
3232
.Nm
3333
acts as a Microsoft link.exe-compatible linker if invoked as
3434
.Nm lld-link

‎lld/test/ELF/emulation-loongarch.s

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# REQUIRES: loongarch
2+
3+
# RUN: llvm-mc -filetype=obj -triple=loongarch32 %s -o %t.o
4+
# RUN: ld.lld %t.o -o %t
5+
# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=LA32 %s
6+
# RUN: ld.lld -m elf32loongarch %t.o -o %t
7+
# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=LA32 %s
8+
# RUN: echo 'OUTPUT_FORMAT(elf32-loongarch)' > %t.script
9+
# RUN: ld.lld %t.script %t.o -o %t
10+
# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=LA32 %s
11+
12+
# LA32: ElfHeader {
13+
# LA32-NEXT: Ident {
14+
# LA32-NEXT: Magic: (7F 45 4C 46)
15+
# LA32-NEXT: Class: 32-bit (0x1)
16+
# LA32-NEXT: DataEncoding: LittleEndian (0x1)
17+
# LA32-NEXT: FileVersion: 1
18+
# LA32-NEXT: OS/ABI: SystemV (0x0)
19+
# LA32-NEXT: ABIVersion: 0
20+
# LA32-NEXT: Unused: (00 00 00 00 00 00 00)
21+
# LA32-NEXT: }
22+
# LA32-NEXT: Type: Executable (0x2)
23+
# LA32-NEXT: Machine: EM_LOONGARCH (0x102)
24+
# LA32-NEXT: Version: 1
25+
# LA32-NEXT: Entry:
26+
# LA32-NEXT: ProgramHeaderOffset: 0x34
27+
# LA32-NEXT: SectionHeaderOffset:
28+
# LA32-NEXT: Flags [ (0x43)
29+
# LA32-NEXT: EF_LOONGARCH_ABI_DOUBLE_FLOAT (0x3)
30+
# LA32-NEXT: EF_LOONGARCH_OBJABI_V1 (0x40)
31+
# LA32-NEXT: ]
32+
# LA32-NEXT: HeaderSize: 52
33+
# LA32-NEXT: ProgramHeaderEntrySize: 32
34+
# LA32-NEXT: ProgramHeaderCount:
35+
# LA32-NEXT: SectionHeaderEntrySize: 40
36+
# LA32-NEXT: SectionHeaderCount:
37+
# LA32-NEXT: StringTableSectionIndex:
38+
# LA32-NEXT: }
39+
40+
# RUN: llvm-mc -filetype=obj -triple=loongarch64 %s -o %t.o
41+
# RUN: ld.lld %t.o -o %t
42+
# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=LA64 %s
43+
# RUN: ld.lld -m elf64loongarch %t.o -o %t
44+
# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=LA64 %s
45+
# RUN: echo 'OUTPUT_FORMAT(elf64-loongarch)' > %t.script
46+
# RUN: ld.lld %t.script %t.o -o %t
47+
# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=LA64 %s
48+
49+
# LA64: ElfHeader {
50+
# LA64-NEXT: Ident {
51+
# LA64-NEXT: Magic: (7F 45 4C 46)
52+
# LA64-NEXT: Class: 64-bit (0x2)
53+
# LA64-NEXT: DataEncoding: LittleEndian (0x1)
54+
# LA64-NEXT: FileVersion: 1
55+
# LA64-NEXT: OS/ABI: SystemV (0x0)
56+
# LA64-NEXT: ABIVersion: 0
57+
# LA64-NEXT: Unused: (00 00 00 00 00 00 00)
58+
# LA64-NEXT: }
59+
# LA64-NEXT: Type: Executable (0x2)
60+
# LA64-NEXT: Machine: EM_LOONGARCH (0x102)
61+
# LA64-NEXT: Version: 1
62+
# LA64-NEXT: Entry:
63+
# LA64-NEXT: ProgramHeaderOffset: 0x40
64+
# LA64-NEXT: SectionHeaderOffset:
65+
# LA64-NEXT: Flags [ (0x43)
66+
# LA64-NEXT: EF_LOONGARCH_ABI_DOUBLE_FLOAT (0x3)
67+
# LA64-NEXT: EF_LOONGARCH_OBJABI_V1 (0x40)
68+
# LA64-NEXT: ]
69+
# LA64-NEXT: HeaderSize: 64
70+
# LA64-NEXT: ProgramHeaderEntrySize: 56
71+
# LA64-NEXT: ProgramHeaderCount:
72+
# LA64-NEXT: SectionHeaderEntrySize: 64
73+
# LA64-NEXT: SectionHeaderCount:
74+
# LA64-NEXT: StringTableSectionIndex:
75+
# LA64-NEXT: }
76+
77+
.globl _start
78+
_start:

‎lld/test/ELF/loongarch-abs64.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: llvm-mc --filetype=obj --triple=loongarch64-unknown-elf %s -o %t.la64.o
4+
5+
# RUN: ld.lld %t.la64.o --defsym foo=0 --defsym bar=42 -o %t.la64.1
6+
# RUN: llvm-objdump --no-show-raw-insn -d %t.la64.1 | FileCheck --check-prefix=CASE1 %s
7+
# CASE1: lu12i.w $a0, 0
8+
# CASE1-NEXT: ori $a0, $a0, 0
9+
# CASE1-NEXT: lu32i.d $a0, 0
10+
# CASE1-NEXT: lu52i.d $a0, $a0, 0
11+
# CASE1-NEXT: lu12i.w $a1, 0
12+
# CASE1-NEXT: ori $a1, $a1, 42
13+
# CASE1-NEXT: lu32i.d $a1, 0
14+
# CASE1-NEXT: lu52i.d $a1, $a1, 0
15+
16+
# RUN: ld.lld %t.la64.o --defsym foo=0x12345678 --defsym bar=0x87654321 -o %t.la64.2
17+
# RUN: llvm-objdump --no-show-raw-insn -d %t.la64.2 | FileCheck --check-prefix=CASE2 %s
18+
# CASE2: lu12i.w $a0, 74565
19+
# CASE2-NEXT: ori $a0, $a0, 1656
20+
# CASE2-NEXT: lu32i.d $a0, 0
21+
# CASE2-NEXT: lu52i.d $a0, $a0, 0
22+
# CASE2-NEXT: lu12i.w $a1, -493996
23+
# CASE2-NEXT: ori $a1, $a1, 801
24+
# CASE2-NEXT: lu32i.d $a1, 0
25+
# CASE2-NEXT: lu52i.d $a1, $a1, 0
26+
27+
# RUN: ld.lld %t.la64.o --defsym foo=0x12345fedcb678 --defsym bar=0xfedcb12345000 -o %t.la64.3
28+
# RUN: llvm-objdump --no-show-raw-insn -d %t.la64.3 | FileCheck --check-prefix=CASE3 %s
29+
# CASE3: lu12i.w $a0, -4661
30+
# CASE3-NEXT: ori $a0, $a0, 1656
31+
# CASE3-NEXT: lu32i.d $a0, 74565
32+
# CASE3-NEXT: lu52i.d $a0, $a0, 0
33+
# CASE3-NEXT: lu12i.w $a1, 74565
34+
# CASE3-NEXT: ori $a1, $a1, 0
35+
# CASE3-NEXT: lu32i.d $a1, -4661
36+
# CASE3-NEXT: lu52i.d $a1, $a1, 0
37+
38+
# RUN: ld.lld %t.la64.o --defsym foo=0xfffffeeeeeddd --defsym bar=0xfff00000f1111222 -o %t.la64.4
39+
# RUN: llvm-objdump --no-show-raw-insn -d %t.la64.4 | FileCheck --check-prefix=CASE4 %s
40+
# CASE4: lu12i.w $a0, -69906
41+
# CASE4-NEXT: ori $a0, $a0, 3549
42+
# CASE4-NEXT: lu32i.d $a0, -1
43+
# CASE4-NEXT: lu52i.d $a0, $a0, 0
44+
# CASE4-NEXT: lu12i.w $a1, -61167
45+
# CASE4-NEXT: ori $a1, $a1, 546
46+
# CASE4-NEXT: lu32i.d $a1, 0
47+
# CASE4-NEXT: lu52i.d $a1, $a1, -1
48+
49+
.global _start
50+
51+
_start:
52+
1:
53+
lu12i.w $a0, %abs_hi20(foo)
54+
.reloc 1b, R_LARCH_MARK_LA, foo
55+
ori $a0, $a0, %abs_lo12(foo)
56+
lu32i.d $a0, %abs64_lo20(foo)
57+
lu52i.d $a0, $a0, %abs64_hi12(foo)
58+
59+
2:
60+
lu12i.w $a1, %abs_hi20(bar)
61+
.reloc 1b, R_LARCH_MARK_LA, bar
62+
ori $a1, $a1, %abs_lo12(bar)
63+
lu32i.d $a1, %abs64_lo20(bar)
64+
lu52i.d $a1, $a1, %abs64_hi12(bar)

‎lld/test/ELF/loongarch-add-sub.s

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# REQUIRES: loongarch
2+
3+
# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-elf %s -o %t.la64.o
4+
5+
# RUN: ld.lld --section-start=.rodata=0x1234567890 --section-start=.text=0x9876543210 %t.la64.o -o %t.la64
6+
# RUN: llvm-readelf -x .rodata %t.la64 | FileCheck --check-prefix=CHECK %s
7+
# CHECK: section '.rodata':
8+
# CHECK-NEXT: 0x1234567890 10325476 98badcfe 80b9fd41 86000000
9+
# CHECK-NEXT: 0x12345678a0 80b9fd41 80b980
10+
11+
.global _start
12+
13+
_start:
14+
1:
15+
break 0
16+
17+
.rodata
18+
2:
19+
.dword 0xfedcba9876543210
20+
21+
foo:
22+
.dword 0
23+
.reloc foo, R_LARCH_ADD64, 1b
24+
.reloc foo, R_LARCH_SUB64, 2b
25+
bar:
26+
.word 0
27+
.reloc bar, R_LARCH_ADD32, 1b
28+
.reloc bar, R_LARCH_SUB32, 2b
29+
baz:
30+
.short 0
31+
.reloc baz, R_LARCH_ADD16, 1b
32+
.reloc baz, R_LARCH_SUB16, 2b
33+
quux:
34+
.byte 0
35+
.reloc quux, R_LARCH_ADD8, 1b
36+
.reloc quux, R_LARCH_SUB8, 2b

‎lld/test/ELF/loongarch-branch.s

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# REQUIRES: loongarch
2+
3+
# RUN: llvm-mc --filetype=obj --triple=loongarch32-unknown-elf %s -o %t.la32.o
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-elf %s -o %t.la64.o
5+
6+
# RUN: ld.lld %t.la32.o --defsym foo16=b16+4 --defsym bar16=b16 --defsym foo21=b21+4 --defsym bar21=b21 --defsym foo26=b26+4 --defsym bar26=b26 -o %t.la32
7+
# RUN: ld.lld %t.la64.o --defsym foo16=b16+4 --defsym bar16=b16 --defsym foo21=b21+4 --defsym bar21=b21 --defsym foo26=b26+4 --defsym bar26=b26 -o %t.la64
8+
# RUN: llvm-objdump --no-show-raw-insn -d %t.la32 | FileCheck %s --check-prefix=CHECK
9+
# RUN: llvm-objdump --no-show-raw-insn -d %t.la64 | FileCheck %s --check-prefix=CHECK
10+
# CHECK: beq $zero, $zero, 4
11+
# CHECK: bne $zero, $zero, -4
12+
# CHECK: beqz $s8, 4
13+
# CHECK: bnez $s8, -4
14+
# CHECK: b 4
15+
# CHECK: bl -4
16+
17+
# RUN: ld.lld %t.la32.o --defsym foo16=b16+0x1fffc --defsym bar16=b16+4-0x20000 --defsym foo21=b21+0x3ffffc --defsym bar21=b21+4-0x400000 --defsym foo26=b26+0x7fffffc --defsym bar26=b26+4-0x8000000 -o %t.la32.limits
18+
# RUN: ld.lld %t.la64.o --defsym foo16=b16+0x1fffc --defsym bar16=b16+4-0x20000 --defsym foo21=b21+0x3ffffc --defsym bar21=b21+4-0x400000 --defsym foo26=b26+0x7fffffc --defsym bar26=b26+4-0x8000000 -o %t.la64.limits
19+
# RUN: llvm-objdump --no-show-raw-insn -d %t.la32.limits | FileCheck --check-prefix=LIMITS %s
20+
# RUN: llvm-objdump --no-show-raw-insn -d %t.la64.limits | FileCheck --check-prefix=LIMITS %s
21+
# LIMITS: beq $zero, $zero, 131068
22+
# LIMITS-NEXT: bne $zero, $zero, -131072
23+
# LIMITS: beqz $s8, 4194300
24+
# LIMITS-NEXT: bnez $s8, -4194304
25+
# LIMITS: b 134217724
26+
# LIMITS-NEXT: bl -134217728
27+
28+
# RUN: not ld.lld %t.la32.o --defsym foo16=b16+0x20000 --defsym bar16=b16+4-0x20004 --defsym foo21=b21+0x400000 --defsym bar21=b21+4-0x400004 --defsym foo26=b26+0x8000000 --defsym bar26=b26+4-0x8000004 -o /dev/null 2>&1 | FileCheck -DFILE=%t.la32.o --check-prefix=ERROR-RANGE %s
29+
# RUN: not ld.lld %t.la64.o --defsym foo16=b16+0x20000 --defsym bar16=b16+4-0x20004 --defsym foo21=b21+0x400000 --defsym bar21=b21+4-0x400004 --defsym foo26=b26+0x8000000 --defsym bar26=b26+4-0x8000004 -o /dev/null 2>&1 | FileCheck -DFILE=%t.la64.o --check-prefix=ERROR-RANGE %s
30+
# ERROR-RANGE: error: [[FILE]]:(.text+0x0): relocation R_LARCH_B16 out of range: 131072 is not in [-131072, 131071]; references 'foo16'
31+
# ERROR-RANGE: error: [[FILE]]:(.text+0x4): relocation R_LARCH_B16 out of range: -131076 is not in [-131072, 131071]; references 'bar16'
32+
# ERROR-RANGE: error: [[FILE]]:(.text+0x8): relocation R_LARCH_B21 out of range: 4194304 is not in [-4194304, 4194303]; references 'foo21'
33+
# ERROR-RANGE: error: [[FILE]]:(.text+0xc): relocation R_LARCH_B21 out of range: -4194308 is not in [-4194304, 4194303]; references 'bar21'
34+
# ERROR-RANGE: error: [[FILE]]:(.text+0x10): relocation R_LARCH_B26 out of range: 134217728 is not in [-134217728, 134217727]; references 'foo26'
35+
# ERROR-RANGE: error: [[FILE]]:(.text+0x14): relocation R_LARCH_B26 out of range: -134217732 is not in [-134217728, 134217727]; references 'bar26'
36+
37+
# RUN: not ld.lld %t.la32.o --defsym foo16=b16+1 --defsym bar16=b16-1 --defsym foo21=b21+1 --defsym bar21=b21-1 --defsym foo26=b26+1 --defsym bar26=b26-1 -o /dev/null 2>&1 | FileCheck -DFILE=%t.la32.o --check-prefix=ERROR-ALIGN-1 %s
38+
# RUN: not ld.lld %t.la64.o --defsym foo16=b16+1 --defsym bar16=b16-1 --defsym foo21=b21+1 --defsym bar21=b21-1 --defsym foo26=b26+1 --defsym bar26=b26-1 -o /dev/null 2>&1 | FileCheck -DFILE=%t.la64.o --check-prefix=ERROR-ALIGN-1 %s
39+
# ERROR-ALIGN-1: error: [[FILE]]:(.text+0x0): improper alignment for relocation R_LARCH_B16: 0x1 is not aligned to 4 bytes
40+
# ERROR-ALIGN-1-NEXT: error: [[FILE]]:(.text+0x4): improper alignment for relocation R_LARCH_B16: 0xFFFFFFFFFFFFFFFB is not aligned to 4 bytes
41+
# ERROR-ALIGN-1-NEXT: error: [[FILE]]:(.text+0x8): improper alignment for relocation R_LARCH_B21: 0x1 is not aligned to 4 bytes
42+
# ERROR-ALIGN-1-NEXT: error: [[FILE]]:(.text+0xc): improper alignment for relocation R_LARCH_B21: 0xFFFFFFFFFFFFFFFB is not aligned to 4 bytes
43+
# ERROR-ALIGN-1-NEXT: error: [[FILE]]:(.text+0x10): improper alignment for relocation R_LARCH_B26: 0x1 is not aligned to 4 bytes
44+
# ERROR-ALIGN-1-NEXT: error: [[FILE]]:(.text+0x14): improper alignment for relocation R_LARCH_B26: 0xFFFFFFFFFFFFFFFB is not aligned to 4 bytes
45+
46+
# RUN: not ld.lld %t.la32.o --defsym foo16=b16+2 --defsym bar16=b16-2 --defsym foo21=b21+2 --defsym bar21=b21-2 --defsym foo26=b26+2 --defsym bar26=b26-2 -o /dev/null 2>&1 | FileCheck -DFILE=%t.la32.o --check-prefix=ERROR-ALIGN-2 %s
47+
# RUN: not ld.lld %t.la64.o --defsym foo16=b16+2 --defsym bar16=b16-2 --defsym foo21=b21+2 --defsym bar21=b21-2 --defsym foo26=b26+2 --defsym bar26=b26-2 -o /dev/null 2>&1 | FileCheck -DFILE=%t.la64.o --check-prefix=ERROR-ALIGN-2 %s
48+
# ERROR-ALIGN-2: error: [[FILE]]:(.text+0x0): improper alignment for relocation R_LARCH_B16: 0x2 is not aligned to 4 bytes
49+
# ERROR-ALIGN-2-NEXT: error: [[FILE]]:(.text+0x4): improper alignment for relocation R_LARCH_B16: 0xFFFFFFFFFFFFFFFA is not aligned to 4 bytes
50+
# ERROR-ALIGN-2-NEXT: error: [[FILE]]:(.text+0x8): improper alignment for relocation R_LARCH_B21: 0x2 is not aligned to 4 bytes
51+
# ERROR-ALIGN-2-NEXT: error: [[FILE]]:(.text+0xc): improper alignment for relocation R_LARCH_B21: 0xFFFFFFFFFFFFFFFA is not aligned to 4 bytes
52+
# ERROR-ALIGN-2-NEXT: error: [[FILE]]:(.text+0x10): improper alignment for relocation R_LARCH_B26: 0x2 is not aligned to 4 bytes
53+
# ERROR-ALIGN-2-NEXT: error: [[FILE]]:(.text+0x14): improper alignment for relocation R_LARCH_B26: 0xFFFFFFFFFFFFFFFA is not aligned to 4 bytes
54+
55+
.global _start
56+
.global b16
57+
.global b21
58+
.global b26
59+
_start:
60+
b16:
61+
beq $zero, $zero, foo16
62+
bne $zero, $zero, bar16
63+
b21:
64+
beqz $s8, foo21
65+
bnez $s8, bar21
66+
b26:
67+
b foo26
68+
bl bar26

‎lld/test/ELF/loongarch-interlink.test

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t
3+
4+
# RUN: yaml2obj %t/blob.yaml -o %t/blob.o
5+
# RUN: yaml2obj %t/v0-lp64d.yaml -o %t/v0-lp64d.o
6+
# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-gnu %t/start.s -o %t/v1-lp64d.o
7+
# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-gnusf %t/start.s -o %t/v1-lp64s.o
8+
# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-gnu %t/bar.s -o %t/v1-b-lp64d.o
9+
10+
## Check that binary input results in e_flags=0 output.
11+
# RUN: ld.lld -m elf64loongarch -b binary %t/blob.bin -o %t/blob.out
12+
# RUN: llvm-readobj -h %t/blob.out | FileCheck --check-prefix=EMPTY %s
13+
# EMPTY: Flags [
14+
# EMPTY-NEXT: ]
15+
16+
## Check that interlink between e_flags=0 and normal input (that contain code)
17+
## is allowed.
18+
## Also check that the e_flags logic work as intended regardless of input file
19+
## order.
20+
# RUN: ld.lld %t/blob.o %t/v1-lp64d.o -o %t/v1-lp64d.out
21+
# RUN: ld.lld %t/v1-lp64s.o %t/blob.o -o %t/v1-lp64s.out
22+
# RUN: llvm-readobj -h %t/v1-lp64d.out | FileCheck --check-prefix=V1-LP64D %s
23+
# RUN: llvm-readobj -h %t/v1-lp64s.out | FileCheck --check-prefix=V1-LP64S %s
24+
# V1-LP64D: Flags [ (0x43)
25+
# V1-LP64S: Flags [ (0x41)
26+
27+
## Check that interlink between different ABIs is disallowed.
28+
# RUN: not ld.lld %t/v1-lp64s.o %t/v1-b-lp64d.o -o /dev/null 2>&1 | FileCheck -DFILE1=%t/v1-b-lp64d.o -DFILE2=%t/v1-lp64s.o --check-prefix=INTERLINK-ERR %s
29+
# INTERLINK-ERR: error: [[FILE1]]: cannot link object files with different ABI from [[FILE2]]
30+
31+
## Check that interlink between different object ABI versions is disallowed.
32+
# RUN: not ld.lld %t/v0-lp64d.o %t/v1-b-lp64d.o %t/blob.o -o /dev/null 2>&1 | FileCheck -DFILE=%t/v0-lp64d.o --check-prefix=VERSION-ERR %s
33+
# VERSION-ERR: error: [[FILE]]: unsupported object file ABI version
34+
35+
#--- blob.bin
36+
BLOB
37+
38+
#--- blob.yaml
39+
--- !ELF
40+
FileHeader:
41+
Class: ELFCLASS64
42+
Data: ELFDATA2LSB
43+
Type: ET_REL
44+
Machine: EM_LOONGARCH
45+
SectionHeaderStringTable: .strtab
46+
Sections:
47+
- Name: .data
48+
Type: SHT_PROGBITS
49+
Flags: [ SHF_WRITE, SHF_ALLOC ]
50+
AddressAlign: 0x1
51+
Content: 424C4F42
52+
Symbols:
53+
- Name: blob
54+
Section: .data
55+
Binding: STB_GLOBAL
56+
57+
#--- v0-lp64d.yaml
58+
--- !ELF
59+
FileHeader:
60+
Class: ELFCLASS64
61+
Data: ELFDATA2LSB
62+
Type: ET_REL
63+
Machine: EM_LOONGARCH
64+
Flags: [ EF_LOONGARCH_ABI_DOUBLE_FLOAT ]
65+
SectionHeaderStringTable: .strtab
66+
Sections:
67+
- Name: .text
68+
Type: SHT_PROGBITS
69+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
70+
AddressAlign: 0x4
71+
Content: 0000a002
72+
73+
#--- start.s
74+
.global _start
75+
_start:
76+
la $a0, blob
77+
ld.b $a0, $a0, 0
78+
li.w $a7, 94
79+
syscall 0
80+
81+
#--- bar.s
82+
bar:
83+
move $a0, $zero
84+
ret

‎lld/test/ELF/loongarch-pc-aligned.s

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t
3+
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/a.s -o %t/a.la32.o
5+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/a.s -o %t/a.la64.o
6+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/extreme.s -o %t/extreme.o
7+
8+
# RUN: ld.lld %t/a.la32.o --section-start=.rodata=0x11000 --section-start=.text=0x11ffc -o %t/case1.la32
9+
# RUN: ld.lld %t/a.la64.o --section-start=.rodata=0x11000 --section-start=.text=0x11ffc -o %t/case1.la64
10+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case1.la32 | FileCheck %s --check-prefix=CASE1
11+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case1.la64 | FileCheck %s --check-prefix=CASE1
12+
# CASE1: pcalau12i $a0, 0
13+
# CASE1-NEXT: ld.w $a0, $a0, 0
14+
15+
# RUN: ld.lld %t/a.la32.o --section-start=.rodata=0x11000 --section-start=.text=0x12000 -o %t/case2.la32
16+
# RUN: ld.lld %t/a.la64.o --section-start=.rodata=0x11000 --section-start=.text=0x12000 -o %t/case2.la64
17+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case2.la32 | FileCheck %s --check-prefix=CASE2
18+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case2.la64 | FileCheck %s --check-prefix=CASE2
19+
# CASE2: pcalau12i $a0, -1
20+
# CASE2-NEXT: ld.w $a0, $a0, 0
21+
22+
# RUN: ld.lld %t/a.la32.o --section-start=.rodata=0x117ff --section-start=.text=0x12000 -o %t/case3.la32
23+
# RUN: ld.lld %t/a.la64.o --section-start=.rodata=0x117ff --section-start=.text=0x12000 -o %t/case3.la64
24+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case3.la32 | FileCheck %s --check-prefix=CASE3
25+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case3.la64 | FileCheck %s --check-prefix=CASE3
26+
# CASE3: pcalau12i $a0, -1
27+
# CASE3-NEXT: ld.w $a0, $a0, 2047
28+
29+
# RUN: ld.lld %t/a.la32.o --section-start=.rodata=0x11800 --section-start=.text=0x12000 -o %t/case4.la32
30+
# RUN: ld.lld %t/a.la64.o --section-start=.rodata=0x11800 --section-start=.text=0x12000 -o %t/case4.la64
31+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case4.la32 | FileCheck %s --check-prefix=CASE4
32+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case4.la64 | FileCheck %s --check-prefix=CASE4
33+
# CASE4: pcalau12i $a0, 0
34+
# CASE4-NEXT: ld.w $a0, $a0, -2048
35+
36+
# RUN: ld.lld %t/a.la32.o --section-start=.rodata=0x12004 --section-start=.text=0x11ffc -o %t/case5.la32
37+
# RUN: ld.lld %t/a.la64.o --section-start=.rodata=0x12004 --section-start=.text=0x11ffc -o %t/case5.la64
38+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case5.la32 | FileCheck %s --check-prefix=CASE5
39+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case5.la64 | FileCheck %s --check-prefix=CASE5
40+
# CASE5: pcalau12i $a0, 1
41+
# CASE5-NEXT: ld.w $a0, $a0, 4
42+
43+
# RUN: ld.lld %t/a.la32.o --section-start=.rodata=0x12800 --section-start=.text=0x11ffc -o %t/case6.la32
44+
# RUN: ld.lld %t/a.la64.o --section-start=.rodata=0x12800 --section-start=.text=0x11ffc -o %t/case6.la64
45+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case6.la32 | FileCheck %s --check-prefix=CASE6
46+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case6.la64 | FileCheck %s --check-prefix=CASE6
47+
# CASE6: pcalau12i $a0, 2
48+
# CASE6-NEXT: ld.w $a0, $a0, -2048
49+
50+
# RUN: ld.lld %t/a.la32.o --section-start=.rodata=0x7ffff123 --section-start=.text=0x0 -o %t/case7.la32
51+
# RUN: ld.lld %t/a.la64.o --section-start=.rodata=0x7ffff123 --section-start=.text=0x0 -o %t/case7.la64
52+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case7.la32 | FileCheck %s --check-prefix=CASE7
53+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case7.la64 | FileCheck %s --check-prefix=CASE7
54+
# CASE7: pcalau12i $a0, 524287
55+
# CASE7-NEXT: ld.w $a0, $a0, 291
56+
57+
# RUN: ld.lld %t/a.la32.o --section-start=.rodata=0x7ffffabc --section-start=.text=0x0 -o %t/case8.la32
58+
# RUN: ld.lld %t/a.la64.o --section-start=.rodata=0x7ffffabc --section-start=.text=0x0 -o %t/case8.la64
59+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case8.la32 | FileCheck %s --check-prefix=CASE8
60+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case8.la64 | FileCheck %s --check-prefix=CASE8
61+
# CASE8: pcalau12i $a0, -524288
62+
# CASE8-NEXT: ld.w $a0, $a0, -1348
63+
64+
# RUN: ld.lld %t/a.la32.o --section-start=.rodata=0x10123 --section-start=.text=0x80010000 -o %t/case9.la32
65+
# RUN: ld.lld %t/a.la64.o --section-start=.rodata=0x10123 --section-start=.text=0x80010000 -o %t/case9.la64
66+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case9.la32 | FileCheck %s --check-prefix=CASE9
67+
# RUN: llvm-objdump -d --no-show-raw-insn %t/case9.la64 | FileCheck %s --check-prefix=CASE9
68+
# CASE9: pcalau12i $a0, -524288
69+
# CASE9-NEXT: ld.w $a0, $a0, 291
70+
71+
## page delta = 0x4443333322222000, page offset = 0x111
72+
## %pc_lo12 = 0x111 = 273
73+
## %pc_hi20 = 0x22222 = 139810
74+
## %pc64_lo20 = 0x33333 = 209715
75+
## %pc64_hi12 = 0x444 = 1092
76+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0x4443333334567111 --section-start=.text=0x0000000012345678 -o %t/extreme0
77+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme0 | FileCheck %s --check-prefix=EXTREME0
78+
# EXTREME0: addi.d $t0, $zero, 273
79+
# EXTREME0-NEXT: pcalau12i $t1, 139810
80+
# EXTREME0-NEXT: lu32i.d $t0, 209715
81+
# EXTREME0-NEXT: lu52i.d $t0, $t0, 1092
82+
83+
## page delta = 0x4443333222223000, page offset = 0x888
84+
## %pc_lo12 = 0x888 = -1912
85+
## %pc_hi20 = 0x22223 = 139811
86+
## %pc64_lo20 = 0x33332 = 209714
87+
## %pc64_hi12 = 0x444 = 1092
88+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0x4443333334567888 --section-start=.text=0x0000000012345678 -o %t/extreme1
89+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme1 | FileCheck %s --check-prefix=EXTREME1
90+
# EXTREME1: addi.d $t0, $zero, -1912
91+
# EXTREME1-NEXT: pcalau12i $t1, 139811
92+
# EXTREME1-NEXT: lu32i.d $t0, 209714
93+
# EXTREME1-NEXT: lu52i.d $t0, $t0, 1092
94+
95+
## page delta = 0x4443333499999000, page offset = 0x111
96+
## %pc_lo12 = 0x111 = 273
97+
## %pc_hi20 = 0x99999 = -419431
98+
## %pc64_lo20 = 0x33334 = 209716
99+
## %pc64_hi12 = 0x444 = 1092
100+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0x44433333abcde111 --section-start=.text=0x0000000012345678 -o %t/extreme2
101+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme2 | FileCheck %s --check-prefix=EXTREME2
102+
# EXTREME2: addi.d $t0, $zero, 273
103+
# EXTREME2-NEXT: pcalau12i $t1, -419431
104+
# EXTREME2-NEXT: lu32i.d $t0, 209716
105+
# EXTREME2-NEXT: lu52i.d $t0, $t0, 1092
106+
107+
## page delta = 0x444333339999a000, page offset = 0x888
108+
## %pc_lo12 = 0x888 = -1912
109+
## %pc_hi20 = 0x9999a = -419430
110+
## %pc64_lo20 = 0x33333 = 209715
111+
## %pc64_hi12 = 0x444 = 1092
112+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0x44433333abcde888 --section-start=.text=0x0000000012345678 -o %t/extreme3
113+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme3 | FileCheck %s --check-prefix=EXTREME3
114+
# EXTREME3: addi.d $t0, $zero, -1912
115+
# EXTREME3-NEXT: pcalau12i $t1, -419430
116+
# EXTREME3-NEXT: lu32i.d $t0, 209715
117+
# EXTREME3-NEXT: lu52i.d $t0, $t0, 1092
118+
119+
## page delta = 0x444aaaaa22222000, page offset = 0x111
120+
## %pc_lo12 = 0x111 = 273
121+
## %pc_hi20 = 0x22222 = 139810
122+
## %pc64_lo20 = 0xaaaaa = -349526
123+
## %pc64_hi12 = 0x444 = 1092
124+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0x444aaaaa34567111 --section-start=.text=0x0000000012345678 -o %t/extreme4
125+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme4 | FileCheck %s --check-prefix=EXTREME4
126+
# EXTREME4: addi.d $t0, $zero, 273
127+
# EXTREME4-NEXT: pcalau12i $t1, 139810
128+
# EXTREME4-NEXT: lu32i.d $t0, -349526
129+
# EXTREME4-NEXT: lu52i.d $t0, $t0, 1092
130+
131+
## page delta = 0x444aaaa922223000, page offset = 0x888
132+
## %pc_lo12 = 0x888 = -1912
133+
## %pc_hi20 = 0x22223 = 139811
134+
## %pc64_lo20 = 0xaaaa9 = -349527
135+
## %pc64_hi12 = 0x444 = 1092
136+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0x444aaaaa34567888 --section-start=.text=0x0000000012345678 -o %t/extreme5
137+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme5 | FileCheck %s --check-prefix=EXTREME5
138+
# EXTREME5: addi.d $t0, $zero, -1912
139+
# EXTREME5-NEXT: pcalau12i $t1, 139811
140+
# EXTREME5-NEXT: lu32i.d $t0, -349527
141+
# EXTREME5-NEXT: lu52i.d $t0, $t0, 1092
142+
143+
## page delta = 0x444aaaab99999000, page offset = 0x111
144+
## %pc_lo12 = 0x111 = 273
145+
## %pc_hi20 = 0x99999 = -419431
146+
## %pc64_lo20 = 0xaaaab = -349525
147+
## %pc64_hi12 = 0x444 = 1092
148+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0x444aaaaaabcde111 --section-start=.text=0x0000000012345678 -o %t/extreme6
149+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme6 | FileCheck %s --check-prefix=EXTREME6
150+
# EXTREME6: addi.d $t0, $zero, 273
151+
# EXTREME6-NEXT: pcalau12i $t1, -419431
152+
# EXTREME6-NEXT: lu32i.d $t0, -349525
153+
# EXTREME6-NEXT: lu52i.d $t0, $t0, 1092
154+
155+
## page delta = 0x444aaaaa9999a000, page offset = 0x888
156+
## %pc_lo12 = 0x888 = -1912
157+
## %pc_hi20 = 0x9999a = -419430
158+
## %pc64_lo20 = 0xaaaaa = -349526
159+
## %pc64_hi12 = 0x444 = 1092
160+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0x444aaaaaabcde888 --section-start=.text=0x0000000012345678 -o %t/extreme7
161+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme7 | FileCheck %s --check-prefix=EXTREME7
162+
# EXTREME7: addi.d $t0, $zero, -1912
163+
# EXTREME7-NEXT: pcalau12i $t1, -419430
164+
# EXTREME7-NEXT: lu32i.d $t0, -349526
165+
# EXTREME7-NEXT: lu52i.d $t0, $t0, 1092
166+
167+
## page delta = 0xbbb3333322222000, page offset = 0x111
168+
## %pc_lo12 = 0x111 = 273
169+
## %pc_hi20 = 0x22222 = 139810
170+
## %pc64_lo20 = 0x33333 = 209715
171+
## %pc64_hi12 = 0xbbb = -1093
172+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0xbbb3333334567111 --section-start=.text=0x0000000012345678 -o %t/extreme8
173+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme8 | FileCheck %s --check-prefix=EXTREME8
174+
# EXTREME8: addi.d $t0, $zero, 273
175+
# EXTREME8-NEXT: pcalau12i $t1, 139810
176+
# EXTREME8-NEXT: lu32i.d $t0, 209715
177+
# EXTREME8-NEXT: lu52i.d $t0, $t0, -1093
178+
179+
## page delta = 0xbbb3333222223000, page offset = 0x888
180+
## %pc_lo12 = 0x888 = -1912
181+
## %pc_hi20 = 0x22223 = 139811
182+
## %pc64_lo20 = 0x33332 = 209714
183+
## %pc64_hi12 = 0xbbb = -1093
184+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0xbbb3333334567888 --section-start=.text=0x0000000012345678 -o %t/extreme9
185+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme9 | FileCheck %s --check-prefix=EXTREME9
186+
# EXTREME9: addi.d $t0, $zero, -1912
187+
# EXTREME9-NEXT: pcalau12i $t1, 139811
188+
# EXTREME9-NEXT: lu32i.d $t0, 209714
189+
# EXTREME9-NEXT: lu52i.d $t0, $t0, -1093
190+
191+
## page delta = 0xbbb3333499999000, page offset = 0x111
192+
## %pc_lo12 = 0x111 = 273
193+
## %pc_hi20 = 0x99999 = -419431
194+
## %pc64_lo20 = 0x33334 = 209716
195+
## %pc64_hi12 = 0xbbb = -1093
196+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0xbbb33333abcde111 --section-start=.text=0x0000000012345678 -o %t/extreme10
197+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme10 | FileCheck %s --check-prefix=EXTREME10
198+
# EXTREME10: addi.d $t0, $zero, 273
199+
# EXTREME10-NEXT: pcalau12i $t1, -419431
200+
# EXTREME10-NEXT: lu32i.d $t0, 209716
201+
# EXTREME10-NEXT: lu52i.d $t0, $t0, -1093
202+
203+
## page delta = 0xbbb333339999a000, page offset = 0x888
204+
## %pc_lo12 = 0x888 = -1912
205+
## %pc_hi20 = 0x9999a = -419430
206+
## %pc64_lo20 = 0x33333 = 209715
207+
## %pc64_hi12 = 0xbbb = -1093
208+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0xbbb33333abcde888 --section-start=.text=0x0000000012345678 -o %t/extreme11
209+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme11 | FileCheck %s --check-prefix=EXTREME11
210+
# EXTREME11: addi.d $t0, $zero, -1912
211+
# EXTREME11-NEXT: pcalau12i $t1, -419430
212+
# EXTREME11-NEXT: lu32i.d $t0, 209715
213+
# EXTREME11-NEXT: lu52i.d $t0, $t0, -1093
214+
215+
## page delta = 0xbbbaaaaa22222000, page offset = 0x111
216+
## %pc_lo12 = 0x111 = 273
217+
## %pc_hi20 = 0x22222 = 139810
218+
## %pc64_lo20 = 0xaaaaa = -349526
219+
## %pc64_hi12 = 0xbbb = -1093
220+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0xbbbaaaaa34567111 --section-start=.text=0x0000000012345678 -o %t/extreme12
221+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme12 | FileCheck %s --check-prefix=EXTREME12
222+
# EXTREME12: addi.d $t0, $zero, 273
223+
# EXTREME12-NEXT: pcalau12i $t1, 139810
224+
# EXTREME12-NEXT: lu32i.d $t0, -349526
225+
# EXTREME12-NEXT: lu52i.d $t0, $t0, -1093
226+
227+
## page delta = 0xbbbaaaa922223000, page offset = 0x888
228+
## %pc_lo12 = 0x888 = -1912
229+
## %pc_hi20 = 0x22223 = 139811
230+
## %pc64_lo20 = 0xaaaa9 = -349527
231+
## %pc64_hi12 = 0xbbb = -1093
232+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0xbbbaaaaa34567888 --section-start=.text=0x0000000012345678 -o %t/extreme13
233+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme13 | FileCheck %s --check-prefix=EXTREME13
234+
# EXTREME13: addi.d $t0, $zero, -1912
235+
# EXTREME13-NEXT: pcalau12i $t1, 139811
236+
# EXTREME13-NEXT: lu32i.d $t0, -349527
237+
# EXTREME13-NEXT: lu52i.d $t0, $t0, -1093
238+
239+
## page delta = 0xbbbaaaab99999000, page offset = 0x111
240+
## %pc_lo12 = 0x111 = 273
241+
## %pc_hi20 = 0x99999 = -419431
242+
## %pc64_lo20 = 0xaaaab = -349525
243+
## %pc64_hi12 = 0xbbb = -1093
244+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0xbbbaaaaaabcde111 --section-start=.text=0x0000000012345678 -o %t/extreme14
245+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme14 | FileCheck %s --check-prefix=EXTREME14
246+
# EXTREME14: addi.d $t0, $zero, 273
247+
# EXTREME14-NEXT: pcalau12i $t1, -419431
248+
# EXTREME14-NEXT: lu32i.d $t0, -349525
249+
# EXTREME14-NEXT: lu52i.d $t0, $t0, -1093
250+
251+
## page delta = 0xbbbaaaaa9999a000, page offset = 0x888
252+
## %pc_lo12 = 0x888 = -1912
253+
## %pc_hi20 = 0x9999a = -419430
254+
## %pc64_lo20 = 0xaaaaa = -349526
255+
## %pc64_hi12 = 0xbbb = -1093
256+
# RUN: ld.lld %t/extreme.o --section-start=.rodata=0xbbbaaaaaabcde888 --section-start=.text=0x0000000012345678 -o %t/extreme15
257+
# RUN: llvm-objdump -d --no-show-raw-insn %t/extreme15 | FileCheck %s --check-prefix=EXTREME15
258+
# EXTREME15: addi.d $t0, $zero, -1912
259+
# EXTREME15-NEXT: pcalau12i $t1, -419430
260+
# EXTREME15-NEXT: lu32i.d $t0, -349526
261+
# EXTREME15-NEXT: lu52i.d $t0, $t0, -1093
262+
263+
#--- a.s
264+
.rodata
265+
x:
266+
.word 10
267+
.text
268+
.global _start
269+
_start:
270+
pcalau12i $a0, %pc_hi20(x)
271+
ld.w $a0, $a0, %pc_lo12(x)
272+
273+
#--- extreme.s
274+
.rodata
275+
x:
276+
.word 10
277+
.text
278+
.global _start
279+
_start:
280+
addi.d $t0, $zero, %pc_lo12(x)
281+
pcalau12i $t1, %pc_hi20(x)
282+
lu32i.d $t0, %pc64_lo20(x)
283+
lu52i.d $t0, $t0, %pc64_hi12(x)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t
3+
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch32-unknown-elf %t/a.s -o %t/a.la32.o
5+
# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-elf %t/a.s -o %t/a.la64.o
6+
7+
# RUN: ld.lld %t/a.la32.o -shared -T %t/a.t -o %t/a.la32.so
8+
# RUN: ld.lld %t/a.la64.o -shared -T %t/a.t -o %t/a.la64.so
9+
10+
# RUN: llvm-objdump -d --no-show-raw-insn %t/a.la32.so | FileCheck --check-prefixes=DIS,DIS32 %s
11+
# RUN: llvm-objdump -d --no-show-raw-insn %t/a.la64.so | FileCheck --check-prefixes=DIS,DIS64 %s
12+
13+
## PLT should be present in this case.
14+
# DIS: Disassembly of section .plt:
15+
# DIS: <.plt>:
16+
# DIS: 234020: pcaddu12i $t3, 510
17+
# DIS32-NEXT: ld.w $t3, $t3, 84
18+
# DIS64-NEXT: ld.d $t3, $t3, 184
19+
# DIS-NEXT: jirl $t1, $t3, 0
20+
# DIS-NEXT: nop
21+
22+
# DIS: Disassembly of section .text:
23+
# DIS: <foo>:
24+
# DIS-NEXT: nop
25+
# DIS-NEXT: nop
26+
# DIS-NEXT: nop
27+
# DIS-NEXT: pcalau12i $t0, -510
28+
# DIS-NEXT: jirl $zero, $t0, 32
29+
30+
# RUN: llvm-mc --filetype=obj --triple=loongarch32-unknown-elf %t/error.s -o %t/error.la32.o
31+
# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-elf %t/error.s -o %t/error.la64.o
32+
# RUN: not ld.lld %t/error.la32.o -shared -o %t/error.la32.so 2>&1 | FileCheck --check-prefix=ERR %s
33+
# RUN: not ld.lld %t/error.la64.o -shared -o %t/error.la64.so 2>&1 | FileCheck --check-prefix=ERR %s
34+
# ERR: error: relocation R_LARCH_PCALA_LO12 cannot be used against symbol 'bar'; recompile with -fPIC
35+
36+
#--- a.t
37+
SECTIONS {
38+
.plt 0x234000: { *(.plt) }
39+
.text 0x432000: { *(.text) }
40+
}
41+
42+
#--- a.s
43+
.p2align 12
44+
.global foo
45+
foo:
46+
## The nops are for pushing the relocs off page boundary, to better see the
47+
## page-aligned semantics in action.
48+
nop
49+
nop
50+
nop
51+
## The offsets should be -510 (0x234 - 0x432) and 32 (PLT header size + 0)
52+
## respectively.
53+
pcalau12i $t0, %pc_hi20(bar)
54+
jirl $zero, $t0, %pc_lo12(bar)
55+
56+
#--- error.s
57+
.global foo
58+
foo:
59+
pcalau12i $t0, %pc_hi20(bar)
60+
ld.w $t0, $t0, %pc_lo12(bar)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# REQUIRES: loongarch
2+
3+
# RUN: llvm-mc --filetype=obj --triple=loongarch32-unknown-elf %s -o %t.la32.o
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-elf %s -o %t.la64.o
5+
6+
# RUN: ld.lld %t.la32.o -o %t.la32
7+
# RUN: ld.lld %t.la64.o -o %t.la64
8+
# RUN: llvm-objdump -d --no-show-raw-insn %t.la32 | FileCheck %s
9+
# RUN: llvm-objdump -d --no-show-raw-insn %t.la64 | FileCheck %s
10+
# CHECK: pcalau12i $t0, -1
11+
# CHECK-NEXT: jirl $ra, $t0, 564
12+
# CHECK-NEXT: pcalau12i $t0, 0
13+
# CHECK-NEXT: jirl $zero, $t0, -1348
14+
15+
## PLT shouldn't get generated in this case.
16+
# CHECK-NOT: Disassembly of section .plt:
17+
18+
.p2align 12
19+
.org 0x234
20+
.global foo
21+
foo:
22+
li.w $a0, 42
23+
ret
24+
25+
.org 0xabc
26+
.global bar
27+
bar:
28+
li.w $a7, 94
29+
syscall 0
30+
31+
.org 0x1000
32+
.global _start
33+
_start:
34+
## The nops are for pushing the relocs off page boundary, to better see the
35+
## page-aligned semantics in action.
36+
nop
37+
nop
38+
nop
39+
pcalau12i $t0, %pc_hi20(foo)
40+
jirl $ra, $t0, %pc_lo12(foo)
41+
pcalau12i $t0, %pc_hi20(bar)
42+
jirl $zero, $t0, %pc_lo12(bar)

‎lld/test/ELF/loongarch-plt.s

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# REQUIRES: loongarch
2+
# RUN: echo '.globl bar, weak; .type bar,@function; .type weak,@function; bar: weak:' > %t1.s
3+
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t1.s -o %t1.32.o
5+
# RUN: ld.lld -shared %t1.32.o -soname=t1.32.so -o %t1.32.so
6+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %s -o %t.32.o
7+
# RUN: ld.lld %t.32.o %t1.32.so -z separate-code -o %t.32
8+
# RUN: llvm-readelf -S -s %t.32 | FileCheck --check-prefixes=SEC,NM %s
9+
# RUN: llvm-readobj -r %t.32 | FileCheck --check-prefix=RELOC32 %s
10+
# RUN: llvm-readelf -x .got.plt %t.32 | FileCheck --check-prefix=GOTPLT32 %s
11+
# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=DIS,DIS32 %s
12+
13+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t1.s -o %t1.64.o
14+
# RUN: ld.lld -shared %t1.64.o -soname=t1.64.so -o %t1.64.so
15+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t.64.o
16+
# RUN: ld.lld %t.64.o %t1.64.so -z separate-code -o %t.64
17+
# RUN: llvm-readelf -S -s %t.64 | FileCheck --check-prefixes=SEC,NM %s
18+
# RUN: llvm-readobj -r %t.64 | FileCheck --check-prefix=RELOC64 %s
19+
# RUN: llvm-readelf -x .got.plt %t.64 | FileCheck --check-prefix=GOTPLT64 %s
20+
# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=DIS,DIS64 %s
21+
22+
# SEC: .plt PROGBITS {{0*}}00020020
23+
24+
## A canonical PLT has a non-zero st_value. bar and weak are called but their
25+
## addresses are not taken, so a canonical PLT is not necessary.
26+
# NM: {{0*}}00000000 0 FUNC GLOBAL DEFAULT UND bar
27+
# NM: {{0*}}00000000 0 FUNC WEAK DEFAULT UND weak
28+
29+
## The .got.plt slots relocated by .rela.plt point to .plt
30+
## This is required by glibc.
31+
# RELOC32: .rela.plt {
32+
# RELOC32-NEXT: 0x40070 R_LARCH_JUMP_SLOT bar 0x0
33+
# RELOC32-NEXT: 0x40074 R_LARCH_JUMP_SLOT weak 0x0
34+
# RELOC32-NEXT: }
35+
# GOTPLT32: section '.got.plt'
36+
# GOTPLT32-NEXT: 0x00040068 00000000 00000000 20000200 20000200
37+
38+
# RELOC64: .rela.plt {
39+
# RELOC64-NEXT: 0x400E0 R_LARCH_JUMP_SLOT bar 0x0
40+
# RELOC64-NEXT: 0x400E8 R_LARCH_JUMP_SLOT weak 0x0
41+
# RELOC64-NEXT: }
42+
# GOTPLT64: section '.got.plt'
43+
# GOTPLT64-NEXT: 0x000400d0 00000000 00000000 00000000 00000000
44+
# GOTPLT64-NEXT: 0x000400e0 20000200 00000000 20000200 00000000
45+
46+
# DIS: <_start>:
47+
## Direct call
48+
## foo - . = 0x20010-0x20000 = 16
49+
# DIS-NEXT: 20000: bl 16
50+
## bar@plt - . = 0x20040-0x20004 = 60
51+
# DIS-NEXT: 20004: bl 60
52+
## bar@plt - . = 0x20040-0x20008 = 56
53+
# DIS-NEXT: 20008: bl 56
54+
## weak@plt - . = 0x20050-0x2000c = 68
55+
# DIS-NEXT: 2000c: bl 68
56+
# DIS: <foo>:
57+
# DIS-NEXT: 20010:
58+
59+
# DIS: Disassembly of section .plt:
60+
# DIS: <.plt>:
61+
## 32-bit: .got.plt - .plt = 0x40068 - 0x20020 = 4096*32+72
62+
# DIS32-NEXT: pcaddu12i $t2, 32
63+
# DIS32-NEXT: sub.w $t1, $t1, $t3
64+
# DIS32-NEXT: ld.w $t3, $t2, 72
65+
# DIS32-NEXT: addi.w $t1, $t1, -44
66+
# DIS32-NEXT: addi.w $t0, $t2, 72
67+
# DIS32-NEXT: srli.w $t1, $t1, 2
68+
# DIS32-NEXT: ld.w $t0, $t0, 4
69+
# DIS32-NEXT: jr $t3
70+
71+
## 64-bit: .got.plt - .plt = 0x400d0 - 0x20020 = 4096*32+176
72+
# DIS64-NEXT: pcaddu12i $t2, 32
73+
# DIS64-NEXT: sub.d $t1, $t1, $t3
74+
# DIS64-NEXT: ld.d $t3, $t2, 176
75+
# DIS64-NEXT: addi.d $t1, $t1, -44
76+
# DIS64-NEXT: addi.d $t0, $t2, 176
77+
# DIS64-NEXT: srli.d $t1, $t1, 1
78+
# DIS64-NEXT: ld.d $t0, $t0, 8
79+
# DIS64-NEXT: jr $t3
80+
81+
## 32-bit: &.got.plt[bar]-. = 0x40070-0x20040 = 4096*32+48
82+
## 64-bit: &.got.plt[bar]-. = 0x400e0-0x20040 = 4096*32+160
83+
# DIS: 20040: pcaddu12i $t3, 32
84+
# DIS32-NEXT: ld.w $t3, $t3, 48
85+
# DIS64-NEXT: ld.d $t3, $t3, 160
86+
# DIS-NEXT: jirl $t1, $t3, 0
87+
# DIS-NEXT: nop
88+
89+
## 32-bit: &.got.plt[weak]-. = 0x40074-0x20050 = 4096*32+36
90+
## 64-bit: &.got.plt[weak]-. = 0x400e8-0x20050 = 4096*32+152
91+
# DIS: 20050: pcaddu12i $t3, 32
92+
# DIS32-NEXT: ld.w $t3, $t3, 36
93+
# DIS64-NEXT: ld.d $t3, $t3, 152
94+
# DIS-NEXT: jirl $t1, $t3, 0
95+
# DIS-NEXT: nop
96+
97+
.global _start, foo, bar
98+
.weak weak
99+
100+
_start:
101+
bl foo
102+
bl bar
103+
bl %plt(bar)
104+
bl weak
105+
106+
## foo is local and non-preemptible, no PLT is generated.
107+
foo:
108+
ret

‎lld/test/ELF/loongarch-reloc-pic.s

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t
3+
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/32.s -o %t/32.o
5+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/64.s -o %t/64.o
6+
# RUN: ld.lld -shared %t/32.o -o %t/32.so
7+
# RUN: llvm-nm %t/32.so | FileCheck --check-prefix=NM32 %s
8+
# RUN: llvm-readobj -r %t/32.so | FileCheck --check-prefix=RELOC32 %s
9+
# RUN: ld.lld -shared %t/64.o -o %t/64.so
10+
# RUN: llvm-nm %t/64.so | FileCheck --check-prefix=NM64 %s
11+
# RUN: llvm-readobj -r %t/64.so | FileCheck --check-prefix=RELOC64 %s
12+
13+
## R_LARCH_32 and R_LARCH_64 are absolute relocation types.
14+
## In PIC mode, they create relative relocations if the symbol is non-preemptable.
15+
16+
# NM32: 000301fc d b
17+
# NM64: 00030350 d b
18+
19+
# RELOC32: .rela.dyn {
20+
# RELOC32-NEXT: 0x301FC R_LARCH_RELATIVE - 0x301FC
21+
# RELOC32-NEXT: 0x301F8 R_LARCH_32 a 0
22+
# RELOC32-NEXT: }
23+
# RELOC64: .rela.dyn {
24+
# RELOC64-NEXT: 0x30350 R_LARCH_RELATIVE - 0x30350
25+
# RELOC64-NEXT: 0x30348 R_LARCH_64 a 0
26+
# RELOC64-NEXT: }
27+
28+
#--- 32.s
29+
.globl a, b
30+
.hidden b
31+
32+
.data
33+
.long a
34+
b:
35+
.long b
36+
37+
#--- 64.s
38+
.globl a, b
39+
.hidden b
40+
41+
.data
42+
.quad a
43+
b:
44+
.quad b
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# REQUIRES: loongarch
2+
3+
## Edge case: when a TLS symbol is being accessed in both GD and IE manners,
4+
## correct reloc behavior should be preserved for both kinds of accesses.
5+
6+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %s -o %t.la32.o
7+
# RUN: ld.lld %t.la32.o -shared -o %t.la32
8+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t.la64.o
9+
# RUN: ld.lld %t.la64.o -shared -o %t.la64
10+
11+
# RUN: llvm-readelf -Wr %t.la32 | FileCheck --check-prefix=LA32-REL %s
12+
# RUN: llvm-objdump -d --no-show-raw-insn %t.la32 | FileCheck --check-prefix=LA32 %s
13+
14+
# RUN: llvm-readelf -Wr %t.la64 | FileCheck --check-prefix=LA64-REL %s
15+
# RUN: llvm-objdump -d --no-show-raw-insn %t.la64 | FileCheck --check-prefix=LA64 %s
16+
17+
# LA32-REL-NOT: R_LARCH_32
18+
# LA32-REL: 0002023c 00000206 R_LARCH_TLS_DTPMOD32 00000000 y + 0
19+
# LA32-REL-NEXT: 00020240 00000208 R_LARCH_TLS_DTPREL32 00000000 y + 0
20+
# LA32-REL-NEXT: 00020244 0000020a R_LARCH_TLS_TPREL32 00000000 y + 0
21+
22+
# LA64-REL-NOT: R_LARCH_64
23+
# LA64-REL: 00000000000203a0 0000000200000007 R_LARCH_TLS_DTPMOD64 0000000000000000 y + 0
24+
# LA64-REL-NEXT: 00000000000203a8 0000000200000009 R_LARCH_TLS_DTPREL64 0000000000000000 y + 0
25+
# LA64-REL-NEXT: 00000000000203b0 000000020000000b R_LARCH_TLS_TPREL64 0000000000000000 y + 0
26+
27+
# LA32: 101d4: pcalau12i $a0, 16
28+
# LA32-NEXT: ld.w $a0, $a0, 580
29+
# LA32-NEXT: pcalau12i $a1, 16
30+
# LA32-NEXT: addi.w $a1, $a1, 572
31+
32+
# LA64: 102e0: pcalau12i $a0, 16
33+
# LA64-NEXT: ld.d $a0, $a0, 944
34+
# LA64-NEXT: pcalau12i $a1, 16
35+
# LA64-NEXT: addi.d $a1, $a1, 928
36+
37+
.global _start
38+
_start:
39+
la.tls.ie $a0, y # should refer to the GOT entry relocated by the R_LARCH_TLS_TPRELnn record
40+
la.tls.gd $a1, y # should refer to the GOT entry relocated by the R_LARCH_TLS_DTPMODnn record
41+
42+
.section .tbss,"awT",@nobits
43+
.global y
44+
y:
45+
.word 0
46+
.size y, 4

‎lld/test/ELF/loongarch-tls-gd.s

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t
3+
4+
## LoongArch psABI doesn't specify TLS relaxation. Though the code sequences are not
5+
## relaxed, dynamic relocations can be omitted for GD->LE relaxation.
6+
7+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/a.s -o %t/a.32.o
8+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/bc.s -o %t/bc.32.o
9+
# RUN: ld.lld -shared -soname=bc.so %t/bc.32.o -o %t/bc.32.so
10+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/tga.s -o %t/tga.32.o
11+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/a.s -o %t/a.64.o
12+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/bc.s -o %t/bc.64.o
13+
# RUN: ld.lld -shared -soname=bc.so %t/bc.64.o -o %t/bc.64.so
14+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/tga.s -o %t/tga.64.o
15+
16+
## LA32 GD
17+
# RUN: ld.lld -shared %t/a.32.o %t/bc.32.o -o %t/gd.32.so
18+
# RUN: llvm-readobj -r %t/gd.32.so | FileCheck --check-prefix=GD32-REL %s
19+
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.32.so | FileCheck --check-prefix=GD32 %s
20+
21+
## LA32 GD -> LE
22+
# RUN: ld.lld %t/a.32.o %t/bc.32.o %t/tga.32.o -o %t/le.32
23+
# RUN: llvm-readelf -r %t/le.32 | FileCheck --check-prefix=NOREL %s
24+
# RUN: llvm-readelf -x .got %t/le.32 | FileCheck --check-prefix=LE32-GOT %s
25+
# RUN: ld.lld -pie %t/a.32.o %t/bc.32.o %t/tga.32.o -o %t/le-pie.32
26+
# RUN: llvm-readelf -r %t/le-pie.32 | FileCheck --check-prefix=NOREL %s
27+
# RUN: llvm-readelf -x .got %t/le-pie.32 | FileCheck --check-prefix=LE32-GOT %s
28+
29+
## LA32 GD -> IE
30+
# RUN: ld.lld %t/a.32.o %t/bc.32.so %t/tga.32.o -o %t/ie.32
31+
# RUN: llvm-readobj -r %t/ie.32 | FileCheck --check-prefix=IE32-REL %s
32+
# RUN: llvm-readelf -x .got %t/ie.32 | FileCheck --check-prefix=IE32-GOT %s
33+
34+
## LA64 GD
35+
# RUN: ld.lld -shared %t/a.64.o %t/bc.64.o -o %t/gd.64.so
36+
# RUN: llvm-readobj -r %t/gd.64.so | FileCheck --check-prefix=GD64-REL %s
37+
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.64.so | FileCheck --check-prefix=GD64 %s
38+
39+
## LA64 GD -> LE
40+
# RUN: ld.lld %t/a.64.o %t/bc.64.o %t/tga.64.o -o %t/le.64
41+
# RUN: llvm-readelf -r %t/le.64 | FileCheck --check-prefix=NOREL %s
42+
# RUN: llvm-readelf -x .got %t/le.64 | FileCheck --check-prefix=LE64-GOT %s
43+
# RUN: ld.lld -pie %t/a.64.o %t/bc.64.o %t/tga.64.o -o %t/le-pie.64
44+
# RUN: llvm-readelf -r %t/le-pie.64 | FileCheck --check-prefix=NOREL %s
45+
# RUN: llvm-readelf -x .got %t/le-pie.64 | FileCheck --check-prefix=LE64-GOT %s
46+
47+
## LA64 GD -> IE
48+
# RUN: ld.lld %t/a.64.o %t/bc.64.so %t/tga.64.o -o %t/ie.64
49+
# RUN: llvm-readobj -r %t/ie.64 | FileCheck --check-prefix=IE64-REL %s
50+
# RUN: llvm-readelf -x .got %t/ie.64 | FileCheck --check-prefix=IE64-GOT %s
51+
52+
# GD32-REL: .rela.dyn {
53+
# GD32-REL-NEXT: 0x20310 R_LARCH_TLS_DTPMOD32 a 0x0
54+
# GD32-REL-NEXT: 0x20314 R_LARCH_TLS_DTPREL32 a 0x0
55+
# GD32-REL-NEXT: 0x20318 R_LARCH_TLS_DTPMOD32 b 0x0
56+
# GD32-REL-NEXT: 0x2031C R_LARCH_TLS_DTPREL32 b 0x0
57+
# GD32-REL-NEXT: }
58+
59+
## &DTPMOD(a) - . = 0x20310 - 0x10250: 0x10 pages, page offset 0x310
60+
# GD32: 10250: pcalau12i $a0, 16
61+
# GD32-NEXT: addi.w $a0, $a0, 784
62+
# GD32-NEXT: bl 56
63+
64+
## &DTPMOD(b) - . = 0x20318 - 0x1025c: 0x10 pages, page offset 0x318
65+
# GD32: 1025c: pcalau12i $a0, 16
66+
# GD32-NEXT: addi.w $a0, $a0, 792
67+
# GD32-NEXT: bl 44
68+
69+
# GD64-REL: .rela.dyn {
70+
# GD64-REL-NEXT: 0x204C0 R_LARCH_TLS_DTPMOD64 a 0x0
71+
# GD64-REL-NEXT: 0x204C8 R_LARCH_TLS_DTPREL64 a 0x0
72+
# GD64-REL-NEXT: 0x204D0 R_LARCH_TLS_DTPMOD64 b 0x0
73+
# GD64-REL-NEXT: 0x204D8 R_LARCH_TLS_DTPREL64 b 0x0
74+
# GD64-REL-NEXT: }
75+
76+
## &DTPMOD(a) - . = 0x204c0 - 0x10398: 0x10 pages, page offset 0x4c0
77+
# GD64: 10398: pcalau12i $a0, 16
78+
# GD64-NEXT: addi.d $a0, $a0, 1216
79+
# GD64-NEXT: bl 48
80+
81+
## &DTPMOD(b) - . = 0x204d0 - 0x103a4: 0x10 pages, page offset 0x4d0
82+
# GD64: 103a4: pcalau12i $a0, 16
83+
# GD64-NEXT: addi.d $a0, $a0, 1232
84+
# GD64-NEXT: bl 36
85+
86+
# NOREL: no relocations
87+
88+
## .got contains pre-populated values: [a@dtpmod, a@dtprel, b@dtpmod, b@dtprel]
89+
## a@dtprel = st_value(a) = 0x8
90+
## b@dtprel = st_value(b) = 0xc
91+
# LE32-GOT: section '.got':
92+
# LE32-GOT-NEXT: 0x[[#%x,A:]] 01000000 08000000 01000000 0c000000
93+
# LE64-GOT: section '.got':
94+
# LE64-GOT-NEXT: 0x[[#%x,A:]] 01000000 00000000 08000000 00000000
95+
# LE64-GOT-NEXT: 0x[[#%x,A:]] 01000000 00000000 0c000000 00000000
96+
97+
## a is local - relaxed to LE - its DTPMOD/DTPREL slots are link-time constants.
98+
## b is external - DTPMOD/DTPREL dynamic relocations are required.
99+
# IE32-REL: .rela.dyn {
100+
# IE32-REL-NEXT: 0x30228 R_LARCH_TLS_DTPMOD32 b 0x0
101+
# IE32-REL-NEXT: 0x3022C R_LARCH_TLS_DTPREL32 b 0x0
102+
# IE32-REL-NEXT: }
103+
# IE32-GOT: section '.got':
104+
# IE32-GOT-NEXT: 0x00030220 01000000 08000000 00000000 00000000
105+
106+
# IE64-REL: .rela.dyn {
107+
# IE64-REL-NEXT: 0x30388 R_LARCH_TLS_DTPMOD64 b 0x0
108+
# IE64-REL-NEXT: 0x30390 R_LARCH_TLS_DTPREL64 b 0x0
109+
# IE64-REL-NEXT: }
110+
# IE64-GOT: section '.got':
111+
# IE64-GOT-NEXT: 0x00030378 01000000 00000000 08000000 00000000
112+
# IE64-GOT-NEXT: 0x00030388 00000000 00000000 00000000 00000000
113+
114+
#--- a.s
115+
la.tls.gd $a0, a
116+
bl %plt(__tls_get_addr)
117+
118+
la.tls.gd $a0, b
119+
bl %plt(__tls_get_addr)
120+
121+
.section .tbss,"awT",@nobits
122+
.globl a
123+
.zero 8
124+
a:
125+
.zero 4
126+
127+
#--- bc.s
128+
.section .tbss,"awT",@nobits
129+
.globl b, c
130+
b:
131+
.zero 4
132+
c:
133+
134+
#--- tga.s
135+
.globl __tls_get_addr
136+
__tls_get_addr:

‎lld/test/ELF/loongarch-tls-ie.s

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t
3+
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/32.s -o %t/32.o
5+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/64.s -o %t/64.o
6+
7+
## LA32 IE
8+
# RUN: ld.lld -shared %t/32.o -o %t/32.so
9+
# RUN: llvm-readobj -r -d %t/32.so | FileCheck --check-prefix=IE32-REL %s
10+
# RUN: llvm-objdump -d --no-show-raw-insn %t/32.so | FileCheck --check-prefixes=IE32 %s
11+
12+
## LA32 IE -> LE
13+
# RUN: ld.lld %t/32.o -o %t/32
14+
# RUN: llvm-readelf -r %t/32 | FileCheck --check-prefix=NOREL %s
15+
# RUN: llvm-readelf -x .got %t/32 | FileCheck --check-prefix=LE32-GOT %s
16+
# RUN: llvm-objdump -d --no-show-raw-insn %t/32 | FileCheck --check-prefixes=LE32 %s
17+
18+
## LA64 IE
19+
# RUN: ld.lld -shared %t/64.o -o %t/64.so
20+
# RUN: llvm-readobj -r -d %t/64.so | FileCheck --check-prefix=IE64-REL %s
21+
# RUN: llvm-objdump -d --no-show-raw-insn %t/64.so | FileCheck --check-prefixes=IE64 %s
22+
23+
## LA64 IE -> LE
24+
# RUN: ld.lld %t/64.o -o %t/64
25+
# RUN: llvm-readelf -r %t/64 | FileCheck --check-prefix=NOREL %s
26+
# RUN: llvm-readelf -x .got %t/64 | FileCheck --check-prefix=LE64-GOT %s
27+
# RUN: llvm-objdump -d --no-show-raw-insn %t/64 | FileCheck --check-prefixes=LE64 %s
28+
29+
# IE32-REL: FLAGS STATIC_TLS
30+
# IE32-REL: .rela.dyn {
31+
# IE32-REL-NEXT: 0x20218 R_LARCH_TLS_TPREL32 - 0xC
32+
# IE32-REL-NEXT: 0x20214 R_LARCH_TLS_TPREL32 a 0x0
33+
# IE32-REL-NEXT: }
34+
35+
# IE64-REL: FLAGS STATIC_TLS
36+
# IE64-REL: .rela.dyn {
37+
# IE64-REL-NEXT: 0x20370 R_LARCH_TLS_TPREL64 - 0xC
38+
# IE64-REL-NEXT: 0x20368 R_LARCH_TLS_TPREL64 a 0x0
39+
# IE64-REL-NEXT: }
40+
41+
## LA32:
42+
## &.got[0] - . = 0x20214 - 0x101a4: 0x10 pages, page offset 0x214
43+
## &.got[1] - . = 0x20218 - 0x101b0: 0x10 pages, page offset 0x218
44+
# IE32: 101a4: pcalau12i $a4, 16
45+
# IE32-NEXT: ld.w $a4, $a4, 532
46+
# IE32-NEXT: add.w $a4, $a4, $tp
47+
# IE32-NEXT: 101b0: pcalau12i $a5, 16
48+
# IE32-NEXT: ld.w $a5, $a5, 536
49+
# IE32-NEXT: add.w $a5, $a5, $tp
50+
51+
## LA64:
52+
## &.got[0] - . = 0x20368 - 0x102a0: 0x10 pages, page offset 0x368
53+
## &.got[1] - . = 0x20370 - 0x102ac: 0x10 pages, page offset 0x370
54+
# IE64: 102a0: pcalau12i $a4, 16
55+
# IE64-NEXT: ld.d $a4, $a4, 872
56+
# IE64-NEXT: add.d $a4, $a4, $tp
57+
# IE64-NEXT: 102ac: pcalau12i $a5, 16
58+
# IE64-NEXT: ld.d $a5, $a5, 880
59+
# IE64-NEXT: add.d $a5, $a5, $tp
60+
61+
# NOREL: no relocations
62+
63+
# a@tprel = st_value(a) = 0x8
64+
# b@tprel = st_value(a) = 0xc
65+
# LE32-GOT: section '.got':
66+
# LE32-GOT-NEXT: 0x0003012c 08000000 0c000000
67+
# LE64-GOT: section '.got':
68+
# LE64-GOT-NEXT: 0x000301e0 08000000 00000000 0c000000 00000000
69+
70+
## LA32:
71+
## &.got[0] - . = 0x3012c - 0x20114: 0x10 pages, page offset 0x12c
72+
## &.got[1] - . = 0x30130 - 0x20120: 0x10 pages, page offset 0x130
73+
# LE32: 20114: pcalau12i $a4, 16
74+
# LE32-NEXT: ld.w $a4, $a4, 300
75+
# LE32-NEXT: add.w $a4, $a4, $tp
76+
# LE32-NEXT: 20120: pcalau12i $a5, 16
77+
# LE32-NEXT: ld.w $a5, $a5, 304
78+
# LE32-NEXT: add.w $a5, $a5, $tp
79+
80+
## LA64:
81+
## &.got[0] - . = 0x301e0 - 0x201c8: 0x10 pages, page offset 0x1e0
82+
## &.got[1] - . = 0x301e8 - 0x201d4: 0x10 pages, page offset 0x1e8
83+
# LE64: 201c8: pcalau12i $a4, 16
84+
# LE64-NEXT: ld.d $a4, $a4, 480
85+
# LE64-NEXT: add.d $a4, $a4, $tp
86+
# LE64-NEXT: 201d4: pcalau12i $a5, 16
87+
# LE64-NEXT: ld.d $a5, $a5, 488
88+
# LE64-NEXT: add.d $a5, $a5, $tp
89+
90+
#--- 32.s
91+
la.tls.ie $a4, a
92+
add.w $a4, $a4, $tp
93+
la.tls.ie $a5, b
94+
add.w $a5, $a5, $tp
95+
96+
.section .tbss,"awT",@nobits
97+
.globl a
98+
.zero 8
99+
a:
100+
.zero 4
101+
b:
102+
103+
#--- 64.s
104+
la.tls.ie $a4, a
105+
add.d $a4, $a4, $tp
106+
la.tls.ie $a5, b
107+
add.d $a5, $a5, $tp
108+
109+
.section .tbss,"awT",@nobits
110+
.globl a
111+
.zero 8
112+
a:
113+
.zero 4
114+
b:

‎lld/test/ELF/loongarch-tls-ld.s

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t
3+
4+
## LoongArch psABI doesn't specify TLS relaxation. Though the code sequences are not
5+
## relaxed, dynamic relocations can be omitted for LD->LE relaxation.
6+
7+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent %t/a.s -o %t/a.32.o
8+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/tga.s -o %t/tga.32.o
9+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --position-independent %t/a.s -o %t/a.64.o
10+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/tga.s -o %t/tga.64.o
11+
12+
## LA32 LD
13+
# RUN: ld.lld -shared %t/a.32.o -o %t/ld.32.so
14+
# RUN: llvm-readobj -r %t/ld.32.so | FileCheck --check-prefix=LD32-REL %s
15+
# RUN: llvm-readelf -x .got %t/ld.32.so | FileCheck --check-prefix=LD32-GOT %s
16+
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.32.so | FileCheck --check-prefixes=LD32 %s
17+
18+
## LA32 LD -> LE
19+
# RUN: ld.lld %t/a.32.o %t/tga.32.o -o %t/le.32
20+
# RUN: llvm-readelf -r %t/le.32 | FileCheck --check-prefix=NOREL %s
21+
# RUN: llvm-readelf -x .got %t/le.32 | FileCheck --check-prefix=LE32-GOT %s
22+
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.32 | FileCheck --check-prefixes=LE32 %s
23+
24+
## LA64 LD
25+
# RUN: ld.lld -shared %t/a.64.o -o %t/ld.64.so
26+
# RUN: llvm-readobj -r %t/ld.64.so | FileCheck --check-prefix=LD64-REL %s
27+
# RUN: llvm-readelf -x .got %t/ld.64.so | FileCheck --check-prefix=LD64-GOT %s
28+
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.64.so | FileCheck --check-prefixes=LD64 %s
29+
30+
## LA64 LD -> LE
31+
# RUN: ld.lld %t/a.64.o %t/tga.64.o -o %t/le.64
32+
# RUN: llvm-readelf -r %t/le.64 | FileCheck --check-prefix=NOREL %s
33+
# RUN: llvm-readelf -x .got %t/le.64 | FileCheck --check-prefix=LE64-GOT %s
34+
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.64 | FileCheck --check-prefixes=LE64 %s
35+
36+
## a@dtprel = st_value(a) = 0 is a link-time constant.
37+
# LD32-REL: .rela.dyn {
38+
# LD32-REL-NEXT: 0x20280 R_LARCH_TLS_DTPMOD32 - 0x0
39+
# LD32-REL-NEXT: }
40+
# LD32-GOT: section '.got':
41+
# LD32-GOT-NEXT: 0x00020280 00000000 00000000
42+
43+
# LD64-REL: .rela.dyn {
44+
# LD64-REL-NEXT: 0x20400 R_LARCH_TLS_DTPMOD64 - 0x0
45+
# LD64-REL-NEXT: }
46+
# LD64-GOT: section '.got':
47+
# LD64-GOT-NEXT: 0x00020400 00000000 00000000 00000000 00000000
48+
49+
## LA32: &DTPMOD(a) - . = 0x20280 - 0x101cc: 0x10 pages, page offset 0x280
50+
# LD32: 101cc: pcalau12i $a0, 16
51+
# LD32-NEXT: addi.w $a0, $a0, 640
52+
# LD32-NEXT: bl 44
53+
54+
## LA64: &DTPMOD(a) - . = 0x20400 - 0x102e0: 0x10 pages, page offset 0x400
55+
# LD64: 102e0: pcalau12i $a0, 16
56+
# LD64-NEXT: addi.d $a0, $a0, 1024
57+
# LD64-NEXT: bl 40
58+
59+
# NOREL: no relocations
60+
61+
## a is local - its DTPMOD/DTPREL slots are link-time constants.
62+
## a@dtpmod = 1 (main module)
63+
# LE32-GOT: section '.got':
64+
# LE32-GOT-NEXT: 0x00030120 01000000 00000000
65+
66+
# LE64-GOT: section '.got':
67+
# LE64-GOT-NEXT: 0x000301d8 01000000 00000000 00000000 00000000
68+
69+
## LA32: DTPMOD(.LANCHOR0) - . = 0x30120 - 0x20114: 0x10 pages, page offset 0x120
70+
# LE32: 20114: pcalau12i $a0, 16
71+
# LE32-NEXT: addi.w $a0, $a0, 288
72+
# LE32-NEXT: bl 4
73+
74+
## LA64: DTPMOD(.LANCHOR0) - . = 0x301d8 - 0x201c8: 0x10 pages, page offset 0x1d8
75+
# LE64: 201c8: pcalau12i $a0, 16
76+
# LE64-NEXT: addi.d $a0, $a0, 472
77+
# LE64-NEXT: bl 4
78+
79+
#--- a.s
80+
la.tls.ld $a0, .LANCHOR0
81+
bl %plt(__tls_get_addr)
82+
83+
.section .tbss,"awT",@nobits
84+
.set .LANCHOR0, . + 0
85+
.zero 8
86+
87+
#--- tga.s
88+
.globl __tls_get_addr
89+
__tls_get_addr:

‎lld/test/ELF/loongarch-tls-le.s

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# REQUIRES: loongarch
2+
3+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %s -o %t.32.o
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t.64.o
5+
6+
# RUN: ld.lld %t.32.o -o %t.32
7+
# RUN: llvm-nm -p %t.32 | FileCheck --check-prefixes=NM %s
8+
# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=LE %s
9+
10+
# RUN: ld.lld %t.64.o -o %t.64
11+
# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=LE %s
12+
13+
# RUN: not ld.lld -shared %t.32.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
14+
15+
# ERR: error: relocation R_LARCH_TLS_LE_HI20 against .LANCHOR0 cannot be used with -shared
16+
# ERR: error: relocation R_LARCH_TLS_LE_LO12 against .LANCHOR0 cannot be used with -shared
17+
# ERR: error: relocation R_LARCH_TLS_LE_HI20 against a cannot be used with -shared
18+
# ERR: error: relocation R_LARCH_TLS_LE_LO12 against a cannot be used with -shared
19+
20+
# NM: {{0*}}00000008 b .LANCHOR0
21+
# NM: {{0*}}00000800 B a
22+
23+
## .LANCHOR0@tprel = 8
24+
## a@tprel = 0x800
25+
# LE: lu12i.w $a0, 0
26+
# LE-NEXT: ori $a0, $a0, 8
27+
# LE-NEXT: lu12i.w $a1, 0
28+
# LE-NEXT: ori $a1, $a1, 2048
29+
# LE-EMPTY:
30+
31+
.text
32+
_start:
33+
la.tls.le $a0, .LANCHOR0
34+
la.tls.le $a1, a
35+
36+
.section .tbss,"awT",@nobits
37+
.space 8
38+
.LANCHOR0:
39+
.space 0x800-8
40+
.globl a
41+
a:
42+
.zero 4

‎lld/test/lit.cfg.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
"ARM": "arm",
7878
"AVR": "avr",
7979
"Hexagon": "hexagon",
80+
"LoongArch": "loongarch",
8081
"Mips": "mips",
8182
"MSP430": "msp430",
8283
"PowerPC": "ppc",

0 commit comments

Comments
 (0)
Please sign in to comment.