[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
This commit is contained in:
LemonBoy
2022-06-05 14:06:50 -04:00
committed by Brad Smith
parent 4daa33f6d1
commit 1bfc5e720c
13 changed files with 319 additions and 31 deletions

View File

@@ -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 @@ public:
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 @@ public:
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);
if (VK == SparcMCExpr::VK_Sparc_None)
switch (VK) {
case SparcMCExpr::VK_Sparc_None:
Error(getLoc(), "invalid operand modifier");
return false;
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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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.

View File

@@ -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;
}
}

View File

@@ -58,7 +58,12 @@ public:
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:

View File

@@ -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;
}

View File

@@ -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.
};
}

View File

@@ -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)>;

View File

@@ -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> {

View File

@@ -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

View File

@@ -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 - .