diff options
| author | Lauro Ramos Venancio <lauro.venancio@gmail.com> | 2007-04-22 00:04:12 +0000 | 
|---|---|---|
| committer | Lauro Ramos Venancio <lauro.venancio@gmail.com> | 2007-04-22 00:04:12 +0000 | 
| commit | ee2d164f0f983d827d13b30c6a60d3fad1f555f6 (patch) | |
| tree | b68aaa3452c011119d1cb397504aedaab6cc85fc | |
| parent | 2bb29e778a15687097b30e03bdb6154b6ab88913 (diff) | |
| download | bcm5719-llvm-ee2d164f0f983d827d13b30c6a60d3fad1f555f6.tar.gz bcm5719-llvm-ee2d164f0f983d827d13b30c6a60d3fad1f555f6.zip  | |
Implement PIC for arm-linux.
llvm-svn: 36324
| -rw-r--r-- | llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMConstantPoolValue.cpp | 20 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMConstantPoolValue.h | 10 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 53 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.h | 4 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/call.ll | 2 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/load-global.ll | 4 | 
7 files changed, 88 insertions, 13 deletions
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 109ae215ad8..625dd9d8856 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -133,6 +133,7 @@ namespace {          O << TAI->getPrivateGlobalPrefix() << Name << "$stub";        } else          O << Name; +      if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";        if (ACPV->getPCAdjustment() != 0)          O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"            << utostr(ACPV->getLabelId()) @@ -284,7 +285,9 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,        FnStubs.insert(Name);      } else        O << Name; - +    if (isCallOp && Subtarget->isTargetELF() && +        TM.getRelocationModel() == Reloc::PIC_) +      O << "(PLT)";      if (GV->hasExternalWeakLinkage())        ExtWeakSymbols.insert(GV);      break; @@ -299,6 +302,9 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,        FnStubs.insert(Name);      } else        O << Name; +    if (isCallOp && Subtarget->isTargetELF() && +        TM.getRelocationModel() == Reloc::PIC_) +      O << "(PLT)";      break;    }    case MachineOperand::MO_ConstantPoolIndex: diff --git a/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp b/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp index a219c352ba5..1fe66fb174b 100644 --- a/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp +++ b/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -19,15 +19,26 @@ using namespace llvm;  ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id,                                             ARMCP::ARMCPKind k, -                                           unsigned char PCAdj) +                                           unsigned char PCAdj, +                                           const char *Modif)    : MachineConstantPoolValue((const Type*)gv->getType()), -    GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj) {} +    GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj), +    Modifier(Modif) {}  ARMConstantPoolValue::ARMConstantPoolValue(const char *s, unsigned id,                                             ARMCP::ARMCPKind k, -                                           unsigned char PCAdj) +                                           unsigned char PCAdj, +                                           const char *Modif)    : MachineConstantPoolValue((const Type*)Type::Int32Ty), -    GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj) {} +    GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj), +    Modifier(Modif) {} + +ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, +                                           ARMCP::ARMCPKind k, +                                           const char *Modif) +  : MachineConstantPoolValue((const Type*)Type::Int32Ty), +    GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0), +    Modifier(Modif) {}  int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,                                                      unsigned Alignment) { @@ -66,6 +77,7 @@ void ARMConstantPoolValue::print(std::ostream &O) const {      O << S;    if (isNonLazyPointer()) O << "$non_lazy_ptr";    else if (isStub()) O << "$stub"; +  if (Modifier) O << "(" << Modifier << ")";    if (PCAdjust != 0) O << "-(LPIC" << LabelId << "+"                         << (unsigned)PCAdjust << ")";  } diff --git a/llvm/lib/Target/ARM/ARMConstantPoolValue.h b/llvm/lib/Target/ARM/ARMConstantPoolValue.h index a614bec60fe..b7511aa8dd6 100644 --- a/llvm/lib/Target/ARM/ARMConstantPoolValue.h +++ b/llvm/lib/Target/ARM/ARMConstantPoolValue.h @@ -36,17 +36,23 @@ class ARMConstantPoolValue : public MachineConstantPoolValue {    ARMCP::ARMCPKind Kind;   // non_lazy_ptr or stub?    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))  public:    ARMConstantPoolValue(GlobalValue *gv, unsigned id,                         ARMCP::ARMCPKind Kind = ARMCP::CPValue, -                       unsigned char PCAdj = 0); +                       unsigned char PCAdj = 0, const char *Modifier = NULL);    ARMConstantPoolValue(const char *s, unsigned id,                         ARMCP::ARMCPKind Kind = ARMCP::CPValue, -                       unsigned char PCAdj = 0); +                       unsigned char PCAdj = 0, const char *Modifier = NULL); +  ARMConstantPoolValue(GlobalValue *GV, ARMCP::ARMCPKind Kind, +                       const char *Modifier); +    GlobalValue *getGV() const { return GV; }    const char *getSymbol() const { return S; } +  const char *getModifier() const { return Modifier; } +  bool hasModifier() const { return Modifier != NULL; }    unsigned getLabelId() const { return LabelId; }    bool isNonLazyPointer() const { return Kind == ARMCP::CPNonLazyPtr; }    bool isStub() const { return Kind == ARMCP::CPStub; } diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 0cef4cce68f..780e49058f5 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -179,6 +179,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)    setOperationAction(ISD::RET,           MVT::Other, Custom);    setOperationAction(ISD::GlobalAddress, MVT::i32,   Custom);    setOperationAction(ISD::ConstantPool,  MVT::i32,   Custom); +  setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom);    // Expand mem operations genericly.    setOperationAction(ISD::MEMSET          , MVT::Other, Expand); @@ -694,6 +695,31 @@ static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {    return DAG.getNode(ARMISD::Wrapper, MVT::i32, Res);  } +SDOperand ARMTargetLowering::LowerGlobalAddressELF(SDOperand Op, +                                                   SelectionDAG &DAG) { +  MVT::ValueType PtrVT = getPointerTy(); +  GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); +  Reloc::Model RelocM = getTargetMachine().getRelocationModel(); +  if (RelocM == Reloc::PIC_) { +    bool UseGOTOFF = GV->hasInternalLinkage(); +    ARMConstantPoolValue *CPV = +      new ARMConstantPoolValue(GV, ARMCP::CPValue, UseGOTOFF ? "GOTOFF":"GOT"); +    SDOperand CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 2); +    CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr); +    SDOperand Result = DAG.getLoad(PtrVT, DAG.getEntryNode(), CPAddr, NULL, 0); +    SDOperand Chain = Result.getValue(1); +    SDOperand GOT = DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, PtrVT); +    Result = DAG.getNode(ISD::ADD, PtrVT, Result, GOT); +    if (!UseGOTOFF) +      Result = DAG.getLoad(PtrVT, Chain, Result, NULL, 0); +    return Result; +  } else { +    SDOperand CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2); +    CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr); +    return DAG.getLoad(PtrVT, DAG.getEntryNode(), CPAddr, NULL, 0); +  } +} +  /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol  /// even in dynamic-no-pic mode.  static bool GVIsIndirectSymbol(GlobalValue *GV) { @@ -701,12 +727,12 @@ static bool GVIsIndirectSymbol(GlobalValue *GV) {            (GV->isDeclaration() && !GV->hasNotBeenReadFromBytecode()));  } -SDOperand ARMTargetLowering::LowerGlobalAddress(SDOperand Op, -                                                SelectionDAG &DAG) { +SDOperand ARMTargetLowering::LowerGlobalAddressDarwin(SDOperand Op, +                                                      SelectionDAG &DAG) {    MVT::ValueType PtrVT = getPointerTy();    GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();    Reloc::Model RelocM = getTargetMachine().getRelocationModel(); -  bool IsIndirect = Subtarget->isTargetDarwin() && GVIsIndirectSymbol(GV); +  bool IsIndirect = GVIsIndirectSymbol(GV);    SDOperand CPAddr;    if (RelocM == Reloc::Static)      CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2); @@ -734,6 +760,22 @@ SDOperand ARMTargetLowering::LowerGlobalAddress(SDOperand Op,    return Result;  } +SDOperand ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDOperand Op, +                                                      SelectionDAG &DAG){ +  assert(Subtarget->isTargetELF() && +         "GLOBAL OFFSET TABLE not implemented for non-ELF targets"); +  MVT::ValueType PtrVT = getPointerTy(); +  unsigned PCAdj = Subtarget->isThumb() ? 4 : 8; +  ARMConstantPoolValue *CPV = new ARMConstantPoolValue("_GLOBAL_OFFSET_TABLE_", +                                                       ARMPCLabelIndex, +                                                       ARMCP::CPValue, PCAdj); +  SDOperand CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 2); +  CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr); +  SDOperand Result = DAG.getLoad(PtrVT, DAG.getEntryNode(), CPAddr, NULL, 0); +  SDOperand PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32); +  return DAG.getNode(ARMISD::PIC_ADD, PtrVT, Result, PICLabel); +} +  static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,                                unsigned VarArgsFrameIndex) {    // vastart just stores the address of the VarArgsFrameIndex slot into the @@ -1198,7 +1240,9 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {    switch (Op.getOpcode()) {    default: assert(0 && "Don't know how to custom lower this!"); abort();    case ISD::ConstantPool:  return LowerConstantPool(Op, DAG); -  case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); +  case ISD::GlobalAddress: +    return Subtarget->isTargetDarwin() ? LowerGlobalAddressDarwin(Op, DAG) : +      LowerGlobalAddressELF(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); @@ -1220,6 +1264,7 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {      return LowerFORMAL_ARGUMENTS(Op, DAG);    case ISD::RETURNADDR:    break;    case ISD::FRAMEADDR:     break; +  case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);    }    return SDOperand();  } diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h index 90964315d3b..5b182f9b5b0 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.h +++ b/llvm/lib/Target/ARM/ARMISelLowering.h @@ -123,7 +123,9 @@ namespace llvm {      unsigned ARMPCLabelIndex;      SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG); -    SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG); +    SDOperand LowerGlobalAddressDarwin(SDOperand Op, SelectionDAG &DAG); +    SDOperand LowerGlobalAddressELF(SDOperand Op, SelectionDAG &DAG); +    SDOperand LowerGLOBAL_OFFSET_TABLE(SDOperand Op, SelectionDAG &DAG);      SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);      SDOperand LowerBR_JT(SDOperand Op, SelectionDAG &DAG);    }; diff --git a/llvm/test/CodeGen/ARM/call.ll b/llvm/test/CodeGen/ARM/call.ll index c270d7e53b9..c7e10b13e8f 100644 --- a/llvm/test/CodeGen/ARM/call.ll +++ b/llvm/test/CodeGen/ARM/call.ll @@ -1,5 +1,7 @@  ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep {mov lr, pc}  ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm -mattr=+v5t | grep blx +; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm -mtriple=arm-linux-gnueabi\ +; RUN:   -relocation-model=pic | grep {PLT}  %t = weak global int ()* null  declare void %g(int, int, int, int) diff --git a/llvm/test/CodeGen/ARM/load-global.ll b/llvm/test/CodeGen/ARM/load-global.ll index 3c287d473a4..1afa9e993d6 100644 --- a/llvm/test/CodeGen/ARM/load-global.ll +++ b/llvm/test/CodeGen/ARM/load-global.ll @@ -1,10 +1,12 @@ -; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm  ; RUN: llvm-upgrade < %s | llvm-as | \  ; RUN:   llc -mtriple=arm-apple-darwin -relocation-model=dynamic-no-pic | \  ; RUN:   grep {L_G\$non_lazy_ptr} | wc -l | grep 2  ; RUN: llvm-upgrade < %s | llvm-as | \  ; RUN:   llc -mtriple=arm-apple-darwin -relocation-model=pic | \  ; RUN:   grep {ldr.*pc} | wc -l | grep 1 +; RUN: llvm-upgrade < %s | llvm-as | \ +; RUN:   llc -mtriple=arm-linux-gnueabi -relocation-model=pic | \ +; RUN:   grep {GOT} | wc -l | grep 1  %G = external global int  | 

