-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lld][LoongArch] Support the R_LARCH_CALL36 relocation type #73346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lld @llvm/pr-subscribers-lld-elf Author: Lu Weining (SixWeining) ChangesR_LARCH_CALL36 was designed for function call on medium code model where the 2 instructions (pcaddu18i + jirl) must be adjacent. This is expected to replace current medium code model implementation, i.e. R_LARCH_PCALA_{HI20,LO12} on pcalau12i + jirl. See loongson/la-abi-specs#3 for more details. Full diff: https://github.com/llvm/llvm-project/pull/73346.diff 3 Files Affected:
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index d3a538577a59a5d..85debb925754532 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -464,6 +464,7 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
case R_LARCH_B16:
case R_LARCH_B21:
case R_LARCH_B26:
+ case R_LARCH_CALL36:
return R_PLT_PC;
case R_LARCH_GOT_PC_HI20:
case R_LARCH_GOT64_PC_LO20:
@@ -591,6 +592,20 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
write32le(loc, setD10k16(read32le(loc), val >> 2));
return;
+ case R_LARCH_CALL36: {
+ // This relocation type is designed for the adjancent pcaddu18i+jirl pair,
+ // so patch these 2 instructions in one time.
+ checkInt(loc, val, 38, rel);
+ checkAlignment(loc, val, 4, rel);
+ // Since jirl performs sign extension on the offset immediate, adds (1<<17)
+ // to original val to get the correct hi20.
+ uint32_t hi20 = extractBits(val + (1 << 17), 37, 18);
+ uint32_t lo18 = val & (1 << 18) - 1;
+ write32le(loc, setJ20(read32le(loc), hi20));
+ write32le(loc + 4, setK16(read32le(loc + 4), lo18 >> 2));
+ return;
+ }
+
// Relocs intended for `addi`, `ld` or `st`.
case R_LARCH_PCALA_LO12:
// We have to again inspect the insn word to handle the R_LARCH_PCALA_LO12
diff --git a/lld/test/ELF/loongarch-call36-shared.s b/lld/test/ELF/loongarch-call36-shared.s
new file mode 100644
index 000000000000000..937f79bbb179946
--- /dev/null
+++ b/lld/test/ELF/loongarch-call36-shared.s
@@ -0,0 +1,41 @@
+# REQUIRES: loongarch
+# RUN: rm -rf %t && split-file %s %t
+# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-elf %t/a.s -o %t/a.o
+# RUN: ld.lld %t/a.o -shared -T %t/a.t -o %t/a.so
+# RUN: llvm-readelf -x .got.plt %t/a.so | FileCheck --check-prefix=GOTPLT %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t/a.so | FileCheck %s
+
+## PLT should be present in this case.
+# CHECK: Disassembly of section .plt:
+# CHECK: <.plt>:
+## bar@plt:
+# CHECK: 1234520: pcaddu12i $t3, 64{{$}}
+# CHECK-NEXT: ld.d $t3, $t3, 536{{$}}
+# CHECK-NEXT: jirl $t1, $t3, 0
+# CHECK-NEXT: nop
+
+# CHECK: Disassembly of section .text:
+# CHECK: <foo>:
+## hi20 = bar@plt - pc + (1 << 17) >> 18 = 0x1234520 - 0x1274670 + 0x20000 >> 18 = -1
+## lo18 = bar@plt - pc & (1 << 18) - 1 = 0x1234520 - 0x1274670 & 0x3ffff = -336
+# CHECK-NEXT: pcaddu18i $t0, -1{{$}}
+# CHECK-NEXT: jirl $zero, $t0, -336{{$}}
+
+# GOTPLT: section '.got.plt':
+# GOTPLT-NEXT: 0x01274728 00000000 00000000 00000000 00000000
+# GOTPLT-NEXT: 0x01274738 00452301 00000000
+
+#--- a.t
+SECTIONS {
+ .plt 0x1234500: { *(.plt) }
+ .text 0x1274670: { *(.text) }
+}
+
+#--- a.s
+.text
+.global foo
+.global bar
+foo:
+ pcaddu18i $t0, 0
+ jirl $zero, $t0, 0
+ .reloc foo, R_LARCH_CALL36, bar
diff --git a/lld/test/ELF/loongarch-call36.s b/lld/test/ELF/loongarch-call36.s
new file mode 100644
index 000000000000000..f32da0a123fe09d
--- /dev/null
+++ b/lld/test/ELF/loongarch-call36.s
@@ -0,0 +1,40 @@
+# REQUIRES: loongarch
+
+# RUN: llvm-mc --filetype=obj --triple=loongarch64-unknown-elf %s -o %t.o
+
+# RUN: ld.lld %t.o --section-start=.text=0x20010 --section-start=.sec.foo=0x60020 -o %t1
+# RUN: llvm-objdump --no-show-raw-insn -d %t1 | FileCheck --match-full-lines %s --check-prefix=CASE1
+## hi20 = target - pc + (1 << 17) >> 18 = 0x60020 - 0x20010 + 0x20000 >> 18 = 1
+## lo18 = target - pc & (1 << 18) - 1 = 0x60020 - 0x20010 & 0x3ffff = 16
+# CASE1: 20010: pcaddu18i $ra, 1
+# CASE1-NEXT: 20014: jirl $zero, $ra, 16
+
+# RUN: ld.lld %t.o --section-start=.text=0x20010 --section-start=.sec.foo=0x40020 -o %t2
+# RUN: llvm-objdump --no-show-raw-insn -d %t2 | FileCheck --match-full-lines %s --check-prefix=CASE2
+## hi20 = target - pc + (1 << 17) >> 18 = 0x40020 - 0x20010 + 0x20000 >> 18 = 1
+## lo18 = target - pc & (1 << 18) - 1 = 0x40020 - 0x20010 & 0x3ffff = -131056
+# CASE2: 20010: pcaddu18i $ra, 1
+# CASE2-NEXT: 20014: jirl $zero, $ra, -131056
+
+# RUN: not ld.lld %t.o --section-start=.text=0x20000 --section-start=.sec.foo=0x2000020000 -o /dev/null 2>&1 | \
+# RUN: FileCheck -DFILE=%t.o --check-prefix=ERROR-RANGE %s
+# ERROR-RANGE: error: [[FILE]]:(.text+0x0): relocation R_LARCH_CALL36 out of range: 137438953472 is not in [-137438953472, 137438953471]; references 'foo'
+
+## Impossible case in reality becasue all LoongArch instructions are fixed 4-bytes long.
+# RUN: not ld.lld %t.o --section-start=.text=0x20000 --section-start=.sec.foo=0x40001 -o /dev/null 2>&1 | \
+# RUN: FileCheck -DFILE=%t.o --check-prefix=ERROR-ALIGN %s
+# ERROR-ALIGN: error: [[FILE]]:(.text+0x0): improper alignment for relocation R_LARCH_CALL36: 0x20001 is not aligned to 4 bytes
+
+.text
+.global _start
+_start:
+1:
+ pcaddu18i $ra, 0
+ jirl $zero, $ra, 0
+ .reloc 1b, R_LARCH_CALL36, foo
+
+.section .sec.foo,"ax"
+.global foo
+foo:
+ nop
+ ret
|
Depends on #73345 |
R_LARCH_CALL36 was designed for function call on medium code model where the 2 instructions (pcaddu18i + jirl) must be adjacent. This is expected to replace current medium code model implementation, i.e. R_LARCH_PCALA_{HI20,LO12} on pcalau12i + jirl. See loongson/la-abi-specs#3 for more details.
d0be8c2
to
7cd89c3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch!
LGTM, though I'd wish that you gave more time before merging as many people are unavailable during the Christmas season. |
R_LARCH_CALL36 was designed for function call on medium code model where the 2 instructions (pcaddu18i + jirl) must be adjacent. This is expected to replace current medium code model implementation, i.e. R_LARCH_PCALA_{HI20,LO12} on pcalau12i + jirl. See loongson/la-abi-specs#3 for more details. (cherry picked from commit 88548df) Change-Id: Ib2271319acf0eb9313e2150e0bc4e5b30dddc96a
R_LARCH_CALL36 was designed for function call on medium code model where the 2 instructions (pcaddu18i + jirl) must be adjacent. This is expected to replace current medium code model implementation, i.e. R_LARCH_PCALA_{HI20,LO12} on pcalau12i + jirl.
See loongson/la-abi-specs#3 for more details.