Skip to content

Commit bbea642

Browse files
committed
RISCV: adjust handling of relocation emission for RISCV
This re-architects the RISCV relocation handling to bring the implementation closer in line with the implementation in binutils. We would previously aggressively resolve the relocation. With this restructuring, we always will emit a paired relocation for any symbolic difference of the type of S±T[±C] where S and T are labels and C is a constant. GAS has a special target hook controlled by `RELOC_EXPANSION_POSSIBLE` which indicates that a fixup may be expanded into multiple relocations. This is used by the RISCV backend to always emit a paired relocation - either ADD[WIDTH] + SUB[WIDTH] for text relocations or SET[WIDTH] + SUB[WIDTH] for a debug info relocation. Irrespective of whether linker relaxation support is enabled, symbolic difference is always emitted as a paired relocation. This change also sinks the target specific behaviour down into the target specific area rather than exposing it to the shared relocation handling. In the process, we also sink the "special" handling for debug information down into the RISCV target. Although this improves the path for the other targets, this is not necessarily entirely ideal either. The changes in the debug info emission could be done through another type of hook as this functionality would be required by any other target which wishes to do linker relaxation. However, as there are no other targets in LLVM which currently do this, this is a reasonable thing to do until such time as the code needs to be shared. Improve the handling of the relocation (and add a reduced test case from the Linux kernel) to ensure that we handle complex expressions for symbolic difference. This ensures that we correct relocate symbols with the adddends normalized and associated with the addition portion of the paired relocation. This change also addresses some review comments from Alex Bradbury about the relocations meant for use in the DWARF CFA being named incorrectly (using ADD6 instead of SET6) in the original change which introduced the relocation type. This resolves the issues with the symbolic difference emission sufficiently to enable building the Linux kernel with clang+IAS+lld (without linker relaxation). Resolves PR50153, PR50156! Fixes: ClangBuiltLinux/linux#1023, ClangBuiltLinux/linux#1143 Reviewed By: nickdesaulniers, maskray Differential Revision: https://reviews.llvm.org/D103539
1 parent dee2c76 commit bbea642

23 files changed

+502
-350
lines changed

llvm/include/llvm/MC/MCAsmBackend.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,6 @@ class MCAsmBackend {
129129
uint64_t Value, bool IsResolved,
130130
const MCSubtargetInfo *STI) const = 0;
131131

132-
/// Check whether the given target requires emitting differences of two
133-
/// symbols as a set of relocations.
134-
virtual bool requiresDiffExpressionRelocations() const { return false; }
135-
136132
/// @}
137133

138134
/// \name Target Relaxation Interfaces
@@ -169,6 +165,16 @@ class MCAsmBackend {
169165
virtual void relaxInstruction(MCInst &Inst,
170166
const MCSubtargetInfo &STI) const {};
171167

168+
virtual bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF,
169+
MCAsmLayout &Layout, bool &WasRelaxed) const {
170+
return false;
171+
}
172+
173+
virtual bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, MCAsmLayout &Layout,
174+
bool &WasRelaxed) const {
175+
return false;
176+
}
177+
172178
/// @}
173179

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

llvm/include/llvm/MC/MCDwarf.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -387,13 +387,6 @@ class MCDwarfLineAddr {
387387
static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
388388
int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
389389

390-
/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas using
391-
/// fixed length operands. Returns (Offset, Size, SetDelta).
392-
static std::tuple<uint32_t, uint32_t, bool> fixedEncode(MCContext &Context,
393-
int64_t LineDelta,
394-
uint64_t AddrDelta,
395-
raw_ostream &OS);
396-
397390
/// Utility function to emit the encoding to a streamer.
398391
static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
399392
int64_t LineDelta, uint64_t AddrDelta);
@@ -667,8 +660,7 @@ class MCDwarfFrameEmitter {
667660
static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
668661
static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
669662
static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
670-
raw_ostream &OS, uint32_t *Offset = nullptr,
671-
uint32_t *Size = nullptr);
663+
raw_ostream &OS);
672664
};
673665

674666
} // end namespace llvm

