Changes in directory llvm/lib/Target/X86:
X86ATTAsmPrinter.cpp updated: 1.100 -> 1.101 X86AsmPrinter.cpp updated: 1.239 -> 1.240 X86ISelLowering.cpp updated: 1.393 -> 1.394 X86ISelLowering.h updated: 1.98 -> 1.99 X86InstrInfo.td updated: 1.302 -> 1.303 --- Log message: Implement "general dynamic", "initial exec" and "local exec" TLS models for X86 32 bits. --- Diffs of the changes: (+122 -6) X86ATTAsmPrinter.cpp | 16 +++++++++- X86AsmPrinter.cpp | 10 ++++-- X86ISelLowering.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ X86ISelLowering.h | 5 ++- X86InstrInfo.td | 22 ++++++++++++++ 5 files changed, 122 insertions(+), 6 deletions(-) Index: llvm/lib/Target/X86/X86ATTAsmPrinter.cpp diff -u llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.100 llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.101 --- llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.100 Tue Apr 17 12:21:52 2007 +++ llvm/lib/Target/X86/X86ATTAsmPrinter.cpp Fri Apr 20 16:38:10 2007 @@ -272,9 +272,13 @@ case MachineOperand::MO_GlobalAddress: { bool isCallOp = Modifier && !strcmp(Modifier, "call"); bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - if (!isMemOp && !isCallOp) O << '$'; GlobalValue *GV = MO.getGlobal(); + GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); + bool isThreadLocal = GVar && GVar->isThreadLocal(); + + if (!isMemOp && !isCallOp && !isThreadLocal) O << '$'; + std::string Name = Mang->getValueName(GV); X86SharedAsmPrinter::decorateName(Name, GV); @@ -328,7 +332,15 @@ else if (Offset < 0) O << Offset; - if (isMemOp) { + if (isThreadLocal) { + if (TM.getRelocationModel() == Reloc::PIC_) + O << "@TLSGD"; // general dynamic TLS model + else + if (GV->isDeclaration()) + O << "@INDNTPOFF"; // initial exec TLS model + else + O << "@NTPOFF"; // local exec TLS model + } else if (isMemOp) { if (printGOT(TM, Subtarget)) { if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) O << "@GOT"; Index: llvm/lib/Target/X86/X86AsmPrinter.cpp diff -u llvm/lib/Target/X86/X86AsmPrinter.cpp:1.239 llvm/lib/Target/X86/X86AsmPrinter.cpp:1.240 --- llvm/lib/Target/X86/X86AsmPrinter.cpp:1.239 Tue Apr 17 12:21:52 2007 +++ llvm/lib/Target/X86/X86AsmPrinter.cpp Fri Apr 20 16:38:10 2007 @@ -171,7 +171,7 @@ } } - if (!I->hasSection() && + if (!I->hasSection() && !I->isThreadLocal() && (I->hasInternalLinkage() || I->hasWeakLinkage() || I->hasLinkOnceLinkage())) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. @@ -256,9 +256,13 @@ SwitchToDataSection(SectionName.c_str()); } else { if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection()) - SwitchToDataSection(TAI->getBSSSection(), I); + SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSBSSSection() : + TAI->getBSSSection(), I); else if (!I->isConstant()) - SwitchToDataSection(TAI->getDataSection(), I); + SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSDataSection() : + TAI->getDataSection(), I); + else if (I->isThreadLocal()) + SwitchToDataSection(TAI->getTLSDataSection()); else { // Read-only data. bool HasReloc = C->ContainsRelocations(); Index: llvm/lib/Target/X86/X86ISelLowering.cpp diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.393 llvm/lib/Target/X86/X86ISelLowering.cpp:1.394 --- llvm/lib/Target/X86/X86ISelLowering.cpp:1.393 Tue Apr 17 14:34:00 2007 +++ llvm/lib/Target/X86/X86ISelLowering.cpp Fri Apr 20 16:38:10 2007 @@ -20,6 +20,7 @@ #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" #include "llvm/Function.h" #include "llvm/Intrinsics.h" #include "llvm/ADT/VectorExtras.h" @@ -200,6 +201,7 @@ setOperationAction(ISD::ConstantPool , MVT::i32 , Custom); setOperationAction(ISD::JumpTable , MVT::i32 , Custom); setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i32 , Custom); setOperationAction(ISD::ExternalSymbol , MVT::i32 , Custom); if (Subtarget->is64Bit()) { setOperationAction(ISD::ConstantPool , MVT::i64 , Custom); @@ -2943,6 +2945,76 @@ return Result; } +// Lower ISD::GlobalTLSAddress using the "general dynamic" model +static SDOperand +LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const MVT::ValueType PtrVT) { + SDOperand InFlag; + SDOperand Chain = DAG.getCopyToReg(DAG.getEntryNode(), X86::EBX, + DAG.getNode(X86ISD::GlobalBaseReg, + PtrVT), InFlag); + InFlag = Chain.getValue(1); + + // emit leal [EMAIL PROTECTED](,%ebx,1), %eax + SDVTList NodeTys = DAG.getVTList(PtrVT, MVT::Other, MVT::Flag); + SDOperand TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), + GA->getValueType(0), + GA->getOffset()); + SDOperand Ops[] = { Chain, TGA, InFlag }; + SDOperand Result = DAG.getNode(X86ISD::TLSADDR, NodeTys, Ops, 3); + InFlag = Result.getValue(2); + Chain = Result.getValue(1); + + // call ___tls_get_addr. This function receives its argument in + // the register EAX. + Chain = DAG.getCopyToReg(Chain, X86::EAX, Result, InFlag); + InFlag = Chain.getValue(1); + + NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SDOperand Ops1[] = { Chain, + DAG.getTargetExternalSymbol("___tls_get_addr", + PtrVT), + DAG.getRegister(X86::EAX, PtrVT), + DAG.getRegister(X86::EBX, PtrVT), + InFlag }; + Chain = DAG.getNode(X86ISD::CALL, NodeTys, Ops1, 5); + InFlag = Chain.getValue(1); + + return DAG.getCopyFromReg(Chain, X86::EAX, PtrVT, InFlag); +} + +// Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or +// "local exec" model. +static SDOperand +LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG, + const MVT::ValueType PtrVT) { + // Get the Thread Pointer + SDOperand ThreadPointer = DAG.getNode(X86ISD::THREAD_POINTER, PtrVT); + // emit "addl [EMAIL PROTECTED],%eax" (local exec) or "addl [EMAIL PROTECTED],%eax" (initial + // exec) + SDOperand TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), + GA->getValueType(0), + GA->getOffset()); + SDOperand Offset = DAG.getNode(X86ISD::Wrapper, PtrVT, 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, PtrVT, ThreadPointer, Offset); +} + +SDOperand +X86TargetLowering::LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG) { + // TODO: implement the "local dynamic" model + // TODO: implement the "initial exec"model for pic executables + assert(!Subtarget->is64Bit() && "TLS not implemented for X86_64"); + GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); + // If the relocation model is PIC, use the "General Dynamic" TLS Model, + // otherwise use the "Local Exec"TLS Model + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) + return LowerToTLSGeneralDynamicModel(GA, DAG, getPointerTy()); + else + return LowerToTLSExecModel(GA, DAG, getPointerTy()); +} + SDOperand X86TargetLowering::LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) { const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol(); @@ -4022,6 +4094,7 @@ case ISD::SCALAR_TO_VECTOR: return LowerSCALAR_TO_VECTOR(Op, DAG); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG); case ISD::SHL_PARTS: case ISD::SRA_PARTS: @@ -4090,6 +4163,8 @@ case X86ISD::PINSRW: return "X86ISD::PINSRW"; case X86ISD::FMAX: return "X86ISD::FMAX"; case X86ISD::FMIN: return "X86ISD::FMIN"; + case X86ISD::TLSADDR: return "X86ISD::TLSADDR"; + case X86ISD::THREAD_POINTER: return "X86ISD::THREAD_POINTER"; } } Index: llvm/lib/Target/X86/X86ISelLowering.h diff -u llvm/lib/Target/X86/X86ISelLowering.h:1.98 llvm/lib/Target/X86/X86ISelLowering.h:1.99 --- llvm/lib/Target/X86/X86ISelLowering.h:1.98 Tue Apr 17 04:20:00 2007 +++ llvm/lib/Target/X86/X86ISelLowering.h Fri Apr 20 16:38:10 2007 @@ -176,7 +176,9 @@ /// FMAX, FMIN - Floating point max and min. /// - FMAX, FMIN + FMAX, FMIN, + // Thread Local Storage + TLSADDR, THREAD_POINTER }; } @@ -386,6 +388,7 @@ SDOperand LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG); SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG); SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG); SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG); SDOperand LowerShift(SDOperand Op, SelectionDAG &DAG); SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG); Index: llvm/lib/Target/X86/X86InstrInfo.td diff -u llvm/lib/Target/X86/X86InstrInfo.td:1.302 llvm/lib/Target/X86/X86InstrInfo.td:1.303 --- llvm/lib/Target/X86/X86InstrInfo.td:1.302 Tue Apr 17 04:20:00 2007 +++ llvm/lib/Target/X86/X86InstrInfo.td Fri Apr 20 16:38:10 2007 @@ -47,6 +47,10 @@ def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; +def SDT_X86TLSADDR : SDTypeProfile<1, 1, [SDTCisPtrTy<0>, SDTCisInt<1>]>; + +def SDT_X86TLSTP : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; + def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>; def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>; @@ -87,6 +91,11 @@ def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; +def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; +def X86TLStp : SDNode<"X86ISD::THREAD_POINTER", SDT_X86TLSTP, []>; + + //===----------------------------------------------------------------------===// // X86 Operand Definitions. // @@ -2449,6 +2458,19 @@ "mov{l} {$src, $dst|$dst, $src}", []>; //===----------------------------------------------------------------------===// +// Thread Local Storage Instructions +// + +def TLS_addr : I<0, Pseudo, (ops GR32:$dst, i32imm:$sym), + "leal $sym(,%ebx,1), $dst", + [(set GR32:$dst, (X86tlsaddr tglobaltlsaddr:$sym))]>, + Imp<[EBX],[]>; + +def TLS_tp : I<0, Pseudo, (ops GR32:$dst), + "movl %gs:0, $dst", + [(set GR32:$dst, X86TLStp)]>; + +//===----------------------------------------------------------------------===// // DWARF Pseudo Instructions // _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits