diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def @@ -54,3 +54,5 @@ ELF_RELOC(R_RISCV_SET32, 56) ELF_RELOC(R_RISCV_32_PCREL, 57) ELF_RELOC(R_RISCV_IRELATIVE, 58) +ELF_RELOC(R_RISCV_SET_ULEB128, 59) +ELF_RELOC(R_RISCV_SUB_ULEB128, 60) 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 @@ -93,6 +93,9 @@ {"fixup_riscv_set_6b", 2, 6, 0}, {"fixup_riscv_sub_6b", 2, 6, 0}, + + {"fixup_riscv_set_uleb128", 0, 0, 0}, + {"fixup_riscv_sub_uleb128", 0, 0, 0}, }; static_assert((std::size(Infos)) == RISCV::NumTargetFixupKinds, "Not all fixup kinds added to Infos array"); @@ -381,6 +384,8 @@ case RISCV::fixup_riscv_sub_32: case RISCV::fixup_riscv_add_64: case RISCV::fixup_riscv_sub_64: + case RISCV::fixup_riscv_set_uleb128: + case RISCV::fixup_riscv_sub_uleb128: case FK_Data_1: case FK_Data_2: case FK_Data_4: diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -166,6 +166,10 @@ return ELF::R_RISCV_ADD64; case RISCV::fixup_riscv_sub_64: return ELF::R_RISCV_SUB64; + case RISCV::fixup_riscv_set_uleb128: + return ELF::R_RISCV_SET_ULEB128; + case RISCV::fixup_riscv_sub_uleb128: + return ELF::R_RISCV_SUB_ULEB128; } } 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 @@ -27,6 +27,7 @@ : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {} void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override; + void emitULEB128Value(const MCExpr *Value) 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 @@ -272,6 +272,37 @@ DF->getContents().resize(DF->getContents().size() + Size, 0); } +void RISCVELFStreamer::emitULEB128Value(const MCExpr *Value) { + const MCExpr *A, *B; + + if (!requiresFixups(getContext(), Value, A, B)) + return MCELFStreamer::emitULEB128Value(Value); + + SMLoc Loc = Value->getLoc(); + + int64_t IntValue; + if (!Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) { + // Emit a placeholder to make sure we'll emit enough space could be filled + // by linker later. + IntValue = -1ll; + } + MCDataFragment *DF = getOrCreateDataFragment(); + flushPendingLabels(DF, DF->getContents().size()); + MCDwarfLineEntry::make(this, getCurrentSectionOnly()); + + DF->getFixups().push_back(MCFixup::create( + DF->getContents().size(), A, + static_cast(RISCV::fixup_riscv_set_uleb128), Loc)); + DF->getFixups().push_back(MCFixup::create( + DF->getContents().size(), B, + static_cast(RISCV::fixup_riscv_sub_uleb128), Loc)); + + SmallString<128> Tmp; + raw_svector_ostream OSE(Tmp); + encodeULEB128(IntValue, OSE); + emitBytes(OSE.str()); +} + namespace llvm { MCELFStreamer *createRISCVELFStreamer(MCContext &C, std::unique_ptr MAB, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h @@ -103,6 +103,10 @@ // 6-bit fixup corresponding to R_RISCV_SUB6 for local label assignment in // DWARF CFA. fixup_riscv_sub_6b, + // fixup corresponding to R_RISCV_SET_ULEB128 for local label assignment. + fixup_riscv_set_uleb128, + // fixup corresponding to R_RISCV_SUB_ULEB128 for local label assignment. + fixup_riscv_sub_uleb128, // Used as a sentinel, must be the last fixup_riscv_invalid, 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 @@ -27,6 +27,8 @@ .half G2-G1 .byte .L2-.L1 .byte G2-G1 +.uleb128 .L2-.L1 +.uleb128 G2-G1 # RELAX: 0x0 R_RISCV_ADD64 .L2 0x0 # RELAX: 0x0 R_RISCV_SUB64 .L1 0x0 # RELAX: 0x8 R_RISCV_ADD64 G2 0x0 @@ -43,3 +45,7 @@ # RELAX: 0x1C R_RISCV_SUB8 .L1 0x0 # RELAX: 0x1D R_RISCV_ADD8 G2 0x0 # RELAX: 0x1D R_RISCV_SUB8 G1 0x0 +# RELAX: 0x1E R_RISCV_SET_ULEB128 .L2 0x0 +# RELAX: 0x1E R_RISCV_SUB_ULEB128 .L1 0x0 +# RELAX: 0x1F R_RISCV_SET_ULEB128 G2 0x0 +# RELAX: 0x1F R_RISCV_SUB_ULEB128 G1 0x0