[lld] [lld][ELF] Fix a corner case of elf::getLoongArchPageDelta (PR #71907)
Xi Ruoyao via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 20 09:23:57 PST 2023
xry111 wrote:
I made a brute force algorithm:
```python
def uintptr_t(x):
return x & ((1 << 64) - 1)
def ptrdiff_t(x):
x = uintptr_t(x)
if x & (1 << 63):
x = (1 << 64) - x
return x
def pcalau12i(pc, imm):
assert(imm in range(-0x80000, 0x80000))
return uintptr_t(pc + (imm << 12)) & ~0xfff
def simm(width, bits):
assert(bits >= 0 and bits < (1 << width))
return bits - ((1 << width) if bits & (1 << (width - 1)) else 0)
def reloc(dest, pc):
lo12 = dest & 0xfff
a1_first_val = uintptr_t(simm(12, lo12))
for hi20 in range(-0x80000, 0x80000):
a0 = pcalau12i(pc, hi20)
# We need to insert something into a1[32..] to make a0 + a1 = dest,
# i. e. a1 = dest - a0.
want_a1 = uintptr_t(dest - a0)
if (want_a1 & 0xffffffff) != (a1_first_val & 0xffffffff):
continue
lo20 = (want_a1 >> 32) & 0xfffff
hi12 = (want_a1 >> 52) & 0xfff
return (lo12, hi20 & 0xfffff, lo20, hi12)
raise Exception("should not be reachable")
def test(dest, pc):
reloc(dest, pc)
lo12, hi20, lo20, hi12 = reloc(dest, pc)
a0 = pcalau12i(pc, simm(20, hi20))
a1 = uintptr_t(simm(12, lo12))
a1 &= ~(0xffffffff << 32)
a1 |= lo20 << 32
a1 |= hi12 << 52
assert(uintptr_t(a1 + a0) == dest)
test(0xfffffffffffff8ee, 0x8ee)
test(0, 0x80000ffc)
test(0, 0x80001000)
```
Now I need to optimize `for hi20 in range(-0x80000, 0x80000):` line, limiting hi20 into one or two possible values.
https://github.com/llvm/llvm-project/pull/71907
More information about the llvm-commits
mailing list