diff options
author | Fangrui Song <i@maskray.me> | 2023-03-14 15:17:38 -0700 |
---|---|---|
committer | Tobias Hieta <tobias@hieta.se> | 2023-03-28 08:54:58 +0200 |
commit | 1c1ab11d6e1e45a49fd543fa485d2b1701487e06 (patch) | |
tree | 618583d9a9033e174259f64b82612baaaa249dc6 | |
parent | 34194d85544f9c5295d244ca91e35abcfef98f19 (diff) | |
download | llvm-1c1ab11d6e1e45a49fd543fa485d2b1701487e06.tar.gz |
[RISCV][MC] Adjust conditions to emit R_RISCV_ADD*/R_RISCV_SUB* pairs
D132262 tried to simplify `IsMetadataOrEHFrameSection` originally introduced in
D127549 but caused a regression as `.quad` directives in
```
.section .note,"a",@note; note:
.quad extern-note # extern is undefined
.section .rodata,"a",@progbits; rodata:
.quad extern-rodata # extern is undefined
.section .nonalloc,"",@progbits; nw:
.quad extern-nw
```
are incorrectly rejected: these differences may be link-time constants and
are allowed in GNU assembler and LLVM MC's non-RISC-V ports.
Relax the conditions to allow these cases. For A-B, A may be defined later, but
this requiresFixups call has to eagerly make a decision. For now, emit ADD/SUB
unless A is `.L*`. This euristic handles many temporary label differences for
.debug_* and .apple_types sections. Ideally we should delay the decision of
PC-relative vs ADD/SUB until A is defined.
Reviewed By: compnerd
Differential Revision: https://reviews.llvm.org/D145474
(cherry picked from commit 2f5fe16e6d29c55ebd9ec098b03d4de47a804a18)
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp | 10 | ||||
-rw-r--r-- | llvm/test/MC/RISCV/riscv64-64b-pcrel.s | 26 |
2 files changed, 27 insertions, 9 deletions
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index 379aaa713a00..88b926fce2aa 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -239,6 +239,16 @@ bool RISCVELFStreamer::requiresFixups(MCContext &C, const MCExpr *Value, if (B.isInSection() && B.getSection().getKind().isText()) return true; + // If A is undefined and B is defined, we should emit ADD/SUB for A-B. + // Unfortunately, A may be defined later, but this requiresFixups call has to + // eagerly make a decision. For now, emit ADD/SUB unless A is .L*. This + // heuristic handles many temporary label differences for .debug_* and + // .apple_types sections. + // + // TODO Implement delayed relocation decision. + if (!A.isInSection() && !A.isTemporary() && B.isInSection()) + return true; + // Support cross-section symbolic differences ... return A.isInSection() && B.isInSection() && A.getSection().getName() != B.getSection().getName(); diff --git a/llvm/test/MC/RISCV/riscv64-64b-pcrel.s b/llvm/test/MC/RISCV/riscv64-64b-pcrel.s index 7df442874fb4..9dd7879fc805 100644 --- a/llvm/test/MC/RISCV/riscv64-64b-pcrel.s +++ b/llvm/test/MC/RISCV/riscv64-64b-pcrel.s @@ -4,6 +4,14 @@ # RUN: | FileCheck %s --check-prefix=ERROR # CHECK: Relocations [ +# CHECK-NEXT: Section ({{.*}}) .rela.note { +# CHECK-NEXT: 0x0 R_RISCV_ADD64 extern 0x0 +# CHECK-NEXT: 0x0 R_RISCV_SUB64 note 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: Section ({{.*}}) .rela.rodata { +# CHECK-NEXT: 0x0 R_RISCV_ADD64 extern 0x0 +# CHECK-NEXT: 0x0 R_RISCV_SUB64 rodata 0x0 +# CHECK-NEXT: } # CHECK-NEXT: Section ({{.*}}) .rela.alloc_w { # CHECK-NEXT: 0x0 R_RISCV_ADD64 extern 0x0 # CHECK-NEXT: 0x0 R_RISCV_SUB64 w 0x0 @@ -24,20 +32,24 @@ # CHECK-NEXT: 0x0 R_RISCV_ADD64 x 0x0 # CHECK-NEXT: 0x0 R_RISCV_SUB64 y 0x0 # CHECK-NEXT: } +# CHECK-NEXT: Section ({{.*}}) .rela.nonalloc_w { +# CHECK-NEXT: 0x0 R_RISCV_ADD64 extern 0x0 +# CHECK-NEXT: 0x0 R_RISCV_SUB64 nw 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: Section ({{.*}}) .rela.nonalloc_x { +# CHECK-NEXT: 0x0 R_RISCV_ADD64 ny 0x0 +# CHECK-NEXT: 0x0 R_RISCV_SUB64 nx 0x0 +# CHECK-NEXT: } # CHECK-NEXT: Section ({{.*}}) .rela.nonalloc_y { # CHECK-NEXT: 0x0 R_RISCV_ADD64 nx 0x0 # CHECK-NEXT: 0x0 R_RISCV_SUB64 ny 0x0 # CHECK-NEXT: } # CHECK-NEXT: ] -.ifdef ERR .section .note,"a",@note; note: -# ERROR: :[[#@LINE+1]]:7: error: unsupported relocation type .quad extern-note .section .rodata,"a",@progbits; rodata: -# ERROR: :[[#@LINE+1]]:7: error: unsupported relocation type .quad extern-rodata -.endif .section .alloc_w,"aw",@progbits; w: .quad extern-w # extern is undefined @@ -53,17 +65,13 @@ w1: .quad x-y .section .nonalloc_w; nw: -.ifdef ERR -# ERROR: :[[#@LINE+1]]:7: error: unsupported relocation type .quad extern-nw +.ifdef ERR # ERROR: :[[#@LINE+1]]:7: error: symbol 'extern' can not be undefined in a subtraction expression .quad nw-extern .endif .section .nonalloc_x; nx: -.ifdef ERR -# ERROR: :[[#@LINE+1]]:7: error: unsupported relocation type .quad ny-nx -.endif .section .nonalloc_y; ny: .quad nx-ny |