Skip to content

Commit 9a5b2d6

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 d906463 commit 9a5b2d6

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
@@ -4469,6 +4469,9 @@ class TargetLowering : public TargetLoweringBase {
44694469
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA,
44704470
SelectionDAG &DAG) const;
44714471

4472+
SDValue LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
4473+
SelectionDAG &DAG, bool is64bit) const; // LDC
4474+
44724475
/// Expands target specific indirect branch for the case of JumpTable
44734476
/// expanasion.
44744477
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
@@ -7240,6 +7240,33 @@ SDValue TargetLowering::getVectorElementPointer(SelectionDAG &DAG,
72407240
return DAG.getMemBasePlusOffset(VecPtr, Index, dl);
72417241
}
72427242

7243+
SDValue
7244+
TargetLowering::LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
7245+
SelectionDAG &DAG, bool is64bit) const { // LDC
7246+
SDLoc DL(Op);
7247+
SDValue Chain = DAG.getEntryNode();
7248+
ArgListTy Args;
7249+
ArgListEntry Entry;
7250+
Type *Ty;
7251+
if (is64bit)
7252+
Ty = (Type *)Type::getInt64Ty(*DAG.getContext());
7253+
else
7254+
Ty = (Type *)Type::getInt32Ty(*DAG.getContext());
7255+
Entry.Node = Result;
7256+
Entry.Ty = Ty;
7257+
Args.push_back(Entry);
7258+
7259+
// copied, modified from ARMTargetLowering::LowerToTLSGeneralDynamicModel
7260+
TargetLowering::CallLoweringInfo CLI(DAG);
7261+
CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
7262+
CallingConv::C, Ty,
7263+
DAG.getExternalSymbol("__tls_get_addr",
7264+
getPointerTy(DAG.getDataLayout())),
7265+
std::move(Args));
7266+
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
7267+
return CallResult.first;
7268+
}
7269+
72437270
//===----------------------------------------------------------------------===//
72447271
// Implementation of Emulated TLS Model
72457272
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

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

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

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

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

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

670670
StringRef Group = "";
671-
unsigned Flags = getELFSectionFlags(Kind);
671+
unsigned Flags = getELFSectionFlags(Kind, getTargetTriple());
672672
if (const Comdat *C = getELFComdat(GO)) {
673673
Group = C->getName();
674674
Flags |= ELF::SHF_GROUP;
@@ -790,7 +790,7 @@ static MCSectionELF *selectELFSectionForGlobal(
790790

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

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

llvm/lib/MC/MCObjectFileInfo.cpp

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

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

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

375377
DataRelROSection = Ctx->getELFSection(".data.rel.ro", ELF::SHT_PROGBITS,
376378
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
@@ -5346,8 +5346,12 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
53465346

53475347
if (Subtarget->isTargetDarwin())
53485348
return LowerDarwinGlobalTLSAddress(Op, DAG);
5349-
if (Subtarget->isTargetELF())
5350-
return LowerELFGlobalTLSAddress(Op, DAG);
5349+
if (Subtarget->isTargetELF()) {
5350+
if (Subtarget->isTargetAndroid())
5351+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, true); // LDC
5352+
else
5353+
return LowerELFGlobalTLSAddress(Op, DAG);
5354+
}
53515355
if (Subtarget->isTargetWindows())
53525356
return LowerWindowsGlobalTLSAddress(Op, DAG);
53535357

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
@@ -3513,6 +3513,8 @@ ARMTargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
35133513

35143514
// TODO: implement the "local dynamic" model
35153515
assert(Subtarget->isTargetELF() && "Only ELF implemented here");
3516+
if (Subtarget->isTargetAndroid())
3517+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, false); // LDC
35163518
TLSModel::Model model = getTargetMachine().getTLSModel(GA->getGlobal());
35173519

35183520
switch (model) {

llvm/lib/Target/X86/X86ISelLowering.cpp

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

1891318913
if (Subtarget.isTargetELF()) {
18914+
if (Subtarget.isTargetAndroid())
18915+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, Subtarget.is64Bit()); // LDC
18916+
1891418917
TLSModel::Model model = DAG.getTarget().getTLSModel(GV);
1891518918
switch (model) {
1891618919
case TLSModel::GeneralDynamic:

0 commit comments

Comments
 (0)