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