Skip to content

Commit 8d7b718

Browse files
committed
[LoongArch][RISCV] Support R_LARCH_{ADD,SUB}_ULEB128/R_RISCV_{SET,SUB}_ULEB128 for .uleb128 directives
This patch is originally from three upstream commits: 1, R_LARCH_{ADD,SUB}_ULEB128 are originally landed from b57159c(llvm#76433). 2, R_RISCV_{SET,SUB}_ULEB128 are originally supported from 1df5ea2. Among it, we change the default behaviour of `-riscv-uleb128-reloc` to not produce uleb128 reloc, in order to avoid any other side-effects due to the updated implementation of `MCAssembler::relaxLEB()` function. And at the same time, we ensure that this patch can't introduce new default traits (such as the generation for uleb128 reloc) on RISCV in this version. 3, Fix invalid-sleb.s in original commit d7398a3. Change-Id: Ie687b7d8483c76cf647141162641db1a9d819a04
1 parent be6e5c5 commit 8d7b718

File tree

14 files changed

+252
-48
lines changed

14 files changed

+252
-48
lines changed

llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,5 @@ ELF_RELOC(R_RISCV_SET32, 56)
5555
ELF_RELOC(R_RISCV_32_PCREL, 57)
5656
ELF_RELOC(R_RISCV_IRELATIVE, 58)
5757
ELF_RELOC(R_RISCV_PLT32, 59)
58+
ELF_RELOC(R_RISCV_SET_ULEB128, 60)
59+
ELF_RELOC(R_RISCV_SUB_ULEB128, 61)

llvm/include/llvm/MC/MCAsmBackend.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class MCAlignFragment;
2121
class MCDwarfCallFrameFragment;
2222
class MCDwarfLineAddrFragment;
2323
class MCFragment;
24+
class MCLEBFragment;
2425
class MCRelaxableFragment;
2526
class MCSymbol;
2627
class MCAsmLayout;
@@ -194,6 +195,13 @@ class MCAsmBackend {
194195
return false;
195196
}
196197

198+
// Defined by linker relaxation targets to possibly emit LEB128 relocations
199+
// and set Value at the relocated location.
200+
virtual std::pair<bool, bool>
201+
relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout, int64_t &Value) const {
202+
return std::make_pair(false, false);
203+
}
204+
197205
/// @}
198206

199207
/// Returns the minimum size of a nop in bytes on this target. The assembler

llvm/include/llvm/MC/MCFixup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ enum MCFixupKind {
2525
FK_Data_4, ///< A four-byte fixup.
2626
FK_Data_8, ///< A eight-byte fixup.
2727
FK_Data_6b, ///< A six-bits fixup.
28+
FK_Data_leb128, ///< A leb128 fixup.
2829
FK_PCRel_1, ///< A one-byte pc relative fixup.
2930
FK_PCRel_2, ///< A two-byte pc relative fixup.
3031
FK_PCRel_4, ///< A four-byte pc relative fixup.

llvm/include/llvm/MC/MCFragment.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ class MCOrgFragment : public MCFragment {
428428
}
429429
};
430430

