mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-13 17:38:39 +00:00
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229652 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
582e77af02
commit
ca1a3cf45b
@ -57,6 +57,7 @@ private:
|
|||||||
KindReg,
|
KindReg,
|
||||||
KindAccessReg,
|
KindAccessReg,
|
||||||
KindImm,
|
KindImm,
|
||||||
|
KindImmTLS,
|
||||||
KindMem
|
KindMem
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -96,11 +97,19 @@ private:
|
|||||||
const MCExpr *Length;
|
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 {
|
union {
|
||||||
TokenOp Token;
|
TokenOp Token;
|
||||||
RegOp Reg;
|
RegOp Reg;
|
||||||
unsigned AccessReg;
|
unsigned AccessReg;
|
||||||
const MCExpr *Imm;
|
const MCExpr *Imm;
|
||||||
|
ImmTLSOp ImmTLS;
|
||||||
MemOp Mem;
|
MemOp Mem;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -160,6 +169,14 @@ public:
|
|||||||
Op->Mem.Length = Length;
|
Op->Mem.Length = Length;
|
||||||
return Op;
|
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
|
// Token operands
|
||||||
bool isToken() const override {
|
bool isToken() const override {
|
||||||
@ -200,6 +217,11 @@ public:
|
|||||||
return Imm;
|
return Imm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Immediate operands with optional TLS symbol.
|
||||||
|
bool isImmTLS() const {
|
||||||
|
return Kind == KindImmTLS;
|
||||||
|
}
|
||||||
|
|
||||||
// Memory operands.
|
// Memory operands.
|
||||||
bool isMem() const override {
|
bool isMem() const override {
|
||||||
return Kind == KindMem;
|
return Kind == KindMem;
|
||||||
@ -260,6 +282,13 @@ public:
|
|||||||
addExpr(Inst, Mem.Disp);
|
addExpr(Inst, Mem.Disp);
|
||||||
addExpr(Inst, Mem.Length);
|
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.
|
// Used by the TableGen code to check for particular operand types.
|
||||||
bool isGR32() const { return isReg(GR32Reg); }
|
bool isGR32() const { return isReg(GR32Reg); }
|
||||||
@ -325,6 +354,9 @@ private:
|
|||||||
const unsigned *Regs, RegisterKind RegKind,
|
const unsigned *Regs, RegisterKind RegKind,
|
||||||
MemoryKind MemKind);
|
MemoryKind MemKind);
|
||||||
|
|
||||||
|
OperandMatchResultTy parsePCRel(OperandVector &Operands, int64_t MinVal,
|
||||||
|
int64_t MaxVal, bool AllowTLS);
|
||||||
|
|
||||||
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
|
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -395,13 +427,17 @@ public:
|
|||||||
return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDLMem);
|
return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDLMem);
|
||||||
}
|
}
|
||||||
OperandMatchResultTy parseAccessReg(OperandVector &Operands);
|
OperandMatchResultTy parseAccessReg(OperandVector &Operands);
|
||||||
OperandMatchResultTy parsePCRel(OperandVector &Operands, int64_t MinVal,
|
|
||||||
int64_t MaxVal);
|
|
||||||
OperandMatchResultTy parsePCRel16(OperandVector &Operands) {
|
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) {
|
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
|
} // end anonymous namespace
|
||||||
@ -743,7 +779,7 @@ SystemZAsmParser::parseAccessReg(OperandVector &Operands) {
|
|||||||
|
|
||||||
SystemZAsmParser::OperandMatchResultTy
|
SystemZAsmParser::OperandMatchResultTy
|
||||||
SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal,
|
SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal,
|
||||||
int64_t MaxVal) {
|
int64_t MaxVal, bool AllowTLS) {
|
||||||
MCContext &Ctx = getContext();
|
MCContext &Ctx = getContext();
|
||||||
MCStreamer &Out = getStreamer();
|
MCStreamer &Out = getStreamer();
|
||||||
const MCExpr *Expr;
|
const MCExpr *Expr;
|
||||||
@ -766,9 +802,54 @@ SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal,
|
|||||||
Expr = Value == 0 ? Base : MCBinaryExpr::CreateAdd(Base, Expr, Ctx);
|
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 EndLoc =
|
||||||
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||||
|
|
||||||
|
if (AllowTLS)
|
||||||
|
Operands.push_back(SystemZOperand::createImmTLS(Expr, Sym,
|
||||||
|
StartLoc, EndLoc));
|
||||||
|
else
|
||||||
Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
|
Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));
|
||||||
|
|
||||||
return MatchOperand_Success;
|
return MatchOperand_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "SystemZInstPrinter.h"
|
#include "SystemZInstPrinter.h"
|
||||||
#include "llvm/MC/MCExpr.h"
|
#include "llvm/MC/MCExpr.h"
|
||||||
#include "llvm/MC/MCInstrInfo.h"
|
#include "llvm/MC/MCInstrInfo.h"
|
||||||
|
#include "llvm/MC/MCSymbol.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -124,6 +125,29 @@ void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
|
|||||||
O << *MO.getExpr();
|
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,
|
void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
|
||||||
raw_ostream &O) {
|
raw_ostream &O) {
|
||||||
printOperand(MI->getOperand(OpNum), O);
|
printOperand(MI->getOperand(OpNum), O);
|
||||||
|
@ -56,6 +56,7 @@ private:
|
|||||||
void printS32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
|
void printS32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
|
||||||
void printU32ImmOperand(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 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);
|
void printAccessRegOperand(const MCInst *MI, int OpNum, raw_ostream &O);
|
||||||
|
|
||||||
// Print the mnemonic for a condition-code mask ("ne", "lh", etc.)
|
// 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)) {
|
switch (unsigned(Kind)) {
|
||||||
case SystemZ::FK_390_PC16DBL:
|
case SystemZ::FK_390_PC16DBL:
|
||||||
case SystemZ::FK_390_PC32DBL:
|
case SystemZ::FK_390_PC32DBL:
|
||||||
case SystemZ::FK_390_PLT16DBL:
|
|
||||||
case SystemZ::FK_390_PLT32DBL:
|
|
||||||
return (int64_t)Value / 2;
|
return (int64_t)Value / 2;
|
||||||
|
|
||||||
|
case SystemZ::FK_390_TLS_CALL:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_unreachable("Unknown fixup kind!");
|
llvm_unreachable("Unknown fixup kind!");
|
||||||
@ -72,8 +73,7 @@ SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
|||||||
const static MCFixupKindInfo Infos[SystemZ::NumTargetFixupKinds] = {
|
const static MCFixupKindInfo Infos[SystemZ::NumTargetFixupKinds] = {
|
||||||
{ "FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
{ "FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
{ "FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "FK_390_PLT16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
{ "FK_390_TLS_CALL", 0, 0, 0 }
|
||||||
{ "FK_390_PLT32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Kind < FirstTargetFixupKind)
|
if (Kind < FirstTargetFixupKind)
|
||||||
|
@ -74,20 +74,36 @@ private:
|
|||||||
// Operand OpNum of MI needs a PC-relative fixup of kind Kind at
|
// 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
|
// 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
|
// 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,
|
uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
|
||||||
SmallVectorImpl<MCFixup> &Fixups,
|
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,
|
uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
|
||||||
SmallVectorImpl<MCFixup> &Fixups,
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
const MCSubtargetInfo &STI) const {
|
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,
|
uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
|
||||||
SmallVectorImpl<MCFixup> &Fixups,
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
const MCSubtargetInfo &STI) const {
|
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
|
} // end anonymous namespace
|
||||||
@ -181,7 +197,8 @@ getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
|
|||||||
uint64_t
|
uint64_t
|
||||||
SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
|
SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
|
||||||
SmallVectorImpl<MCFixup> &Fixups,
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
unsigned Kind, int64_t Offset) const {
|
unsigned Kind, int64_t Offset,
|
||||||
|
bool AllowTLS) const {
|
||||||
const MCOperand &MO = MI.getOperand(OpNum);
|
const MCOperand &MO = MI.getOperand(OpNum);
|
||||||
const MCExpr *Expr;
|
const MCExpr *Expr;
|
||||||
if (MO.isImm())
|
if (MO.isImm())
|
||||||
@ -198,6 +215,13 @@ SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,7 @@ enum FixupKind {
|
|||||||
// These correspond directly to R_390_* relocations.
|
// These correspond directly to R_390_* relocations.
|
||||||
FK_390_PC16DBL = FirstTargetFixupKind,
|
FK_390_PC16DBL = FirstTargetFixupKind,
|
||||||
FK_390_PC32DBL,
|
FK_390_PC32DBL,
|
||||||
FK_390_PLT16DBL,
|
FK_390_TLS_CALL,
|
||||||
FK_390_PLT32DBL,
|
|
||||||
|
|
||||||
// Marker
|
// Marker
|
||||||
LastTargetFixupKind,
|
LastTargetFixupKind,
|
||||||
|
@ -55,8 +55,6 @@ static unsigned getPCRelReloc(unsigned Kind) {
|
|||||||
case FK_Data_8: return ELF::R_390_PC64;
|
case FK_Data_8: return ELF::R_390_PC64;
|
||||||
case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL;
|
case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL;
|
||||||
case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL;
|
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");
|
llvm_unreachable("Unsupported PC-relative address");
|
||||||
}
|
}
|
||||||
@ -70,6 +68,35 @@ static unsigned getTLSLEReloc(unsigned Kind) {
|
|||||||
llvm_unreachable("Unsupported absolute address");
|
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.
|
// Return the PLT relocation counterpart of MCFixupKind Kind.
|
||||||
static unsigned getPLTReloc(unsigned Kind) {
|
static unsigned getPLTReloc(unsigned Kind) {
|
||||||
switch (Kind) {
|
switch (Kind) {
|
||||||
@ -94,6 +121,23 @@ unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target,
|
|||||||
assert(!IsPCRel && "NTPOFF shouldn't be PC-relative");
|
assert(!IsPCRel && "NTPOFF shouldn't be PC-relative");
|
||||||
return getTLSLEReloc(Kind);
|
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:
|
case MCSymbolRefExpr::VK_GOT:
|
||||||
if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
|
if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
|
||||||
return ELF::R_390_GOTENT;
|
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.
|
// Define the general form of the call instructions for the asm parser.
|
||||||
// These instructions don't hard-code %r14 as the return address register.
|
// 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", []>;
|
"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", []>;
|
"brasl\t$R1, $I2", []>;
|
||||||
def BASR : InstRR<0x0D, (outs), (ins GR64:$R1, ADDR64:$R2),
|
def BASR : InstRR<0x0D, (outs), (ins GR64:$R1, ADDR64:$R2),
|
||||||
"basr\t$R1, $R2", []>;
|
"basr\t$R1, $R2", []>;
|
||||||
|
@ -16,6 +16,11 @@ class ImmediateAsmOperand<string name>
|
|||||||
let Name = name;
|
let Name = name;
|
||||||
let RenderMethod = "addImmOperands";
|
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
|
// 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
|
// 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 PredicateMethod = "isImm";
|
||||||
let ParserMethod = "parsePCRel"##size;
|
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.
|
// Constructs an operand for a PC-relative address with address type VT.
|
||||||
// ASMOP is the associated asm operand.
|
// ASMOP is the associated asm operand.
|
||||||
@ -41,6 +51,10 @@ class PCRelOperand<ValueType vt, AsmOperandClass asmop> : Operand<vt> {
|
|||||||
let PrintMethod = "printPCRelOperand";
|
let PrintMethod = "printPCRelOperand";
|
||||||
let ParserMatchClass = asmop;
|
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
|
// 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
|
// 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.
|
// PC-relative asm operands.
|
||||||
def PCRel16 : PCRelAsmOperand<"16">;
|
def PCRel16 : PCRelAsmOperand<"16">;
|
||||||
def PCRel32 : PCRelAsmOperand<"32">;
|
def PCRel32 : PCRelAsmOperand<"32">;
|
||||||
|
def PCRelTLS16 : PCRelTLSAsmOperand<"16">;
|
||||||
|
def PCRelTLS32 : PCRelTLSAsmOperand<"32">;
|
||||||
|
|
||||||
// PC-relative offsets of a basic block. The offset is sign-extended
|
// PC-relative offsets of a basic block. The offset is sign-extended
|
||||||
// and multiplied by 2.
|
// and multiplied by 2.
|
||||||
@ -382,6 +398,20 @@ def brtarget32 : PCRelOperand<OtherVT, PCRel32> {
|
|||||||
let DecoderMethod = "decodePC32DBLOperand";
|
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
|
// A PC-relative offset of a global value. The offset is sign-extended
|
||||||
// and multiplied by 2.
|
// and multiplied by 2.
|
||||||
def pcrel32 : PCRelAddress<i64, "pcrel32", PCRel32> {
|
def pcrel32 : PCRelAddress<i64, "pcrel32", PCRel32> {
|
||||||
|
119
test/MC/SystemZ/fixups.s
Normal file
119
test/MC/SystemZ/fixups.s
Normal file
@ -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…
x
Reference in New Issue
Block a user