forked from OSchip/llvm-project
[SystemZ] Support all TLS access models - MC part
The current SystemZ back-end only supports the local-exec TLS access model. This patch adds all required MC support for the other TLS models, which means in particular: - Support additional relocation types for Initial-exec model: R_390_TLS_IEENT Local-dynamic-model: R_390_TLS_LDO32, R_390_TLS_LDO64, R_390_TLS_LDM32, R_390_TLS_LDM64, R_390_TLS_LDCALL General-dynamic model: R_390_TLS_GD32, R_390_TLS_GD64, R_390_TLS_GDCALL - Support assembler syntax to generate additional relocations for use with __tls_get_offset calls: :tls_gdcall: :tls_ldcall: The patch also adds a new test to verify fixups and relocations, and removes the (already unused) FK_390_PLT16DBL/FK_390_PLT32DBL fixup kinds. llvm-svn: 229652
This commit is contained in:
parent
a250484c4c
commit
7bdd7c2346
|
@ -57,6 +57,7 @@ private:
|
|||
KindReg,
|
||||
KindAccessReg,
|
||||
KindImm,
|
||||
KindImmTLS,
|
||||
KindMem
|
||||
};
|
||||
|
||||
|
@ -96,11 +97,19 @@ private:
|
|||
const MCExpr *Length;
|
||||
};
|
||||
|
||||
// Imm is an immediate operand, and Sym is an optional TLS symbol
|
||||
// for use with a __tls_get_offset marker relocation.
|
||||
struct ImmTLSOp {
|
||||
const MCExpr *Imm;
|
||||
const MCExpr *Sym;
|
||||
};
|
||||
|
||||
union {
|
||||
TokenOp Token;
|
||||
RegOp Reg;
|
||||
unsigned AccessReg;
|
||||
const MCExpr *Imm;
|
||||
ImmTLSOp ImmTLS;
|
||||
MemOp Mem;
|
||||
};
|
||||
|
||||
|
@ -160,6 +169,14 @@ public:
|
|||
Op->Mem.Length = Length;
|
||||
return Op;
|
||||
}
|
||||
static std::unique_ptr<SystemZOperand>
|
||||
createImmTLS(const MCExpr *Imm, const MCExpr *Sym,
|
||||
SMLoc StartLoc, SMLoc EndLoc) {
|
||||
auto Op = make_unique<SystemZOperand>(KindImmTLS, StartLoc, EndLoc);
|
||||
Op->ImmTLS.Imm = Imm;
|
||||
Op->ImmTLS.Sym = Sym;
|
||||
return Op;
|
||||
}
|
||||
|
||||
// Token operands
|
||||
bool isToken() const override {
|
||||
|
@ -200,6 +217,11 @@ public:
|
|||
return Imm;
|
||||
}
|
||||
|
||||
// Immediate operands with optional TLS symbol.
|
||||
bool isImmTLS() const {
|
||||
return Kind == KindImmTLS;
|
||||
}
|
||||
|
||||
// Memory operands.
|
||||
bool isMem() const override {
|
||||
return Kind == KindMem;
|
||||
|
@ -260,6 +282,13 @@ public:
|
|||
addExpr(Inst, Mem.Disp);
|
||||
addExpr(Inst, Mem.Length);
|
||||
}
|
||||
void addImmTLSOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands");
|
||||
assert(Kind == KindImmTLS && "Invalid operand type");
|
||||
addExpr(Inst, ImmTLS.Imm);
|
||||
if (ImmTLS.Sym)
|
||||
addExpr(Inst, ImmTLS.Sym);
|
||||
}
|
||||
|
||||
// Used by the TableGen code to check for particular operand types.
|
||||
bool isGR32() const { return isReg(GR32Reg); }
|
||||
|
@ -325,6 +354,9 @@ private:
|
|||
const unsigned *Regs, RegisterKind RegKind,
|
||||
MemoryKind MemKind);
|
||||
|
||||
OperandMatchResultTy parsePCRel(OperandVector &Operands, int64_t MinVal,
|
||||
int64_t MaxVal, bool AllowTLS);
|
||||
|
||||
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
|
||||
|
||||
public:
|
||||
|
@ -395,13 +427,17 @@ public:
|
|||
return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDLMem);
|
||||
}
|
||||
OperandMatchResultTy parseAccessReg(OperandVector &Operands);
|
||||
OperandMatchResultTy parsePCRel(OperandVector &Operands, int64_t MinVal,
|
||||
int64_t MaxVal);
|
||||
OperandMatchResultTy parsePCRel16(OperandVector &Operands) {
|
||||
return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1);
|
||||
return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, false);
|
||||
}
|
||||
OperandMatchResultTy parsePCRel32(OperandVector &Operands) {
|
||||
return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1);
|
||||
return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, false);
|
||||
}
|
||||
OperandMatchResultTy parsePCRelTLS16(OperandVector &Operands) {
|
||||
return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, true);
|
||||
}
|
||||
OperandMatchResultTy parsePCRelTLS32(OperandVector &Operands) {
|
||||
return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, true);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
@ -743,7 +779,7 @@ SystemZAsmParser::parseAccessReg(OperandVector &Operands) {
|
|||
|
||||
SystemZAsmParser::OperandMatchResultTy
|
||||
SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal,
|
||||
int64_t MaxVal) {
|
||||
int64_t MaxVal, bool AllowTLS) {
|
||||
MCContext &Ctx = getContext();
|
||||
MCStreamer &Out = getStreamer();
|
||||
const MCExpr *Expr;
|
||||
|
@ -766,9 +802,54 @@ SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal,
|
|||
Expr = Value == 0 ? Base : MCBinaryExpr::CreateAdd(Base, Expr, Ctx);
|
||||
}
|
||||
|
||||
// Optionally match :tls_gdcall: or :tls_ldcall: followed by a TLS symbol.
|
||||
const MCExpr *Sym = nullptr;
|
||||
if (AllowTLS && getLexer().is(AsmToken::Colon)) {
|
||||
Parser.Lex();
|
||||
|
||||
if (Parser.getTok().isNot(AsmToken::Identifier)) {
|
||||
Error(Parser.getTok().getLoc(), "unexpected token");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
|
||||
StringRef Name = Parser.getTok().getString();
|
||||
if (Name == "tls_gdcall")
|
||||
Kind = MCSymbolRefExpr::VK_TLSGD;
|
||||
else if (Name == "tls_ldcall")
|
||||
Kind = MCSymbolRefExpr::VK_TLSLDM;
|
||||
else {
|
||||
Error(Parser.getTok().getLoc(), "unknown TLS tag");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
Parser.Lex();
|
||||
|
||||
if (Parser.getTok().isNot(AsmToken::Colon)) {
|
||||
Error(Parser.getTok().getLoc(), "unexpected token");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
Parser.Lex();
|
||||
|
||||
if (Parser.getTok().isNot(AsmToken::Identifier)) {
|
||||
Error(Parser.getTok().getLoc(), "unexpected token");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
StringRef Identifier = Parser.getTok().getString();
|
||||
Sym = MCSymbolRefExpr::Create(Ctx.GetOrCreateSymbol(Identifier),
|
||||
Kind, Ctx);
|
||||
Parser.Lex();
|
||||
}
|
||||
|
||||
SMLoc EndLoc =
|
||||
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||
Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
|
||||
|
||||
if (AllowTLS)
|
||||
Operands.push_back(SystemZOperand::createImmTLS(Expr, Sym,
|
||||
StartLoc, EndLoc));
|
||||
else
|
||||
Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
|
||||
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "SystemZInstPrinter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
@ -124,6 +125,29 @@ void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
|
|||
O << *MO.getExpr();
|
||||
}
|
||||
|
||||
void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI, int OpNum,
|
||||
raw_ostream &O) {
|
||||
// Output the PC-relative operand.
|
||||
printPCRelOperand(MI, OpNum, O);
|
||||
|
||||
// Output the TLS marker if present.
|
||||
if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
|
||||
const MCOperand &MO = MI->getOperand(OpNum + 1);
|
||||
const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
|
||||
switch (refExp.getKind()) {
|
||||
case MCSymbolRefExpr::VK_TLSGD:
|
||||
O << ":tls_gdcall:";
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_TLSLDM:
|
||||
O << ":tls_ldcall:";
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unexpected symbol kind");
|
||||
}
|
||||
O << refExp.getSymbol().getName();
|
||||
}
|
||||
}
|
||||
|
||||
void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
|
||||
raw_ostream &O) {
|
||||
printOperand(MI->getOperand(OpNum), O);
|
||||
|
|
|
@ -56,6 +56,7 @@ private:
|
|||
void printS32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
|
||||
void printU32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
|
||||
void printPCRelOperand(const MCInst *MI, int OpNum, raw_ostream &O);
|
||||
void printPCRelTLSOperand(const MCInst *MI, int OpNum, raw_ostream &O);
|
||||
void printAccessRegOperand(const MCInst *MI, int OpNum, raw_ostream &O);
|
||||
|
||||
// Print the mnemonic for a condition-code mask ("ne", "lh", etc.)
|
||||
|
|
|
@ -27,9 +27,10 @@ static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value) {
|
|||
switch (unsigned(Kind)) {
|
||||
case SystemZ::FK_390_PC16DBL:
|
||||
case SystemZ::FK_390_PC32DBL:
|
||||
case SystemZ::FK_390_PLT16DBL:
|
||||
case SystemZ::FK_390_PLT32DBL:
|
||||
return (int64_t)Value / 2;
|
||||
|
||||
case SystemZ::FK_390_TLS_CALL:
|
||||
return 0;
|
||||
}
|
||||
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
|
@ -72,8 +73,7 @@ SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
|||
const static MCFixupKindInfo Infos[SystemZ::NumTargetFixupKinds] = {
|
||||
{ "FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "FK_390_PLT16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "FK_390_PLT32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel }
|
||||
{ "FK_390_TLS_CALL", 0, 0, 0 }
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
|
|
|
@ -74,20 +74,36 @@ private:
|
|||
// Operand OpNum of MI needs a PC-relative fixup of kind Kind at
|
||||
// Offset bytes from the start of MI. Add the fixup to Fixups
|
||||
// and return the in-place addend, which since we're a RELA target
|
||||
// is always 0.
|
||||
// is always 0. If AllowTLS is true and optional operand OpNum + 1
|
||||
// is present, also emit a TLS call fixup for it.
|
||||
uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
unsigned Kind, int64_t Offset) const;
|
||||
unsigned Kind, int64_t Offset,
|
||||
bool AllowTLS) const;
|
||||
|
||||
uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC16DBL, 2);
|
||||
return getPCRelEncoding(MI, OpNum, Fixups,
|
||||
SystemZ::FK_390_PC16DBL, 2, false);
|
||||
}
|
||||
uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2);
|
||||
return getPCRelEncoding(MI, OpNum, Fixups,
|
||||
SystemZ::FK_390_PC32DBL, 2, false);
|
||||
}
|
||||
uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return getPCRelEncoding(MI, OpNum, Fixups,
|
||||
SystemZ::FK_390_PC16DBL, 2, true);
|
||||
}
|
||||
uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return getPCRelEncoding(MI, OpNum, Fixups,
|
||||
SystemZ::FK_390_PC32DBL, 2, true);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
@ -181,7 +197,8 @@ getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
|
|||
uint64_t
|
||||
SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
unsigned Kind, int64_t Offset) const {
|
||||
unsigned Kind, int64_t Offset,
|
||||
bool AllowTLS) const {
|
||||
const MCOperand &MO = MI.getOperand(OpNum);
|
||||
const MCExpr *Expr;
|
||||
if (MO.isImm())
|
||||
|
@ -198,6 +215,13 @@ SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
|
|||
}
|
||||
}
|
||||
Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind));
|
||||
|
||||
// Output the fixup for the TLS marker if present.
|
||||
if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
|
||||
const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
|
||||
Fixups.push_back(MCFixup::Create(0, MOTLS.getExpr(),
|
||||
(MCFixupKind)SystemZ::FK_390_TLS_CALL));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,7 @@ enum FixupKind {
|
|||
// These correspond directly to R_390_* relocations.
|
||||
FK_390_PC16DBL = FirstTargetFixupKind,
|
||||
FK_390_PC32DBL,
|
||||
FK_390_PLT16DBL,
|
||||
FK_390_PLT32DBL,
|
||||
FK_390_TLS_CALL,
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
|
|
|
@ -55,8 +55,6 @@ static unsigned getPCRelReloc(unsigned Kind) {
|
|||
case FK_Data_8: return ELF::R_390_PC64;
|
||||
case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL;
|
||||
case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL;
|
||||
case SystemZ::FK_390_PLT16DBL: return ELF::R_390_PLT16DBL;
|
||||
case SystemZ::FK_390_PLT32DBL: return ELF::R_390_PLT32DBL;
|
||||
}
|
||||
llvm_unreachable("Unsupported PC-relative address");
|
||||
}
|
||||
|
@ -70,6 +68,35 @@ static unsigned getTLSLEReloc(unsigned Kind) {
|
|||
llvm_unreachable("Unsupported absolute address");
|
||||
}
|
||||
|
||||
// Return the R_390_TLS_LDO* relocation type for MCFixupKind Kind.
|
||||
static unsigned getTLSLDOReloc(unsigned Kind) {
|
||||
switch (Kind) {
|
||||
case FK_Data_4: return ELF::R_390_TLS_LDO32;
|
||||
case FK_Data_8: return ELF::R_390_TLS_LDO64;
|
||||
}
|
||||
llvm_unreachable("Unsupported absolute address");
|
||||
}
|
||||
|
||||
// Return the R_390_TLS_LDM* relocation type for MCFixupKind Kind.
|
||||
static unsigned getTLSLDMReloc(unsigned Kind) {
|
||||
switch (Kind) {
|
||||
case FK_Data_4: return ELF::R_390_TLS_LDM32;
|
||||
case FK_Data_8: return ELF::R_390_TLS_LDM64;
|
||||
case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_LDCALL;
|
||||
}
|
||||
llvm_unreachable("Unsupported absolute address");
|
||||
}
|
||||
|
||||
// Return the R_390_TLS_GD* relocation type for MCFixupKind Kind.
|
||||
static unsigned getTLSGDReloc(unsigned Kind) {
|
||||
switch (Kind) {
|
||||
case FK_Data_4: return ELF::R_390_TLS_GD32;
|
||||
case FK_Data_8: return ELF::R_390_TLS_GD64;
|
||||
case SystemZ::FK_390_TLS_CALL: return ELF::R_390_TLS_GDCALL;
|
||||
}
|
||||
llvm_unreachable("Unsupported absolute address");
|
||||
}
|
||||
|
||||
// Return the PLT relocation counterpart of MCFixupKind Kind.
|
||||
static unsigned getPLTReloc(unsigned Kind) {
|
||||
switch (Kind) {
|
||||
|
@ -94,6 +121,23 @@ unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target,
|
|||
assert(!IsPCRel && "NTPOFF shouldn't be PC-relative");
|
||||
return getTLSLEReloc(Kind);
|
||||
|
||||
case MCSymbolRefExpr::VK_INDNTPOFF:
|
||||
if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
|
||||
return ELF::R_390_TLS_IEENT;
|
||||
llvm_unreachable("Only PC-relative INDNTPOFF accesses are supported for now");
|
||||
|
||||
case MCSymbolRefExpr::VK_DTPOFF:
|
||||
assert(!IsPCRel && "DTPOFF shouldn't be PC-relative");
|
||||
return getTLSLDOReloc(Kind);
|
||||
|
||||
case MCSymbolRefExpr::VK_TLSLDM:
|
||||
assert(!IsPCRel && "TLSLDM shouldn't be PC-relative");
|
||||
return getTLSLDMReloc(Kind);
|
||||
|
||||
case MCSymbolRefExpr::VK_TLSGD:
|
||||
assert(!IsPCRel && "TLSGD shouldn't be PC-relative");
|
||||
return getTLSGDReloc(Kind);
|
||||
|
||||
case MCSymbolRefExpr::VK_GOT:
|
||||
if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
|
||||
return ELF::R_390_GOTENT;
|
||||
|
|
|
@ -251,9 +251,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
|||
|
||||
// Define the general form of the call instructions for the asm parser.
|
||||
// These instructions don't hard-code %r14 as the return address register.
|
||||
def BRAS : InstRI<0xA75, (outs), (ins GR64:$R1, brtarget16:$I2),
|
||||
// Allow an optional TLS marker symbol to generate TLS call relocations.
|
||||
def BRAS : InstRI<0xA75, (outs), (ins GR64:$R1, brtarget16tls:$I2),
|
||||
"bras\t$R1, $I2", []>;
|
||||
def BRASL : InstRIL<0xC05, (outs), (ins GR64:$R1, brtarget32:$I2),
|
||||
def BRASL : InstRIL<0xC05, (outs), (ins GR64:$R1, brtarget32tls:$I2),
|
||||
"brasl\t$R1, $I2", []>;
|
||||
def BASR : InstRR<0x0D, (outs), (ins GR64:$R1, ADDR64:$R2),
|
||||
"basr\t$R1, $R2", []>;
|
||||
|
|
|
@ -16,6 +16,11 @@ class ImmediateAsmOperand<string name>
|
|||
let Name = name;
|
||||
let RenderMethod = "addImmOperands";
|
||||
}
|
||||
class ImmediateTLSAsmOperand<string name>
|
||||
: AsmOperandClass {
|
||||
let Name = name;
|
||||
let RenderMethod = "addImmTLSOperands";
|
||||
}
|
||||
|
||||
// Constructs both a DAG pattern and instruction operand for an immediate
|
||||
// of type VT. PRED returns true if a node is acceptable and XFORM returns
|
||||
|
@ -34,6 +39,11 @@ class PCRelAsmOperand<string size> : ImmediateAsmOperand<"PCRel"##size> {
|
|||
let PredicateMethod = "isImm";
|
||||
let ParserMethod = "parsePCRel"##size;
|
||||
}
|
||||
class PCRelTLSAsmOperand<string size>
|
||||
: ImmediateTLSAsmOperand<"PCRelTLS"##size> {
|
||||
let PredicateMethod = "isImmTLS";
|
||||
let ParserMethod = "parsePCRelTLS"##size;
|
||||
}
|
||||
|
||||
// Constructs an operand for a PC-relative address with address type VT.
|
||||
// ASMOP is the associated asm operand.
|
||||
|
@ -41,6 +51,10 @@ class PCRelOperand<ValueType vt, AsmOperandClass asmop> : Operand<vt> {
|
|||
let PrintMethod = "printPCRelOperand";
|
||||
let ParserMatchClass = asmop;
|
||||
}
|
||||
class PCRelTLSOperand<ValueType vt, AsmOperandClass asmop> : Operand<vt> {
|
||||
let PrintMethod = "printPCRelTLSOperand";
|
||||
let ParserMatchClass = asmop;
|
||||
}
|
||||
|
||||
// Constructs both a DAG pattern and instruction operand for a PC-relative
|
||||
// address with address size VT. SELF is the name of the operand and
|
||||
|
@ -370,6 +384,8 @@ def fpimmneg0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(-0.0); }]>;
|
|||
// PC-relative asm operands.
|
||||
def PCRel16 : PCRelAsmOperand<"16">;
|
||||
def PCRel32 : PCRelAsmOperand<"32">;
|
||||
def PCRelTLS16 : PCRelTLSAsmOperand<"16">;
|
||||
def PCRelTLS32 : PCRelTLSAsmOperand<"32">;
|
||||
|
||||
// PC-relative offsets of a basic block. The offset is sign-extended
|
||||
// and multiplied by 2.
|
||||
|
@ -382,6 +398,20 @@ def brtarget32 : PCRelOperand<OtherVT, PCRel32> {
|
|||
let DecoderMethod = "decodePC32DBLOperand";
|
||||
}
|
||||
|
||||
// Variants of brtarget16/32 with an optional additional TLS symbol.
|
||||
// These are used to annotate calls to __tls_get_offset.
|
||||
def tlssym : Operand<i64> { }
|
||||
def brtarget16tls : PCRelTLSOperand<OtherVT, PCRelTLS16> {
|
||||
let MIOperandInfo = (ops brtarget16:$func, tlssym:$sym);
|
||||
let EncoderMethod = "getPC16DBLTLSEncoding";
|
||||
let DecoderMethod = "decodePC16DBLOperand";
|
||||
}
|
||||
def brtarget32tls : PCRelTLSOperand<OtherVT, PCRelTLS32> {
|
||||
let MIOperandInfo = (ops brtarget32:$func, tlssym:$sym);
|
||||
let EncoderMethod = "getPC32DBLTLSEncoding";
|
||||
let DecoderMethod = "decodePC32DBLOperand";
|
||||
}
|
||||
|
||||
// A PC-relative offset of a global value. The offset is sign-extended
|
||||
// and multiplied by 2.
|
||||
def pcrel32 : PCRelAddress<i64, "pcrel32", PCRel32> {
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
|
||||
# RUN: llvm-mc -triple s390x-unknown-unknown --show-encoding %s | FileCheck %s
|
||||
|
||||
# RUN: llvm-mc -triple s390x-unknown-unknown -filetype=obj %s | \
|
||||
# RUN: llvm-readobj -r | FileCheck %s -check-prefix=CHECK-REL
|
||||
|
||||
# CHECK: larl %r14, target # encoding: [0xc0,0xe0,A,A,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target+2, kind: FK_390_PC32DBL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PC32DBL target 0x2
|
||||
.align 16
|
||||
larl %r14, target
|
||||
|
||||
# CHECK: larl %r14, target@GOT # encoding: [0xc0,0xe0,A,A,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target@GOT+2, kind: FK_390_PC32DBL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_GOTENT target 0x2
|
||||
.align 16
|
||||
larl %r14, target@got
|
||||
|
||||
# CHECK: larl %r14, target@INDNTPOFF # encoding: [0xc0,0xe0,A,A,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target@INDNTPOFF+2, kind: FK_390_PC32DBL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_TLS_IEENT target 0x2
|
||||
.align 16
|
||||
larl %r14, target@indntpoff
|
||||
|
||||
# CHECK: brasl %r14, target # encoding: [0xc0,0xe5,A,A,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target+2, kind: FK_390_PC32DBL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PC32DBL target 0x2
|
||||
.align 16
|
||||
brasl %r14, target
|
||||
|
||||
# CHECK: brasl %r14, target@PLT # encoding: [0xc0,0xe5,A,A,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target@PLT+2, kind: FK_390_PC32DBL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PLT32DBL target 0x2
|
||||
.align 16
|
||||
brasl %r14, target@plt
|
||||
|
||||
# CHECK: brasl %r14, target@PLT:tls_gdcall:sym # encoding: [0xc0,0xe5,A,A,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target@PLT+2, kind: FK_390_PC32DBL
|
||||
# CHECK-NEXT: # fixup B - offset: 0, value: sym@TLSGD, kind: FK_390_TLS_CALL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_GDCALL sym 0x0
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PLT32DBL target 0x2
|
||||
.align 16
|
||||
brasl %r14, target@plt:tls_gdcall:sym
|
||||
|
||||
# CHECK: brasl %r14, target@PLT:tls_ldcall:sym # encoding: [0xc0,0xe5,A,A,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target@PLT+2, kind: FK_390_PC32DBL
|
||||
# CHECK-NEXT: # fixup B - offset: 0, value: sym@TLSLDM, kind: FK_390_TLS_CALL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_LDCALL sym 0x0
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PLT32DBL target 0x2
|
||||
.align 16
|
||||
brasl %r14, target@plt:tls_ldcall:sym
|
||||
|
||||
# CHECK: bras %r14, target # encoding: [0xa7,0xe5,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target+2, kind: FK_390_PC16DBL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PC16DBL target 0x2
|
||||
.align 16
|
||||
bras %r14, target
|
||||
|
||||
# CHECK: bras %r14, target@PLT # encoding: [0xa7,0xe5,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target@PLT+2, kind: FK_390_PC16DBL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PLT16DBL target 0x2
|
||||
.align 16
|
||||
bras %r14, target@plt
|
||||
|
||||
# CHECK: bras %r14, target@PLT:tls_gdcall:sym # encoding: [0xa7,0xe5,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target@PLT+2, kind: FK_390_PC16DBL
|
||||
# CHECK-NEXT: # fixup B - offset: 0, value: sym@TLSGD, kind: FK_390_TLS_CALL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_GDCALL sym 0x0
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PLT16DBL target 0x2
|
||||
.align 16
|
||||
bras %r14, target@plt:tls_gdcall:sym
|
||||
|
||||
# CHECK: bras %r14, target@PLT:tls_ldcall:sym # encoding: [0xa7,0xe5,A,A]
|
||||
# CHECK-NEXT: # fixup A - offset: 2, value: target@PLT+2, kind: FK_390_PC16DBL
|
||||
# CHECK-NEXT: # fixup B - offset: 0, value: sym@TLSLDM, kind: FK_390_TLS_CALL
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_LDCALL sym 0x0
|
||||
# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PLT16DBL target 0x2
|
||||
.align 16
|
||||
bras %r14, target@plt:tls_ldcall:sym
|
||||
|
||||
|
||||
# Data relocs
|
||||
# llvm-mc does not show any "encoding" string for data, so we just check the relocs
|
||||
|
||||
# CHECK-REL: .rela.data
|
||||
.data
|
||||
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_LE64 target 0x0
|
||||
.align 16
|
||||
.quad target@ntpoff
|
||||
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_LDO64 target 0x0
|
||||
.align 16
|
||||
.quad target@dtpoff
|
||||
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_LDM64 target 0x0
|
||||
.align 16
|
||||
.quad target@tlsldm
|
||||
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_GD64 target 0x0
|
||||
.align 16
|
||||
.quad target@tlsgd
|
||||
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_LE32 target 0x0
|
||||
.align 16
|
||||
.long target@ntpoff
|
||||
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_LDO32 target 0x0
|
||||
.align 16
|
||||
.long target@dtpoff
|
||||
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_LDM32 target 0x0
|
||||
.align 16
|
||||
.long target@tlsldm
|
||||
|
||||
# CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_GD32 target 0x0
|
||||
.align 16
|
||||
.long target@tlsgd
|
||||
|
Loading…
Reference in New Issue