431-
class MCLEBFragment : public MCFragment {
431+
class MCLEBFragment final : public MCEncodedFragmentWithFixups<10, 1> {
432432
/// True if this is a sleb128, false if uleb128.
433433
bool IsSigned;
434434

@@ -439,17 +439,16 @@ class MCLEBFragment : public MCFragment {
439439

440440
public:
441441
MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
442-
: MCFragment(FT_LEB, false, Sec), IsSigned(IsSigned_), Value(&Value_) {
442+
: MCEncodedFragmentWithFixups<10, 1>(FT_LEB, false, Sec),
443+
IsSigned(IsSigned_), Value(&Value_) {
443444
Contents.push_back(0);
444445
}
445446

446447
const MCExpr &getValue() const { return *Value; }
448+
void setValue(const MCExpr *Expr) { Value = Expr; }
447449

448450
bool isSigned() const { return IsSigned; }
449451

450-
SmallString<8> &getContents() { return Contents; }
451-
const SmallString<8> &getContents() const { return Contents; }
452-
453452
/// @}
454453

455454
static bool classof(const MCFragment *F) {

llvm/lib/MC/MCAsmBackend.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
8989
{"FK_Data_4", 0, 32, 0},
9090
{"FK_Data_8", 0, 64, 0},
9191
{"FK_Data_6b", 0, 6, 0},
92+
{"FK_Data_leb128", 0, 0, 0},
9293
{"FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel},
9394
{"FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
9495
{"FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel},

llvm/lib/MC/MCAssembler.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,12 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
918918
Contents = DF.getContents();
919919
break;
920920
}
921+
case MCFragment::FT_LEB: {
922+
auto &LF = cast<MCLEBFragment>(Frag);
923+
Fixups = LF.getFixups();
924+
Contents = LF.getContents();
925+
break;
926+
}
921927
case MCFragment::FT_PseudoProbe: {
922928
MCPseudoProbeAddrFragment &PF = cast<MCPseudoProbeAddrFragment>(Frag);
923929
Fixups = PF.getFixups();
@@ -1006,22 +1012,41 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
10061012
}
10071013

10081014
bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
1009-
uint64_t OldSize = LF.getContents().size();
1015+
const unsigned OldSize = static_cast<unsigned>(LF.getContents().size());
1016+
unsigned PadTo = OldSize;
10101017
int64_t Value;
1011-
bool Abs = LF.getValue().evaluateKnownAbsolute(Value, Layout);
1012-
if (!Abs)
1013-
report_fatal_error("sleb128 and uleb128 expressions must be absolute");
1014-
SmallString<8> &Data = LF.getContents();
1018+
SmallVectorImpl<char> &Data = LF.getContents();
1019+
LF.getFixups().clear();
1020+
// Use evaluateKnownAbsolute for Mach-O as a hack: .subsections_via_symbols
1021+
// requires that .uleb128 A-B is foldable where A and B reside in different
1022+
// fragments. This is used by __gcc_except_table.
1023+
bool Abs = getSubsectionsViaSymbols()
1024+
? LF.getValue().evaluateKnownAbsolute(Value, Layout)
1025+
: LF.getValue().evaluateAsAbsolute(Value, Layout);
1026+
if (!Abs) {
1027+
bool Relaxed, UseZeroPad;
1028+
std::tie(Relaxed, UseZeroPad) = getBackend().relaxLEB128(LF, Layout, Value);
1029+
if (!Relaxed) {
1030+
getContext().reportError(LF.getValue().getLoc(),
1031+
Twine(LF.isSigned() ? ".s" : ".u") +
1032+
"leb128 expression is not absolute");
1033+
LF.setValue(MCConstantExpr::create(0, Context));
1034+
}
1035+
uint8_t Tmp[10]; // maximum size: ceil(64/7)
1036+
PadTo = std::max(PadTo, encodeULEB128(uint64_t(Value), Tmp));
1037+
if (UseZeroPad)
1038+
Value = 0;
1039+
}
10151040
Data.clear();
10161041
raw_svector_ostream OSE(Data);
10171042
// The compiler can generate EH table assembly that is impossible to assemble
10181043
// without either adding padding to an LEB fragment or adding extra padding
10191044
// to a later alignment fragment. To accommodate such tables, relaxation can
10201045
// only increase an LEB fragment size here, not decrease it. See PR35809.
10211046
if (LF.isSigned())
1022-
encodeSLEB128(Value, OSE, OldSize);
1047+
encodeSLEB128(Value, OSE, PadTo);
10231048
else
1024-
encodeULEB128(Value, OSE, OldSize);
1049+
encodeULEB128(Value, OSE, PadTo);
10251050
return OldSize != LF.getContents().size();
10261051
}
10271052

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
9292
case FK_Data_2:
9393
case FK_Data_4:
9494
case FK_Data_8:
95+
case FK_Data_leb128:
9596
return Value;
9697
case LoongArch::fixup_loongarch_b16: {
9798
if (!isInt<18>(Value))
@@ -129,6 +130,15 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
129130
}
130131
}
131132

133+
static void fixupLeb128(MCContext &Ctx, const MCFixup &Fixup,
134+
MutableArrayRef<char> Data, uint64_t Value) {
135+
unsigned I;
136+
for (I = 0; I != Data.size() && Value; ++I, Value >>= 7)
137+
Data[I] |= uint8_t(Value & 0x7f);
138+
if (Value)
139+
Ctx.reportError(Fixup.getLoc(), "Invalid uleb128 value!");
140+
}
141+
132142
void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm,
133143
const MCFixup &Fixup,
134144
const MCValue &Target,
@@ -144,6 +154,10 @@ void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm,
144154
MCFixupKindInfo Info = getFixupKindInfo(Kind);
145155
MCContext &Ctx = Asm.getContext();
146156

157+
// Fixup leb128 separately.
158+
if (Fixup.getTargetKind() == FK_Data_leb128)
159+
return fixupLeb128(Ctx, Fixup, Data, Value);
160+
147161
// Apply any target-specific value adjustments.
148162
Value = adjustFixupValue(Fixup, Value, Ctx);
149163

@@ -173,6 +187,7 @@ bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
173187
case FK_Data_2:
174188
case FK_Data_4:
175189
case FK_Data_8:
190+
case FK_Data_leb128:
176191
return !Target.isAbsolute();
177192
}
178193
}
@@ -202,9 +217,24 @@ getRelocPairForSize(unsigned Size) {
202217
return std::make_pair(
203218
MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD64),
204219
MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB64));
220+
case 128:
221+
return std::make_pair(
222+
MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD_ULEB128),
223+
MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB_ULEB128));
205224
}
206225
}
207226

