summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2019-08-09 09:32:38 +0000
committerTim Northover <tnorthover@apple.com>2019-08-09 09:32:38 +0000
commit01eb869114bd307e879cdbf7607e7fb546c7d31a (patch)
treea5d7cf81946a1000da886cf9973b55eeb250e1c0 /llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
parent94fbbf712e906464f5f3abbeabcfcbc05d5352ec (diff)
downloadbcm5719-llvm-01eb869114bd307e879cdbf7607e7fb546c7d31a.tar.gz
bcm5719-llvm-01eb869114bd307e879cdbf7607e7fb546c7d31a.zip
AArch64: support TLS on Darwin platforms in GlobalISel.
All TLS access on Darwin is in the "general dynamic" form where we call a function to resolve the address, so implementation is pretty simple. llvm-svn: 368418
Diffstat (limited to 'llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp')
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp38
1 files changed, 34 insertions, 4 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
index 61da8d74221..c74d101e455 100644
--- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
@@ -121,6 +121,7 @@ private:
bool selectIntrinsicRound(MachineInstr &I, MachineRegisterInfo &MRI) const;
bool selectJumpTable(MachineInstr &I, MachineRegisterInfo &MRI) const;
bool selectBrJT(MachineInstr &I, MachineRegisterInfo &MRI) const;
+ bool selectTLSGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI) const;
unsigned emitConstantPoolEntry(Constant *CPVal, MachineFunction &MF) const;
MachineInstr *emitLoadFromConstantPool(Constant *CPVal,
@@ -1690,10 +1691,9 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
case TargetOpcode::G_GLOBAL_VALUE: {
auto GV = I.getOperand(1).getGlobal();
- if (GV->isThreadLocal()) {
- // FIXME: we don't support TLS yet.
- return false;
- }
+ if (GV->isThreadLocal())
+ return selectTLSGlobalValue(I, MRI);
+
unsigned OpFlags = STI.ClassifyGlobalReference(GV, TM);
if (OpFlags & AArch64II::MO_GOT) {
I.setDesc(TII.get(AArch64::LOADgot));
@@ -2361,6 +2361,36 @@ bool AArch64InstructionSelector::selectJumpTable(
return constrainSelectedInstRegOperands(*MovMI, TII, TRI, RBI);
}
+bool AArch64InstructionSelector::selectTLSGlobalValue(
+ MachineInstr &I, MachineRegisterInfo &MRI) const {
+ if (!STI.isTargetMachO())
+ return false;
+ MachineFunction &MF = *I.getParent()->getParent();
+ MF.getFrameInfo().setAdjustsStack(true);
+
+ const GlobalValue &GV = *I.getOperand(1).getGlobal();
+ MachineIRBuilder MIB(I);
+
+ MIB.buildInstr(AArch64::LOADgot, {AArch64::X0}, {})
+ .addGlobalAddress(&GV, 0, AArch64II::MO_TLS);
+
+ Register DestReg = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
+ MIB.buildInstr(AArch64::LDRXui, {DestReg}, {Register(AArch64::X0)}).addImm(0);
+
+ // TLS calls preserve all registers except those that absolutely must be
+ // trashed: X0 (it takes an argument), LR (it's a call) and NZCV (let's not be
+ // silly).
+ MIB.buildInstr(AArch64::BLR, {}, {DestReg})
+ .addDef(AArch64::X0, RegState::Implicit)
+ .addRegMask(TRI.getTLSCallPreservedMask());
+
+ MIB.buildCopy(I.getOperand(0).getReg(), Register(AArch64::X0));
+ RBI.constrainGenericRegister(I.getOperand(0).getReg(), AArch64::GPR64RegClass,
+ MRI);
+ I.eraseFromParent();
+ return true;
+}
+
bool AArch64InstructionSelector::selectIntrinsicTrunc(
MachineInstr &I, MachineRegisterInfo &MRI) const {
const LLT SrcTy = MRI.getType(I.getOperand(0).getReg());
OpenPOWER on IntegriCloud