Skip to content

Commit 2385592

Browse files
committed
[LDC] Custom TLS emulation for Android targets
The Bionic C library ignores thread-local data stored in the normal .tbss/.tdata ELF sections, which are marked with the SHF_TLS/STT_TLS flags. LDC rolls its own emulated TLS scheme for Android instead, by keeping TLS data in the .tdata/.tbss sections but removing the SHF_TLS/STT_TLS flags, and replacing direct access to these globals by a call to __tls_get_addr() (implemented in druntime's rt.sections_android). The function is expected to translate an address in the TLS static data to the corresponding address in the actual TLS dynamic per-thread data.
1 parent 1f920ed commit 2385592

File tree

9 files changed

+66
-13
lines changed

9 files changed

+66
-13
lines changed

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4525,6 +4525,9 @@ class TargetLowering : public TargetLoweringBase {
45254525
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA,
45264526
SelectionDAG &DAG) const;
45274527

4528+
SDValue LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
4529+
SelectionDAG &DAG, bool is64bit) const; // LDC
4530+
45284531
/// Expands target specific indirect branch for the case of JumpTable
45294532
/// expanasion.
45304533
virtual SDValue expandIndirectJTBranch(const SDLoc& dl, SDValue Value, SDValue Addr,

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7572,6 +7572,33 @@ SDValue TargetLowering::getVectorElementPointer(SelectionDAG &DAG,
75727572
return DAG.getMemBasePlusOffset(VecPtr, Index, dl);
75737573
}
75747574

7575+
SDValue
7576+
TargetLowering::LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
7577+
SelectionDAG &DAG, bool is64bit) const { // LDC
7578+
SDLoc DL(Op);
7579+
SDValue Chain = DAG.getEntryNode();
7580+
ArgListTy Args;
7581+
ArgListEntry Entry;
7582+
Type *Ty;
7583+
if (is64bit)
7584+
Ty = (Type *)Type::getInt64Ty(*DAG.getContext());
7585+
else
7586+
Ty = (Type *)Type::getInt32Ty(*DAG.getContext());
7587+
Entry.Node = Result;
7588+
Entry.Ty = Ty;
7589+
Args.push_back(Entry);
7590+
7591+
// copied, modified from ARMTargetLowering::LowerToTLSGeneralDynamicModel
7592+
TargetLowering::CallLoweringInfo CLI(DAG);
7593+
CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
7594+
CallingConv::C, Ty,
7595+
DAG.getExternalSymbol("__tls_get_addr",
7596+
getPointerTy(DAG.getDataLayout())),
7597+
std::move(Args));
7598+
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
7599+
return CallResult.first;
7600+
}
7601+
75757602
//===----------------------------------------------------------------------===//
75767603
// Implementation of Emulated TLS Model
75777604
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ static unsigned getELFSectionType(StringRef Name, SectionKind K) {
490490
return ELF::SHT_PROGBITS;
491491
}
492492

