Index: lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -41,11 +41,18 @@ void setForceRelocs() { ForceRelocs = true; } + // Returns true if relocations will be forced for shouldForceRelocation by + // default. This will be true if relaxation is enabled or had previously + // been enabled. + bool willForceRelocations() const { + return ForceRelocs || STI.getFeatureBits()[RISCV::FeatureRelax]; + } + // Generate diff expression relocations if the relax feature is enabled or had // previously been enabled, otherwise it is safe for the assembler to // calculate these internally. bool requiresDiffExpressionRelocations() const override { - return STI.getFeatureBits()[RISCV::FeatureRelax] || ForceRelocs; + return willForceRelocations(); } // Return Size with extra Nop Bytes for alignment directive in code section. Index: lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp @@ -11,9 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "RISCV.h" #include "RISCVMCExpr.h" +#include "MCTargetDesc/RISCVAsmBackend.h" +#include "RISCV.h" #include "RISCVFixupKinds.h" +#include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCStreamer.h" @@ -87,6 +89,16 @@ // ( + ). The Fixup // is pcrel relative to the VK_RISCV_PCREL_LO fixup, so we need to add the // offset to the VK_RISCV_PCREL_HI Fixup from VK_RISCV_PCREL_LO to correct. + + // Don't try to evaluate if the fixup will be forced as a relocation (e.g. + // as linker relaxation is enabled). If we evaluated pcrel_lo in this case, + // the modified fixup will be converted into a relocation that no longer + // points to the pcrel_hi as the linker requires. + auto &RAB = + static_cast(Layout->getAssembler().getBackend()); + if (RAB.willForceRelocations()) + return false; + MCValue AUIPCLoc; if (!getSubExpr()->evaluateAsValue(AUIPCLoc, *Layout)) return false; Index: test/MC/RISCV/linker-relaxation.s =================================================================== --- test/MC/RISCV/linker-relaxation.s +++ test/MC/RISCV/linker-relaxation.s @@ -121,14 +121,10 @@ # RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_hi(bar), kind: fixup_riscv_pcrel_hi20 # RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax -# TODO/FIXME: The generated PCREL_LO relocations are incorrect. -# RISCVMCExpr::evaluatePCRelLo should not be evaluating the fixup when linker -# relaxation is enabled. - addi t1, t1, %pcrel_lo(2b) # NORELAX-RELOC-NOT: R_RISCV_PCREL_LO12_I # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_PCREL_LO12_I bar 0x4 +# RELAX-RELOC: R_RISCV_PCREL_LO12_I .Ltmp1 0x0 # RELAX-RELOC: R_RISCV_RELAX - 0x0 # RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_lo(.Ltmp1), kind: fixup_riscv_pcrel_lo12_i # RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax @@ -136,7 +132,7 @@ sb t1, %pcrel_lo(2b)(a2) # NORELAX-RELOC-NOT: R_RISCV_PCREL_LO12_S # NORELAX-RELOC-NOT: R_RISCV_RELAX -# RELAX-RELOC: R_RISCV_PCREL_LO12_S bar 0x8 +# RELAX-RELOC: R_RISCV_PCREL_LO12_S .Ltmp1 0x0 # RELAX-RELOC: R_RISCV_RELAX - 0x0 # RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_lo(.Ltmp1), kind: fixup_riscv_pcrel_lo12_s # RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax