Merging MIPS GOT changeset into 3.2 release branch.

Merging r168471:

Mips direct object xgot support

This patch provides support for the MIPS relocations:

    *)  R_MIPS_GOT_HI16
    *)  R_MIPS_GOT_LO16
    *)  R_MIPS_CALL_HI16
    *)  R_MIPS_CALL_LO16

These are used for large GOT instruction sequences.

Contributer: Jack Carter

Merging r168460:

[mips] Generate big GOT code.

Merging r168458:

[mips] Simplify lowering functions in MipsISelLowering.cpp by using the helper
functions added in r168456.

Merging r168456:

[mips] Add helper functions that create nodes for computing address.

Merging r168455:

[mips] Add command line option "-mxgot".

Merging r168453:

[mips] When a node which loads from a GOT is created, pass a MachinePointerInfo
referring to a GOT entry.

Merging r168450:

[mips] Add target operand flag enums for big GOT relocations.

Merging r168448:

Add relocations used for mips big GOT.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_32@169294 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Pawel Wodnicki committed 2012-12-04 19:47:56 +00:00
1 parent a902024940
commit bdcb22211f
14 files changed
+276 -149

No files matched your search

+5 -1
View File
@@ -197,7 +197,11 @@ public:
VK_Mips_GOT_PAGE,
VK_Mips_GOT_OFST,
VK_Mips_HIGHER,
VK_Mips_HIGHEST
VK_Mips_HIGHEST,
VK_Mips_GOT_HI16,
VK_Mips_GOT_LO16,
VK_Mips_CALL_HI16,
VK_Mips_CALL_LO16
};
private:
+4
View File
@@ -229,6 +229,10 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_Mips_GOT_OFST: return "GOT_OFST";
case VK_Mips_HIGHER: return "HIGHER";
case VK_Mips_HIGHEST: return "HIGHEST";
case VK_Mips_GOT_HI16: return "GOT_HI16";
case VK_Mips_GOT_LO16: return "GOT_LO16";
case VK_Mips_CALL_HI16: return "CALL_HI16";
case VK_Mips_CALL_LO16: return "CALL_LO16";
}
llvm_unreachable("Invalid variant kind");
}
@@ -128,6 +128,10 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) {
case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break;
case MCSymbolRefExpr::VK_Mips_HIGHER: OS << "%higher("; break;
case MCSymbolRefExpr::VK_Mips_HIGHEST: OS << "%highest("; break;
case MCSymbolRefExpr::VK_Mips_GOT_HI16: OS << "%got_hi("; break;
case MCSymbolRefExpr::VK_Mips_GOT_LO16: OS << "%got_lo("; break;
case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break;
case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break;
}
OS << SRE->getSymbol();
@@ -42,6 +42,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
case Mips::fixup_Mips_GOT_PAGE:
case Mips::fixup_Mips_GOT_OFST:
case Mips::fixup_Mips_GOT_DISP:
case Mips::fixup_Mips_GOT_LO16:
case Mips::fixup_Mips_CALL_LO16:
break;
case Mips::fixup_Mips_PC16:
// So far we are only using this type for branches.
@@ -60,6 +62,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
break;
case Mips::fixup_Mips_HI16:
case Mips::fixup_Mips_GOT_Local:
case Mips::fixup_Mips_GOT_HI16:
case Mips::fixup_Mips_CALL_HI16:
// Get the 2nd 16-bits. Also add 1 if bit 15 is 1.
Value = ((Value + 0x8000) >> 16) & 0xffff;
break;
@@ -179,7 +183,11 @@ public:
{ "fixup_Mips_GOT_OFST", 0, 16, 0 },
{ "fixup_Mips_GOT_DISP", 0, 16, 0 },
{ "fixup_Mips_HIGHER", 0, 16, 0 },
{ "fixup_Mips_HIGHEST", 0, 16, 0 }
{ "fixup_Mips_HIGHEST", 0, 16, 0 },
{ "fixup_Mips_GOT_HI16", 0, 16, 0 },
{ "fixup_Mips_GOT_LO16", 0, 16, 0 },
{ "fixup_Mips_CALL_HI16", 0, 16, 0 },
{ "fixup_Mips_CALL_LO16", 0, 16, 0 }
};
if (Kind < FirstTargetFixupKind)
+7 -1
View File
@@ -84,7 +84,13 @@ namespace MipsII {
/// MO_HIGHER/HIGHEST - Represents the highest or higher half word of a
/// 64-bit symbol address.
MO_HIGHER,
MO_HIGHEST
MO_HIGHEST,
/// MO_GOT_HI16/LO16, MO_CALL_HI16/LO16 - Relocations used for large GOTs.
MO_GOT_HI16,
MO_GOT_LO16,
MO_CALL_HI16,
MO_CALL_LO16
};
enum {
@@ -179,6 +179,18 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
case Mips::fixup_Mips_HIGHEST:
Type = ELF::R_MIPS_HIGHEST;
break;
case Mips::fixup_Mips_GOT_HI16:
Type = ELF::R_MIPS_GOT_HI16;
break;
case Mips::fixup_Mips_GOT_LO16:
Type = ELF::R_MIPS_GOT_LO16;
break;
case Mips::fixup_Mips_CALL_HI16:
Type = ELF::R_MIPS_CALL_HI16;
break;
case Mips::fixup_Mips_CALL_LO16:
Type = ELF::R_MIPS_CALL_LO16;
break;
}
return Type;
}
@@ -116,6 +116,18 @@ namespace Mips {
// resulting in - R_MIPS_HIGHEST
fixup_Mips_HIGHEST,
// resulting in - R_MIPS_GOT_HI16
fixup_Mips_GOT_HI16,
// resulting in - R_MIPS_GOT_LO16
fixup_Mips_GOT_LO16,
// resulting in - R_MIPS_CALL_HI16
fixup_Mips_CALL_HI16,
// resulting in - R_MIPS_CALL_LO16
fixup_Mips_CALL_LO16,
// Marker
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
@@ -287,6 +287,18 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
case MCSymbolRefExpr::VK_Mips_HIGHEST:
FixupKind = Mips::fixup_Mips_HIGHEST;
break;
case MCSymbolRefExpr::VK_Mips_GOT_HI16:
FixupKind = Mips::fixup_Mips_GOT_HI16;
break;
case MCSymbolRefExpr::VK_Mips_GOT_LO16:
FixupKind = Mips::fixup_Mips_GOT_LO16;
break;
case MCSymbolRefExpr::VK_Mips_CALL_HI16:
FixupKind = Mips::fixup_Mips_CALL_HI16;
break;
case MCSymbolRefExpr::VK_Mips_CALL_LO16:
FixupKind = Mips::fixup_Mips_CALL_LO16;
break;
} // switch
Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind)));
+2
View File
@@ -255,6 +255,7 @@ def : MipsPat<(MipsHi tblockaddress:$in), (LUi64 tblockaddress:$in)>;
def : MipsPat<(MipsHi tjumptable:$in), (LUi64 tjumptable:$in)>;
def : MipsPat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>;
def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>;
def : MipsPat<(MipsHi texternalsym:$in), (LUi64 texternalsym:$in)>;
def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>;
def : MipsPat<(MipsLo tblockaddress:$in), (DADDiu ZERO_64, tblockaddress:$in)>;
@@ -262,6 +263,7 @@ def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>;
def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>;
def : MipsPat<(MipsLo tglobaltlsaddr:$in),
(DADDiu ZERO_64, tglobaltlsaddr:$in)>;
def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>;
def : MipsPat<(add CPU64Regs:$hi, (MipsLo tglobaladdr:$lo)),
(DADDiu CPU64Regs:$hi, tglobaladdr:$lo)>;
+111 -146
View File
@@ -46,6 +46,10 @@ static cl::opt<bool>
EnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden,
cl::desc("MIPS: Enable tail calls."), cl::init(false));
static cl::opt<bool>
LargeGOT("mxgot", cl::Hidden,
cl::desc("MIPS: Enable GOT larger than 64k."), cl::init(false));
static const uint16_t O32IntRegs[4] = {
Mips::A0, Mips::A1, Mips::A2, Mips::A3
};
@@ -77,6 +81,71 @@ static SDValue GetGlobalReg(SelectionDAG &DAG, EVT Ty) {
return DAG.getRegister(FI->getGlobalBaseReg(), Ty);
}
static SDValue getTargetNode(SDValue Op, SelectionDAG &DAG, unsigned Flag) {
EVT Ty = Op.getValueType();
if (GlobalAddressSDNode *N = dyn_cast<GlobalAddressSDNode>(Op))
return DAG.getTargetGlobalAddress(N->getGlobal(), Op.getDebugLoc(), Ty, 0,
Flag);
if (ExternalSymbolSDNode *N = dyn_cast<ExternalSymbolSDNode>(Op))
return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flag);
if (BlockAddressSDNode *N = dyn_cast<BlockAddressSDNode>(Op))
return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, 0, Flag);
if (JumpTableSDNode *N = dyn_cast<JumpTableSDNode>(Op))
return DAG.getTargetJumpTable(N->getIndex(), Ty, Flag);
if (ConstantPoolSDNode *N = dyn_cast<ConstantPoolSDNode>(Op))
return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlignment(),
N->getOffset(), Flag);
llvm_unreachable("Unexpected node type.");
return SDValue();
}
static SDValue getAddrNonPIC(SDValue Op, SelectionDAG &DAG) {
DebugLoc DL = Op.getDebugLoc();
EVT Ty = Op.getValueType();
SDValue Hi = getTargetNode(Op, DAG, MipsII::MO_ABS_HI);
SDValue Lo = getTargetNode(Op, DAG, MipsII::MO_ABS_LO);
return DAG.getNode(ISD::ADD, DL, Ty,
DAG.getNode(MipsISD::Hi, DL, Ty, Hi),
DAG.getNode(MipsISD::Lo, DL, Ty, Lo));
}
static SDValue getAddrLocal(SDValue Op, SelectionDAG &DAG, bool HasMips64) {
DebugLoc DL = Op.getDebugLoc();
EVT Ty = Op.getValueType();
unsigned GOTFlag = HasMips64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, GetGlobalReg(DAG, Ty),
getTargetNode(Op, DAG, GOTFlag));
SDValue Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), GOT,
MachinePointerInfo::getGOT(), false, false, false,
0);
unsigned LoFlag = HasMips64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
SDValue Lo = DAG.getNode(MipsISD::Lo, DL, Ty, getTargetNode(Op, DAG, LoFlag));
return DAG.getNode(ISD::ADD, DL, Ty, Load, Lo);
}
static SDValue getAddrGlobal(SDValue Op, SelectionDAG &DAG, unsigned Flag) {
DebugLoc DL = Op.getDebugLoc();
EVT Ty = Op.getValueType();
SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, GetGlobalReg(DAG, Ty),
getTargetNode(Op, DAG, Flag));
return DAG.getLoad(Ty, DL, DAG.getEntryNode(), Tgt,
MachinePointerInfo::getGOT(), false, false, false, 0);
}
static SDValue getAddrGlobalLargeGOT(SDValue Op, SelectionDAG &DAG,
unsigned HiFlag, unsigned LoFlag) {
DebugLoc DL = Op.getDebugLoc();
EVT Ty = Op.getValueType();
SDValue Hi = DAG.getNode(MipsISD::Hi, DL, Ty, getTargetNode(Op, DAG, HiFlag));
Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, GetGlobalReg(DAG, Ty));
SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi,
getTargetNode(Op, DAG, LoFlag));
return DAG.getLoad(Ty, DL, DAG.getEntryNode(), Wrapper,
MachinePointerInfo::getGOT(), false, false, false, 0);
}
const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
case MipsISD::JmpLink: return "MipsISD::JmpLink";
@@ -1743,8 +1812,6 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op,
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) {
SDVTList VTs = DAG.getVTList(MVT::i32);
const MipsTargetObjectFile &TLOF =
(const MipsTargetObjectFile&)getObjFileLowering();
@@ -1752,69 +1819,33 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op,
if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) {
SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0,
MipsII::MO_GPREL);
SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, dl, VTs, &GA, 1);
SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, dl,
DAG.getVTList(MVT::i32), &GA, 1);
SDValue GPReg = DAG.getRegister(Mips::GP, MVT::i32);
return DAG.getNode(ISD::ADD, dl, MVT::i32, GPReg, GPRelNode);
}
// %hi/%lo relocation
SDValue GAHi = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0,
MipsII::MO_ABS_HI);
SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0,
MipsII::MO_ABS_LO);
SDValue HiPart = DAG.getNode(MipsISD::Hi, dl, VTs, &GAHi, 1);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, GALo);
return DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo);
return getAddrNonPIC(Op, DAG);
}
EVT ValTy = Op.getValueType();
bool HasGotOfst = (GV->hasInternalLinkage() ||
(GV->hasLocalLinkage() && !isa<Function>(GV)));
unsigned GotFlag = HasMips64 ?
(HasGotOfst ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT_DISP) :
(HasGotOfst ? MipsII::MO_GOT : MipsII::MO_GOT16);
SDValue GA = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, GotFlag);
GA = DAG.getNode(MipsISD::Wrapper, dl, ValTy, GetGlobalReg(DAG, ValTy), GA);
SDValue ResNode = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), GA,
MachinePointerInfo(), false, false, false, 0);
// On functions and global targets not internal linked only
// a load from got/GP is necessary for PIC to work.
if (!HasGotOfst)
return ResNode;
SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0,
HasMips64 ? MipsII::MO_GOT_OFST :
MipsII::MO_ABS_LO);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, GALo);
return DAG.getNode(ISD::ADD, dl, ValTy, ResNode, Lo);
if (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa<Function>(GV)))
return getAddrLocal(Op, DAG, HasMips64);
if (LargeGOT)
return getAddrGlobalLargeGOT(Op, DAG, MipsII::MO_GOT_HI16,
MipsII::MO_GOT_LO16);
return getAddrGlobal(Op, DAG,
HasMips64 ? MipsII::MO_GOT_DISP : MipsII::MO_GOT16);
}
SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const {
const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
// FIXME there isn't actually debug info here
DebugLoc dl = Op.getDebugLoc();
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64)
return getAddrNonPIC(Op, DAG);
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) {
// %hi/%lo relocation
SDValue BAHi =
DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_HI);
SDValue BALo =
DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_LO);
SDValue Hi = DAG.getNode(MipsISD::Hi, dl, MVT::i32, BAHi);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALo);
return DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo);
}
EVT ValTy = Op.getValueType();
unsigned GOTFlag = HasMips64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
unsigned OFSTFlag = HasMips64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
SDValue BAGOTOffset = DAG.getTargetBlockAddress(BA, ValTy, 0, GOTFlag);
BAGOTOffset = DAG.getNode(MipsISD::Wrapper, dl, ValTy,
GetGlobalReg(DAG, ValTy), BAGOTOffset);
SDValue BALOOffset = DAG.getTargetBlockAddress(BA, ValTy, 0, OFSTFlag);
SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), BAGOTOffset,
MachinePointerInfo(), false, false, false, 0);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, BALOOffset);
return DAG.getNode(ISD::ADD, dl, ValTy, Load, Lo);
return getAddrLocal(Op, DAG, HasMips64);
}
SDValue MipsTargetLowering::
@@ -1901,41 +1932,15 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
SDValue MipsTargetLowering::
LowerJumpTable(SDValue Op, SelectionDAG &DAG) const
{
SDValue HiPart, JTI, JTILo;
// FIXME there isn't actually debug info here
DebugLoc dl = Op.getDebugLoc();
bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_;
EVT PtrVT = Op.getValueType();
JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64)
return getAddrNonPIC(Op, DAG);
if (!IsPIC && !IsN64) {
JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, MipsII::MO_ABS_HI);
HiPart = DAG.getNode(MipsISD::Hi, dl, PtrVT, JTI);
JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, MipsII::MO_ABS_LO);
} else {// Emit Load from Global Pointer
unsigned GOTFlag = HasMips64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
unsigned OfstFlag = HasMips64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, GOTFlag);
JTI = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, GetGlobalReg(DAG, PtrVT),
JTI);
HiPart = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), JTI,
MachinePointerInfo(), false, false, false, 0);
JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OfstFlag);
}
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, PtrVT, JTILo);
return DAG.getNode(ISD::ADD, dl, PtrVT, HiPart, Lo);
return getAddrLocal(Op, DAG, HasMips64);
}
SDValue MipsTargetLowering::
LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
{
SDValue ResNode;
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
const Constant *C = N->getConstVal();
// FIXME there isn't actually debug info here
DebugLoc dl = Op.getDebugLoc();
// gp_rel relocation
// FIXME: we should reference the constant pool using small data sections,
// but the asm printer currently doesn't support this feature without
@@ -1946,31 +1951,10 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
// SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32);
// ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode);
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) {
SDValue CPHi = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(),
N->getOffset(), MipsII::MO_ABS_HI);
SDValue CPLo = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(),
N->getOffset(), MipsII::MO_ABS_LO);
SDValue HiPart = DAG.getNode(MipsISD::Hi, dl, MVT::i32, CPHi);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CPLo);
ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo);
} else {
EVT ValTy = Op.getValueType();
unsigned GOTFlag = HasMips64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
unsigned OFSTFlag = HasMips64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
SDValue CP = DAG.getTargetConstantPool(C, ValTy, N->getAlignment(),
N->getOffset(), GOTFlag);
CP = DAG.getNode(MipsISD::Wrapper, dl, ValTy, GetGlobalReg(DAG, ValTy), CP);
SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), CP,
MachinePointerInfo::getConstantPool(), false,
false, false, 0);
SDValue CPLo = DAG.getTargetConstantPool(C, ValTy, N->getAlignment(),
N->getOffset(), OFSTFlag);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, CPLo);
ResNode = DAG.getNode(ISD::ADD, dl, ValTy, Load, Lo);
}
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64)
return getAddrNonPIC(Op, DAG);
return ResNode;
return getAddrLocal(Op, DAG, HasMips64);
}
SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
@@ -2862,60 +2846,41 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
// node so that legalize doesn't hack it.
unsigned char OpFlag;
bool IsPICCall = (IsN64 || IsPIC); // true if calls are translated to jalr $25
bool GlobalOrExternal = false;
SDValue CalleeLo;
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
if (IsPICCall && G->getGlobal()->hasInternalLinkage()) {
OpFlag = IsO32 ? MipsII::MO_GOT : MipsII::MO_GOT_PAGE;
unsigned char LoFlag = IsO32 ? MipsII::MO_ABS_LO : MipsII::MO_GOT_OFST;
if (IsPICCall) {
if (G->getGlobal()->hasInternalLinkage())
Callee = getAddrLocal(Callee, DAG, HasMips64);
else if (LargeGOT)
Callee = getAddrGlobalLargeGOT(Callee, DAG, MipsII::MO_CALL_HI16,
MipsII::MO_CALL_LO16);
else
Callee = getAddrGlobal(Callee, DAG, MipsII::MO_GOT_CALL);
} else
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0,
OpFlag);
CalleeLo = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(),
0, LoFlag);
} else {
OpFlag = IsPICCall ? MipsII::MO_GOT_CALL : MipsII::MO_NO_FLAG;
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl,
getPointerTy(), 0, OpFlag);
}
MipsII::MO_NO_FLAG);
GlobalOrExternal = true;
}
else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
if (IsN64 || (!IsO32 && IsPIC))
OpFlag = MipsII::MO_GOT_DISP;
else if (!IsPIC) // !N64 && static
OpFlag = MipsII::MO_NO_FLAG;
if (!IsN64 && !IsPIC) // !N64 && static
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(),
MipsII::MO_NO_FLAG);
else if (LargeGOT)
Callee = getAddrGlobalLargeGOT(Callee, DAG, MipsII::MO_CALL_HI16,
MipsII::MO_CALL_LO16);
else if (HasMips64)
Callee = getAddrGlobal(Callee, DAG, MipsII::MO_GOT_DISP);
else // O32 & PIC
OpFlag = MipsII::MO_GOT_CALL;
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(),
OpFlag);
Callee = getAddrGlobal(Callee, DAG, MipsII::MO_GOT_CALL);
GlobalOrExternal = true;
}
SDValue InFlag;
// Create nodes that load address of callee and copy it to T9
if (IsPICCall) {
if (GlobalOrExternal) {
// Load callee address
Callee = DAG.getNode(MipsISD::Wrapper, dl, getPointerTy(),
GetGlobalReg(DAG, getPointerTy()), Callee);
SDValue LoadValue = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(),
Callee, MachinePointerInfo::getGOT(),
false, false, false, 0);
// Use GOT+LO if callee has internal linkage.
if (CalleeLo.getNode()) {
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, getPointerTy(), CalleeLo);
Callee = DAG.getNode(ISD::ADD, dl, getPointerTy(), LoadValue, Lo);
} else
Callee = LoadValue;
}
}
// T9 register operand.
SDValue T9;
+2
View File
@@ -1154,12 +1154,14 @@ def : MipsPat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>;
def : MipsPat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>;
def : MipsPat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>;
def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>;
def : MipsPat<(MipsHi texternalsym:$in), (LUi texternalsym:$in)>;
def : MipsPat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
def : MipsPat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>;
def : MipsPat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>;
def : MipsPat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>;
def : MipsPat<(MipsLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>;
def : MipsPat<(MipsLo texternalsym:$in), (ADDiu ZERO, texternalsym:$in)>;
def : MipsPat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
(ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
+4
View File
@@ -62,6 +62,10 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break;
case MipsII::MO_HIGHER: Kind = MCSymbolRefExpr::VK_Mips_HIGHER; break;
case MipsII::MO_HIGHEST: Kind = MCSymbolRefExpr::VK_Mips_HIGHEST; break;
case MipsII::MO_GOT_HI16: Kind = MCSymbolRefExpr::VK_Mips_GOT_HI16; break;
case MipsII::MO_GOT_LO16: Kind = MCSymbolRefExpr::VK_Mips_GOT_LO16; break;
case MipsII::MO_CALL_HI16: Kind = MCSymbolRefExpr::VK_Mips_CALL_HI16; break;
case MipsII::MO_CALL_LO16: Kind = MCSymbolRefExpr::VK_Mips_CALL_LO16; break;
}
switch (MOTy) {
+50
View File
@@ -0,0 +1,50 @@
; RUN: llc -march=mipsel -mxgot < %s | FileCheck %s -check-prefix=O32
; RUN: llc -march=mips64el -mcpu=mips64r2 -mattr=+n64 -mxgot < %s | \
; RUN: FileCheck %s -check-prefix=N64
@v0 = external global i32
define void @foo1() nounwind {
entry:
; O32: lui $[[R0:[0-9]+]], %got_hi(v0)
; O32: addu $[[R1:[0-9]+]], $[[R0]], ${{[a-z0-9]+}}
; O32: lw ${{[0-9]+}}, %got_lo(v0)($[[R1]])
; O32: lui $[[R2:[0-9]+]], %call_hi(foo0)
; O32: addu $[[R3:[0-9]+]], $[[R2]], ${{[a-z0-9]+}}
; O32: lw ${{[0-9]+}}, %call_lo(foo0)($[[R3]])
; N64: lui $[[R0:[0-9]+]], %got_hi(v0)
; N64: daddu $[[R1:[0-9]+]], $[[R0]], ${{[a-z0-9]+}}
; N64: ld ${{[0-9]+}}, %got_lo(v0)($[[R1]])
; N64: lui $[[R2:[0-9]+]], %call_hi(foo0)
; N64: daddu $[[R3:[0-9]+]], $[[R2]], ${{[a-z0-9]+}}
; N64: ld ${{[0-9]+}}, %call_lo(foo0)($[[R3]])
%0 = load i32* @v0, align 4
tail call void @foo0(i32 %0) nounwind
ret void
}
declare void @foo0(i32)
; call to external function.
define void @foo2(i32* nocapture %d, i32* nocapture %s, i32 %n) nounwind {
entry:
; O32: foo2:
; O32: lui $[[R2:[0-9]+]], %call_hi(memcpy)
; O32: addu $[[R3:[0-9]+]], $[[R2]], ${{[a-z0-9]+}}
; O32: lw ${{[0-9]+}}, %call_lo(memcpy)($[[R3]])
; N64: foo2:
; N64: lui $[[R2:[0-9]+]], %call_hi(memcpy)
; N64: daddu $[[R3:[0-9]+]], $[[R2]], ${{[a-z0-9]+}}
; N64: ld ${{[0-9]+}}, %call_lo(memcpy)($[[R3]])
%0 = bitcast i32* %d to i8*
%1 = bitcast i32* %s to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 %n, i32 4, i1 false)
ret void
}
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
+42
View File
@@ -0,0 +1,42 @@
; RUN: llc -filetype=obj -mtriple mipsel-unknown-linux -mxgot %s -o - | elf-dump --dump-section-data | FileCheck %s
@.str = private unnamed_addr constant [16 x i8] c"ext_1=%d, i=%d\0A\00", align 1
@ext_1 = external global i32
define void @fill() nounwind {
entry:
; Check that the appropriate relocations were created.
; For the xgot case we want to see R_MIPS_[GOT|CALL]_[HI|LO]16.
; R_MIPS_HI16
; CHECK: ('r_type', 0x05)
; R_MIPS_LO16
; CHECK: ('r_type', 0x06)
; R_MIPS_GOT_HI16
; CHECK: ('r_type', 0x16)
; R_MIPS_GOT_LO16
; CHECK: ('r_type', 0x17)
; R_MIPS_GOT
; CHECK: ('r_type', 0x09)
; R_MIPS_LO16
; CHECK: ('r_type', 0x06)
; R_MIPS_CALL_HI16
; CHECK: ('r_type', 0x1e)
; R_MIPS_CALL_LO16
; CHECK: ('r_type', 0x1f)
%0 = load i32* @ext_1, align 4
%call = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([16 x i8]* @.str, i32 0, i32 0), i32 %0) nounwind
ret void
}
declare i32 @printf(i8* nocapture, ...) nounwind