Skip to content

Commit cdc9ee6

Browse files
committed
[X86] Add Support for X86 TLSDESC Relocations
1 parent 5ec535b commit cdc9ee6

File tree

7 files changed

+273
-41
lines changed

7 files changed

+273
-41
lines changed

clang/lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,8 @@ bool tools::isTLSDESCEnabled(const ToolChain &TC,
740740
SupportedArgument = V == "desc" || V == "trad";
741741
EnableTLSDESC = V == "desc";
742742
} else if (Triple.isX86()) {
743-
SupportedArgument = V == "gnu";
743+
SupportedArgument = V == "gnu" || V == "gnu2";
744+
EnableTLSDESC = V == "gnu2";
744745
} else {
745746
Unsupported = true;
746747
}

clang/test/Driver/tls-dialect.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// RUN: %clang -### --target=riscv64-linux -mtls-dialect=trad %s 2>&1 | FileCheck --check-prefix=NODESC %s
33
// RUN: %clang -### --target=riscv64-linux %s 2>&1 | FileCheck --check-prefix=NODESC %s
44
// RUN: %clang -### --target=x86_64-linux -mtls-dialect=gnu %s 2>&1 | FileCheck --check-prefix=NODESC %s
5+
// RUN: %clang -### --target=x86_64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=DESC %s
56

67
/// Android supports TLSDESC by default on RISC-V
78
/// TLSDESC is not on by default in Linux, even on RISC-V, and is covered above
@@ -18,7 +19,6 @@
1819

1920
/// Unsupported argument
2021
// RUN: not %clang -### --target=riscv64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED-ARG %s
21-
// RUN: not %clang -### --target=x86_64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED-ARG %s
2222

2323
// DESC: "-cc1" {{.*}}"-enable-tlsdesc"
2424
// NODESC-NOT: "-enable-tlsdesc"

llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,20 @@ enum TOF {
431431
/// See 'ELF Handling for Thread-Local Storage' for more details.
432432
/// SYMBOL_LABEL @TLSLDM
433433
MO_TLSLDM,
434+
/// MO_TLSCALL - On a symbol operand this indicates that the immediate is
435+
/// the index of the TLS descriptor function for the symbol. Used in both
436+
/// the IA32 and x86-64 local dynamic TLS access model.
437+
/// See 'RFC-TLSDESC-x86' for more details.
438+
/// SYMBOL_LABEL @TLSCALL
439+
MO_TLSCALL,
440+
/// MO_TLSDESC - On a symbol operand this indicates that the immediate is
441+
/// the index of the TLS descriptor argument for the symbol. When this
442+
/// argument is passed to a call getting from index@TLSCALL, the function will
443+
/// return the offset for the symbol. Used in both the IA32 and x86-64 local
444+
/// dynamic TLS access model.
445+
/// See 'RFC-TLSDESC-x86' for more details.
446+
/// SYMBOL_LABEL @TLSDESC
447+
MO_TLSDESC,
434448
/// MO_GOTTPOFF - On a symbol operand this indicates that the immediate is
435449
/// the offset of the GOT entry with the thread-pointer offset for the
436450
/// symbol. Used in the x86-64 initial exec TLS access model.

llvm/lib/Target/X86/X86AsmPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ void X86AsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
271271
case X86II::MO_TLSGD: O << "@TLSGD"; break;
272272
case X86II::MO_TLSLD: O << "@TLSLD"; break;
273273
case X86II::MO_TLSLDM: O << "@TLSLDM"; break;
274+
case X86II::MO_TLSDESC: O << "@TLSDESC"; break;
275+
case X86II::MO_TLSCALL: O << "@TLSCALL"; break;
274276
case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break;
275277
case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break;
276278
case X86II::MO_TPOFF: O << "@TPOFF"; break;

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18515,17 +18515,17 @@ X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const {
1851518515
return LowerGlobalOrExternal(Op, DAG, /*ForCall=*/false);
1851618516
}
1851718517

18518-
static SDValue
18519-
GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA,
18520-
SDValue *InGlue, const EVT PtrVT, unsigned ReturnReg,
18521-
unsigned char OperandFlags, bool LocalDynamic = false) {
18518+
static SDValue GetTLSADDR(SelectionDAG &DAG, SDValue Chain,
18519+
GlobalAddressSDNode *GA, SDValue *InGlue,
18520+
const EVT PtrVT, unsigned ReturnReg,
18521+
unsigned char OperandFlags, bool UseTLSDESC = false,
18522+
bool LocalDynamic = false) {
1852218523
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
1852318524
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1852418525
SDLoc dl(GA);
18525-
SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
18526-
GA->getValueType(0),
18527-
GA->getOffset(),
18528-
OperandFlags);
18526+
SDValue TGA = DAG.getTargetGlobalAddress(
18527+
GA->getGlobal(), dl, GA->getValueType(0), GA->getOffset(),
18528+
UseTLSDESC ? X86II::MO_TLSDESC : OperandFlags);
1852918529

1853018530
X86ISD::NodeType CallType = LocalDynamic ? X86ISD::TLSBASEADDR
1853118531
: X86ISD::TLSADDR;
@@ -18543,37 +18543,54 @@ GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA,
1854318543
MFI.setHasCalls(true);
1854418544

1854518545
SDValue Glue = Chain.getValue(1);
18546-
return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
18546+
SDValue Ret = DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
18547+
18548+
if (!UseTLSDESC)
18549+
return Ret;
18550+
18551+
const X86Subtarget &Subtarget = DAG.getSubtarget<X86Subtarget>();
18552+
MVT VT = Subtarget.isTarget64BitLP64() ? MVT::i64 : MVT::i32;
18553+
unsigned Seg = Subtarget.is64Bit() ? X86AS::FS : X86AS::GS;
18554+
18555+
Value *Ptr = Constant::getNullValue(PointerType::get(*DAG.getContext(), Seg));
18556+
SDValue Offset =
18557+
DAG.getLoad(VT, dl, DAG.getEntryNode(), DAG.getIntPtrConstant(0, dl),
18558+
MachinePointerInfo(Ptr));
18559+
return DAG.getNode(ISD::ADD, dl, VT, Ret, Offset);
1854718560
}
1854818561

1854918562
// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit
18550-
static SDValue
18551-
LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG,
18552-
const EVT PtrVT) {
18563+
static SDValue LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA,
18564+
SelectionDAG &DAG,
18565+
const EVT PtrVT,
18566+
bool UseTLSDESC) {
1855318567
SDValue InGlue;
1855418568
SDLoc dl(GA); // ? function entry point might be better
1855518569
SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, X86::EBX,
1855618570
DAG.getNode(X86ISD::GlobalBaseReg,
1855718571
SDLoc(), PtrVT), InGlue);
1855818572
InGlue = Chain.getValue(1);
1855918573

18560-
return GetTLSADDR(DAG, Chain, GA, &InGlue, PtrVT, X86::EAX, X86II::MO_TLSGD);
18574+
return GetTLSADDR(DAG, Chain, GA, &InGlue, PtrVT, X86::EAX, X86II::MO_TLSGD,
18575+
UseTLSDESC);
1856118576
}
1856218577

1856318578
// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit LP64
18564-
static SDValue
18565-
LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG,
18566-
const EVT PtrVT) {
18567-
return GetTLSADDR(DAG, DAG.getEntryNode(), GA, nullptr, PtrVT,
18568-
X86::RAX, X86II::MO_TLSGD);
18579+
static SDValue LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA,
18580+
SelectionDAG &DAG,
18581+
const EVT PtrVT,
18582+
bool UseTLSDESC) {
18583+
return GetTLSADDR(DAG, DAG.getEntryNode(), GA, nullptr, PtrVT, X86::RAX,
18584+
X86II::MO_TLSGD, UseTLSDESC);
1856918585
}
1857018586