227+
std::pair<bool, bool> LoongArchAsmBackend::relaxLEB128(MCLEBFragment &LF,
228+
MCAsmLayout &Layout,
229+
int64_t &Value) const {
230+
const MCExpr &Expr = LF.getValue();
231+
if (LF.isSigned() || !Expr.evaluateKnownAbsolute(Value, Layout))
232+
return std::make_pair(false, false);
233+
LF.getFixups().push_back(
234+
MCFixup::create(0, &Expr, FK_Data_leb128, Expr.getLoc()));
235+
return std::make_pair(true, true);
236+
}
237+
208238
bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
209239
const MCSubtargetInfo *STI) const {
210240
// We mostly follow binutils' convention here: align to 4-byte boundary with a
@@ -226,21 +256,27 @@ bool LoongArchAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout,
226256
uint64_t &FixedValue) const {
227257
std::pair<MCFixupKind, MCFixupKind> FK;
228258
uint64_t FixedValueA, FixedValueB;
229-
const MCSection &SecA = Target.getSymA()->getSymbol().getSection();
230-
const MCSection &SecB = Target.getSymB()->getSymbol().getSection();
231-
232-
// We need record relocation if SecA != SecB. Usually SecB is same as the
233-
// section of Fixup, which will be record the relocation as PCRel. If SecB
234-
// is not same as the section of Fixup, it will report error. Just return
235-
// false and then this work can be finished by handleFixup.
236-
if (&SecA != &SecB)
237-
return false;
238-
239-
// In SecA == SecB case. If the linker relaxation is enabled, we need record
240-
// the ADD, SUB relocations. Otherwise the FixedValue has already been
241-
// calculated out in evaluateFixup, return true and avoid record relocations.
242-
if (!STI.hasFeature(LoongArch::FeatureRelax))
243-
return true;
259+
const MCSymbol &SA = Target.getSymA()->getSymbol();
260+
const MCSymbol &SB = Target.getSymB()->getSymbol();
261+
262+
bool force = !SA.isInSection() || !SB.isInSection();
263+
if (!force) {
264+
const MCSection &SecA = SA.getSection();
265+
const MCSection &SecB = SB.getSection();
266+
267+
// We need record relocation if SecA != SecB. Usually SecB is same as the
268+
// section of Fixup, which will be record the relocation as PCRel. If SecB
269+
// is not same as the section of Fixup, it will report error. Just return
270+
// false and then this work can be finished by handleFixup.
271+
if (&SecA != &SecB)
272+
return false;
273+
274+
// In SecA == SecB case. If the linker relaxation is enabled, we need record
275+
// the ADD, SUB relocations. Otherwise the FixedValue has already been calc-
276+
// ulated out in evaluateFixup, return true and avoid record relocations.
277+
if (!STI.hasFeature(LoongArch::FeatureRelax))
278+
return true;
279+
}
244280

245281
switch (Fixup.getKind()) {
246282
case llvm::FK_Data_1:
@@ -255,6 +291,9 @@ bool LoongArchAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout,
255291
case llvm::FK_Data_8:
256292
FK = getRelocPairForSize(64);
257293
break;
294+
case llvm::FK_Data_leb128:
295+
FK = getRelocPairForSize(128);
296+
break;
258297
default:
259298
llvm_unreachable("unsupported fixup size");
260299
}

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ class LoongArchAsmBackend : public MCAsmBackend {
6565
void relaxInstruction(MCInst &Inst,
6666
const MCSubtargetInfo &STI) const override {}
6767

68+
std::pair<bool, bool> relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout,
69+
int64_t &Value) const override;
70+
6871
bool writeNopData(raw_ostream &OS, uint64_t Count,
6972
const MCSubtargetInfo *STI) const override;
7073

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/MC/MCObjectWriter.h"
2020
#include "llvm/MC/MCSymbol.h"
2121
#include "llvm/MC/MCValue.h"
22+
#include "llvm/Support/CommandLine.h"
2223
#include "llvm/Support/Endian.h"
2324
#include "llvm/Support/EndianStream.h"
2425
#include "llvm/Support/ErrorHandling.h"
@@ -27,6 +28,13 @@
2728

2829
using namespace llvm;
2930

31+
// Temporary workaround for old linkers that do not support ULEB128 relocations,
32+
// which are abused by DWARF v5 DW_LLE_offset_pair/DW_RLE_offset_pair
33+
// implemented in Clang/LLVM.
34+
static cl::opt<bool> ULEB128Reloc(
35+
"riscv-uleb128-reloc", cl::init(false), cl::Hidden,
36+
cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"));
37+
3038
std::optional<MCFixupKind> RISCVAsmBackend::getFixupKind(StringRef Name) const {
3139
if (STI.getTargetTriple().isOSBinFormatELF()) {
3240
unsigned Type;
@@ -126,6 +134,7 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
126134
case FK_Data_2:
127135
case FK_Data_4:
128136
case FK_Data_8:
137+
case FK_Data_leb128:
129138
if (Target.isAbsolute())
130139
return false;
131140
break;
@@ -330,6 +339,19 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF,
330339
return true;
331340
}
332341

342+
std::pair<bool, bool> RISCVAsmBackend::relaxLEB128(MCLEBFragment &LF,
343+
MCAsmLayout &Layout,
344+
int64_t &Value) const {
345+
if (LF.isSigned())
346+
return std::make_pair(false, false);
347+
const MCExpr &Expr = LF.getValue();
348+
if (ULEB128Reloc) {
349+
LF.getFixups().push_back(
350+
MCFixup::create(0, &Expr, FK_Data_leb128, Expr.getLoc()));
351+
}
352+
return std::make_pair(Expr.evaluateKnownAbsolute(Value, Layout), false);
353+
}
354+
333355
// Given a compressed control flow instruction this function returns
334356
// the expanded instruction.
335357
unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
@@ -416,6 +438,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
416438
case FK_Data_4:
417439
case FK_Data_8:
418440
case FK_Data_6b:
441+
case FK_Data_leb128:
419442
return Value;
420443
case RISCV::fixup_riscv_set_6b:
421444
return Value & 0x03;
@@ -596,6 +619,10 @@ bool RISCVAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout,
596619
TA = ELF::R_RISCV_ADD64;
597620
TB = ELF::R_RISCV_SUB64;
598621
break;
622+
case llvm::FK_Data_leb128:
623+
TA = ELF::R_RISCV_SET_ULEB128;
624+
TB = ELF::R_RISCV_SUB_ULEB128;
625+
break;
599626
default:
600627
llvm_unreachable("unsupported fixup size");
601628
}

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ class RISCVAsmBackend : public MCAsmBackend {
9999
bool &WasRelaxed) const override;
100100
bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, MCAsmLayout &Layout,
101101
bool &WasRelaxed) const override;
102+
std::pair<bool, bool> relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout,
103+
int64_t &Value) const override;
102104

