Skip to content

Commit f4676b6

Browse files
authored
[X86] Add Support for X86 TLSDESC Relocations (#83136)
1 parent 0b9f19a commit f4676b6

File tree

9 files changed

+289
-19
lines changed

9 files changed

+289
-19
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/X86ISelDAGToDAG.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,13 +3090,19 @@ bool X86DAGToDAGISel::selectLEAAddr(SDValue N,
30903090
bool X86DAGToDAGISel::selectTLSADDRAddr(SDValue N, SDValue &Base,
30913091
SDValue &Scale, SDValue &Index,
30923092
SDValue &Disp, SDValue &Segment) {
3093-
assert(N.getOpcode() == ISD::TargetGlobalTLSAddress);
3094-
auto *GA = cast<GlobalAddressSDNode>(N);
3093+
assert(N.getOpcode() == ISD::TargetGlobalTLSAddress ||
3094+
N.getOpcode() == ISD::TargetExternalSymbol);
30953095

30963096
X86ISelAddressMode AM;
3097-
AM.GV = GA->getGlobal();
3098-
AM.Disp += GA->getOffset();
3099-
AM.SymbolFlags = GA->getTargetFlags();
3097+
if (auto *GA = dyn_cast<GlobalAddressSDNode>(N)) {
3098+
AM.GV = GA->getGlobal();
3099+
AM.Disp += GA->getOffset();
3100+
AM.SymbolFlags = GA->getTargetFlags();
3101+
} else {
3102+
auto *SA = cast<ExternalSymbolSDNode>(N);
3103+
AM.ES = SA->getSymbol();
3104+
AM.SymbolFlags = SA->getTargetFlags();
3105+
}
31003106

31013107
if (Subtarget->is32Bit()) {
31023108
AM.Scale = 1;

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18592,13 +18592,22 @@ GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA,
1859218592
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
1859318593
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1859418594
SDLoc dl(GA);
18595-
SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
18596-
GA->getValueType(0),
18597-
GA->getOffset(),
18598-
OperandFlags);
18595+
SDValue TGA;
18596+
bool UseTLSDESC = DAG.getTarget().useTLSDESC();
18597+
if (LocalDynamic && UseTLSDESC) {
18598+
TGA = DAG.getTargetExternalSymbol("_TLS_MODULE_BASE_", PtrVT, OperandFlags);
18599+
auto UI = TGA->use_begin();
18600+
// Reuse existing GetTLSADDR node if we can find it.
18601+
if (UI != TGA->use_end())
18602+
return SDValue(*UI->use_begin()->use_begin(), 0);
18603+
} else {
18604+
TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, GA->getValueType(0),
18605+
GA->getOffset(), OperandFlags);
18606+
}
1859918607

18600-
X86ISD::NodeType CallType = LocalDynamic ? X86ISD::TLSBASEADDR
18601-
: X86ISD::TLSADDR;
18608+
X86ISD::NodeType CallType = UseTLSDESC ? X86ISD::TLSDESC
18609+
: LocalDynamic ? X86ISD::TLSBASEADDR
18610+
: X86ISD::TLSADDR;
1860218611

1860318612
if (InGlue) {
1860418613
SDValue Ops[] = { Chain, TGA, *InGlue };
@@ -18613,7 +18622,19 @@ GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA,
1861318622
MFI.setHasCalls(true);
1861418623

1861518624
SDValue Glue = Chain.getValue(1);
18616-
return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
18625+
SDValue Ret = DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
18626+
18627+
if (!UseTLSDESC)
18628+
return Ret;
18629+
18630+
const X86Subtarget &Subtarget = DAG.getSubtarget<X86Subtarget>();
18631+
unsigned Seg = Subtarget.is64Bit() ? X86AS::FS : X86AS::GS;
18632+
18633+
Value *Ptr = Constant::getNullValue(PointerType::get(*DAG.getContext(), Seg));
18634+
SDValue Offset =
18635+
DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), DAG.getIntPtrConstant(0, dl),
18636+
MachinePointerInfo(Ptr));
18637+
return DAG.getNode(ISD::ADD, dl, PtrVT, Ret, Offset);
1861718638
}
1861818639

1861918640
// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit
@@ -33426,6 +33447,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
3342633447
NODE_NAME_CASE(TLSADDR)
3342733448
NODE_NAME_CASE(TLSBASEADDR)
3342833449
NODE_NAME_CASE(TLSCALL)
33450+
NODE_NAME_CASE(TLSDESC)
3342933451
NODE_NAME_CASE(EH_SJLJ_SETJMP)
3343033452
NODE_NAME_CASE(EH_SJLJ_LONGJMP)
3343133453
NODE_NAME_CASE(EH_SJLJ_SETUP_DISPATCH)
@@ -36206,6 +36228,8 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
3620636228
case X86::TLS_base_addr32:
3620736229
case X86::TLS_base_addr64:
3620836230
case X86::TLS_base_addrX32:
36231+
case X86::TLS_desc32:
36232+
case X86::TLS_desc64:
3620936233
return EmitLoweredTLSAddr(MI, BB);
3621036234
case X86::INDIRECT_THUNK_CALL32:
3621136235
case X86::INDIRECT_THUNK_CALL64:

