diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -129,6 +129,14 @@ llvm_unreachable("Need to implement hook if target has custom fixups"); } + virtual bool handleAddSubRelocations(const MCAsmLayout &Layout, + const MCFragment &F, + const MCFixup &Fixup, + const MCValue &Target, + uint64_t &FixedValue) const { + return false; + } + /// Apply the \p Value for given \p Fixup into the provided data fragment, at /// the offset specified by the fixup and following the fixup kind as /// appropriate. Errors (such as an out of range fixup value) should be diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -287,6 +287,13 @@ WasForced = true; } + // A linker relaxation target may emit ADD/SUB relocations for A-B+C. Let + // recordRelocation handle non-VK_None cases like A@plt-B+C. + if (!IsResolved && Target.getSymA() && Target.getSymB() && + Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None && + getBackend().handleAddSubRelocations(Layout, *DF, Fixup, Target, Value)) + return true; + return IsResolved; } @@ -303,7 +310,7 @@ case MCFragment::FT_Fill: { auto &FF = cast(F); int64_t NumValues = 0; - if (!FF.getNumValues().evaluateAsAbsolute(NumValues, Layout)) { + if (!FF.getNumValues().evaluateKnownAbsolute(NumValues, Layout)) { getContext().reportError(FF.getLoc(), "expected assembly-time absolute expression"); return 0; diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -628,7 +628,14 @@ if ((&SecA != &SecB) && !Addrs) return; - if (Layout) { + // When layout is available, we can generally compute the difference using the + // getSymbolOffset path, which also avoids the possible slow fragment walk. + // However, linker relaxation may cause incorrect fold of A-B if A and B are + // separated by a linker-relaxable instruction. If the section contains + // instructions and InSet is false (not expressions in directive like + // .size/.fill), disable the fast path. + if (Layout && (InSet || !SecA.hasInstructions() || + !Asm->getContext().getTargetTriple().isRISCV())) { // If both symbols are in the same fragment, return the difference of their // offsets. canGetFragmentOffset(FA) may be false. if (FA == FB && !SA.isVariable() && !SB.isVariable()) { diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -53,6 +53,10 @@ const MCValue &Target, uint64_t &Value, bool &WasForced) override; + bool handleAddSubRelocations(const MCAsmLayout &Layout, const MCFragment &F, + const MCFixup &Fixup, const MCValue &Target, + uint64_t &FixedValue) const override; + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, bool IsResolved, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -281,7 +281,7 @@ int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, Layout.getAssembler())) return false; - bool IsAbsolute = AddrDelta.evaluateAsAbsolute(Value, Layout); + bool IsAbsolute = AddrDelta.evaluateKnownAbsolute(Value, Layout); assert(IsAbsolute && "CFA with invalid expression"); (void)IsAbsolute; @@ -572,6 +572,48 @@ return true; } +bool RISCVAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout, + const MCFragment &F, + const MCFixup &Fixup, + const MCValue &Target, + uint64_t &FixedValue) const { + uint64_t FixedValueA, FixedValueB; + unsigned TA = 0, TB = 0; + switch (Fixup.getKind()) { + case llvm::FK_Data_1: + TA = ELF::R_RISCV_ADD8; + TB = ELF::R_RISCV_SUB8; + break; + case llvm::FK_Data_2: + TA = ELF::R_RISCV_ADD16; + TB = ELF::R_RISCV_SUB16; + break; + case llvm::FK_Data_4: + TA = ELF::R_RISCV_ADD32; + TB = ELF::R_RISCV_SUB32; + break; + case llvm::FK_Data_8: + TA = ELF::R_RISCV_ADD64; + TB = ELF::R_RISCV_SUB64; + break; + default: + llvm_unreachable("unsupported fixup size"); + } + MCValue A = MCValue::get(Target.getSymA(), nullptr, Target.getConstant()); + MCValue B = MCValue::get(Target.getSymB()); + auto FA = MCFixup::create( + Fixup.getOffset(), nullptr, + static_cast(FirstLiteralRelocationKind + TA)); + auto FB = MCFixup::create( + Fixup.getOffset(), nullptr, + static_cast(FirstLiteralRelocationKind + TB)); + auto &Asm = Layout.getAssembler(); + Asm.getWriter().recordRelocation(Asm, Layout, &F, FA, A, FixedValueA); + Asm.getWriter().recordRelocation(Asm, Layout, &F, FB, B, FixedValueB); + FixedValue = FixedValueA - FixedValueB; + return true; +} + void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h @@ -15,8 +15,6 @@ using namespace llvm; class RISCVELFStreamer : public MCELFStreamer { - static bool requiresFixups(MCContext &C, const MCExpr *Value, - const MCExpr *&LHS, const MCExpr *&RHS); void reset() override; public: @@ -24,8 +22,6 @@ std::unique_ptr MOW, std::unique_ptr MCE) : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {} - - void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override; }; namespace llvm { 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 @@ -122,84 +122,11 @@ cast(Symbol).setOther(ELF::STO_RISCV_VARIANT_CC); } -bool RISCVELFStreamer::requiresFixups(MCContext &C, const MCExpr *Value, - const MCExpr *&LHS, const MCExpr *&RHS) { - const auto *MBE = dyn_cast(Value); - if (MBE == nullptr) - return false; - - MCValue E; - if (!Value->evaluateAsRelocatable(E, nullptr, nullptr)) - return false; - if (E.getSymA() == nullptr || E.getSymB() == nullptr) - return false; - - const auto &A = E.getSymA()->getSymbol(); - const auto &B = E.getSymB()->getSymbol(); - - LHS = MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C), - MCConstantExpr::create(E.getConstant(), C), C); - RHS = E.getSymB(); - - // Avoid ADD/SUB if Kind is not VK_None, e.g. A@plt - B + C. - if (E.getSymA()->getKind() != MCSymbolRefExpr::VK_None) - return false; - - // If either symbol is in a text section, we need to delay the relocation - // evaluation as relaxation may alter the size of the symbol. - // - // 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; - - // 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(); -} - void RISCVELFStreamer::reset() { static_cast(getTargetStreamer())->reset(); MCELFStreamer::reset(); } -void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc) { - const MCExpr *A, *B; - if (!requiresFixups(getContext(), Value, A, B)) - return MCELFStreamer::emitValueImpl(Value, Size, Loc); - - MCStreamer::emitValueImpl(Value, Size, Loc); - - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - MCDwarfLineEntry::make(this, getCurrentSectionOnly()); - - MCFixupKind Add, Sub; - std::tie(Add, Sub) = RISCV::getRelocPairForSize(Size); - - DF->getFixups().push_back( - MCFixup::create(DF->getContents().size(), A, Add, Loc)); - DF->getFixups().push_back( - MCFixup::create(DF->getContents().size(), B, Sub, Loc)); - - DF->getContents().resize(DF->getContents().size() + Size, 0); -} - namespace llvm { MCELFStreamer *createRISCVELFStreamer(MCContext &C, std::unique_ptr MAB, diff --git a/llvm/test/CodeGen/RISCV/fixups-diff.ll b/llvm/test/CodeGen/RISCV/fixups-diff.ll --- a/llvm/test/CodeGen/RISCV/fixups-diff.ll +++ b/llvm/test/CodeGen/RISCV/fixups-diff.ll @@ -3,13 +3,12 @@ ; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=-relax %s -o - \ ; RUN: | llvm-readobj -r - | FileCheck %s -; Check that a difference between two symbols in the same fragment -; causes relocations to be emitted. -; -; This specific test is checking that the size of the function in -; the debug information is represented by a relocation. This isn't -; an assembly test as the assembler takes a different path through -; LLVM, which is already covered by the fixups-expr.s test. +;; b-a in the inline asm is unaffected by linker relaxation, so we don't emit +;; relocations. + +;; b-a in the inline asm and DW_AT_high_pc are unaffected by linker relaxation, +;; so we don't emit ADD/SUB relocations. +;; See also MC/RISCV/fixups-expr.s. source_filename = "tmp.c" target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" @@ -19,21 +18,17 @@ entry: %retval = alloca i32, align 4 store i32 0, ptr %retval, align 4 + call void asm sideeffect "a:\0Ab:\0A.dword b-a", ""() ret i32 0 } ; CHECK: Section {{.*}} .rela.debug_info { -; CHECK: 0x22 R_RISCV_ADD32 0x0 -; CHECK-NEXT: 0x22 R_RISCV_SUB32 0x0 -; CHECK: 0x2B R_RISCV_ADD32 0x0 -; CHECK-NEXT: 0x2B R_RISCV_SUB32 0x0 +; CHECK-NOT: R_RISCV_ADD32 ; CHECK: } ; CHECK: Section {{.*}} .rela.eh_frame { -; CHECK: 0x1C R_RISCV_32_PCREL 0x0 -; CHECK: 0x20 R_RISCV_ADD32 0x0 -; CHECK-NEXT: 0x20 R_RISCV_SUB32 0x0 -; CHECK: } +; CHECK-NEXT: 0x1C R_RISCV_32_PCREL 0x0 +; CHECK-NEXT: } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4, !5} diff --git a/llvm/test/CodeGen/RISCV/fixups-relax-diff.ll b/llvm/test/CodeGen/RISCV/fixups-relax-diff.ll deleted file mode 100644 --- a/llvm/test/CodeGen/RISCV/fixups-relax-diff.ll +++ /dev/null @@ -1,16 +0,0 @@ -; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=+relax %s -o - | llvm-readobj -r - | FileCheck %s -; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=-relax %s -o - | llvm-readobj -r - | FileCheck %s - -; This test checks that a diff inserted via inline assembly always causes -; relocations. This isn't an assembly test as the assembler takes a different -; path through LLVM, which is already covered by the fixups-expr.s test. - -define i32 @main() nounwind { -entry: - %retval = alloca i32, align 4 - store i32 0, ptr %retval, align 4 - ; CHECK: R_RISCV_ADD64 b - ; CHECK-NEXT: R_RISCV_SUB64 a - call void asm sideeffect "a:\0Ab:\0A.dword b-a", ""() - ret i32 0 -} diff --git a/llvm/test/DebugInfo/RISCV/dwarf-riscv-relocs.ll b/llvm/test/DebugInfo/RISCV/dwarf-riscv-relocs.ll --- a/llvm/test/DebugInfo/RISCV/dwarf-riscv-relocs.ll +++ b/llvm/test/DebugInfo/RISCV/dwarf-riscv-relocs.ll @@ -70,9 +70,9 @@ ; DWARF-DUMP-NEXT: Address Line Column File ISA Discriminator OpIndex Flags ; DWARF-DUMP-NEXT: ------------------ ------ ------ ------ --- ------------- ------- ------------- ; DWARF-DUMP-NEXT: 0x0000000000000000 2 0 0 0 0 0 is_stmt -; DWARF-DUMP-NEXT: 0x0000000000000014 3 5 0 0 0 0 is_stmt prologue_end -; DWARF-DUMP-NEXT: 0x0000000000000020 3 5 0 0 0 0 epilogue_begin -; DWARF-DUMP-NEXT: 0x0000000000000028 3 5 0 0 0 0 end_sequence +; DWARF-DUMP-NEXT: 0x000000000000001c 3 5 0 0 0 0 is_stmt prologue_end +; DWARF-DUMP-NEXT: 0x0000000000000028 3 5 0 0 0 0 epilogue_begin +; DWARF-DUMP-NEXT: 0x0000000000000030 3 5 0 0 0 0 end_sequence ; ModuleID = 'dwarf-riscv-relocs.c' source_filename = "dwarf-riscv-relocs.c" @@ -82,11 +82,14 @@ ; Function Attrs: noinline nounwind optnone define dso_local i32 @main() #0 !dbg !7 { entry: + call void @ext() %retval = alloca i32, align 4 store i32 0, ptr %retval, align 4 ret i32 0, !dbg !11 } +declare void @ext() + attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "frame-pointer"="all" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+relax" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} diff --git a/llvm/test/DebugInfo/RISCV/relax-debug-frame.ll b/llvm/test/DebugInfo/RISCV/relax-debug-frame.ll --- a/llvm/test/DebugInfo/RISCV/relax-debug-frame.ll +++ b/llvm/test/DebugInfo/RISCV/relax-debug-frame.ll @@ -5,11 +5,7 @@ ; ; RELAX: Section ({{.*}}) .rela.eh_frame { ; RELAX-NEXT: 0x1C R_RISCV_32_PCREL 0x0 -; RELAX-NEXT: 0x20 R_RISCV_ADD32 0x0 -; RELAX-NEXT: 0x20 R_RISCV_SUB32 0x0 ; RELAX-NEXT: 0x30 R_RISCV_32_PCREL 0x0 -; RELAX-NEXT: 0x34 R_RISCV_ADD32 0x0 -; RELAX-NEXT: 0x34 R_RISCV_SUB32 0x0 ; RELAX-NEXT: 0x44 R_RISCV_32_PCREL 0x0 ; RELAX-NEXT: 0x48 R_RISCV_ADD32 0x0 ; RELAX-NEXT: 0x48 R_RISCV_SUB32 0x0 diff --git a/llvm/test/ExecutionEngine/JITLink/RISCV/anonymous_symbol.s b/llvm/test/ExecutionEngine/JITLink/RISCV/anonymous_symbol.s --- a/llvm/test/ExecutionEngine/JITLink/RISCV/anonymous_symbol.s +++ b/llvm/test/ExecutionEngine/JITLink/RISCV/anonymous_symbol.s @@ -8,7 +8,7 @@ # can be calculated. # # CHECK: Creating defined graph symbol for ELF symbol "" -# CHECK: Creating defined graph symbol for ELF symbol "" +# CHECK: Creating defined graph symbol for ELF symbol "main" .text .globl main .p2align 2 diff --git a/llvm/test/MC/ELF/RISCV/gen-dwarf.s b/llvm/test/MC/ELF/RISCV/gen-dwarf.s --- a/llvm/test/MC/ELF/RISCV/gen-dwarf.s +++ b/llvm/test/MC/ELF/RISCV/gen-dwarf.s @@ -11,7 +11,7 @@ # RUN: llvm-mc -filetype=obj -triple=riscv64 -g -dwarf-version=5 -mattr=+relax < %s -o %t # RUN: llvm-dwarfdump -eh-frame -debug-line -debug-rnglists -v %t | FileCheck %s -# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC +# RUN: llvm-readobj -r -x .eh_frame %t | FileCheck %s --check-prefix=RELOC # CHECK: FDE # CHECK-NEXT: Format: DWARF32 @@ -46,8 +46,6 @@ # RELOC-NEXT: 0x25 R_RISCV_SET6 0x0 # RELOC-NEXT: 0x25 R_RISCV_SUB6 0x0 # RELOC-NEXT: 0x34 R_RISCV_32_PCREL 0x0 -# RELOC-NEXT: 0x38 R_RISCV_ADD32 0x0 -# RELOC-NEXT: 0x38 R_RISCV_SUB32 0x0 # RELOC-NEXT: } ## TODO A section needs two relocations. @@ -65,6 +63,13 @@ # RELOC-NEXT: R_RISCV_SUB16 0x0 # RELOC: } +# RELOC: Hex dump of section '.eh_frame': +# RELOC-NEXT: 0x00000000 +# RELOC-NEXT: 0x00000010 +# RELOC-NEXT: 0x00000020 +# RELOC-NEXT: 0x00000030 30000000 00000000 04000000 00000000 +# ^ address_range + .section .text.foo,"ax" .globl foo foo: diff --git a/llvm/test/MC/RISCV/cfi-advance.s b/llvm/test/MC/RISCV/cfi-advance.s --- a/llvm/test/MC/RISCV/cfi-advance.s +++ b/llvm/test/MC/RISCV/cfi-advance.s @@ -5,15 +5,13 @@ # CHECK: .rela.eh_frame { # CHECK-NEXT: 0x1C R_RISCV_32_PCREL 0x0 -# CHECK-NEXT: 0x20 R_RISCV_ADD32 0x0 -# CHECK-NEXT: 0x20 R_RISCV_SUB32 0x0 # CHECK-NEXT: } -# CHECK-DWARFDUMP: DW_CFA_advance_loc1 -# CHECK-DWARFDUMP-NEXT: DW_CFA_def_cfa_offset -# CHECK-DWARFDUMP-NEXT: DW_CFA_advance_loc2 -# CHECK-DWARFDUMP-NEXT: DW_CFA_def_cfa_offset -# CHECK-DWARFDUMP-NEXT: DW_CFA_advance_loc4 -# CHECK-DWARFDUMP-NEXT: DW_CFA_def_cfa_offset +# CHECK-DWARFDUMP: DW_CFA_advance_loc1: 104 +# CHECK-DWARFDUMP-NEXT: DW_CFA_def_cfa_offset: +8 +# CHECK-DWARFDUMP-NEXT: DW_CFA_advance_loc2: 259 +# CHECK-DWARFDUMP-NEXT: DW_CFA_def_cfa_offset: +8 +# CHECK-DWARFDUMP-NEXT: DW_CFA_advance_loc4: 65539 +# CHECK-DWARFDUMP-NEXT: DW_CFA_def_cfa_offset: +8 .text .globl test # -- Begin function test .p2align 1 diff --git a/llvm/test/MC/RISCV/fde-reloc.s b/llvm/test/MC/RISCV/fde-reloc.s --- a/llvm/test/MC/RISCV/fde-reloc.s +++ b/llvm/test/MC/RISCV/fde-reloc.s @@ -1,7 +1,7 @@ # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+relax < %s \ -# RUN: | llvm-readobj -r - | FileCheck %s +# RUN: | llvm-readobj -r -x .eh_frame - | FileCheck %s # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=-relax < %s \ -# RUN: | llvm-readobj -r - | FileCheck %s +# RUN: | llvm-readobj -r -x .eh_frame - | FileCheck %s # Ensure that the eh_frame records the symbolic difference with the paired # relocations always. @@ -13,6 +13,9 @@ # CHECK: Section (4) .rela.eh_frame { # CHECK-NEXT: 0x1C R_RISCV_32_PCREL 0x0 -# CHECK-NEXT: 0x20 R_RISCV_ADD32 0x0 -# CHECK-NEXT: 0x20 R_RISCV_SUB32 0x0 # CHECK-NEXT: } +# CHECK: Hex dump of section '.eh_frame': +# CHECK-NEXT: 0x00000000 10000000 00000000 017a5200 017c0101 +# CHECK-NEXT: 0x00000010 1b0c0200 10000000 18000000 00000000 +# CHECK-NEXT: 0x00000020 04000000 00000000 +# ^ address_range diff --git a/llvm/test/MC/RISCV/fixups-expr.s b/llvm/test/MC/RISCV/fixups-expr.s --- a/llvm/test/MC/RISCV/fixups-expr.s +++ b/llvm/test/MC/RISCV/fixups-expr.s @@ -1,20 +1,24 @@ # RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax %s \ # RUN: | llvm-readobj -r - | FileCheck -check-prefix RELAX %s # RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=-relax %s \ -# RUN: | llvm-readobj -r - | FileCheck -check-prefix RELAX %s +# RUN: | llvm-readobj -r - | FileCheck -check-prefix NORELAX %s # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax %s \ # RUN: | llvm-readobj -r - | FileCheck -check-prefix RELAX %s # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=-relax %s \ -# RUN: | llvm-readobj -r - | FileCheck -check-prefix RELAX %s +# RUN: | llvm-readobj -r - | FileCheck -check-prefix NORELAX %s -# Check that subtraction expressions are emitted as two relocations always. +# NORELAX: Relocations [ +# NORELAX-NEXT: .rela.text { +# NORELAX-NEXT: R_RISCV_CALL_PLT +# NORELAX-NEXT: } +# NORELAX-NEXT: ] .globl G1 .globl G2 .L1: G1: -addi a0, a0, 0 + call extern .L2: G2: 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,7 +1,6 @@ -# 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 +# RUN: llvm-mc -triple riscv64-unknown-linux-gnu -filetype obj %s -o %t +# RUN: llvm-readobj -r %t | FileCheck %s +# RUN: llvm-objdump -s %t | FileCheck %s --check-prefix=CONTENT # CHECK: Relocations [ # CHECK-NEXT: Section ({{.*}}) .rela.note { @@ -19,8 +18,6 @@ # CHECK-NEXT: 0x8 R_RISCV_SUB64 extern 0x0 # CHECK-NEXT: 0x10 R_RISCV_ADD32 x 0x0 # CHECK-NEXT: 0x10 R_RISCV_SUB32 w 0x0 -# CHECK-NEXT: 0x14 R_RISCV_ADD32 w1 0x0 -# CHECK-NEXT: 0x14 R_RISCV_SUB32 w 0x0 # CHECK-NEXT: 0x18 R_RISCV_ADD32 .L.str 0x0 # CHECK-NEXT: 0x18 R_RISCV_SUB32 w 0x0 # CHECK-NEXT: } @@ -35,6 +32,8 @@ # 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 @@ -46,6 +45,10 @@ # CHECK-NEXT: } # CHECK-NEXT: ] +# CONTENT: Contents of section .alloc_w: +# CONTENT-NEXT: 0000 00000000 00000000 00000000 00000000 +# CONTENT-NEXT: 0010 00000000 1c000000 00000000 + .section .note,"a",@note; note: .quad extern-note .section .rodata,"a",@progbits; rodata: @@ -66,10 +69,7 @@ .section .nonalloc_w; nw: .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: .quad ny-nx .section .nonalloc_y; ny: