diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -194,6 +194,10 @@ bool RISCVELFStreamer::requiresFixups(MCContext &C, const MCExpr *Value, const MCExpr *&LHS, const MCExpr *&RHS) { + auto IsEHOrAppleSection = [](const MCSection &S) -> bool { + return S.getName() == ".eh_frame" || S.getName() == ".apple_names" || + S.getName() == ".apple_types"; + }; const auto *MBE = dyn_cast(Value); if (MBE == nullptr) return false; @@ -211,21 +215,23 @@ MCConstantExpr::create(E.getConstant(), C), C); RHS = E.getSymB(); - // If either symbol is in a text section, we need to delay the relocation - // evaluation as relaxation may alter the size of the symbol. + // Avoid R_RISCV_{ADD,SUB}* if Kind is not VK_None, e.g. A@plt - B + C. + if (E.getSymA()->getKind() != MCSymbolRefExpr::VK_None) + return false; + + // At this point we should emit ADD/SUB pairs for most A - B + C expressions. + // Unfortunately, MCDwarf has some instances like FrameEmitterImpl::EmitCIE + // that need to avoid ADD/SUB while it is unknown that A is in a section. For + // .apple_names/.apple_types. They are fixed-size and do not need fixups. + // llvm-dwarfdump --apple-names does not process R_RISCV_{ADD,SUB}32 in them. // - // Unfortunately, we cannot identify if the symbol was built with relaxation - // as we do not track the state per symbol or section. However, BFD will - // always emit the relocation and so we follow suit which avoids the need to - // track that information. - if (A.isInSection() && A.getSection().getKind().isText()) - return true; - if (B.isInSection() && B.getSection().getKind().isText()) - return true; + // For now, hard code these sections that avoid ADD/SUB. + if (A.isInSection()) + return !IsEHOrAppleSection(A.getSection()); + if (B.isInSection()) + return !IsEHOrAppleSection(B.getSection()); - // Support cross-section symbolic differences ... - return A.isInSection() && B.isInSection() && - A.getSection().getName() != B.getSection().getName(); + return false; } void RISCVELFStreamer::reset() { diff --git a/llvm/test/MC/RISCV/riscv64-64b-pcrel.s b/llvm/test/MC/RISCV/riscv64-64b-pcrel.s --- a/llvm/test/MC/RISCV/riscv64-64b-pcrel.s +++ b/llvm/test/MC/RISCV/riscv64-64b-pcrel.s @@ -1,9 +1,15 @@ # RUN: llvm-mc -triple riscv64-unknown-linux-gnu -filetype obj -o - %s \ # RUN: | llvm-readobj -r - | FileCheck %s -# RUN: not llvm-mc -triple riscv64-unknown-linux-gnu -filetype obj --defsym ERR=1 -o /dev/null %s 2>&1 \ -# 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 @@ -18,20 +24,26 @@ # 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: 0x8 R_RISCV_ADD64 nw 0x0 +# CHECK-NEXT: 0x8 R_RISCV_SUB64 extern 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 @@ -42,17 +54,10 @@ .quad x-y .section .nonalloc_w; nw: -.ifdef ERR -# ERROR: :[[#@LINE+1]]:7: error: unsupported relocation type .quad extern-nw -# 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