Skip to content

Commit 4c7aeb6

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 26b5914 commit 4c7aeb6

File tree

9 files changed

+70
-15
lines changed

9 files changed

+70
-15
lines changed

llvm/include/llvm/CodeGen/TargetLowering.h

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

4253+
SDValue LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
4254+
SelectionDAG &DAG, bool is64bit) const; // LDC
4255+
42534256
/// Expands target specific indirect branch for the case of JumpTable
42544257
/// expanasion.
42554258
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
@@ -7023,6 +7023,33 @@ SDValue TargetLowering::getVectorElementPointer(SelectionDAG &DAG,
70237023
return DAG.getMemBasePlusOffset(VecPtr, Index, dl);
70247024
}
70257025

7026+
SDValue
7027+
TargetLowering::LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
7028+
SelectionDAG &DAG, bool is64bit) const { // LDC
7029+
SDLoc DL(Op);
7030+
SDValue Chain = DAG.getEntryNode();
7031+
ArgListTy Args;
7032+
ArgListEntry Entry;
7033+
Type *Ty;
7034+
if (is64bit)
7035+
Ty = (Type *)Type::getInt64Ty(*DAG.getContext());
7036+
else
7037+
Ty = (Type *)Type::getInt32Ty(*DAG.getContext());
7038+
Entry.Node = Result;
7039+
Entry.Ty = Ty;
7040+
Args.push_back(Entry);
7041+
7042+
// copied, modified from ARMTargetLowering::LowerToTLSGeneralDynamicModel
7043+
TargetLowering::CallLoweringInfo CLI(DAG);
7044+
CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
7045+
CallingConv::C, Ty,
7046+
DAG.getExternalSymbol("__tls_get_addr",
7047+
getPointerTy(DAG.getDataLayout())),
7048+
std::move(Args));
7049+
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
7050+
return CallResult.first;
7051+
}
7052+
70267053
//===----------------------------------------------------------------------===//
70277054
// Implementation of Emulated TLS Model
70287055
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,8 @@ const MCExpr *TargetLoweringObjectFileELF::getTTypeGlobalReference(
411411
MMI, Streamer);
412412
}
413413

414-
static SectionKind getELFKindForNamedSection(StringRef Name, SectionKind K) {
414+
static SectionKind getELFKindForNamedSection(StringRef Name, SectionKind K,
415+
const Triple &TargetTriple) {
415416
// N.B.: The defaults used in here are not the same ones used in MC.
416417
// We follow gcc, MC follows gas. For example, given ".section .eh_frame",
417418
// both gas and MC will produce a section with no flags. Given
@@ -443,6 +444,7 @@ static SectionKind getELFKindForNamedSection(StringRef Name, SectionKind K) {
443444
return SectionKind::getThreadData();
444445

445446
if (Name == ".tbss" ||
447+
(TargetTriple.isAndroid() && Name == ".tcommon") || // LDC
446448
Name.startswith(".tbss.") ||
447449
Name.startswith(".gnu.linkonce.tb.") ||
448450
Name.startswith(".llvm.linkonce.tb."))
@@ -473,7 +475,7 @@ static unsigned getELFSectionType(StringRef Name, SectionKind K) {
473475
return ELF::SHT_PROGBITS;
474476
}
475477

476-
static unsigned getELFSectionFlags(SectionKind K) {
478+
static unsigned getELFSectionFlags(SectionKind K, const Triple &TargetTriple) {
477479
unsigned Flags = 0;
478480

479481
if (!K.isMetadata())
@@ -488,7 +490,7 @@ static unsigned getELFSectionFlags(SectionKind K) {
488490
if (K.isWriteable())
489491
Flags |= ELF::SHF_WRITE;
490492

491-
if (K.isThreadLocal())
493+
if (K.isThreadLocal() && !TargetTriple.isAndroid()) // LDC
492494
Flags |= ELF::SHF_TLS;
493495

494496
if (K.isMergeableCString() || K.isMergeableConst())
@@ -580,10 +582,10 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
580582
}
581583

582584
// Infer section flags from the section name if we can.
583-
Kind = getELFKindForNamedSection(SectionName, Kind);
585+
Kind = getELFKindForNamedSection(SectionName, Kind, getTargetTriple());
584586

585587
StringRef Group = "";
586-
unsigned Flags = getELFSectionFlags(Kind);
588+
unsigned Flags = getELFSectionFlags(Kind, getTargetTriple());
587589
if (const Comdat *C = getELFComdat(GO)) {
588590
Group = C->getName();
589591
Flags |= ELF::SHF_GROUP;
@@ -683,7 +685,7 @@ static MCSectionELF *selectELFSectionForGlobal(
683685

684686
MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
685687
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
686-
unsigned Flags = getELFSectionFlags(Kind);
688+
unsigned Flags = getELFSectionFlags(Kind, getTargetTriple());
687689

688690
// If we have -ffunction-section or -fdata-section then we should emit the
689691
// 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
@@ -450,7 +450,12 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
450450
break;
451451
}
452452
getAssembler().registerSymbol(symRef.getSymbol());
453-
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
453+
// LDC
454+
{
455+
auto ofi = getContext().getObjectFileInfo();
456+
if (!(ofi && ofi->getTargetTriple().isAndroid()))
457+
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
458+
}
454459
break;
455460
}
456461

llvm/lib/MC/MCObjectFileInfo.cpp

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

365-
TLSDataSection =
366-
Ctx->getELFSection(".tdata", ELF::SHT_PROGBITS,
367-
ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
365+
// LDC
366+
const auto tlsFlag = (!getTargetTriple().isAndroid() ? ELF::SHF_TLS : 0);
368367

369-
TLSBSSSection = Ctx->getELFSection(
370-
".tbss", ELF::SHT_NOBITS, ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
368+
TLSDataSection = Ctx->getELFSection(
369+
".tdata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);
370+
371+
TLSBSSSection = Ctx->getELFSection(".tbss", ELF::SHT_NOBITS,
372+
ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);
371373

372374
DataRelROSection = Ctx->getELFSection(".data.rel.ro", ELF::SHT_PROGBITS,
373375
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
@@ -4935,8 +4935,12 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
49354935

49364936
if (Subtarget->isTargetDarwin())
49374937
return LowerDarwinGlobalTLSAddress(Op, DAG);
4938-
if (Subtarget->isTargetELF())
4939-
return LowerELFGlobalTLSAddress(Op, DAG);
4938+
if (Subtarget->isTargetELF()) {
4939+
if (Subtarget->isTargetAndroid())
4940+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, true); // LDC
4941+
else
4942+
return LowerELFGlobalTLSAddress(Op, DAG);
4943+
}
49404944
if (Subtarget->isTargetWindows())
49414945
return LowerWindowsGlobalTLSAddress(Op, DAG);
49424946

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"
@@ -129,7 +131,12 @@ static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
129131
// We're known to be under a TLS fixup, so any symbol should be
130132
// modified. There should be only one.
131133
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
132-
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
134+
// LDC
135+
{
136+
auto ofi = Asm.getContext().getObjectFileInfo();
137+
if (!(ofi && ofi->getTargetTriple().isAndroid()))
138+
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
139+
}
133140
break;
134141
}
135142

llvm/lib/Target/ARM/ARMISelLowering.cpp

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

33153315
// TODO: implement the "local dynamic" model
33163316
assert(Subtarget->isTargetELF() && "Only ELF implemented here");
3317+
if (Subtarget->isTargetAndroid())
3318+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, false); // LDC
33173319
TLSModel::Model model = getTargetMachine().getTLSModel(GA->getGlobal());
33183320

33193321
switch (model) {

llvm/lib/Target/X86/X86ISelLowering.cpp

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

1834518345
if (Subtarget.isTargetELF()) {
18346+
if (Subtarget.isTargetAndroid())
18347+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, Subtarget.is64Bit()); // LDC
18348+
1834618349
TLSModel::Model model = DAG.getTarget().getTLSModel(GV);
1834718350
switch (model) {
1834818351
case TLSModel::GeneralDynamic:

0 commit comments

Comments
 (0)