[llvm] [AVR] Fix parsing & emitting relative jumps (PR #102936)

via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 26 05:08:18 PDT 2024


aykevl wrote:

This patch makes it so that relative branches are typically resolved at compile time, with no emitted relocations.
That's not like avr-gcc which _does_ seem to emit relocations every time.
For example, with this code:

```c
void asdf(void);

void foobar(char x) {
        while (x != 0) {
                asdf();
                x--;
        }
}
```

I get the following output for avr-gcc 5.4.0 (Debian), which includes relocations:

```
00000000 <foobar>:
   0:   push    r28
   2:   mov     r28, r24
   4:   and     r28, r28
   6:   breq    .+0             ; 0x8 <foobar+0x8>
                        6: R_AVR_7_PCREL        .text+0xe
   8:   rcall   .+0             ; 0xa <foobar+0xa>
                        8: R_AVR_13_PCREL       asdf
   a:   subi    r28, 0x01       ; 1
   c:   rjmp    .+0             ; 0xe <foobar+0xe>
                        c: R_AVR_13_PCREL       .text+0x4
   e:   pop     r28
  10:   ret
```

And the following for avr-gcc 14.1.0 in Fedora 40, which also includes relocations:

```
00000000 <foobar>:
   0:   push    r28
   2:   mov     r28, r24

00000004 <.L2>:
   4:   cpse    r28, r1
   6:   rjmp    .+0             ; 0x8 <.L2+0x4>
                        6: R_AVR_13_PCREL       .L3
   8:   pop     r28
   a:   ret

0000000c <.L3>:
   c:   rcall   .+0             ; 0xe <.L3+0x2>
                        c: R_AVR_13_PCREL       asdf
   e:   subi    r28, 0x01       ; 1
  10:   rjmp    .+0             ; 0x12 <.L3+0x6>
                        10: R_AVR_13_PCREL      .L2
```

But Clang outputs the following, with no relocations:

```
00000000 <foobar>:
   0:   push    r17
   2:   mov     r17, r24
   4:   cpi     r17, 0x00       ; 0
   6:   breq    .+8             ; 0x10 <foobar+0x10>
   8:   call    0       ; 0x0 <foobar>
                        8: R_AVR_CALL   asdf
   c:   dec     r17
   e:   rjmp    .-12            ; 0x4 <foobar+0x4>
  10:   pop     r17
  12:   ret
```

(In all cases, I compiled to an object file and disassembled using `avr-objdump -dr`).

I don't know why this is, but my guess would be to support linker relaxation.

In any case:

> ... which causes most of the relative jumps to be actually resolved late, by the linker, which applies the offsetting logic on its own, hiding the issue within LLVM.

I think that would in fact be a reasonable solution: to let the linker deal with relocation offsets in all cases.



https://github.com/llvm/llvm-project/pull/102936


More information about the llvm-commits mailing list