TLS for iOS - how to proceed

Dan Olson zans.is.for.cans at yahoo.com
Tue Apr 1 23:44:12 PDT 2014


"David Nadlinger" <code at klickverbot.at> writes:

>> Also, I'd like help making my LLVM changes better.  I didn't do things
>> the proper way (had to cheat with a const_cast).
>
> Did I miss a link to the changes?
>
> David

I did not put up the change anywhere yet.  I just tried to create a gist
of the changes, but keep getting a gist website error.  I can't access
any of my gists.  Hmm, how about a svn diff until gist recovers?

The new code in ARMTargetLowering::LowerGlobalTLSAddress() for Darwin is
based somewhat on a function of the same name in
llvm/lib/Target/X86/X86ISelLowering.cpp and on pieces from
ARMTargetLowering::LowerGlobalAddressDarwin() and
ARMTargetLowering::LowerToTLSGeneralDynamicModel().

Loading the address of the global GV though didn't work (got internal
error) when using this call I found in LowerGlobalAddressDarwin().

  DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, ARMII::MO_NONLAZY);

apparently because GV is thread local.  So I cheated by temporarily
changing GV into a normal global, and then the proper assembly was
created.  I really don't know what I am doing, just found a way to get
something to work.  My comments begin with // dano

llvm/lib/Target/ARM/ARMISelLowering.cpp

Index: ARMISelLowering.cpp
===================================================================
--- ARMISelLowering.cpp	(revision 199570)
+++ ARMISelLowering.cpp	(working copy)
@@ -2460,9 +2460,12 @@
 SDValue
 ARMTargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
   // TODO: implement the "local dynamic" model
+#if 0
   assert(Subtarget->isTargetELF() &&
          "TLS not implemented for non-ELF targets");
+#endif
   GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
+  if (Subtarget->isTargetELF()) {
 
   TLSModel::Model model = getTargetMachine().getTLSModel(GA->getGlobal());
 
@@ -2475,6 +2478,61 @@
       return LowerToTLSExecModels(GA, DAG, model);
   }
   llvm_unreachable("bogus TLS model");
+  }
+
+  if (Subtarget->isTargetDarwin()) {
+      EVT PtrVT = getPointerTy();
+      SDLoc dl(Op);
+      const GlobalValue *GV = GA->getGlobal();
+      Reloc::Model RelocM = getTargetMachine().getRelocationModel();
+
+  if (Subtarget->useMovt())
+    ++NumMovwMovt;
+
+  // FIXME: Once remat is capable of dealing with instructions with register
+  // operands, expand this into multiple nodes
+  unsigned Wrapper =
+      RelocM == Reloc::PIC_ ? ARMISD::WrapperPIC : ARMISD::Wrapper;
+
+  // dano: Get an internal compiler error unless I cheat and temp change to
+  // no thread local.  There must be a better way.
+  GlobalVariable *GVar = const_cast<GlobalVariable*>(dyn_cast<GlobalVariable>(GV));
+  GlobalVariable::ThreadLocalMode tlsMode = GVar->getThreadLocalMode();
+  GVar->setThreadLocalMode(GlobalVariable::NotThreadLocal);
+  SDValue G = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, ARMII::MO_NONLAZY);
+  SDValue Result = DAG.getNode(Wrapper, dl, PtrVT, G);
+  GVar->setThreadLocalMode(tlsMode);
+
+  if (Subtarget->GVIsIndirectSymbol(GV, RelocM))
+    Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Result,
+                         MachinePointerInfo::getGOT(), false, false, false, 0);
+
+  // dano: call __tls_get_addr(TLVDescriptor *Result)
+  //   blx ___tls_get_addr
+  // Really want this to be be an indirect call (*Result->thunk)(Result)
+  //   ld r1, [r0]
+  //   blx r1
+  SDValue Chain = DAG.getEntryNode();
+  ArgListTy Args;
+  ArgListEntry Entry;
+  Entry.Node = Result;
+  Entry.Ty = (Type *) Type::getInt32Ty(*DAG.getContext());
+  Args.push_back(Entry);
+
+  TargetLowering::CallLoweringInfo CLI
+      (Chain,
+       (Type *) Type::getInt32Ty(*DAG.getContext()),
+       false, false, false, false,
+       0, CallingConv::C, /*isTailCall=*/false,
+       /*doesNotRet=*/false, /*isReturnValueUsed=*/true,
+       DAG.getExternalSymbol("__tls_get_addr", PtrVT),
+       Args, DAG, dl);
+  std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
+  return CallResult.first;
+  }
+
+  llvm_unreachable("TLS not implemented for this target.");
 }
 
 SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op,


More information about the digitalmars-d-ldc mailing list