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
This commit is contained in:
Chris Lattner 2005-08-19 22:38:53 +00:00
parent 9b78db7f16
commit 4416f1a0a5

View File

@ -15,10 +15,14 @@
#include "PowerPC.h" #include "PowerPC.h"
#include "PPC32TargetMachine.h" #include "PPC32TargetMachine.h"
#include "PPC32ISelLowering.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/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/GlobalValue.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
using namespace llvm; using namespace llvm;
@ -34,16 +38,26 @@ namespace {
/// ///
class PPC32DAGToDAGISel : public SelectionDAGISel { class PPC32DAGToDAGISel : public SelectionDAGISel {
PPC32TargetLowering PPC32Lowering; PPC32TargetLowering PPC32Lowering;
unsigned GlobalBaseReg;
public: public:
PPC32DAGToDAGISel(TargetMachine &TM) PPC32DAGToDAGISel(TargetMachine &TM)
: SelectionDAGISel(PPC32Lowering), PPC32Lowering(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 /// getI32Imm - Return a target constant with the specified value, of type
/// i32. /// i32.
inline SDOperand getI32Imm(unsigned Imm) { inline SDOperand getI32Imm(unsigned Imm) {
return CurDAG->getTargetConstant(Imm, MVT::i32); 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 // Select - Convert the specified operand from a target-independent to a
// target-specific node if it hasn't already been changed. // 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. // isIntImmediate - This method tests to see if a constant operand.
// If so Imm will receive the 32 bit value. // If so Imm will receive the 32 bit value.
static bool isIntImmediate(SDNode *N, unsigned& Imm) { static bool isIntImmediate(SDNode *N, unsigned& Imm) {
@ -392,6 +423,22 @@ SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) {
} }
break; 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: case ISD::SIGN_EXTEND_INREG:
switch(cast<VTSDNode>(N->getOperand(1))->getVT()) { switch(cast<VTSDNode>(N->getOperand(1))->getVT()) {
default: assert(0 && "Illegal type in SIGN_EXTEND_INREG"); break; default: assert(0 && "Illegal type in SIGN_EXTEND_INREG"); break;