[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