[llvm] 1bfc5e7 - [SPARC][MC] Support more relocation types
Brad Smith via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 5 11:09:53 PDT 2022
Author: LemonBoy
Date: 2022-06-05T14:09:39-04:00
New Revision: 1bfc5e720cadecb3aaa9fed8bec77f0533c8398b
URL: https://github.com/llvm/llvm-project/commit/1bfc5e720cadecb3aaa9fed8bec77f0533c8398b
DIFF: https://github.com/llvm/llvm-project/commit/1bfc5e720cadecb3aaa9fed8bec77f0533c8398b.diff
LOG: [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
Added:
llvm/test/MC/Sparc/sparc-fixups.s
Modified:
llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
llvm/lib/Target/Sparc/SparcISelLowering.cpp
llvm/lib/Target/Sparc/SparcISelLowering.h
llvm/lib/Target/Sparc/SparcInstr64Bit.td
llvm/lib/Target/Sparc/SparcInstrInfo.td
llvm/test/MC/Sparc/sparc-relocations.s
Removed:
################################################################################
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index 9252db61c7c5..bb494ce144f8 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -55,6 +55,8 @@ class SparcOperand;
class SparcAsmParser : public MCTargetAsmParser {
MCAsmParser &Parser;
+ enum class TailRelocKind { Load_GOT, Add_TLS, Load_TLS, Call_TLS };
+
/// @name Auto-generated Match Functions
/// {
@@ -83,6 +85,9 @@ class SparcAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseMembarTag(OperandVector &Operands);
+ template <TailRelocKind Kind>
+ OperandMatchResultTy parseTailRelocSym(OperandVector &Operands);
+
template <unsigned N>
OperandMatchResultTy parseShiftAmtImm(OperandVector &Operands);
@@ -113,6 +118,8 @@ class SparcAsmParser : public MCTargetAsmParser {
bool expandSET(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
+ SMLoc getLoc() const { return getParser().getTok().getLoc(); }
+
public:
SparcAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
const MCInstrInfo &MII,
@@ -267,6 +274,7 @@ class SparcOperand : public MCParsedAsmOperand {
bool isMEMrr() const { return Kind == k_MemoryReg; }
bool isMEMri() const { return Kind == k_MemoryImm; }
bool isMembarTag() const { return Kind == k_Immediate; }
+ bool isTailRelocSym() const { return Kind == k_Immediate; }
bool isCallTarget() const {
if (!isImm())
@@ -427,6 +435,11 @@ class SparcOperand : public MCParsedAsmOperand {
addExpr(Inst, getImm());
}
+ void addTailRelocSymOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
auto Op = std::make_unique<SparcOperand>(k_Token);
Op->Tok.Data = Str.data();
@@ -850,6 +863,98 @@ OperandMatchResultTy SparcAsmParser::parseShiftAmtImm(OperandVector &Operands) {
return MatchOperand_Success;
}
+template <SparcAsmParser::TailRelocKind Kind>
+OperandMatchResultTy
+SparcAsmParser::parseTailRelocSym(OperandVector &Operands) {
+ SMLoc S = getLoc();
+ SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+
+ auto MatchesKind = [](SparcMCExpr::VariantKind VK) -> bool {
+ switch (Kind) {
+ case TailRelocKind::Load_GOT:
+ // Non-TLS relocations on ld (or ldx).
+ // ld [%rr + %rr], %rr, %rel(sym)
+ return VK == SparcMCExpr::VK_Sparc_GOTDATA_OP;
+ case TailRelocKind::Add_TLS:
+ // TLS relocations on add.
+ // add %rr, %rr, %rr, %rel(sym)
+ switch (VK) {
+ case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
+ case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
+ case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
+ case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
+ return true;
+ default:
+ return false;
+ }
+ case TailRelocKind::Load_TLS:
+ // TLS relocations on ld (or ldx).
+ // ld[x] %addr, %rr, %rel(sym)
+ switch (VK) {
+ case SparcMCExpr::VK_Sparc_TLS_IE_LD:
+ case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
+ return true;
+ default:
+ return false;
+ }
+ case TailRelocKind::Call_TLS:
+ // TLS relocations on call.
+ // call sym, %rel(sym)
+ switch (VK) {
+ case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
+ case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
+ return true;
+ default:
+ return false;
+ }
+ default:
+ llvm_unreachable("Unexpected kind parameter");
+ }
+ };
+
+ if (getLexer().getKind() != AsmToken::Percent) {
+ Error(getLoc(), "expected '%' for operand modifier");
+ return MatchOperand_ParseFail;
+ }
+
+ const AsmToken Tok = Parser.getTok();
+ getParser().Lex(); // Eat '%'
+
+ if (getLexer().getKind() != AsmToken::Identifier) {
+ Error(getLoc(), "expected valid identifier for operand modifier");
+ return MatchOperand_ParseFail;
+ }
+
+ StringRef Name = getParser().getTok().getIdentifier();
+ SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(Name);
+ if (VK == SparcMCExpr::VK_Sparc_None) {
+ Error(getLoc(), "invalid operand modifier");
+ return MatchOperand_ParseFail;
+ }
+
+ if (!MatchesKind(VK)) {
+ // Did not match the specified set of relocation types, put '%' back.
+ getLexer().UnLex(Tok);
+ return MatchOperand_NoMatch;
+ }
+
+ Parser.Lex(); // Eat the identifier.
+ if (getLexer().getKind() != AsmToken::LParen) {
+ Error(getLoc(), "expected '('");
+ return MatchOperand_ParseFail;
+ }
+
+ getParser().Lex(); // Eat '('
+ const MCExpr *SubExpr;
+ if (getParser().parseParenExpression(SubExpr, E)) {
+ return MatchOperand_ParseFail;
+ }
+
+ const MCExpr *Val = adjustPICRelocation(VK, SubExpr);
+ Operands.push_back(SparcOperand::CreateImm(Val, S, E));
+ return MatchOperand_Success;
+}
+
OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) {
SMLoc S = Parser.getTok().getLoc();
const MCExpr *EVal;
@@ -1409,10 +1514,27 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
StringRef name = Tok.getString();
SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name);
+ switch (VK) {
+ case SparcMCExpr::VK_Sparc_None:
+ Error(getLoc(), "invalid operand modifier");
+ return false;
- if (VK == SparcMCExpr::VK_Sparc_None)
+ case SparcMCExpr::VK_Sparc_GOTDATA_OP:
+ case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
+ case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
+ case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
+ case SparcMCExpr::VK_Sparc_TLS_IE_LD:
+ case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
+ case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
+ case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
+ case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
+ // These are special-cased at tablegen level.
return false;
+ default:
+ break;
+ }
+
Parser.Lex(); // Eat the identifier.
if (Parser.getTok().getKind() != AsmToken::LParen)
return false;
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
index 4d69040a4508..7b2d8afd3605 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -47,6 +47,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
case Sparc::fixup_sparc_br16_14:
return (Value >> 2) & 0x3fff;
+ case Sparc::fixup_sparc_hix22:
+ return (~Value >> 10) & 0x3fffff;
+
case Sparc::fixup_sparc_pc22:
case Sparc::fixup_sparc_got22:
case Sparc::fixup_sparc_tls_gd_hi22:
@@ -60,6 +63,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
case Sparc::fixup_sparc_13:
return Value & 0x1fff;
+ case Sparc::fixup_sparc_lox10:
+ return (Value & 0x3ff) | 0x1c00;
+
case Sparc::fixup_sparc_pc10:
case Sparc::fixup_sparc_got10:
case Sparc::fixup_sparc_tls_gd_lo10:
@@ -98,6 +104,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
case Sparc::fixup_sparc_tls_ie_ld:
case Sparc::fixup_sparc_tls_ie_ldx:
case Sparc::fixup_sparc_tls_ie_add:
+ case Sparc::fixup_sparc_gotdata_lox10:
+ case Sparc::fixup_sparc_gotdata_hix22:
+ case Sparc::fixup_sparc_gotdata_op:
return 0;
}
}
@@ -189,7 +198,12 @@ namespace {
{ "fixup_sparc_tls_ie_ldx", 0, 0, 0 },
{ "fixup_sparc_tls_ie_add", 0, 0, 0 },
{ "fixup_sparc_tls_le_hix22", 0, 0, 0 },
- { "fixup_sparc_tls_le_lox10", 0, 0, 0 }
+ { "fixup_sparc_tls_le_lox10", 0, 0, 0 },
+ { "fixup_sparc_hix22", 10, 22, 0 },
+ { "fixup_sparc_lox10", 19, 13, 0 },
+ { "fixup_sparc_gotdata_hix22", 0, 0, 0 },
+ { "fixup_sparc_gotdata_lox10", 0, 0, 0 },
+ { "fixup_sparc_gotdata_op", 0, 0, 0 },
};
const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
@@ -231,7 +245,12 @@ namespace {
{ "fixup_sparc_tls_ie_ldx", 0, 0, 0 },
{ "fixup_sparc_tls_ie_add", 0, 0, 0 },
{ "fixup_sparc_tls_le_hix22", 0, 0, 0 },
- { "fixup_sparc_tls_le_lox10", 0, 0, 0 }
+ { "fixup_sparc_tls_le_lox10", 0, 0, 0 },
+ { "fixup_sparc_hix22", 0, 22, 0 },
+ { "fixup_sparc_lox10", 0, 13, 0 },
+ { "fixup_sparc_gotdata_hix22", 0, 0, 0 },
+ { "fixup_sparc_gotdata_lox10", 0, 0, 0 },
+ { "fixup_sparc_gotdata_op", 0, 0, 0 },
};
// Fixup kinds from .reloc directive are like R_SPARC_NONE. They do
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
index dc01cba8d191..9c50c41f6bf2 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
@@ -112,6 +112,11 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx,
case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD;
case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22;
case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10;
+ case Sparc::fixup_sparc_hix22: return ELF::R_SPARC_HIX22;
+ case Sparc::fixup_sparc_lox10: return ELF::R_SPARC_LOX10;
+ case Sparc::fixup_sparc_gotdata_hix22: return ELF::R_SPARC_GOTDATA_HIX22;
+ case Sparc::fixup_sparc_gotdata_lox10: return ELF::R_SPARC_GOTDATA_LOX10;
+ case Sparc::fixup_sparc_gotdata_op: return ELF::R_SPARC_GOTDATA_OP;
}
return ELF::R_SPARC_NONE;
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
index e0a43095ec0b..701d8513e657 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
@@ -95,6 +95,18 @@ namespace llvm {
fixup_sparc_tls_le_hix22,
fixup_sparc_tls_le_lox10,
+ /// 22-bit fixup corresponding to %hix(foo)
+ fixup_sparc_hix22,
+ /// 13-bit fixup corresponding to %lox(foo)
+ fixup_sparc_lox10,
+
+ /// 22-bit fixup corresponding to %gdop_hix22(foo)
+ fixup_sparc_gotdata_hix22,
+ /// 13-bit fixup corresponding to %gdop_lox10(foo)
+ fixup_sparc_gotdata_lox10,
+ /// 32-bit fixup corresponding to %gdop(foo)
+ fixup_sparc_gotdata_op,
+
// Marker
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
index 0a7e4bdaa0a6..d75d41b35838 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
@@ -104,17 +104,21 @@ void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
support::endian::write(OS, Bits,
Ctx.getAsmInfo()->isLittleEndian() ? support::little
: support::big);
- unsigned tlsOpNo = 0;
+
+ // Some instructions have phantom operands that only contribute a fixup entry.
+ unsigned SymOpNo = 0;
switch (MI.getOpcode()) {
default: break;
- case SP::TLS_CALL: tlsOpNo = 1; break;
+ case SP::TLS_CALL: SymOpNo = 1; break;
+ case SP::GDOP_LDrr:
+ case SP::GDOP_LDXrr:
case SP::TLS_ADDrr:
case SP::TLS_ADDXrr:
case SP::TLS_LDrr:
- case SP::TLS_LDXrr: tlsOpNo = 3; break;
+ case SP::TLS_LDXrr: SymOpNo = 3; break;
}
- if (tlsOpNo != 0) {
- const MCOperand &MO = MI.getOperand(tlsOpNo);
+ if (SymOpNo != 0) {
+ const MCOperand &MO = MI.getOperand(SymOpNo);
uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
assert(op == 0 && "Unexpected operand value!");
(void)op; // suppress warning.
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
index 7f64032c5a48..cc73ea7e6120 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
@@ -81,6 +81,11 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind)
case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; return true;
case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; return true;
case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; return true;
+ case VK_Sparc_HIX22: OS << "%hix("; return true;
+ case VK_Sparc_LOX10: OS << "%lox("; return true;
+ case VK_Sparc_GOTDATA_HIX22: OS << "%gdop_hix22("; return true;
+ case VK_Sparc_GOTDATA_LOX10: OS << "%gdop_lox10("; return true;
+ case VK_Sparc_GOTDATA_OP: OS << "%gdop("; return true;
}
llvm_unreachable("Unhandled SparcMCExpr::VariantKind");
}
@@ -120,6 +125,11 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name)
.Case("tie_add", VK_Sparc_TLS_IE_ADD)
.Case("tle_hix22", VK_Sparc_TLS_LE_HIX22)
.Case("tle_lox10", VK_Sparc_TLS_LE_LOX10)
+ .Case("hix", VK_Sparc_HIX22)
+ .Case("lox", VK_Sparc_LOX10)
+ .Case("gdop_hix22", VK_Sparc_GOTDATA_HIX22)
+ .Case("gdop_lox10", VK_Sparc_GOTDATA_LOX10)
+ .Case("gdop", VK_Sparc_GOTDATA_OP)
.Default(VK_Sparc_None);
}
@@ -160,6 +170,11 @@ Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) {
case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add;
case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22;
case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10;
+ case VK_Sparc_HIX22: return Sparc::fixup_sparc_hix22;
+ case VK_Sparc_LOX10: return Sparc::fixup_sparc_lox10;
+ case VK_Sparc_GOTDATA_HIX22: return Sparc::fixup_sparc_gotdata_hix22;
+ case VK_Sparc_GOTDATA_LOX10: return Sparc::fixup_sparc_gotdata_lox10;
+ case VK_Sparc_GOTDATA_OP: return Sparc::fixup_sparc_gotdata_op;
}
}
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
index 504e959194f5..d98ad26c96a9 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
@@ -58,7 +58,12 @@ class SparcMCExpr : public MCTargetExpr {
VK_Sparc_TLS_IE_LDX,
VK_Sparc_TLS_IE_ADD,
VK_Sparc_TLS_LE_HIX22,
- VK_Sparc_TLS_LE_LOX10
+ VK_Sparc_TLS_LE_LOX10,
+ VK_Sparc_HIX22,
+ VK_Sparc_LOX10,
+ VK_Sparc_GOTDATA_HIX22,
+ VK_Sparc_GOTDATA_LOX10,
+ VK_Sparc_GOTDATA_OP,
};
private:
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 06d278dfa981..2cb74e7709c7 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1900,6 +1900,7 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
case SPISD::TLS_LD: return "SPISD::TLS_LD";
case SPISD::TLS_CALL: return "SPISD::TLS_CALL";
case SPISD::TAIL_CALL: return "SPISD::TAIL_CALL";
+ case SPISD::LOAD_GDOP: return "SPISD::LOAD_GDOP";
}
return nullptr;
}
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index 94a5141d95b2..2768bb20566a 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -48,7 +48,9 @@ namespace llvm {
TLS_ADD, // For Thread Local Storage (TLS).
TLS_LD,
- TLS_CALL
+ TLS_CALL,
+
+ LOAD_GDOP, // Load operation w/ gdop relocation.
};
}
diff --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
index dc60f563ae87..a471d65201c3 100644
--- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td
+++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
@@ -163,7 +163,7 @@ defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>;
defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>;
def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd),
- (ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym),
+ (ins I64Regs:$rs1, I64Regs:$rs2, TailRelocSymTLSAdd:$sym),
"add $rs1, $rs2, $rd, $sym",
[(set i64:$rd,
(tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>;
@@ -238,12 +238,20 @@ let Predicates = [Is64Bit] in {
let DecoderMethod = "DecodeLoadInt" in
defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>;
-let mayLoad = 1, isAsmParserOnly = 1 in
+let mayLoad = 1, isAsmParserOnly = 1 in {
def TLS_LDXrr : F3_1<3, 0b001011,
- (outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
+ (outs IntRegs:$dst),
+ (ins MEMrr:$addr, TailRelocSymTLSLoad:$sym),
"ldx [$addr], $dst, $sym",
[(set i64:$dst,
(tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>;
+ def GDOP_LDXrr : F3_1<3, 0b001011,
+ (outs I64Regs:$dst),
+ (ins MEMrr:$addr, TailRelocSymGOTLoad:$sym),
+ "ldx [$addr], $dst, $sym",
+ [(set i64:$dst,
+ (load_gdop ADDRrr:$addr, tglobaladdr:$sym))]>;
+}
// Extending loads to i64.
def : Pat<(i64 (zextloadi1 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>;
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index 34444246019f..481bd7d2f7fa 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -147,7 +147,29 @@ def MEMri : Operand<iPTR> {
let ParserMatchClass = SparcMEMriAsmOperand;
}
-def TLSSym : Operand<iPTR>;
+// Represents a tail relocation operand for instructions such as add, ld, call.
+class SparcTailRelocSymAsmOperand<string Kind> : AsmOperandClass {
+ let Name = "TailRelocSym" # Kind;
+ let RenderMethod = "addTailRelocSymOperands";
+ let PredicateMethod = "isTailRelocSym";
+ let ParserMethod = "parseTailRelocSym<TailRelocKind::" # Kind # ">";
+}
+
+def TailRelocSymGOTLoad : Operand<iPTR> {
+ let ParserMatchClass = SparcTailRelocSymAsmOperand<"Load_GOT">;
+}
+
+def TailRelocSymTLSAdd : Operand<iPTR> {
+ let ParserMatchClass = SparcTailRelocSymAsmOperand<"Add_TLS">;
+}
+
+def TailRelocSymTLSLoad : Operand<iPTR> {
+ let ParserMatchClass = SparcTailRelocSymAsmOperand<"Load_TLS">;
+}
+
+def TailRelocSymTLSCall : Operand<iPTR> {
+ let ParserMatchClass = SparcTailRelocSymAsmOperand<"Call_TLS">;
+}
def SparcMembarTagAsmOperand : AsmOperandClass {
let Name = "MembarTag";
@@ -214,6 +236,9 @@ SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>;
def SDTSPtlsld :
SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
+def SDTSPloadgdop :
+SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
+
def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>;
def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>;
def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
@@ -265,6 +290,8 @@ def tlscall : SDNode<"SPISD::TLS_CALL", SDT_SPCall,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
SDNPVariadic]>;
+def load_gdop : SDNode<"SPISD::LOAD_GDOP", SDTSPloadgdop>;
+
def getPCX : Operand<iPTR> {
let PrintMethod = "printGetPCX";
}
@@ -587,6 +614,15 @@ let DecoderMethod = "DecodeLoadFP" in
}
}
+let mayLoad = 1, isAsmParserOnly = 1 in {
+ def GDOP_LDrr : F3_1<3, 0b000000,
+ (outs IntRegs:$dst),
+ (ins MEMrr:$addr, TailRelocSymGOTLoad:$sym),
+ "ld [$addr], $dst, $sym",
+ [(set i32:$dst,
+ (load_gdop ADDRrr:$addr, tglobaladdr:$sym))]>;
+}
+
// Section B.4 - Store Integer Instructions, p. 95
let DecoderMethod = "DecodeStoreInt" in {
defm STB : StoreA<"stb", 0b000101, 0b010101, truncstorei8, IntRegs, i32>;
@@ -1369,21 +1405,24 @@ let Defs = [FCC0], rd = 0, isCodeGenOnly = 1 in {
let isAsmParserOnly = 1 in {
def TLS_ADDrr : F3_1<2, 0b000000,
(outs IntRegs:$rd),
- (ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym),
+ (ins IntRegs:$rs1, IntRegs:$rs2, TailRelocSymTLSAdd:$sym),
"add $rs1, $rs2, $rd, $sym",
[(set i32:$rd,
(tlsadd i32:$rs1, i32:$rs2, tglobaltlsaddr:$sym))]>;
-let mayLoad = 1 in
+let mayLoad = 1 in {
def TLS_LDrr : F3_1<3, 0b000000,
- (outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
+ (outs IntRegs:$dst),
+ (ins MEMrr:$addr, TailRelocSymTLSLoad:$sym),
"ld [$addr], $dst, $sym",
[(set i32:$dst,
(tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>;
+}
let Uses = [O6], isCall = 1, hasDelaySlot = 1 in
def TLS_CALL : InstSP<(outs),
- (ins calltarget:$disp, TLSSym:$sym, variable_ops),
+ (ins calltarget:$disp, TailRelocSymTLSCall:$sym,
+ variable_ops),
"call $disp, $sym",
[(tlscall texternalsym:$disp, tglobaltlsaddr:$sym)],
IIC_jmp_or_call> {
diff --git a/llvm/test/MC/Sparc/sparc-fixups.s b/llvm/test/MC/Sparc/sparc-fixups.s
new file mode 100644
index 000000000000..cdf006e7cff5
--- /dev/null
+++ b/llvm/test/MC/Sparc/sparc-fixups.s
@@ -0,0 +1,30 @@
+! RUN: llvm-mc %s -arch=sparcv9 -filetype=obj | llvm-objdump -dr - | FileCheck %s
+.text
+
+! Check that fixups are correctly applied.
+
+.set sym, 0xfedcba98
+
+! CHECK: sethi 4175662, %o0
+sethi %hi(sym), %o0
+! CHECK: xor %o0, 664, %o0
+xor %o0, %lo(sym), %o0
+
+! CHECK: sethi 1019, %o0
+sethi %h44(sym), %o0
+! CHECK: or %o0, 459, %o0
+or %o0, %m44(sym), %o0
+! CHECK: ld [%o0+2712], %o0
+ld [%o0 + %l44(sym)], %o0
+
+! CHECK: sethi 0, %o0
+sethi %hh(sym), %o0
+! CHECK: sethi 4175662, %o0
+sethi %lm(sym), %o0
+! CHECK: or %o0, 0, %o0
+or %o0, %hm(sym), %o0
+
+! CHECK: sethi 18641, %o0
+sethi %hix(sym), %o0
+! CHECK: xor %o0, -360, %o0
+xor %o0, %lox(sym), %o0
diff --git a/llvm/test/MC/Sparc/sparc-relocations.s b/llvm/test/MC/Sparc/sparc-relocations.s
index 9acb1b34954a..f812105f503b 100644
--- a/llvm/test/MC/Sparc/sparc-relocations.s
+++ b/llvm/test/MC/Sparc/sparc-relocations.s
@@ -2,18 +2,24 @@
! RUN: llvm-mc %s -arch=sparcv9 -filetype=obj | llvm-readobj -r - | FileCheck %s --check-prefix=CHECK-OBJ
! CHECK-OBJ: Format: elf64-sparc
- ! CHECK-OBJ: Relocations [
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 foo
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_LO10 sym
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HI22 sym
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_H44 sym
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_M44 sym
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_L44 sym
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HH22 sym
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HM10 sym
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_LM22 sym
- ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_13 sym
- ! CHECK-ELF: ]
+ ! CHECK-OBJ: .rela.text {
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 foo
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_H44 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_M44 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_L44 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HH22 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HM10 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LM22 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_13 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_13 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HIX22 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LOX10 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOTDATA_HIX22 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOTDATA_LOX10 sym
+ ! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOTDATA_OP sym
+ ! CHECK-OBJ-NEXT: }
! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A]
! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30
@@ -59,6 +65,26 @@
! CHECK-NEXT: ! fixup A - offset: 0, value: sym+4, kind: fixup_sparc_13
or %g1, (sym+4), %g3
+ ! CHECK: sethi %hix(sym), %g1 ! encoding: [0x03,0b00AAAAAA,A,A]
+ ! CHECK-NEXT: ! fixup A - offset: 0, value: %hix(sym), kind: fixup_sparc_hix22
+ sethi %hix(sym), %g1
+
+ ! CHECK: xor %g1, %lox(sym), %g1 ! encoding: [0x82,0x18,0b011AAAAA,A]
+ ! CHECK-NEXT: ! fixup A - offset: 0, value: %lox(sym), kind: fixup_sparc_lox10
+ xor %g1, %lox(sym), %g1
+
+ ! CHECK: sethi %gdop_hix22(sym), %l1 ! encoding: [0x23,0x00,0x00,0x00]
+ ! CHECK-NEXT: ! fixup A - offset: 0, value: %gdop_hix22(sym), kind: fixup_sparc_gotdata_hix22
+ sethi %gdop_hix22(sym), %l1
+
+ ! CHECK: or %l1, %gdop_lox10(sym), %l1 ! encoding: [0xa2,0x14,0x60,0x00]
+ ! CHECK-NEXT: ! fixup A - offset: 0, value: %gdop_lox10(sym), kind: fixup_sparc_gotdata_lox10
+ or %l1, %gdop_lox10(sym), %l1
+
+ ! CHECK: ldx [%l7+%l1], %l2, %gdop(sym) ! encoding: [0xe4,0x5d,0xc0,0x11]
+ ! CHECK-NEXT: ! fixup A - offset: 0, value: %gdop(sym), kind: fixup_sparc_gotdata_op
+ ldx [%l7 + %l1], %l2, %gdop(sym)
+
! This test needs to placed last in the file
! CHECK: .half a-.Ltmp0
.half a - .
More information about the llvm-commits
mailing list