Implement PIC for arm-linux.
authorLauro Ramos Venancio <lauro.venancio@gmail.com>
Sun, 22 Apr 2007 00:04:12 +0000 (00:04 +0000)
committerLauro Ramos Venancio <lauro.venancio@gmail.com>
Sun, 22 Apr 2007 00:04:12 +0000 (00:04 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36324 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMAsmPrinter.cpp
lib/Target/ARM/ARMConstantPoolValue.cpp
lib/Target/ARM/ARMConstantPoolValue.h
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMISelLowering.h
test/CodeGen/ARM/call.ll
test/CodeGen/ARM/load-global.ll

index 109ae215ad841c073ea66838906683dde090b927..625dd9d88565691bc69758176901ae9c7235ee86 100644 (file)
@@ -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:
index a219c352ba5714a7bbc703509d4dee33ccc579f1..1fe66fb174bdd214a534621de493afa0f36a0c7b 100644 (file)
@@ -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 << ")";
 }
index a614bec60fec83e4778592814a3eb5ea38b41af7..b7511aa8dd644a4756e43778d40c358c5830e643 100644 (file)
@@ -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; }
index 0cef4cce68f773deb1ff8ca232df0ee6b669a963..780e49058f5b1a439a3b426ae761e387ed7a0459 100644 (file)
@@ -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();
 }
index 90964315d3b05c8ba2789e3cad4c3f415048f4c6..5b182f9b5b0c291f4d06d0365273b412b1dc560c 100644 (file)
@@ -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);
   };
index c270d7e53b9082dc7b1544d992c93ffd5ca1548b..c7e10b13e8fd76b7a44d47821d8bfbeaf99eadc6 100644 (file)
@@ -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)
index 3c287d473a4192595ce2fc038a35c6619529ad0b..1afa9e993d670ab7d52de121b454cf745535fb0b 100644 (file)
@@ -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