llvm/include/llvm/MC/MCFixup.h

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,6 @@ enum MCFixupKind {
4141
FK_SecRel_2, ///< A two-byte section relative fixup.
4242
FK_SecRel_4, ///< A four-byte section relative fixup.
4343
FK_SecRel_8, ///< A eight-byte section relative fixup.
44-
FK_Data_Add_1, ///< A one-byte add fixup.
45-
FK_Data_Add_2, ///< A two-byte add fixup.
46-
FK_Data_Add_4, ///< A four-byte add fixup.
47-
FK_Data_Add_8, ///< A eight-byte add fixup.
48-
FK_Data_Add_6b, ///< A six-bits add fixup.
49-
FK_Data_Sub_1, ///< A one-byte sub fixup.
50-
FK_Data_Sub_2, ///< A two-byte sub fixup.
51-
FK_Data_Sub_4, ///< A four-byte sub fixup.
52-
FK_Data_Sub_8, ///< A eight-byte sub fixup.
53-
FK_Data_Sub_6b, ///< A six-bits sub fixup.
5444

5545
FirstTargetFixupKind = 128,
5646

@@ -105,28 +95,6 @@ class MCFixup {
10595
return FI;
10696
}
10797

108-
/// Return a fixup corresponding to the add half of a add/sub fixup pair for
109-
/// the given Fixup.
110-
static MCFixup createAddFor(const MCFixup &Fixup) {
111-
MCFixup FI;
112-
FI.Value = Fixup.getValue();
113-
FI.Offset = Fixup.getOffset();
114-
FI.Kind = getAddKindForKind(Fixup.getKind());
115-
FI.Loc = Fixup.getLoc();
116-
return FI;
117-
}
118-
119-
/// Return a fixup corresponding to the sub half of a add/sub fixup pair for
120-
/// the given Fixup.
121-
static MCFixup createSubFor(const MCFixup &Fixup) {
122-
MCFixup FI;
123-
FI.Value = Fixup.getValue();
124-
FI.Offset = Fixup.getOffset();
125-
FI.Kind = getSubKindForKind(Fixup.getKind());
126-
FI.Loc = Fixup.getLoc();
127-
return FI;
128-
}
129-
13098
MCFixupKind getKind() const { return Kind; }
13199

132100
unsigned getTargetKind() const { return Kind; }
@@ -172,32 +140,6 @@ class MCFixup {
172140
}
173141
}
174142

175-
/// Return the generic fixup kind for an addition with a given size. It
176-
/// is an error to pass an unsupported size.
177-
static MCFixupKind getAddKindForKind(MCFixupKind Kind) {
178-
switch (Kind) {
179-
default: llvm_unreachable("Unknown type to convert!");
180-
case FK_Data_1: return FK_Data_Add_1;
181-
case FK_Data_2: return FK_Data_Add_2;
182-
case FK_Data_4: return FK_Data_Add_4;
183-
case FK_Data_8: return FK_Data_Add_8;
184-
case FK_Data_6b: return FK_Data_Add_6b;
185-
}
186-
}
187-
188-
/// Return the generic fixup kind for an subtraction with a given size. It
189-
/// is an error to pass an unsupported size.
190-
static MCFixupKind getSubKindForKind(MCFixupKind Kind) {
191-
switch (Kind) {
192-
default: llvm_unreachable("Unknown type to convert!");
193-
case FK_Data_1: return FK_Data_Sub_1;
194-
case FK_Data_2: return FK_Data_Sub_2;
195-
case FK_Data_4: return FK_Data_Sub_4;
196-
case FK_Data_8: return FK_Data_Sub_8;
197-
case FK_Data_6b: return FK_Data_Sub_6b;
198-
}
199-
}
200-
201143
SMLoc getLoc() const { return Loc; }
202144
};
203145

llvm/lib/MC/MCAsmBackend.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,7 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
9595
{"FK_SecRel_2", 0, 16, 0},
9696
{"FK_SecRel_4", 0, 32, 0},
9797
{"FK_SecRel_8", 0, 64, 0},
98-
{"FK_Data_Add_1", 0, 8, 0},
99-
{"FK_Data_Add_2", 0, 16, 0},
100-
{"FK_Data_Add_4", 0, 32, 0},
101-
{"FK_Data_Add_8", 0, 64, 0},
102-
{"FK_Data_Add_6b", 0, 6, 0},
103-
{"FK_Data_Sub_1", 0, 8, 0},
104-
{"FK_Data_Sub_2", 0, 16, 0},
105-
{"FK_Data_Sub_4", 0, 32, 0},
106-
{"FK_Data_Sub_8", 0, 64, 0},
107-
{"FK_Data_Sub_6b", 0, 6, 0}};
98+
};
10899

109100
assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind");
110101
return Builtins[Kind];

llvm/lib/MC/MCAssembler.cpp

Lines changed: 13 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -792,26 +792,7 @@ MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F,
792792
// The fixup was unresolved, we need a relocation. Inform the object
793793
// writer of the relocation, and give it an opportunity to adjust the
794794
// fixup value if need be.
795-
if (Target.getSymA() && Target.getSymB() &&
796-
getBackend().requiresDiffExpressionRelocations()) {
797-
// The fixup represents the difference between two symbols, which the
798-
// backend has indicated must be resolved at link time. Split up the fixup
799-
// into two relocations, one for the add, and one for the sub, and emit
800-
// both of these. The constant will be associated with the add half of the
801-
// expression.
802-
MCFixup FixupAdd = MCFixup::createAddFor(Fixup);
803-
MCValue TargetAdd =
804-
MCValue::get(Target.getSymA(), nullptr, Target.getConstant());
805-
getWriter().recordRelocation(*this, Layout, &F, FixupAdd, TargetAdd,
806-
FixedValue);
807-
MCFixup FixupSub = MCFixup::createSubFor(Fixup);
808-
MCValue TargetSub = MCValue::get(Target.getSymB());
809-
getWriter().recordRelocation(*this, Layout, &F, FixupSub, TargetSub,
810-
FixedValue);
811-
} else {
812-
getWriter().recordRelocation(*this, Layout, &F, Fixup, Target,
813-
FixedValue);
814-
}
795+
getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, FixedValue);
815796
}
816797
return std::make_tuple(Target, FixedValue, IsResolved);
817798
}
@@ -1100,6 +1081,11 @@ bool MCAssembler::relaxBoundaryAlign(MCAsmLayout &Layout,
11001081

11011082
bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
11021083
MCDwarfLineAddrFragment &DF) {
1084+
1085+
bool WasRelaxed;
1086+
if (getBackend().relaxDwarfLineAddr(DF, Layout, WasRelaxed))
1087+
return WasRelaxed;
1088+
11031089
MCContext &Context = Layout.getAssembler().getContext();
11041090
uint64_t OldSize = DF.getContents().size();
11051091
int64_t AddrDelta;
@@ -1113,33 +1099,17 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
11131099
raw_svector_ostream OSE(Data);
11141100
DF.getFixups().clear();
11151101

1116-
if (!getBackend().requiresDiffExpressionRelocations()) {
1117-
MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
1118-
AddrDelta, OSE);
1119-
} else {
1120-
uint32_t Offset;
1121-
uint32_t Size;
1122-
bool SetDelta;
1123-
std::tie(Offset, Size, SetDelta) =
1124-
MCDwarfLineAddr::fixedEncode(Context, LineDelta, AddrDelta, OSE);
1125-
// Add Fixups for address delta or new address.
1126-
const MCExpr *FixupExpr;
1127-
if (SetDelta) {
1128-
FixupExpr = &DF.getAddrDelta();
1129-
} else {
1130-
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(&DF.getAddrDelta());
1131-
FixupExpr = ABE->getLHS();
1132-
}
1133-
DF.getFixups().push_back(
1134-
MCFixup::create(Offset, FixupExpr,
1135-
MCFixup::getKindForSize(Size, false /*isPCRel*/)));
1136-
}
1137-
1102+
MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
1103+
AddrDelta, OSE);
11381104
return OldSize != Data.size();
11391105
}
11401106

11411107
bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
11421108
MCDwarfCallFrameFragment &DF) {
1109+
bool WasRelaxed;
1110+
if (getBackend().relaxDwarfCFA(DF, Layout, WasRelaxed))
1111+
return WasRelaxed;
1112+
11431113
MCContext &Context = Layout.getAssembler().getContext();
11441114
uint64_t OldSize = DF.getContents().size();
11451115
int64_t AddrDelta;
@@ -1151,20 +1121,7 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
11511121
raw_svector_ostream OSE(Data);
11521122
DF.getFixups().clear();
11531123

1154-
if (getBackend().requiresDiffExpressionRelocations()) {
1155-
uint32_t Offset;
1156-
uint32_t Size;
1157-
MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE, &Offset,
1158-
&Size);
1159-
if (Size) {
1160-
DF.getFixups().push_back(MCFixup::create(
1161-
Offset, &DF.getAddrDelta(),
1162-
MCFixup::getKindForSizeInBits(Size /*In bits.*/, false /*isPCRel*/)));
1163-
}
1164-
} else {
1165-
MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE);
1166-
}
1167-
1124+
MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE);
11681125
return OldSize != Data.size();
11691126
}
11701127

@@ -1194,10 +1151,6 @@ bool MCAssembler::relaxPseudoProbeAddr(MCAsmLayout &Layout,
11941151
raw_svector_ostream OSE(Data);
11951152
PF.getFixups().clear();
11961153

1197-
// Relocations should not be needed in general except on RISC-V which we are
1198-
// not targeted for now.
1199-
assert(!getBackend().requiresDiffExpressionRelocations() &&
1200-
"cannot relax relocations");
12011154
// AddrDelta is a signed integer
12021155
encodeSLEB128(AddrDelta, OSE, OldSize);
12031156
return OldSize != Data.size();

llvm/lib/MC/MCDwarf.cpp

Lines changed: 10 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -734,54 +734,6 @@ void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params,
734734
}
735735
}
736736

737-
std::tuple<uint32_t, uint32_t, bool>
738-
MCDwarfLineAddr::fixedEncode(MCContext &Context, int64_t LineDelta,
739-
uint64_t AddrDelta, raw_ostream &OS) {
740-
uint32_t Offset, Size;
741-
if (LineDelta != INT64_MAX) {
742-
OS << char(dwarf::DW_LNS_advance_line);
743-
encodeSLEB128(LineDelta, OS);
744-
}
745-
746-
// Use address delta to adjust address or use absolute address to adjust
747-
// address.
748-
bool SetDelta;
749-
// According to DWARF spec., the DW_LNS_fixed_advance_pc opcode takes a
750-
// single uhalf (unencoded) operand. So, the maximum value of AddrDelta
751-
// is 65535. We set a conservative upper bound for it for relaxation.
752-
if (AddrDelta > 60000) {
753-
const MCAsmInfo *asmInfo = Context.getAsmInfo();
754-
unsigned AddrSize = asmInfo->getCodePointerSize();
755-
756-
OS << char(dwarf::DW_LNS_extended_op);
757-
encodeULEB128(1 + AddrSize, OS);
758-
OS << char(dwarf::DW_LNE_set_address);
759-
// Generate fixup for the address.
760-
Offset = OS.tell();
761-
Size = AddrSize;
762-
SetDelta = false;
763-
OS.write_zeros(AddrSize);
764-
} else {
765-
OS << char(dwarf::DW_LNS_fixed_advance_pc);
766-
// Generate fixup for 2-bytes address delta.
767-
Offset = OS.tell();
768-
Size = 2;
769-
SetDelta = true;
770-
OS << char(0);
771-
OS << char(0);
772-
}
773-
774-
if (LineDelta == INT64_MAX) {
775-
OS << char(dwarf::DW_LNS_extended_op);
776-
OS << char(1);
777-
OS << char(dwarf::DW_LNE_end_sequence);
778-
} else {
779-
OS << char(dwarf::DW_LNS_copy);
780-
}
781-
782-
return std::make_tuple(Offset, Size, SetDelta);
783-
}
784-
785737
// Utility function to write a tuple for .debug_abbrev.
786738
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
787739
MCOS->emitULEB128IntValue(Name);
@@ -1940,54 +1892,28 @@ void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer,
19401892
}
19411893

19421894
void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
1943-
uint64_t AddrDelta, raw_ostream &OS,
1944-
uint32_t *Offset, uint32_t *Size) {
1895+
uint64_t AddrDelta,
1896+
raw_ostream &OS) {
19451897
// Scale the address delta by the minimum instruction length.
19461898
AddrDelta = ScaleAddrDelta(Context, AddrDelta);
1947-
1948-
bool WithFixups = false;
1949-
if (Offset && Size)
1950-
WithFixups = true;
1899+
if (AddrDelta == 0)
1900+
return;
19511901

19521902
support::endianness E =
19531903
Context.getAsmInfo()->isLittleEndian() ? support::little : support::big;
1954-
if (AddrDelta == 0) {
1955-
if (WithFixups) {
1956-
*Offset = 0;
1957-
*Size = 0;
1958-
}
1959-
} else if (isUIntN(6, AddrDelta)) {
1904+
1905+
if (isUIntN(6, AddrDelta)) {
19601906
uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
1961-
if (WithFixups) {
1962-
*Offset = OS.tell();
1963-
*Size = 6;
1964-
OS << uint8_t(dwarf::DW_CFA_advance_loc);
1965-
} else
1966-
OS << Opcode;
1907+
OS << Opcode;
19671908
} else if (isUInt<8>(AddrDelta)) {
19681909
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
1969-
if (WithFixups) {
1970-
*Offset = OS.tell();
1971-
*Size = 8;
1972-
OS.write_zeros(1);
1973-
} else
1974-
OS << uint8_t(AddrDelta);
1910+
OS << uint8_t(AddrDelta);
19751911
} else if (isUInt<16>(AddrDelta)) {
19761912
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
1977-
if (WithFixups) {
1978-
*Offset = OS.tell();
1979-
*Size = 16;
1980-
OS.write_zeros(2);
1981-
} else
1982-
support::endian::write<uint16_t>(OS, AddrDelta, E);
1913+
support::endian::write<uint16_t>(OS, AddrDelta, E);
19831914
} else {
19841915
assert(isUInt<32>(AddrDelta));
19851916
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
1986-
if (WithFixups) {
1987-
*Offset = OS.tell();
1988-
*Size = 32;
1989-
OS.write_zeros(4);
1990-
} else
1991-
support::endian::write<uint32_t>(OS, AddrDelta, E);
1917+
support::endian::write<uint32_t>(OS, AddrDelta, E);
19921918
}
19931919
}

0 commit comments

Comments
 (0)