mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-01 00:17:01 +00:00
Add support for implicit TLS model used with MS VC runtime.
Patch by Kai Nacke! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@150307 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -7355,6 +7355,68 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
|
||||
unsigned Reg = Subtarget->is64Bit() ? X86::RAX : X86::EAX;
|
||||
return DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(),
|
||||
Chain.getValue(1));
|
||||
} else if (Subtarget->isTargetWindows()) {
|
||||
// Just use the implicit TLS architecture
|
||||
// Need to generate someting similar to:
|
||||
// mov rdx, qword [gs:abs 58H]; Load pointer to ThreadLocalStorage
|
||||
// ; from TEB
|
||||
// mov ecx, dword [rel _tls_index]: Load index (from C runtime)
|
||||
// mov rcx, qword [rdx+rcx*8]
|
||||
// mov eax, .tls$:tlsvar
|
||||
// [rax+rcx] contains the address
|
||||
// Windows 64bit: gs:0x58
|
||||
// Windows 32bit: fs:__tls_array
|
||||
|
||||
// If GV is an alias then use the aliasee for determining
|
||||
// thread-localness.
|
||||
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
|
||||
GV = GA->resolveAliasedGlobal(false);
|
||||
DebugLoc dl = GA->getDebugLoc();
|
||||
SDValue Chain = DAG.getEntryNode();
|
||||
|
||||
// Get the Thread Pointer, which is %fs:__tls_array (32-bit) or
|
||||
// %gs:0x58 (64-bit).
|
||||
Value *Ptr = Constant::getNullValue(Subtarget->is64Bit()
|
||||
? Type::getInt8PtrTy(*DAG.getContext(),
|
||||
256)
|
||||
: Type::getInt32PtrTy(*DAG.getContext(),
|
||||
257));
|
||||
|
||||
SDValue ThreadPointer = DAG.getLoad(getPointerTy(), dl, Chain,
|
||||
Subtarget->is64Bit()
|
||||
? DAG.getIntPtrConstant(0x58)
|
||||
: DAG.getExternalSymbol("_tls_array",
|
||||
getPointerTy()),
|
||||
MachinePointerInfo(Ptr),
|
||||
false, false, false, 0);
|
||||
|
||||
// Load the _tls_index variable
|
||||
SDValue IDX = DAG.getExternalSymbol("_tls_index", getPointerTy());
|
||||
if (Subtarget->is64Bit())
|
||||
IDX = DAG.getExtLoad(ISD::ZEXTLOAD, dl, getPointerTy(), Chain,
|
||||
IDX, MachinePointerInfo(), MVT::i32,
|
||||
false, false, 0);
|
||||
else
|
||||
IDX = DAG.getLoad(getPointerTy(), dl, Chain, IDX, MachinePointerInfo(),
|
||||
false, false, false, 0);
|
||||
|
||||
SDValue Scale = DAG.getConstant(Log2_64_Ceil(TD->getPointerSize()),
|
||||
getPointerTy());
|
||||
IDX = DAG.getNode(ISD::SHL, dl, getPointerTy(), IDX, Scale);
|
||||
|
||||
SDValue res = DAG.getNode(ISD::ADD, dl, getPointerTy(), ThreadPointer, IDX);
|
||||
res = DAG.getLoad(getPointerTy(), dl, Chain, res, MachinePointerInfo(),
|
||||
false, false, false, 0);
|
||||
|
||||
// Get the offset of start of .tls section
|
||||
SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
|
||||
GA->getValueType(0),
|
||||
GA->getOffset(), X86II::MO_SECREL);
|
||||
SDValue Offset = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), TGA);
|
||||
|
||||
// The address of the thread local variable is the add of the thread
|
||||
// pointer with the offset of the variable.
|
||||
return DAG.getNode(ISD::ADD, dl, getPointerTy(), res, Offset);
|
||||
}
|
||||
|
||||
llvm_unreachable("TLS not implemented for this target.");
|
||||
|
||||
Reference in New Issue
Block a user