llvm/lib/Target/X86/X86ISelLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ namespace llvm {
295295
// thunk at the address from an earlier relocation.
296296
TLSCALL,
297297

298+
// Thread Local Storage. A descriptor containing pointer to
299+
// code and to argument to get the TLS offset for the symbol.
300+
TLSDESC,
301+
298302
// Exception Handling helpers.
299303
EH_RETURN,
300304

llvm/lib/Target/X86/X86InstrCompiler.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,16 @@ def TLS_base_addrX32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
507507
Requires<[In64BitMode, NotLP64]>;
508508
}
509509

510+
// TLSDESC only clobbers EAX and EFLAGS. ESP is marked as a use to prevent
511+
// stack-pointer assignments that appear immediately before calls from
512+
// potentially appearing dead.
513+
let Defs = [EAX, EFLAGS], usesCustomInserter = 1, Uses = [RSP, SSP] in {
514+
def TLS_desc32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
515+
"# TLS_desc32", [(X86tlsdesc tls32addr:$sym)]>;
516+
def TLS_desc64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
517+
"# TLS_desc64", [(X86tlsdesc tls64addr:$sym)]>;
518+
}
519+
510520
// Darwin TLS Support
511521
// For i386, the address of the thunk is passed on the stack, on return the
512522
// address of the variable is in %eax. %ecx is trashed during the function

llvm/lib/Target/X86/X86InstrFragments.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR,
223223
def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR,
224224
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
225225

226+
def X86tlsdesc : SDNode<"X86ISD::TLSDESC", SDT_X86TLSADDR,
227+
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
228+
226229
def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET,
227230
[SDNPHasChain]>;
228231

llvm/lib/Target/X86/X86MCInstLower.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -519,10 +519,8 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
519519
void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering,
520520
const MachineInstr &MI) {
521521
NoAutoPaddingScope NoPadScope(*OutStreamer);
522-
bool Is64Bits = MI.getOpcode() != X86::TLS_addr32 &&
523-
MI.getOpcode() != X86::TLS_base_addr32;
524-
bool Is64BitsLP64 = MI.getOpcode() == X86::TLS_addr64 ||
525-
MI.getOpcode() == X86::TLS_base_addr64;
522+
bool Is64Bits = getSubtarget().is64Bit();
523+
bool Is64BitsLP64 = getSubtarget().isTarget64BitLP64();
526524
MCContext &Ctx = OutStreamer->getContext();
527525

528526
MCSymbolRefExpr::VariantKind SRVK;
@@ -539,6 +537,10 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering,
539537
case X86::TLS_base_addrX32:
540538
SRVK = MCSymbolRefExpr::VK_TLSLD;
541539
break;
540+
case X86::TLS_desc32:
541+
case X86::TLS_desc64:
542+
SRVK = MCSymbolRefExpr::VK_TLSDESC;
543+
break;
542544
default:
543545
llvm_unreachable("unexpected opcode");
544546
}
@@ -554,7 +556,26 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering,
554556
bool UseGot = MMI->getModule()->getRtLibUseGOT() &&
555557
Ctx.getTargetOptions()->X86RelaxRelocations;
556558

557-
if (Is64Bits) {
559+
if (SRVK == MCSymbolRefExpr::VK_TLSDESC) {
560+
const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(
561+
MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)),
562+
MCSymbolRefExpr::VK_TLSCALL, Ctx);
563+
EmitAndCountInstruction(
564+
MCInstBuilder(Is64BitsLP64 ? X86::LEA64r : X86::LEA32r)
565+
.addReg(Is64BitsLP64 ? X86::RAX : X86::EAX)
566+
.addReg(Is64Bits ? X86::RIP : X86::EBX)
567+
.addImm(1)
568+
.addReg(0)
569+
.addExpr(Sym)
570+
.addReg(0));
571+
EmitAndCountInstruction(
572+
MCInstBuilder(Is64Bits ? X86::CALL64m : X86::CALL32m)
573+
.addReg(Is64BitsLP64 ? X86::RAX : X86::EAX)
574+
.addImm(1)
575+
.addReg(0)
576+
.addExpr(Expr)
577+
.addReg(0));
578+
} else if (Is64Bits) {
558579
bool NeedsPadding = SRVK == MCSymbolRefExpr::VK_TLSGD;
559580
if (NeedsPadding && Is64BitsLP64)
560581
EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX));
@@ -2164,6 +2185,8 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
21642185
case X86::TLS_base_addr32:
21652186
case X86::TLS_base_addr64:
21662187
case X86::TLS_base_addrX32:
2188+
case X86::TLS_desc32:
2189+
case X86::TLS_desc64:
21672190
return LowerTlsAddr(MCInstLowering, *MI);
21682191

21692192
case X86::MOVPC32r: {

0 commit comments

Comments
 (0)