Changes in directory llvm/lib/Target/ARM:
ARMAsmPrinter.cpp updated: 1.67 -> 1.68 ARMConstantPoolValue.cpp updated: 1.3 -> 1.4 ARMConstantPoolValue.h updated: 1.3 -> 1.4 ARMISelLowering.cpp updated: 1.46 -> 1.47 ARMISelLowering.h updated: 1.14 -> 1.15 ARMInstrInfo.td updated: 1.96 -> 1.97 ARMInstrThumb.td updated: 1.23 -> 1.24 ARMTargetAsmInfo.cpp updated: 1.14 -> 1.15 --- Log message: ARM TLS: implement "general dynamic", "initial exec" and "local exec" models. --- Diffs of the changes: (+157 -13) ARMAsmPrinter.cpp | 16 ++++++-- ARMConstantPoolValue.cpp | 19 ++++++---- ARMConstantPoolValue.h | 8 +++- ARMISelLowering.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++ ARMISelLowering.h | 9 ++++ ARMInstrInfo.td | 15 +++++++ ARMInstrThumb.td | 12 ++++++ ARMTargetAsmInfo.cpp | 2 + 8 files changed, 157 insertions(+), 13 deletions(-) Index: llvm/lib/Target/ARM/ARMAsmPrinter.cpp diff -u llvm/lib/Target/ARM/ARMAsmPrinter.cpp:1.67 llvm/lib/Target/ARM/ARMAsmPrinter.cpp:1.68 --- llvm/lib/Target/ARM/ARMAsmPrinter.cpp:1.67 Wed Apr 25 09:50:40 2007 +++ llvm/lib/Target/ARM/ARMAsmPrinter.cpp Fri Apr 27 08:54:47 2007 @@ -134,10 +134,14 @@ } else O << Name; if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; - if (ACPV->getPCAdjustment() != 0) + if (ACPV->getPCAdjustment() != 0) { O << "-(" << TAI->getPrivateGlobalPrefix() << "PC" << utostr(ACPV->getLabelId()) - << "+" << (unsigned)ACPV->getPCAdjustment() << ")"; + << "+" << (unsigned)ACPV->getPCAdjustment(); + if (ACPV->mustAddCurrentAddress()) + O << "-."; + O << ")"; + } O << "\n"; // If the constant pool value is a extern weak symbol, remember to emit @@ -869,9 +873,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/ARM/ARMConstantPoolValue.cpp diff -u llvm/lib/Target/ARM/ARMConstantPoolValue.cpp:1.3 llvm/lib/Target/ARM/ARMConstantPoolValue.cpp:1.4 --- llvm/lib/Target/ARM/ARMConstantPoolValue.cpp:1.3 Sat Apr 21 19:04:12 2007 +++ llvm/lib/Target/ARM/ARMConstantPoolValue.cpp Fri Apr 27 08:54:47 2007 @@ -20,18 +20,20 @@ ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id, ARMCP::ARMCPKind k, unsigned char PCAdj, - const char *Modif) + const char *Modif, + bool AddCA) : MachineConstantPoolValue((const Type*)gv->getType()), GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj), - Modifier(Modif) {} + Modifier(Modif), AddCurrentAddress(AddCA) {} ARMConstantPoolValue::ARMConstantPoolValue(const char *s, unsigned id, ARMCP::ARMCPKind k, unsigned char PCAdj, - const char *Modif) + const char *Modif, + bool AddCA) : MachineConstantPoolValue((const Type*)Type::Int32Ty), GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj), - Modifier(Modif) {} + Modifier(Modif), AddCurrentAddress(AddCA) {} ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, ARMCP::ARMCPKind k, @@ -78,6 +80,11 @@ if (isNonLazyPointer()) O << "$non_lazy_ptr"; else if (isStub()) O << "$stub"; if (Modifier) O << "(" << Modifier << ")"; - if (PCAdjust != 0) O << "-(LPIC" << LabelId << "+" - << (unsigned)PCAdjust << ")"; + if (PCAdjust != 0) { + O << "-(LPIC" << LabelId << "+" + << (unsigned)PCAdjust; + if (AddCurrentAddress) + O << "-."; + O << ")"; + } } Index: llvm/lib/Target/ARM/ARMConstantPoolValue.h diff -u llvm/lib/Target/ARM/ARMConstantPoolValue.h:1.3 llvm/lib/Target/ARM/ARMConstantPoolValue.h:1.4 --- llvm/lib/Target/ARM/ARMConstantPoolValue.h:1.3 Sat Apr 21 19:04:12 2007 +++ llvm/lib/Target/ARM/ARMConstantPoolValue.h Fri Apr 27 08:54:47 2007 @@ -37,14 +37,17 @@ unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative. // 8 for ARM, 4 for Thumb. const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8)) + bool AddCurrentAddress; public: ARMConstantPoolValue(GlobalValue *gv, unsigned id, ARMCP::ARMCPKind Kind = ARMCP::CPValue, - unsigned char PCAdj = 0, const char *Modifier = NULL); + unsigned char PCAdj = 0, const char *Modifier = NULL, + bool AddCurrentAddress = false); ARMConstantPoolValue(const char *s, unsigned id, ARMCP::ARMCPKind Kind = ARMCP::CPValue, - unsigned char PCAdj = 0, const char *Modifier = NULL); + unsigned char PCAdj = 0, const char *Modifier = NULL, + bool AddCurrentAddress = false); ARMConstantPoolValue(GlobalValue *GV, ARMCP::ARMCPKind Kind, const char *Modifier); @@ -53,6 +56,7 @@ const char *getSymbol() const { return S; } const char *getModifier() const { return Modifier; } bool hasModifier() const { return Modifier != NULL; } + bool mustAddCurrentAddress() const { return AddCurrentAddress; } unsigned getLabelId() const { return LabelId; } bool isNonLazyPointer() const { return Kind == ARMCP::CPNonLazyPtr; } bool isStub() const { return Kind == ARMCP::CPStub; } Index: llvm/lib/Target/ARM/ARMISelLowering.cpp diff -u llvm/lib/Target/ARM/ARMISelLowering.cpp:1.46 llvm/lib/Target/ARM/ARMISelLowering.cpp:1.47 --- llvm/lib/Target/ARM/ARMISelLowering.cpp:1.46 Fri Apr 27 03:15:43 2007 +++ llvm/lib/Target/ARM/ARMISelLowering.cpp Fri Apr 27 08:54:47 2007 @@ -186,6 +186,7 @@ setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); setOperationAction(ISD::ConstantPool, MVT::i32, Custom); setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); // Expand mem operations genericly. setOperationAction(ISD::MEMSET , MVT::Other, Expand); @@ -293,6 +294,8 @@ case ARMISD::FMRRD: return "ARMISD::FMRRD"; case ARMISD::FMDRR: return "ARMISD::FMDRR"; + + case ARMISD::THREAD_POINTER:return "ARMISD::THREAD_POINTER"; } } @@ -701,6 +704,91 @@ return DAG.getNode(ARMISD::Wrapper, MVT::i32, Res); } +// Lower ISD::GlobalTLSAddress using the "general dynamic" model +SDOperand +ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, + SelectionDAG &DAG) { + MVT::ValueType PtrVT = getPointerTy(); + unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8; + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, ARMCP::CPValue, + PCAdj, "tlsgd", true); + SDOperand Argument = DAG.getTargetConstantPool(CPV, PtrVT, 2); + Argument = DAG.getNode(ARMISD::Wrapper, MVT::i32, Argument); + Argument = DAG.getLoad(PtrVT, DAG.getEntryNode(), Argument, NULL, 0); + SDOperand Chain = Argument.getValue(1); + + SDOperand PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32); + Argument = DAG.getNode(ARMISD::PIC_ADD, PtrVT, Argument, PICLabel); + + // call __tls_get_addr. + ArgListTy Args; + ArgListEntry Entry; + Entry.Node = Argument; + Entry.Ty = (const Type *) Type::Int32Ty; + Args.push_back(Entry); + std::pair<SDOperand, SDOperand> CallResult = + LowerCallTo(Chain, (const Type *) Type::Int32Ty, false, false, + CallingConv::C, false, + DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG); + return CallResult.first; +} + +// Lower ISD::GlobalTLSAddress using the "initial exec" or +// "local exec" model. +SDOperand +ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA, + SelectionDAG &DAG) { + GlobalValue *GV = GA->getGlobal(); + SDOperand Offset; + SDOperand Chain = DAG.getEntryNode(); + MVT::ValueType PtrVT = getPointerTy(); + // Get the Thread Pointer + SDOperand ThreadPointer = DAG.getNode(ARMISD::THREAD_POINTER, PtrVT); + + if (GV->isDeclaration()){ + // initial exec model + unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8; + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, ARMCP::CPValue, + PCAdj, "gottpoff", true); + Offset = DAG.getTargetConstantPool(CPV, PtrVT, 2); + Offset = DAG.getNode(ARMISD::Wrapper, MVT::i32, Offset); + Offset = DAG.getLoad(PtrVT, Chain, Offset, NULL, 0); + Chain = Offset.getValue(1); + + SDOperand PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32); + Offset = DAG.getNode(ARMISD::PIC_ADD, PtrVT, Offset, PICLabel); + + Offset = DAG.getLoad(PtrVT, Chain, Offset, NULL, 0); + } else { + // local exec model + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GV, ARMCP::CPValue, "tpoff"); + Offset = DAG.getTargetConstantPool(CPV, PtrVT, 2); + Offset = DAG.getNode(ARMISD::Wrapper, MVT::i32, Offset); + Offset = DAG.getLoad(PtrVT, Chain, Offset, NULL, 0); + } + + // 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 +ARMTargetLowering::LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG) { + // TODO: implement the "local dynamic" model + assert(Subtarget->isTargetELF() && + "TLS not implemented for non-ELF targets"); + 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); + else + return LowerToTLSExecModels(GA, DAG); +} + SDOperand ARMTargetLowering::LowerGlobalAddressELF(SDOperand Op, SelectionDAG &DAG) { MVT::ValueType PtrVT = getPointerTy(); @@ -1249,6 +1337,7 @@ case ISD::GlobalAddress: return Subtarget->isTargetDarwin() ? LowerGlobalAddressDarwin(Op, DAG) : LowerGlobalAddressELF(Op, DAG); + case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::CALL: return LowerCALL(Op, DAG); case ISD::RET: return LowerRET(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, Subtarget); Index: llvm/lib/Target/ARM/ARMISelLowering.h diff -u llvm/lib/Target/ARM/ARMISelLowering.h:1.14 llvm/lib/Target/ARM/ARMISelLowering.h:1.15 --- llvm/lib/Target/ARM/ARMISelLowering.h:1.14 Sat Apr 21 19:04:12 2007 +++ llvm/lib/Target/ARM/ARMISelLowering.h Fri Apr 27 08:54:47 2007 @@ -63,7 +63,9 @@ RRX, // V = RRX X, Flag -> srl X, 1 + shift in carry flag. FMRRD, // double to two gprs. - FMDRR // Two gprs to double. + FMDRR, // Two gprs to double. + + THREAD_POINTER }; } @@ -125,6 +127,11 @@ SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG); SDOperand LowerGlobalAddressDarwin(SDOperand Op, SelectionDAG &DAG); SDOperand LowerGlobalAddressELF(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, + SelectionDAG &DAG); + SDOperand LowerToTLSExecModels(GlobalAddressSDNode *GA, + SelectionDAG &DAG); SDOperand LowerGLOBAL_OFFSET_TABLE(SDOperand Op, SelectionDAG &DAG); SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG); SDOperand LowerBR_JT(SDOperand Op, SelectionDAG &DAG); Index: llvm/lib/Target/ARM/ARMInstrInfo.td diff -u llvm/lib/Target/ARM/ARMInstrInfo.td:1.96 llvm/lib/Target/ARM/ARMInstrInfo.td:1.97 --- llvm/lib/Target/ARM/ARMInstrInfo.td:1.96 Tue Apr 17 17:39:58 2007 +++ llvm/lib/Target/ARM/ARMInstrInfo.td Fri Apr 27 08:54:47 2007 @@ -39,6 +39,8 @@ def SDT_ARMPICAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, SDTCisPtrTy<1>, SDTCisVT<2, i32>]>; +def SDT_ARMThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; + // Node definitions. def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>; def ARMWrapperJT : SDNode<"ARMISD::WrapperJT", SDTIntBinOp>; @@ -79,6 +81,8 @@ def ARMsra_flag : SDNode<"ARMISD::SRA_FLAG", SDTIntUnaryOp, [SDNPOutFlag]>; def ARMrrx : SDNode<"ARMISD::RRX" , SDTIntUnaryOp, [SDNPInFlag ]>; +def ARMthread_pointer: SDNode<"ARMISD::THREAD_POINTER", SDT_ARMThreadPointer>; + //===----------------------------------------------------------------------===// // ARM Instruction Predicate Definitions. // @@ -1068,6 +1072,17 @@ !strconcat("${:private}PCRELL${:uid}:\n\t", "add $dst, pc, #PCRELV${:uid}")), []>; +//===----------------------------------------------------------------------===// +// TLS Instructions +// + +// __aeabi_read_tp preserves the registers r1-r3. +let isCall = 1, + Defs = [R0, R12, LR] in { + def TPsoft : AI<(ops), + "bl __aeabi_read_tp", + [(set R0, ARMthread_pointer)]>; +} //===----------------------------------------------------------------------===// // Non-Instruction Patterns Index: llvm/lib/Target/ARM/ARMInstrThumb.td diff -u llvm/lib/Target/ARM/ARMInstrThumb.td:1.23 llvm/lib/Target/ARM/ARMInstrThumb.td:1.24 --- llvm/lib/Target/ARM/ARMInstrThumb.td:1.23 Fri Apr 27 02:50:02 2007 +++ llvm/lib/Target/ARM/ARMInstrThumb.td Fri Apr 27 08:54:47 2007 @@ -524,6 +524,18 @@ []>; //===----------------------------------------------------------------------===// +// TLS Instructions +// + +// __aeabi_read_tp preserves the registers r1-r3. +let isCall = 1, + Defs = [R0, LR] in { + def tTPsoft : TIx2<(ops), + "bl __aeabi_read_tp", + [(set R0, ARMthread_pointer)]>; +} + +//===----------------------------------------------------------------------===// // Non-Instruction Patterns // Index: llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp diff -u llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp:1.14 llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp:1.15 --- llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp:1.14 Mon Apr 23 15:04:35 2007 +++ llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp Fri Apr 27 08:54:47 2007 @@ -70,6 +70,8 @@ StaticCtorsSection = "\t.section .ctors,\"aw\",%progbits"; StaticDtorsSection = "\t.section .dtors,\"aw\",%progbits"; } + TLSDataSection = "\t.section .tdata,\"awT\",%progbits"; + TLSBSSSection = "\t.section .tbss,\"awT\",%nobits"; } ZeroDirective = "\t.space\t"; _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits