Index: include/llvm/MC/MCAsmBackend.h =================================================================== --- include/llvm/MC/MCAsmBackend.h +++ include/llvm/MC/MCAsmBackend.h @@ -76,6 +76,13 @@ return false; } + /// Same as shouldForceRelocation but also apply Fixup. + virtual bool shouldForceRelocationWithApplyFixup(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target) { + 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 Index: lib/MC/MCAssembler.cpp =================================================================== --- lib/MC/MCAssembler.cpp +++ lib/MC/MCAssembler.cpp @@ -683,6 +683,14 @@ // writer of the relocation, and give it an opportunity to adjust the // fixup value if need be. getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, FixedValue); + } else if (Backend.shouldForceRelocationWithApplyFixup(*this, Fixup, Target)) { + // For RISCV branch instructions, we need to insert relocation types, so + // that linker relaxation could modify offset. But also calculate fixup + // value, because RISCV MC Branch Relaxation depend on it. + // RISCV MC Branch Relaxation is needed because RISCV could perform 32-bit + // to 16-bit transformation in MC layer. + uint64_t Value = 0; + getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, Value); } return std::make_tuple(Target, FixedValue, IsResolved); } Index: lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -60,6 +60,21 @@ if (FixupKind == RISCV::fixup_riscv_pcrel_lo12_i || FixupKind == RISCV::fixup_riscv_pcrel_hi20) return true; + return false; + } + + // To apply fixup calculation with preserve relocation types. + // Because we need assembler support branch relaxation for MC 32-bit to + // 16-bit instruction transformation. MC branch offset will depend on + // fixup calculation. If we define shouldForceRelocation for branches, + // fixup calculation will be disabled. + // We also need preserve relocation types becuase linker relaxation could + // modify branch offset when the instructions between branch and branch target + // have been relaxed. We need preserve branch relocation type for linker to + // correct the offset. + bool shouldForceRelocationWithApplyFixup(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target) override { return STI.getFeatureBits()[RISCV::FeatureRelax]; } Index: test/MC/RISCV/rv32-relaxation.s =================================================================== --- test/MC/RISCV/rv32-relaxation.s +++ test/MC/RISCV/rv32-relaxation.s @@ -1,5 +1,7 @@ # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c < %s \ # RUN: | llvm-objdump -d - | FileCheck -check-prefix=INSTR %s +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c,+relax < %s \ +# RUN: | llvm-objdump -d - | FileCheck -check-prefix=INSTR %s FAR_JUMP_NEGATIVE: c.nop Index: test/MC/RISCV/rv64-relaxation.s =================================================================== --- test/MC/RISCV/rv64-relaxation.s +++ test/MC/RISCV/rv64-relaxation.s @@ -1,5 +1,7 @@ # RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+c < %s \ # RUN: | llvm-objdump -d - | FileCheck -check-prefix=INSTR %s +# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+c,+relax < %s \ +# RUN: | llvm-objdump -d - | FileCheck -check-prefix=INSTR %s FAR_JUMP_NEGATIVE: c.nop