| Issue |
184854
|
| Summary |
riscv assembly operand using label arithmetic with relaxation enabled produces spurious reloc
|
| Labels |
backend:RISC-V
|
| Assignees |
|
| Reporter |
frobtech
|
Assembling the following input file (e.g. `clang --target=riscv64-fuchsia -c foo.s`):
```
li t0, (9f - 0f)
sd t0, (a0)
lla t0, 0f
sd t0, (a0)
0:lw t1, (a0)
1:j 1b
9:ret
```
produces:
```
Disassembly of section .text:
0000000000000000 <.text>:
0: 00000293 li t0, 0x0
0000000000000000: R_RISCV_NONE .Ltmp0
4: 00553023 sd t0, 0x0(a0)
0000000000000008 <.Lpcrel_hi0>:
8: 00000297 auipc t0, 0x0
0000000000000008: R_RISCV_PCREL_HI20 .Ltmp1
0000000000000008: R_RISCV_RELAX *ABS*
c: 00028293 mv t0, t0
000000000000000c: R_RISCV_PCREL_LO12_I .Lpcrel_hi0
000000000000000c: R_RISCV_RELAX *ABS*
10: 00553023 sd t0, 0x0(a0)
0000000000000014 <.Ltmp1>:
14: 00052303 lw t1, 0x0(a0)
18: a001 j 0x18 <.Ltmp1+0x4>
0000000000000018: R_RISCV_PCREL_LO12_S .Ltmp1
000000000000001a <.Ltmp0>:
1a: 8082 ret
```
The reloc at .text+0x18 is spurious, and the NONE reloc at .text+0 is highly suspect. It seems to be the result of some confusion that arises when label arithmetic is used across a range that includes relaxable sequences.
With `.option norelax`, this input produces no relocs at all, as expected.
The GNU assembler simply refuses to accept _any_ label arithmetic in an operand for riscv, AFAICT: `illegal operands `li t0,(9f-0f)'`. In fact, it refuses even with `.option norelax` and `.option norvc`, which ISTM are enough to make even a simple-minded assembler able to ensure this particular case of label arithmetic is OK. (The `norvc` seems relevant because the `j` at .text+0x18 could in the general case be relaxable between 16-bit and 32-bit forms based on the jump distance. Here it doesn't take much for a slightly savvy assembler to see that this particular jump distance is immediately known and cannot change so the assembler's first pass could actually tell that it can use the shorter instruction.) Not only that, GAS even rejects label arithmetic when the labels are both in the same other non-code section (and fragment) where no relocation is possible.
So it seems that the LLVM assembler could be quite extreme in rejecting all cases of label arithmetic as the GNU assembler does. It would be nice at least to use a better error message than just "illegal operand", such as "label arithmetic not permitted here" or whatever.
If we want to go beyond what GNU supports, then it at least seems easily safe to accept a case like this when `norelax` and `norvc` are in force, to keep it really simple. It doesn't seem all that involved to determine that the span in question has nothing relaxable (including possible RVC instruction choice), and it could get arbitrarily fancy with analysis to determine when a particular _expression_ is actually safely constant through possible relaxation stages (assembly and link time).
But it seems the only real mandate is just to error out reliably rather than produce bogus relocs. Note there could be existing users who are working around (intentionally or otherwise) via `.option norelax` if they've only ever used LLVM and not the GNU assembler, but I think it should not be controversial to break those cases that were never supported by GNU.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs