Skip to content

Commit 1bfc5e7

Browse files
LemonBoybrad0
authored andcommitted
[SPARC][MC] Support more relocation types
This patch introduces support for %hix, %lox, %gdop_hix22, %gdop_lox10 and %gdop. An extra test is introduced to make sure the fixups are correctly applied. Reviewed By: dcederman Differential Revision: https://reviews.llvm.org/D102575
1 parent 4daa33f commit 1bfc5e7

13 files changed

+318
-30
lines changed

llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class SparcOperand;
5555
class SparcAsmParser : public MCTargetAsmParser {
5656
MCAsmParser &Parser;
5757

58+
enum class TailRelocKind { Load_GOT, Add_TLS, Load_TLS, Call_TLS };
59+
5860
/// @name Auto-generated Match Functions
5961
/// {
6062

@@ -83,6 +85,9 @@ class SparcAsmParser : public MCTargetAsmParser {
8385

8486
OperandMatchResultTy parseMembarTag(OperandVector &Operands);
8587

88+
template <TailRelocKind Kind>
89+
OperandMatchResultTy parseTailRelocSym(OperandVector &Operands);
90+
8691
template <unsigned N>
8792
OperandMatchResultTy parseShiftAmtImm(OperandVector &Operands);
8893

@@ -113,6 +118,8 @@ class SparcAsmParser : public MCTargetAsmParser {
113118
bool expandSET(MCInst &Inst, SMLoc IDLoc,
114119
SmallVectorImpl<MCInst> &Instructions);
115120

121+
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
122+
116123
public:
117124
SparcAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
118125
const MCInstrInfo &MII,
@@ -267,6 +274,7 @@ class SparcOperand : public MCParsedAsmOperand {
267274
bool isMEMrr() const { return Kind == k_MemoryReg; }
268275
bool isMEMri() const { return Kind == k_MemoryImm; }
269276
bool isMembarTag() const { return Kind == k_Immediate; }
277+
bool isTailRelocSym() const { return Kind == k_Immediate; }
270278

271279
bool isCallTarget() const {
272280
if (!isImm())
@@ -427,6 +435,11 @@ class SparcOperand : public MCParsedAsmOperand {
427435
addExpr(Inst, getImm());
428436
}
429437

438+
void addTailRelocSymOperands(MCInst &Inst, unsigned N) const {
439+
assert(N == 1 && "Invalid number of operands!");
440+
addExpr(Inst, getImm());
441+
}
442+
430443
static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
431444
auto Op = std::make_unique<SparcOperand>(k_Token);
432445
Op->Tok.Data = Str.data();
@@ -850,6 +863,98 @@ OperandMatchResultTy SparcAsmParser::parseShiftAmtImm(OperandVector &Operands) {
850863
return MatchOperand_Success;
851864
}
852865

866+
template <SparcAsmParser::TailRelocKind Kind>
867+
OperandMatchResultTy
868+
SparcAsmParser::parseTailRelocSym(OperandVector &Operands) {
869+
SMLoc S = getLoc();
870+
SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
871+
872+
auto MatchesKind = [](SparcMCExpr::VariantKind VK) -> bool {
873+
switch (Kind) {
874+
case TailRelocKind::Load_GOT:
875+
// Non-TLS relocations on ld (or ldx).
876+
// ld [%rr + %rr], %rr, %rel(sym)
877+
return VK == SparcMCExpr::VK_Sparc_GOTDATA_OP;
878+
case TailRelocKind::Add_TLS:
879+
// TLS relocations on add.
880+
// add %rr, %rr, %rr, %rel(sym)
881+
switch (VK) {
882+
case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
883+
case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
884+
case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
885+
case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
886+
return true;
887+
default:
888+
return false;
889+
}
890+
case TailRelocKind::Load_TLS:
891+
// TLS relocations on ld (or ldx).
892+
// ld[x] %addr, %rr, %rel(sym)
893+
switch (VK) {
894+
case SparcMCExpr::VK_Sparc_TLS_IE_LD:
895+
case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
896+
return true;
897+
default:
898+
return false;
899+
}
900+
case TailRelocKind::Call_TLS:
901+
// TLS relocations on call.
902+
// call sym, %rel(sym)
903+
switch (VK) {
904+
case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
905+
case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
906+
return true;
907+
default:
908+
return false;
909+
}
910+
default:
911+
llvm_unreachable("Unexpected kind parameter");
912+
}
913+
};
914+
915+
if (getLexer().getKind() != AsmToken::Percent) {
916+
Error(getLoc(), "expected '%' for operand modifier");
917+
return MatchOperand_ParseFail;
918+
}
919+
920+
const AsmToken Tok = Parser.getTok();
921+
getParser().Lex(); // Eat '%'
922+
923+
if (getLexer().getKind() != AsmToken::Identifier) {
924+
Error(getLoc(), "expected valid identifier for operand modifier");
925+
return MatchOperand_ParseFail;
926+
}
927+
928+
StringRef Name = getParser().getTok().getIdentifier();
929+
SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(Name);
930+
if (VK == SparcMCExpr::VK_Sparc_None) {
931+
Error(getLoc(), "invalid operand modifier");
932+
return MatchOperand_ParseFail;
933+
}
934+
935+
if (!MatchesKind(VK)) {
936+
// Did not match the specified set of relocation types, put '%' back.
937+
getLexer().UnLex(Tok);
938+
return MatchOperand_NoMatch;
939+
}
940+
941+
Parser.Lex(); // Eat the identifier.
942+
if (getLexer().getKind() != AsmToken::LParen) {
943+
Error(getLoc(), "expected '('");
944+
return MatchOperand_ParseFail;
945+
}
946+
947+
getParser().Lex(); // Eat '('
948+
const MCExpr *SubExpr;
949+
if (getParser().parseParenExpression(SubExpr, E)) {
950+
return MatchOperand_ParseFail;
951+
}
952+
953+
const MCExpr *Val = adjustPICRelocation(VK, SubExpr);
954+
Operands.push_back(SparcOperand::CreateImm(Val, S, E));
955+
return MatchOperand_Success;
956+
}
957+
853958
OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) {
854959
SMLoc S = Parser.getTok().getLoc();
855960
const MCExpr *EVal;
@@ -1409,10 +1514,27 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
14091514
StringRef name = Tok.getString();
14101515

14111516
SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name);
1517+
switch (VK) {
1518+
case SparcMCExpr::VK_Sparc_None:
1519+
Error(getLoc(), "invalid operand modifier");
1520+
return false;
14121521

1413-
if (VK == SparcMCExpr::VK_Sparc_None)
1522+
case SparcMCExpr::VK_Sparc_GOTDATA_OP:
1523+
case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
1524+
case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
1525+
case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
1526+
case SparcMCExpr::VK_Sparc_TLS_IE_LD:
1527+
case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
1528+
case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
1529+
case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
1530+
case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
1531+
// These are special-cased at tablegen level.
14141532
return false;
14151533

1534+
default:
1535+
break;
1536+
}
1537+
14161538
Parser.Lex(); // Eat the identifier.
14171539
if (Parser.getTok().getKind() != AsmToken::LParen)
14181540
return false;

llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
4747
case Sparc::fixup_sparc_br16_14:
4848
return (Value >> 2) & 0x3fff;
4949

50+
case Sparc::fixup_sparc_hix22:
51+
return (~Value >> 10) & 0x3fffff;
52+
5053
case Sparc::fixup_sparc_pc22:
5154
case Sparc::fixup_sparc_got22:
5255
case Sparc::fixup_sparc_tls_gd_hi22:
@@ -60,6 +63,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
6063
case Sparc::fixup_sparc_13:
6164
return Value & 0x1fff;
6265

66+
case Sparc::fixup_sparc_lox10:
67+
return (Value & 0x3ff) | 0x1c00;
68+
6369
case Sparc::fixup_sparc_pc10:
6470
case Sparc::fixup_sparc_got10:
6571
case Sparc::fixup_sparc_tls_gd_lo10:
@@ -98,6 +104,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
98104
case Sparc::fixup_sparc_tls_ie_ld:
99105
case Sparc::fixup_sparc_tls_ie_ldx:
100106
case Sparc::fixup_sparc_tls_ie_add:
107+
case Sparc::fixup_sparc_gotdata_lox10:
108+
case Sparc::fixup_sparc_gotdata_hix22:
109+
case Sparc::fixup_sparc_gotdata_op:
101110
return 0;
102111
}
103112
}
@@ -189,7 +198,12 @@ namespace {
189198
{ "fixup_sparc_tls_ie_ldx", 0, 0, 0 },
190199
{ "fixup_sparc_tls_ie_add", 0, 0, 0 },
191200
{ "fixup_sparc_tls_le_hix22", 0, 0, 0 },
192-
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 }
201+
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 },
202+
{ "fixup_sparc_hix22", 10, 22, 0 },
203+
{ "fixup_sparc_lox10", 19, 13, 0 },
204+
{ "fixup_sparc_gotdata_hix22", 0, 0, 0 },
205+
{ "fixup_sparc_gotdata_lox10", 0, 0, 0 },
206+
{ "fixup_sparc_gotdata_op", 0, 0, 0 },
193207
};
194208

195209
const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
@@ -231,7 +245,12 @@ namespace {
231245
{ "fixup_sparc_tls_ie_ldx", 0, 0, 0 },
232246
{ "fixup_sparc_tls_ie_add", 0, 0, 0 },
233247
{ "fixup_sparc_tls_le_hix22", 0, 0, 0 },
234-
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 }
248+
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 },
249+
{ "fixup_sparc_hix22", 0, 22, 0 },
250+
{ "fixup_sparc_lox10", 0, 13, 0 },
251+
{ "fixup_sparc_gotdata_hix22", 0, 0, 0 },
252+
{ "fixup_sparc_gotdata_lox10", 0, 0, 0 },
253+
{ "fixup_sparc_gotdata_op", 0, 0, 0 },
235254
};
236255

237256
// Fixup kinds from .reloc directive are like R_SPARC_NONE. They do

llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx,
112112
case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD;
113113
case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22;
114114
case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10;
115+
case Sparc::fixup_sparc_hix22: return ELF::R_SPARC_HIX22;
116+
case Sparc::fixup_sparc_lox10: return ELF::R_SPARC_LOX10;
117+
case Sparc::fixup_sparc_gotdata_hix22: return ELF::R_SPARC_GOTDATA_HIX22;
118+
case Sparc::fixup_sparc_gotdata_lox10: return ELF::R_SPARC_GOTDATA_LOX10;
119+
case Sparc::fixup_sparc_gotdata_op: return ELF::R_SPARC_GOTDATA_OP;
115120
}
116121

117122
return ELF::R_SPARC_NONE;

llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ namespace llvm {
9595
fixup_sparc_tls_le_hix22,
9696
fixup_sparc_tls_le_lox10,
9797

98+
/// 22-bit fixup corresponding to %hix(foo)
99+
fixup_sparc_hix22,
100+
/// 13-bit fixup corresponding to %lox(foo)
101+
fixup_sparc_lox10,
102+
103+
/// 22-bit fixup corresponding to %gdop_hix22(foo)
104+
fixup_sparc_gotdata_hix22,
105+
/// 13-bit fixup corresponding to %gdop_lox10(foo)
106+
fixup_sparc_gotdata_lox10,
107+
/// 32-bit fixup corresponding to %gdop(foo)
108+
fixup_sparc_gotdata_op,
109+
98110
// Marker
99111
LastTargetFixupKind,
100112
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind

llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,21 @@ void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
104104
support::endian::write(OS, Bits,
105105
Ctx.getAsmInfo()->isLittleEndian() ? support::little
106106
: support::big);
107-
unsigned tlsOpNo = 0;
107+
108+
// Some instructions have phantom operands that only contribute a fixup entry.
109+
unsigned SymOpNo = 0;
108110
switch (MI.getOpcode()) {
109111
default: break;
110-
case SP::TLS_CALL: tlsOpNo = 1; break;
112+
case SP::TLS_CALL: SymOpNo = 1; break;
113+
case SP::GDOP_LDrr:
114+
case SP::GDOP_LDXrr:
111115
case SP::TLS_ADDrr:
112116
case SP::TLS_ADDXrr:
113117
case SP::TLS_LDrr:
114-
case SP::TLS_LDXrr: tlsOpNo = 3; break;
118+
case SP::TLS_LDXrr: SymOpNo = 3; break;
115119
}
116-
if (tlsOpNo != 0) {
117-
const MCOperand &MO = MI.getOperand(tlsOpNo);
120+
if (SymOpNo != 0) {
121+
const MCOperand &MO = MI.getOperand(SymOpNo);
118122
uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
119123
assert(op == 0 && "Unexpected operand value!");
120124
(void)op; // suppress warning.

llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind)
8181
case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; return true;
8282
case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; return true;
8383
case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; return true;
84+
case VK_Sparc_HIX22: OS << "%hix("; return true;
85+
case VK_Sparc_LOX10: OS << "%lox("; return true;
86+
case VK_Sparc_GOTDATA_HIX22: OS << "%gdop_hix22("; return true;
87+
case VK_Sparc_GOTDATA_LOX10: OS << "%gdop_lox10("; return true;
88+
case VK_Sparc_GOTDATA_OP: OS << "%gdop("; return true;
8489
}
8590
llvm_unreachable("Unhandled SparcMCExpr::VariantKind");
8691
}
@@ -120,6 +125,11 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name)
120125
.Case("tie_add", VK_Sparc_TLS_IE_ADD)
121126
.Case("tle_hix22", VK_Sparc_TLS_LE_HIX22)
122127
.Case("tle_lox10", VK_Sparc_TLS_LE_LOX10)
128+
.Case("hix", VK_Sparc_HIX22)
129+
.Case("lox", VK_Sparc_LOX10)
130+
.Case("gdop_hix22", VK_Sparc_GOTDATA_HIX22)
131+
.Case("gdop_lox10", VK_Sparc_GOTDATA_LOX10)
132+
.Case("gdop", VK_Sparc_GOTDATA_OP)
123133
.Default(VK_Sparc_None);
124134
}
125135

@@ -160,6 +170,11 @@ Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) {
160170
case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add;
161171
case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22;
162172
case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10;
173+
case VK_Sparc_HIX22: return Sparc::fixup_sparc_hix22;
174+
case VK_Sparc_LOX10: return Sparc::fixup_sparc_lox10;
175+
case VK_Sparc_GOTDATA_HIX22: return Sparc::fixup_sparc_gotdata_hix22;
176+
case VK_Sparc_GOTDATA_LOX10: return Sparc::fixup_sparc_gotdata_lox10;
177+
case VK_Sparc_GOTDATA_OP: return Sparc::fixup_sparc_gotdata_op;
163178
}
164179
}
165180

llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ class SparcMCExpr : public MCTargetExpr {
5858
VK_Sparc_TLS_IE_LDX,
5959
VK_Sparc_TLS_IE_ADD,
6060
VK_Sparc_TLS_LE_HIX22,
61-
VK_Sparc_TLS_LE_LOX10
61+
VK_Sparc_TLS_LE_LOX10,
62+
VK_Sparc_HIX22,
63+
VK_Sparc_LOX10,
64+
VK_Sparc_GOTDATA_HIX22,
65+
VK_Sparc_GOTDATA_LOX10,
66+
VK_Sparc_GOTDATA_OP,
6267
};
6368

6469
private:

llvm/lib/Target/Sparc/SparcISelLowering.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,7 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
19001900
case SPISD::TLS_LD: return "SPISD::TLS_LD";
19011901
case SPISD::TLS_CALL: return "SPISD::TLS_CALL";
19021902
case SPISD::TAIL_CALL: return "SPISD::TAIL_CALL";
1903+
case SPISD::LOAD_GDOP: return "SPISD::LOAD_GDOP";
19031904
}
19041905
return nullptr;
19051906
}

llvm/lib/Target/Sparc/SparcISelLowering.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ namespace llvm {
4848

4949
TLS_ADD, // For Thread Local Storage (TLS).
5050
TLS_LD,
51-
TLS_CALL
51+
TLS_CALL,
52+
53+
LOAD_GDOP, // Load operation w/ gdop relocation.
5254
};
5355
}
5456

llvm/lib/Target/Sparc/SparcInstr64Bit.td

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>;
163163
defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>;
164164

165165
def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd),
166-
(ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym),
166+
(ins I64Regs:$rs1, I64Regs:$rs2, TailRelocSymTLSAdd:$sym),
167167
"add $rs1, $rs2, $rd, $sym",
168168
[(set i64:$rd,
169169
(tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>;
@@ -238,12 +238,20 @@ let Predicates = [Is64Bit] in {
238238
let DecoderMethod = "DecodeLoadInt" in
239239
defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>;
240240

241-
let mayLoad = 1, isAsmParserOnly = 1 in
241+
let mayLoad = 1, isAsmParserOnly = 1 in {
242242
def TLS_LDXrr : F3_1<3, 0b001011,
243-
(outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
243+
(outs IntRegs:$dst),
244+
(ins MEMrr:$addr, TailRelocSymTLSLoad:$sym),
244245
"ldx [$addr], $dst, $sym",
245246
[(set i64:$dst,
246247
(tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>;
248+
def GDOP_LDXrr : F3_1<3, 0b001011,
249+
(outs I64Regs:$dst),
250+
(ins MEMrr:$addr, TailRelocSymGOTLoad:$sym),
251+
"ldx [$addr], $dst, $sym",
252+
[(set i64:$dst,
253+
(load_gdop ADDRrr:$addr, tglobaladdr:$sym))]>;
254+
}
247255

248256
// Extending loads to i64.
249257
def : Pat<(i64 (zextloadi1 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>;

0 commit comments

Comments
 (0)