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 @@ -207,65 +207,76 @@ static bool requiresFixups(MCContext &C, const MCExpr *Value, const MCExpr *&LHS, const MCExpr *&RHS) { + auto IsDebugOrEHFrameSection = [](const MCSection &S) -> bool { + return S.getKind().isMetadata() || S.getName() == ".eh_frame"; + }; + 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(); - return (A.isInSection() ? A.getSection().hasInstructions() - : !A.getName().empty()) || - (B.isInSection() ? B.getSection().hasInstructions() - : !B.getName().empty()); + // TODO: if we are emitting code for the compact code-model, we should avoid + // the fixups here as we should relax the pair-wise relocation to a + // R_RISCV_[32|64|128]_PCREL instead. + + // Avoid relaxation for symbolic difference in debug and eh_frame sections + if (A.isInSection()) + return !IsDebugOrEHFrameSection(A.getSection()); + if (B.isInSection()) + return !IsDebugOrEHFrameSection(B.getSection()); + // as well as for absolute symbols. + return !A.getName().empty() || !B.getName().empty(); } void reset() override { static_cast(getTargetStreamer())->reset(); MCELFStreamer::reset(); } public: RISCVELFStreamer(MCContext &C, std::unique_ptr MAB, 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 { 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()); unsigned Add, Sub; std::tie(Add, Sub) = getRelocPairForSize(Size); DF->getFixups().push_back(MCFixup::create( DF->getContents().size(), A, static_cast(Add), Loc)); DF->getFixups().push_back(MCFixup::create( DF->getContents().size(), B, static_cast(Sub), Loc)); DF->getContents().resize(DF->getContents().size() + Size, 0); } }; } // namespace namespace llvm { MCELFStreamer *createRISCVELFStreamer(MCContext &C, std::unique_ptr MAB, diff --git a/llvm/test/MC/RISCV/instr-profile.s b/llvm/test/MC/RISCV/instr-profile.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/instr-profile.s @@ -0,0 +1,60 @@ +# RUN: llvm-mc -triple riscv64-unknown-linux-gnu -filetype obj -o - %s | llvm-readobj -r - | FileCheck %s + +# CHECK: Relocations [ +# CHECK: .rela.text { +# CHECK: 0x0 R_RISCV_HI20 .L__profc_f 0x0 +# CHECK: 0x4 R_RISCV_LO12_I .L__profc_f 0x0 +# CHECK: 0xE R_RISCV_LO12_S .L__profc_f 0x0 +# CHECK: } + +# CHECK: .rela__llvm_prf_data { +# CHECK: 0x10 R_RISCV_ADD64 .L__profc_f 0x0 +# CHECK-NEXT: 0x10 R_RISCV_SUB64 .L__profd_f 0x0 +# CHECK: } +# CHECK: ] + + .text + + .attribute 4, 16 + .attribute 5, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0" + + .globl f + .p2align 1 + .type f,@function +f: + lui a1, %hi(.L__profc_f) + ld a0, %lo(.L__profc_f)(a1) + addi a2, a0, 1 + li a0, 1 + sd a2, %lo(.L__profc_f)(a1) + ret +.Lfunc_end0: + .size f, .Lfunc_end0-f + + .type .L__profc_f,@object + .section __llvm_prf_cnts,"aGw",@progbits,__profc_f + .p2align 3 +.L__profc_f: + .zero 8 + .size .L__profc_f, 8 + + .type .L__profd_f,@object + .section __llvm_prf_data,"aGw",@progbits,__profc_f + .p2align 3 +.L__profd_f: + .quad -3706093650706652785 # 0xcc914f75dd4ca18f + .quad 24 # 0x18 + .quad .L__profc_f-.L__profd_f + .quad 0 + .quad 0 + .word 1 # 0x1 + .zero 4 + .size .L__profd_f, 48 + + .type .L__llvm_prf_nm,@object + .section __llvm_prf_names,"aR",@progbits,unique,1 +.L__llvm_prf_nm: + .ascii "\001\tx\332K\003\000\000g\000g" + .size .L__llvm_prf_nm, 11 + + .section ".note.GNU-stack","",@progbits