From: Chris Lattner Date: Fri, 19 Aug 2005 22:38:53 +0000 (+0000) Subject: add support for global address, including PIC support. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4416f1a0a5b17906b9e162209fd506656a2e07d8;p=oota-llvm.git add support for global address, including PIC support. 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 --- diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 7f2642c8a5d..03028822d8e 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -15,10 +15,14 @@ #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(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(N->getOperand(1))->getVT()) { default: assert(0 && "Illegal type in SIGN_EXTEND_INREG"); break;