1857118587
// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 64 bit ILP32
18572-
static SDValue
18573-
LowerToTLSGeneralDynamicModelX32(GlobalAddressSDNode *GA, SelectionDAG &DAG,
18574-
const EVT PtrVT) {
18575-
return GetTLSADDR(DAG, DAG.getEntryNode(), GA, nullptr, PtrVT,
18576-
X86::EAX, X86II::MO_TLSGD);
18588+
static SDValue LowerToTLSGeneralDynamicModelX32(GlobalAddressSDNode *GA,
18589+
SelectionDAG &DAG,
18590+
const EVT PtrVT,
18591+
bool UseTLSDESC) {
18592+
return GetTLSADDR(DAG, DAG.getEntryNode(), GA, nullptr, PtrVT, X86::EAX,
18593+
X86II::MO_TLSGD, UseTLSDESC);
1857718594
}
1857818595

1857918596
static SDValue LowerToTLSLocalDynamicModel(GlobalAddressSDNode *GA,
@@ -18590,14 +18607,16 @@ static SDValue LowerToTLSLocalDynamicModel(GlobalAddressSDNode *GA,
1859018607
if (Is64Bit) {
1859118608
unsigned ReturnReg = Is64BitLP64 ? X86::RAX : X86::EAX;
1859218609
Base = GetTLSADDR(DAG, DAG.getEntryNode(), GA, nullptr, PtrVT, ReturnReg,
18593-
X86II::MO_TLSLD, /*LocalDynamic=*/true);
18610+
X86II::MO_TLSLD, /*UseTLSDESC=*/false,
18611+
/*LocalDynamic=*/true);
1859418612
} else {
1859518613
SDValue InGlue;
1859618614
SDValue Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, X86::EBX,
1859718615
DAG.getNode(X86ISD::GlobalBaseReg, SDLoc(), PtrVT), InGlue);
1859818616
InGlue = Chain.getValue(1);
1859918617
Base = GetTLSADDR(DAG, Chain, GA, &InGlue, PtrVT, X86::EAX,
18600-
X86II::MO_TLSLDM, /*LocalDynamic=*/true);
18618+
X86II::MO_TLSLDM, /*UseTLSDESC=*/false,
18619+
/*LocalDynamic=*/true);
1860118620
}
1860218621

1860318622
// Note: the CleanupLocalDynamicTLSPass will remove redundant computations
@@ -18684,21 +18703,26 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
1868418703

1868518704
if (Subtarget.isTargetELF()) {
1868618705
TLSModel::Model model = DAG.getTarget().getTLSModel(GV);
18706+
bool UseTLSDESC = DAG.getTarget().useTLSDESC();
1868718707
switch (model) {
18688-
case TLSModel::GeneralDynamic:
18689-
if (Subtarget.is64Bit()) {
18690-
if (Subtarget.isTarget64BitLP64())
18691-
return LowerToTLSGeneralDynamicModel64(GA, DAG, PtrVT);
18692-
return LowerToTLSGeneralDynamicModelX32(GA, DAG, PtrVT);
18693-
}
18694-
return LowerToTLSGeneralDynamicModel32(GA, DAG, PtrVT);
18695-
case TLSModel::LocalDynamic:
18708+
case TLSModel::LocalDynamic:
18709+
if (!UseTLSDESC)
1869618710
return LowerToTLSLocalDynamicModel(GA, DAG, PtrVT, Subtarget.is64Bit(),
1869718711
Subtarget.isTarget64BitLP64());
18698-
case TLSModel::InitialExec:
18699-
case TLSModel::LocalExec:
18700-
return LowerToTLSExecModel(GA, DAG, PtrVT, model, Subtarget.is64Bit(),
18701-
PositionIndependent);
18712+
[[fallthrough]];
18713+
case TLSModel::GeneralDynamic:
18714+
if (Subtarget.is64Bit()) {
18715+
if (Subtarget.isTarget64BitLP64()) {
18716+
// auto PtrVT = getPointerTy(DAG.getDataLayout(), X86AS::FS);
18717+
return LowerToTLSGeneralDynamicModel64(GA, DAG, PtrVT, UseTLSDESC);
18718+
}
18719+
return LowerToTLSGeneralDynamicModelX32(GA, DAG, PtrVT, UseTLSDESC);
18720+
}
18721+
return LowerToTLSGeneralDynamicModel32(GA, DAG, PtrVT, UseTLSDESC);
18722+
case TLSModel::InitialExec:
18723+
case TLSModel::LocalExec:
18724+
return LowerToTLSExecModel(GA, DAG, PtrVT, model, Subtarget.is64Bit(),
18725+
PositionIndependent);
1870218726
}
1870318727
llvm_unreachable("Unknown TLS model.");
1870418728
}

