Navigation Menu

Skip to content
This repository has been archived by the owner on Dec 20, 2019. It is now read-only.

Commit

Permalink
LDC: Rework emulated TLS patch for Android and include x64 target.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
joakim-noah authored and kinke committed Mar 18, 2019
1 parent 5c1d425 commit 38955d9
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 15 deletions.
3 changes: 3 additions & 0 deletions include/llvm/CodeGen/TargetLowering.h
Expand Up @@ -3880,6 +3880,9 @@ class TargetLowering : public TargetLoweringBase {
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA,
SelectionDAG &DAG) const;

SDValue LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
SelectionDAG &DAG, bool is64bit) const; // LDC

/// Expands target specific indirect branch for the case of JumpTable
/// expanasion.
virtual SDValue expandIndirectJTBranch(const SDLoc& dl, SDValue Value, SDValue Addr,
Expand Down
27 changes: 27 additions & 0 deletions lib/CodeGen/SelectionDAG/TargetLowering.cpp
Expand Up @@ -5209,6 +5209,33 @@ SDValue TargetLowering::getVectorElementPointer(SelectionDAG &DAG,
return DAG.getNode(ISD::ADD, dl, IdxVT, VecPtr, Index);
}

SDValue
TargetLowering::LowerToAndroidEmulatedTLSAddress(SDValue Op, SDValue Result,
SelectionDAG &DAG, bool is64bit) const { // LDC
SDLoc DL(Op);
SDValue Chain = DAG.getEntryNode();
ArgListTy Args;
ArgListEntry Entry;
Type *Ty;
if (is64bit)
Ty = (Type *)Type::getInt64Ty(*DAG.getContext());
else
Ty = (Type *)Type::getInt32Ty(*DAG.getContext());
Entry.Node = Result;
Entry.Ty = Ty;
Args.push_back(Entry);

// copied, modified from ARMTargetLowering::LowerToTLSGeneralDynamicModel
TargetLowering::CallLoweringInfo CLI(DAG);
CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
CallingConv::C, Ty,
DAG.getExternalSymbol("__tls_get_addr",
getPointerTy(DAG.getDataLayout())),
std::move(Args));
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
return CallResult.first;
}

//===----------------------------------------------------------------------===//
// Implementation of Emulated TLS Model
//===----------------------------------------------------------------------===//
Expand Down
14 changes: 8 additions & 6 deletions lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Expand Up @@ -387,7 +387,8 @@ const MCExpr *TargetLoweringObjectFileELF::getTTypeGlobalReference(
MMI, Streamer);
}

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

if (Name == ".tbss" ||
(TargetTriple.isAndroid() && Name == ".tcommon") || // LDC
Name.startswith(".tbss.") ||
Name.startswith(".gnu.linkonce.tb.") ||
Name.startswith(".llvm.linkonce.tb."))
Expand Down Expand Up @@ -449,7 +451,7 @@ static unsigned getELFSectionType(StringRef Name, SectionKind K) {
return ELF::SHT_PROGBITS;
}

static unsigned getELFSectionFlags(SectionKind K) {
static unsigned getELFSectionFlags(SectionKind K, const Triple &TargetTriple) {
unsigned Flags = 0;

if (!K.isMetadata())
Expand All @@ -464,7 +466,7 @@ static unsigned getELFSectionFlags(SectionKind K) {
if (K.isWriteable())
Flags |= ELF::SHF_WRITE;

if (K.isThreadLocal())
if (K.isThreadLocal() && !TargetTriple.isAndroid()) // LDC
Flags |= ELF::SHF_TLS;

if (K.isMergeableCString() || K.isMergeableConst())
Expand Down Expand Up @@ -554,10 +556,10 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
}

// Infer section flags from the section name if we can.
Kind = getELFKindForNamedSection(SectionName, Kind);
Kind = getELFKindForNamedSection(SectionName, Kind, getTargetTriple());

StringRef Group = "";
unsigned Flags = getELFSectionFlags(Kind);
unsigned Flags = getELFSectionFlags(Kind, getTargetTriple());
if (const Comdat *C = getELFComdat(GO)) {
Group = C->getName();
Flags |= ELF::SHF_GROUP;
Expand Down Expand Up @@ -657,7 +659,7 @@ static MCSectionELF *selectELFSectionForGlobal(

MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
unsigned Flags = getELFSectionFlags(Kind);
unsigned Flags = getELFSectionFlags(Kind, getTargetTriple());

// If we have -ffunction-section or -fdata-section then we should emit the
// global value to a uniqued section specifically for it.
Expand Down
7 changes: 6 additions & 1 deletion lib/MC/MCELFStreamer.cpp
Expand Up @@ -448,7 +448,12 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
break;
}
getAssembler().registerSymbol(symRef.getSymbol());
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
// LDC
{
auto ofi = getContext().getObjectFileInfo();
if (!(ofi && ofi->getTargetTriple().isAndroid()))
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
}
break;
}

Expand Down
12 changes: 7 additions & 5 deletions lib/MC/MCObjectFileInfo.cpp
Expand Up @@ -354,12 +354,14 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
ReadOnlySection =
Ctx->getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);

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

TLSBSSSection = Ctx->getELFSection(
".tbss", ELF::SHT_NOBITS, ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
TLSDataSection = Ctx->getELFSection(
".tdata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);

TLSBSSSection = Ctx->getELFSection(".tbss", ELF::SHT_NOBITS,
ELF::SHF_ALLOC | tlsFlag | ELF::SHF_WRITE);

DataRelROSection = Ctx->getELFSection(".data.rel.ro", ELF::SHT_PROGBITS,
ELF::SHF_ALLOC | ELF::SHF_WRITE);
Expand Down
8 changes: 6 additions & 2 deletions lib/Target/AArch64/AArch64ISelLowering.cpp
Expand Up @@ -4367,8 +4367,12 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,

if (Subtarget->isTargetDarwin())
return LowerDarwinGlobalTLSAddress(Op, DAG);
if (Subtarget->isTargetELF())
return LowerELFGlobalTLSAddress(Op, DAG);
if (Subtarget->isTargetELF()) {
if (Subtarget->isTargetAndroid())
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, true); // LDC
else
return LowerELFGlobalTLSAddress(Op, DAG);
}
if (Subtarget->isTargetWindows())
return LowerWindowsGlobalTLSAddress(Op, DAG);

Expand Down
9 changes: 8 additions & 1 deletion lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
Expand Up @@ -14,7 +14,9 @@

#include "AArch64MCExpr.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAssembler.h" // LDC
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h" // LDC
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCValue.h"
Expand Down Expand Up @@ -124,7 +126,12 @@ static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
// We're known to be under a TLS fixup, so any symbol should be
// modified. There should be only one.
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
// LDC
{
auto ofi = Asm.getContext().getObjectFileInfo();
if (!(ofi && ofi->getTargetTriple().isAndroid()))
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
}
break;
}

Expand Down
2 changes: 2 additions & 0 deletions lib/Target/ARM/ARMISelLowering.cpp
Expand Up @@ -3041,6 +3041,8 @@ ARMTargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {

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

switch (model) {
Expand Down
3 changes: 3 additions & 0 deletions lib/Target/X86/X86ISelLowering.cpp
Expand Up @@ -17058,6 +17058,9 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
bool PositionIndependent = isPositionIndependent();

if (Subtarget.isTargetELF()) {
if (Subtarget.isTargetAndroid())
return LowerToAndroidEmulatedTLSAddress(Op, LowerGlobalAddress(Op, DAG), DAG, Subtarget.is64Bit()); // LDC

TLSModel::Model model = DAG.getTarget().getTLSModel(GV);
switch (model) {
case TLSModel::GeneralDynamic:
Expand Down

0 comments on commit 38955d9

Please sign in to comment.