493-
static unsigned getELFSectionFlags(SectionKind K) {
493+
static unsigned getELFSectionFlags(SectionKind K, const Triple &TargetTriple) {
494494
unsigned Flags = 0;
495495

496496
if (!K.isMetadata())
@@ -505,7 +505,7 @@ static unsigned getELFSectionFlags(SectionKind K) {
505505
if (K.isWriteable())
506506
Flags |= ELF::SHF_WRITE;
507507

508-
if (K.isThreadLocal())
508+
if (K.isThreadLocal() && !TargetTriple.isAndroid()) // LDC
509509
Flags |= ELF::SHF_TLS;
510510

511511
if (K.isMergeableCString() || K.isMergeableConst())
@@ -669,7 +669,7 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
669669
Kind = getELFKindForNamedSection(SectionName, Kind);
670670

671671
StringRef Group = "";
672-
unsigned Flags = getELFSectionFlags(Kind);
672+
unsigned Flags = getELFSectionFlags(Kind, getTargetTriple());
673673
if (const Comdat *C = getELFComdat(GO)) {
674674
Group = C->getName();
675675
Flags |= ELF::SHF_GROUP;
@@ -793,7 +793,7 @@ static MCSectionELF *selectELFSectionForGlobal(
793793

794794
MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
795795
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
796-
unsigned Flags = getELFSectionFlags(Kind);
796+
unsigned Flags = getELFSectionFlags(Kind, getTargetTriple());
797797

798798
// If we have -ffunction-section or -fdata-section then we should emit the
799799
// global value to a uniqued section specifically for it.

llvm/lib/MC/MCELFStreamer.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,12 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
464464
break;
465465
}
466466
getAssembler().registerSymbol(symRef.getSymbol());
467-
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
467+
// LDC
468+
{
469+
auto ofi = getContext().getObjectFileInfo();
470+
if (!(ofi && ofi->getTargetTriple().isAndroid()))
471+
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
472+
}
468473
break;
469474
}
470475

llvm/lib/MC/MCObjectFileInfo.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -367,12 +367,14 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
367367
ReadOnlySection =
368368
Ctx->getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
369369

370-
TLSDataSection =
371-
Ctx->getELFSection(".tdata", ELF::SHT_PROGBITS,
372-
ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
370+
// LDC
371+
const auto tlsFlag = (!getTargetTriple().isAndroid() ? ELF::SHF_TLS : 0);
373372

374-
TLSBSSSection = Ctx->getELFSection(
375-
".tbss", ELF::SHT_NOBITS, ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
373+
TLSDataSection = Ctx->getELFSection(
374+
".tdata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);
375+
376+
TLSBSSSection = Ctx->getELFSection(".tbss", ELF::SHT_NOBITS,
377+
ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);
376378

377379
DataRelROSection = Ctx->getELFSection(".data.rel.ro", ELF::SHT_PROGBITS,
378380
ELF::SHF_ALLOC | ELF::SHF_WRITE);

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6270,8 +6270,12 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
62706270

62716271
if (Subtarget->isTargetDarwin())
62726272
return LowerDarwinGlobalTLSAddress(Op, DAG);
6273-
if (Subtarget->isTargetELF())
6274-
return LowerELFGlobalTLSAddress(Op, DAG);
6273+
if (Subtarget->isTargetELF()) {
6274+
if (Subtarget->isTargetAndroid())
6275+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, true); // LDC
6276+
else
6277+
return LowerELFGlobalTLSAddress(Op, DAG);
6278+
}
62756279
if (Subtarget->isTargetWindows())
62766280
return LowerWindowsGlobalTLSAddress(Op, DAG);
62776281

llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313

1414
#include "AArch64MCExpr.h"
1515
#include "llvm/BinaryFormat/ELF.h"
16+
#include "llvm/MC/MCAssembler.h" // LDC
1617
#include "llvm/MC/MCContext.h"
18+
#include "llvm/MC/MCObjectFileInfo.h" // LDC
1719
#include "llvm/MC/MCStreamer.h"
1820
#include "llvm/MC/MCSymbolELF.h"
1921
#include "llvm/MC/MCValue.h"
@@ -130,7 +132,12 @@ static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
130132
// We're known to be under a TLS fixup, so any symbol should be
131133
// modified. There should be only one.
132134
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
133-
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
135+
// LDC
136+
{
137+
auto ofi = Asm.getContext().getObjectFileInfo();
138+
if (!(ofi && ofi->getTargetTriple().isAndroid()))
139+
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
140+
}
134141
break;
135142
}
136143

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3534,6 +3534,8 @@ ARMTargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
35343534

35353535
// TODO: implement the "local dynamic" model
35363536
assert(Subtarget->isTargetELF() && "Only ELF implemented here");
3537+
if (Subtarget->isTargetAndroid())
3538+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, false); // LDC
35373539
TLSModel::Model model = getTargetMachine().getTLSModel(GA->getGlobal());
35383540

35393541
switch (model) {

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19366,6 +19366,9 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
1936619366
bool PositionIndependent = isPositionIndependent();
1936719367

1936819368
if (Subtarget.isTargetELF()) {
19369+
if (Subtarget.isTargetAndroid())
19370+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, Subtarget.is64Bit()); // LDC
19371+
1936919372
TLSModel::Model model = DAG.getTarget().getTLSModel(GV);
1937019373
switch (model) {
1937119374
case TLSModel::GeneralDynamic:

0 commit comments

Comments
 (0)