103105
bool writeNopData(raw_ostream &OS, uint64_t Count,
104106
const MCSubtargetInfo *STI) const override;

llvm/test/MC/ELF/RISCV/gen-dwarf.s

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
## emit special opcodes to make .debug_line smaller, but we don't do this for
1010
## consistency.
1111

12-
# RUN: llvm-mc -filetype=obj -triple=riscv64 -g -dwarf-version=5 -mattr=+relax < %s -o %t
12+
# RUN: llvm-mc -filetype=obj -triple=riscv64 -g -dwarf-version=5 -mattr=+relax -riscv-uleb128-reloc=1 < %s -o %t
1313
# RUN: llvm-dwarfdump -eh-frame -debug-line -debug-rnglists -v %t | FileCheck %s
1414
# RUN: llvm-readobj -r -x .eh_frame %t | FileCheck %s --check-prefix=RELOC
1515

@@ -48,9 +48,10 @@
4848
# RELOC-NEXT: 0x34 R_RISCV_32_PCREL <null> 0x0
4949
# RELOC-NEXT: }
5050

51-
## TODO A section needs two relocations.
5251
# RELOC: Section ([[#]]) .rela.debug_rnglists {
5352
# RELOC-NEXT: 0xD R_RISCV_64 .text.foo 0x0
53+
# RELOC-NEXT: 0x15 R_RISCV_SET_ULEB128 <null> 0x0
54+
# RELOC-NEXT: 0x15 R_RISCV_SUB_ULEB128 .text.foo 0x0
5455
# RELOC-NEXT: 0x17 R_RISCV_64 .text.bar 0x0
5556
# RELOC-NEXT: }
5657

0 commit comments

Comments
 (0)