Skip to content

Commit 5ded841

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 4a1f697 commit 5ded841

File tree

9 files changed

+61
-14
lines changed

9 files changed

+61
-14
lines changed

llvm/include/llvm/CodeGen/TargetLowering.h

+3
Original file line numberDiff line numberDiff line change
@@ -5287,6 +5287,9 @@ class TargetLowering : public TargetLoweringBase {
52875287
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA,
52885288
SelectionDAG &DAG) const;
52895289

5290+
SDValue LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
5291+
SelectionDAG &DAG, bool is64bit) const; // LDC
5292+
52905293
/// Expands target specific indirect branch for the case of JumpTable
52915294
/// expanasion.
52925295
virtual SDValue expandIndirectJTBranch(const SDLoc& dl, SDValue Value, SDValue Addr,

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -9609,6 +9609,33 @@ SDValue TargetLowering::getVectorSubVecPointer(SelectionDAG &DAG,
96099609
return DAG.getMemBasePlusOffset(VecPtr, Index, dl);
96109610
}
96119611

9612+
SDValue
9613+
TargetLowering::LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
9614+
SelectionDAG &DAG, bool is64bit) const { // LDC
9615+
SDLoc DL(Op);
9616+
SDValue Chain = DAG.getEntryNode();
9617+
ArgListTy Args;
9618+
ArgListEntry Entry;
9619+
Type *Ty;
9620+
if (is64bit)
9621+
Ty = (Type *)Type::getInt64Ty(*DAG.getContext());
9622+
else
9623+
Ty = (Type *)Type::getInt32Ty(*DAG.getContext());
9624+
Entry.Node = Result;
9625+
Entry.Ty = Ty;
9626+
Args.push_back(Entry);
9627+
9628+
// copied, modified from ARMTargetLowering::LowerToTLSGeneralDynamicModel
9629+
TargetLowering::CallLoweringInfo CLI(DAG);
9630+
CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
9631+
CallingConv::C, Ty,
9632+
DAG.getExternalSymbol("__tls_get_addr",
9633+
getPointerTy(DAG.getDataLayout())),
9634+
std::move(Args));
9635+
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
9636+
return CallResult.first;
9637+
}
9638+
96129639
//===----------------------------------------------------------------------===//
96139640
// Implementation of Emulated TLS Model
96149641
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ static unsigned getELFSectionType(StringRef Name, SectionKind K) {
533533
return ELF::SHT_PROGBITS;
534534
}
535535

536-
static unsigned getELFSectionFlags(SectionKind K) {
536+
static unsigned getELFSectionFlags(SectionKind K, const Triple &TargetTriple) {
537537
unsigned Flags = 0;
538538

539539
if (!K.isMetadata() && !K.isExclude())
@@ -551,7 +551,7 @@ static unsigned getELFSectionFlags(SectionKind K) {
551551
if (K.isWriteable())
552552
Flags |= ELF::SHF_WRITE;
553553

554-
if (K.isThreadLocal())
554+
if (K.isThreadLocal() && !TargetTriple.isAndroid()) // LDC
555555
Flags |= ELF::SHF_TLS;
556556

557557
if (K.isMergeableCString() || K.isMergeableConst())
@@ -795,7 +795,7 @@ static MCSection *selectExplicitSectionGlobal(
795795

796796
StringRef Group = "";
797797
bool IsComdat = false;
798-
unsigned Flags = getELFSectionFlags(Kind);
798+
unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple());
799799
if (const Comdat *C = getELFComdat(GO)) {
800800
Group = C->getName();
801801
IsComdat = C->getSelectionKind() == Comdat::Any;
@@ -915,7 +915,7 @@ static MCSection *selectELFSectionForGlobal(
915915

916916
MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
917917
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
918-
unsigned Flags = getELFSectionFlags(Kind);
918+
unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple());
919919

920920
// If we have -ffunction-section or -fdata-section then we should emit the
921921
// global value to a uniqued section specifically for it.
@@ -935,7 +935,7 @@ MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
935935
MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction(
936936
const Function &F, const TargetMachine &TM) const {
937937
SectionKind Kind = SectionKind::getText();
938-
unsigned Flags = getELFSectionFlags(Kind);
938+
unsigned Flags = getELFSectionFlags(Kind, TM.getTargetTriple());
939939
// If the function's section names is pre-determined via pragma or a
940940
// section attribute, call selectExplicitSectionGlobal.
941941
if (F.hasSection() || F.hasFnAttribute("implicit-section-name"))

llvm/lib/MC/MCELFStreamer.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,9 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
475475
break;
476476
}
477477
getAssembler().registerSymbol(symRef.getSymbol());
478-
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
478+
// LDC
479+
if (!getContext().getTargetTriple().isAndroid())
480+
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
479481
break;
480482
}
481483

llvm/lib/MC/MCObjectFileInfo.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -393,12 +393,15 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
393393
ReadOnlySection =
394394
Ctx->getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
395395

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

400-
TLSBSSSection = Ctx->getELFSection(
401-
".tbss", ELF::SHT_NOBITS, ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
400+
TLSDataSection = Ctx->getELFSection(
401+
".tdata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);
402+
403+
TLSBSSSection = Ctx->getELFSection(".tbss", ELF::SHT_NOBITS,
404+
ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);
402405

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

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -8359,8 +8359,12 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
83598359

83608360
if (Subtarget->isTargetDarwin())
83618361
return LowerDarwinGlobalTLSAddress(Op, DAG);
8362-
if (Subtarget->isTargetELF())
8363-
return LowerELFGlobalTLSAddress(Op, DAG);
8362+
if (Subtarget->isTargetELF()) {
8363+
if (Subtarget->isTargetAndroid())
8364+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, true); // LDC
8365+
else
8366+
return LowerELFGlobalTLSAddress(Op, DAG);
8367+
}
83648368
if (Subtarget->isTargetWindows())
83658369
return LowerWindowsGlobalTLSAddress(Op, DAG);
83668370

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

+4-1
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"
@@ -131,7 +132,9 @@ static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
131132
// We're known to be under a TLS fixup, so any symbol should be
132133
// modified. There should be only one.
133134
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
134-
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
135+
// LDC
136+
if (!Asm.getContext().getTargetTriple().isAndroid())
137+
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
135138
break;
136139
}
137140

llvm/lib/Target/ARM/ARMISelLowering.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -3754,6 +3754,8 @@ ARMTargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
37543754

37553755
// TODO: implement the "local dynamic" model
37563756
assert(Subtarget->isTargetELF() && "Only ELF implemented here");
3757+
if (Subtarget->isTargetAndroid())
3758+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, false); // LDC
37573759
TLSModel::Model model = getTargetMachine().getTLSModel(GA->getGlobal());
37583760

37593761
switch (model) {

llvm/lib/Target/X86/X86ISelLowering.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -21376,6 +21376,9 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
2137621376
bool PositionIndependent = isPositionIndependent();
2137721377

2137821378
if (Subtarget.isTargetELF()) {
21379+
if (Subtarget.isTargetAndroid())
21380+
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, Subtarget.is64Bit()); // LDC
21381+
2137921382
TLSModel::Model model = DAG.getTarget().getTLSModel(GV);
2138021383
switch (model) {
2138121384
case TLSModel::GeneralDynamic:

0 commit comments

Comments
 (0)