llvm/lib/Target/X86/X86MCInstLower.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,12 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
257257
case X86II::MO_TLSLDM:
258258
RefKind = MCSymbolRefExpr::VK_TLSLDM;
259259
break;
260+
case X86II::MO_TLSDESC:
261+
RefKind = MCSymbolRefExpr::VK_TLSDESC;
262+
break;
263+
case X86II::MO_TLSCALL:
264+
RefKind = MCSymbolRefExpr::VK_TLSCALL;
265+
break;
260266
case X86II::MO_GOTTPOFF:
261267
RefKind = MCSymbolRefExpr::VK_GOTTPOFF;
262268
break;
@@ -524,13 +530,14 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering,
524530
bool Is64BitsLP64 = MI.getOpcode() == X86::TLS_addr64 ||
525531
MI.getOpcode() == X86::TLS_base_addr64;
526532
MCContext &Ctx = OutStreamer->getContext();
533+
bool isTLSDESC = MI.getOperand(3).getTargetFlags() == X86II::MO_TLSDESC;
527534

528535
MCSymbolRefExpr::VariantKind SRVK;
529536
switch (MI.getOpcode()) {
530537
case X86::TLS_addr32:
531538
case X86::TLS_addr64:
532539
case X86::TLS_addrX32:
533-
SRVK = MCSymbolRefExpr::VK_TLSGD;
540+
SRVK = isTLSDESC ? MCSymbolRefExpr::VK_TLSDESC : MCSymbolRefExpr::VK_TLSGD;
534541
break;
535542
case X86::TLS_base_addr32:
536543
SRVK = MCSymbolRefExpr::VK_TLSLDM;
@@ -554,7 +561,26 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering,
554561
bool UseGot = MMI->getModule()->getRtLibUseGOT() &&
555562
Ctx.getAsmInfo()->canRelaxRelocations();
556563

557-
if (Is64Bits) {
564+
if (isTLSDESC) {
565+
const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(
566+
MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)),
567+
MCSymbolRefExpr::VK_TLSCALL, Ctx);
568+
EmitAndCountInstruction(
569+
MCInstBuilder(Is64BitsLP64 ? X86::LEA64r : X86::LEA32r)
570+
.addReg(Is64BitsLP64 ? X86::RAX : X86::EAX)
571+
.addReg(Is64Bits ? X86::RIP : X86::EBX)
572+
.addImm(1)
573+
.addReg(0)
574+
.addExpr(Sym)
575+
.addReg(0));
576+
EmitAndCountInstruction(
577+
MCInstBuilder(Is64Bits ? X86::CALL64m : X86::CALL32m)
578+
.addReg(Is64BitsLP64 ? X86::RAX : X86::EAX)
579+
.addImm(1)
580+
.addReg(0)
581+
.addExpr(Expr)
582+
.addReg(0));
583+
} else if (Is64Bits) {
558584
bool NeedsPadding = SRVK == MCSymbolRefExpr::VK_TLSGD;
559585
if (NeedsPadding && Is64BitsLP64)
560586
EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX));

0 commit comments

Comments
 (0)