add support for global address, including PIC support.
authorChris Lattner <sabre@nondot.org>
Fri, 19 Aug 2005 22:38:53 +0000 (22:38 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 19 Aug 2005 22:38:53 +0000 (22:38 +0000)
This REALLY should be lowered by the legalizer!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22941 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCISelDAGToDAG.cpp

index 7f2642c8a5db4a82ecdfdb812c58c24dd2a2f0ae..03028822d8ed507539349c850ca7f6c0f9098ac9 100644 (file)
 #include "PowerPC.h"
 #include "PPC32TargetMachine.h"
 #include "PPC32ISelLowering.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/GlobalValue.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
 using namespace llvm;
@@ -34,16 +38,26 @@ namespace {
   ///
   class PPC32DAGToDAGISel : public SelectionDAGISel {
     PPC32TargetLowering PPC32Lowering;
-    
+    unsigned GlobalBaseReg;
   public:
     PPC32DAGToDAGISel(TargetMachine &TM)
       : SelectionDAGISel(PPC32Lowering), PPC32Lowering(TM) {}
     
+    virtual bool runOnFunction(Function &Fn) {
+      // Make sure we re-emit a set of the global base reg if necessary
+      GlobalBaseReg = 0;
+      return SelectionDAGISel::runOnFunction(Fn);
+    }
+   
     /// getI32Imm - Return a target constant with the specified value, of type
     /// i32.
     inline SDOperand getI32Imm(unsigned Imm) {
       return CurDAG->getTargetConstant(Imm, MVT::i32);
     }
+
+    /// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC
+    /// base register.  Return the virtual register that holds this value.
+    unsigned getGlobalBaseReg();
     
     // Select - Convert the specified operand from a target-independent to a
     // target-specific node if it hasn't already been changed.
@@ -73,6 +87,23 @@ namespace {
   };
 }
 
+/// getGlobalBaseReg - Output the instructions required to put the
+/// base address to use for accessing globals into a register.
+///
+unsigned PPC32DAGToDAGISel::getGlobalBaseReg() {
+  if (!GlobalBaseReg) {
+    // Insert the set of GlobalBaseReg into the first MBB of the function
+    MachineBasicBlock &FirstMBB = BB->getParent()->front();
+    MachineBasicBlock::iterator MBBI = FirstMBB.begin();
+    SSARegMap *RegMap = BB->getParent()->getSSARegMap();
+    GlobalBaseReg = RegMap->createVirtualRegister(PPC32::GPRCRegisterClass);
+    BuildMI(FirstMBB, MBBI, PPC::MovePCtoLR, 0, PPC::LR);
+    BuildMI(FirstMBB, MBBI, PPC::MFLR, 1, GlobalBaseReg);
+  }
+  return GlobalBaseReg;
+}
+
+
 // isIntImmediate - This method tests to see if a constant operand.
 // If so Imm will receive the 32 bit value.
 static bool isIntImmediate(SDNode *N, unsigned& Imm) {
@@ -392,6 +423,22 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) {
     }
     break;
   }
+  case ISD::GlobalAddress: {
+    GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
+    SDOperand Tmp;
+    SDOperand GA = CurDAG->getTargetGlobalAddress(GV, MVT::i32);
+    if (PICEnabled) {
+      SDOperand PICBaseReg = CurDAG->getRegister(getGlobalBaseReg(), MVT::i32);
+      Tmp = CurDAG->getTargetNode(PPC::ADDIS, MVT::i32, PICBaseReg, GA);
+    } else {
+      Tmp = CurDAG->getTargetNode(PPC::LIS, MVT::i32, GA);
+    }
+    if (GV->hasWeakLinkage() || GV->isExternal())
+      CurDAG->SelectNodeTo(N, MVT::i32, PPC::LWZ, GA, Tmp);
+    else
+      CurDAG->SelectNodeTo(N, MVT::i32, PPC::LA, Tmp, GA);
+    break;
+  }
   case ISD::SIGN_EXTEND_INREG:
     switch(cast<VTSDNode>(N->getOperand(1))->getVT()) {
     default: assert(0 && "Illegal type in SIGN_EXTEND_INREG"); break;