Skip to content

Commit a8f3c7a

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 63267ed commit a8f3c7a

File tree

9 files changed

+61
-14
lines changed

9 files changed

+61
-14
lines changed

llvm/include/llvm/CodeGen/TargetLowering.h

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

4764+
SDValue LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
4765+
SelectionDAG &DAG, bool is64bit) const; // LDC
4766+
47644767
/// Expands target specific indirect branch for the case of JumpTable
47654768
/// expanasion.
47664769
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
@@ -7975,6 +7975,33 @@ SDValue TargetLowering::getVectorSubVecPointer(SelectionDAG &DAG,
79757975
return DAG.getMemBasePlusOffset(VecPtr, Index, dl);
79767976
}
79777977

7978+
SDValue
7979+
TargetLowering::LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
7980+
SelectionDAG &DAG, bool is64bit) const { // LDC
7981+
SDLoc DL(Op);
7982+
SDValue Chain = DAG.getEntryNode();
7983+
ArgListTy Args;
7984+
ArgListEntry Entry;
7985+
Type *Ty;
7986+
if (is64bit)
7987+
Ty = (Type *)Type::getInt64Ty(*DAG.getContext());
7988+
else
7989+
Ty = (Type *)Type::getInt32Ty(*DAG.getContext());
7990+
Entry.Node = Result;
7991+
Entry.Ty = Ty;
7992+
Args.push_back(Entry);
7993+
7994+
// copied, modified from ARMTargetLowering::LowerToTLSGeneralDynamicModel
7995+
TargetLowering::CallLoweringInfo CLI(DAG);
7996+
CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
7997+
CallingConv::C, Ty,
7998+
DAG.getExternalSymbol("__tls_get_addr",
7999+
getPointerTy(DAG.getDataLayout())),
8000+
std::move(Args));
8001+
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
8002+
return CallResult.first;
8003+
}
8004+
79788005
//===----------------------------------------------------------------------===//
79798006
// Implementation of Emulated TLS Model
79808007
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ static unsigned getELFSectionType(StringRef Name, SectionKind K) {
504504
return ELF::SHT_PROGBITS;
505505
}
506506

507-
static unsigned getELFSectionFlags(SectionKind K) {
507+
static unsigned getELFSectionFlags(SectionKind K, const Triple &TargetTriple) {
508508
unsigned Flags = 0;
509509

510510
if (!K.isMetadata())
@@ -519,7 +519,7 @@ static unsigned getELFSectionFlags(SectionKind K) {
519519
if (K.isWriteable())
520520
Flags |= ELF::SHF_WRITE;
521521

522-
if (K.isThreadLocal())
522+
if (K.isThreadLocal() && !TargetTriple.isAndroid()) // LDC
523523
Flags |= ELF::SHF_TLS;
524524

525525
if (K.isMergeableCString() || K.isMergeableConst())
@@ -766,7 +766,7 @@ static MCSection *selectExplicitSectionGlobal(
766766

767767
StringRef Group = "";
768768
bool IsComdat = false;
769-
unsigned Flags = getELFSectionFlags(Kind);
769+
unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple());
770770
if (const Comdat *C = getELFComdat(GO)) {
771771
Group = C->getName();
772772
IsComdat = C->getSelectionKind() == Comdat::Any;
@@ -877,7 +877,7 @@ static MCSection *selectELFSectionForGlobal(
877877

878878
MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
879879
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
880-
unsigned Flags = getELFSectionFlags(Kind);
880+
unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple());
881881

882882
// If we have -ffunction-section or -fdata-section then we should emit the
883883
// global value to a uniqued section specifically for it.
@@ -897,7 +897,7 @@ MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
897897
MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction(
898898
const Function &F, const TargetMachine &TM) const {
899899
SectionKind Kind = SectionKind::getText();
900-
unsigned Flags = getELFSectionFlags(Kind);
900+
unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple());
901901
// If the function's section names is pre-determined via pragma or a
902902
// section attribute, call selectExplicitSectionGlobal.
903903
if (F.hasSection() || F.hasFnAttribute("implicit-section-name"))

llvm/lib/MC/MCELFStreamer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,9 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
469469
break;
470470
}
471471
getAssembler().registerSymbol(symRef.getSymbol());
472-
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
472+
// LDC
473+
if (!getContext().getTargetTriple().isAndroid())
474+
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
473475
break;
474476
}
475477

llvm/lib/MC/MCObjectFileInfo.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,12 +381,15 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
381381
ReadOnlySection =
382382
Ctx->getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
383383

384-
TLSDataSection =
385-
Ctx->getELFSection(".tdata", ELF::SHT_PROGBITS,
386-
ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
384+
// LDC
385+
const auto tlsFlag =
386+
(!getContext().getTargetTriple().isAndroid() ? ELF::SHF_TLS : 0);
387387

388-
TLSBSSSection = Ctx->getELFSection(
389-
".tbss", ELF::SHT_NOBITS, ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
388+
TLSDataSection = Ctx->getELFSection(
389+
".tdata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);
390+
391+
TLSBSSSection = Ctx->getELFSection(".tbss", ELF::SHT_NOBITS,
392+
ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);
390393

391394
DataRelROSection = Ctx->getELFSection(".data.rel.ro", ELF::SHT_PROGBITS,
392395
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
@@ -7150,8 +7150,12 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
71507150

71517151
if (Subtarget->isTargetDarwin())
71527152
return LowerDarwinGlobalTLSAddress(Op, DAG);
7153-
if (Subtarget->isTargetELF())
7154-
return LowerELFGlobalTLSAddress(Op, DAG);
7153+
if (Subtarget->isTargetELF()) {
7154+
if (Subtarget->isTargetAndroid())
7155+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, true); // LDC
7156+
else
7157+
return LowerELFGlobalTLSAddress(Op, DAG);
7158+
}
71557159
if (Subtarget->isTargetWindows())
71567160
return LowerWindowsGlobalTLSAddress(Op, DAG);
71577161

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

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

1414
#include "AArch64MCExpr.h"
1515
#include "llvm/BinaryFormat/ELF.h"
16+
#include "llvm/MC/MCAssembler.h" // LDC
1617
#include "llvm/MC/MCContext.h"
1718
#include "llvm/MC/MCStreamer.h"
1819
#include "llvm/MC/MCSymbolELF.h"
@@ -130,7 +131,9 @@ static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
130131
// We're known to be under a TLS fixup, so any symbol should be
131132
// modified. There should be only one.
132133
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
133-
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
134+
// LDC
135+
if (!Asm.getContext().getTargetTriple().isAndroid())
136+
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
134137
break;
135138
}
136139

llvm/lib/Target/ARM/ARMISelLowering.cpp

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

37043704
// TODO: implement the "local dynamic" model
37053705
assert(Subtarget->isTargetELF() && "Only ELF implemented here");
3706+
if (Subtarget->isTargetAndroid())
3707+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, false); // LDC
37063708
TLSModel::Model model = getTargetMachine().getTLSModel(GA->getGlobal());
37073709

37083710
switch (model) {

llvm/lib/Target/X86/X86ISelLowering.cpp

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

2019220192
if (Subtarget.isTargetELF()) {
20193+
if (Subtarget.isTargetAndroid())
20194+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, Subtarget.is64Bit()); // LDC
20195+
2019320196
TLSModel::Model model = DAG.getTarget().getTLSModel(GV);
2019420197
switch (model) {
2019520198
case TLSModel::GeneralDynamic:

0 commit comments

Comments
 (0)