mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
Added support for PIC code with "explicit relocations" *only*.
Removed all macro code for PIC (goodbye "la"). Support tested with shootout bench. llvm-svn: 43697
This commit is contained in:
parent
314e68f58f
commit
569b5512b0
@ -250,7 +250,7 @@ emitFunctionStart(MachineFunction &MF)
|
|||||||
emitMaskDirective(MF);
|
emitMaskDirective(MF);
|
||||||
emitFMaskDirective(MF);
|
emitFMaskDirective(MF);
|
||||||
|
|
||||||
if (MF.getTarget().getRelocationModel() == Reloc::Static) {
|
if (TM.getRelocationModel() == Reloc::Static) {
|
||||||
emitSetDirective(NOREORDER);
|
emitSetDirective(NOREORDER);
|
||||||
emitSetDirective(NOMACRO);
|
emitSetDirective(NOMACRO);
|
||||||
}
|
}
|
||||||
@ -262,7 +262,7 @@ emitFunctionStart(MachineFunction &MF)
|
|||||||
void MipsAsmPrinter::
|
void MipsAsmPrinter::
|
||||||
emitFunctionEnd(MachineFunction &MF)
|
emitFunctionEnd(MachineFunction &MF)
|
||||||
{
|
{
|
||||||
if (MF.getTarget().getRelocationModel() == Reloc::Static) {
|
if (TM.getRelocationModel() == Reloc::Static) {
|
||||||
emitSetDirective(MACRO);
|
emitSetDirective(MACRO);
|
||||||
emitSetDirective(REORDER);
|
emitSetDirective(REORDER);
|
||||||
}
|
}
|
||||||
@ -305,6 +305,9 @@ runOnMachineFunction(MachineFunction &MF)
|
|||||||
printInstruction(II);
|
printInstruction(II);
|
||||||
++EmittedInsts;
|
++EmittedInsts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Each Basic Block is separated by a newline
|
||||||
|
O << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit function end directives
|
// Emit function end directives
|
||||||
@ -319,17 +322,41 @@ printOperand(const MachineInstr *MI, int opNum)
|
|||||||
{
|
{
|
||||||
const MachineOperand &MO = MI->getOperand(opNum);
|
const MachineOperand &MO = MI->getOperand(opNum);
|
||||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||||
bool closeP=false;
|
bool closeP = false;
|
||||||
|
bool isPIC = (TM.getRelocationModel() == Reloc::PIC_);
|
||||||
|
bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large);
|
||||||
|
|
||||||
// %hi and %lo used on mips gas to break large constants
|
// %hi and %lo used on mips gas to load global addresses on
|
||||||
|
// static code. %got is used to load global addresses when
|
||||||
|
// using PIC_. %call16 is used to load direct call targets
|
||||||
|
// on PIC_ and small code size. %call_lo and %call_hi load
|
||||||
|
// direct call targets on PIC_ and large code size.
|
||||||
if (MI->getOpcode() == Mips::LUi && !MO.isRegister()
|
if (MI->getOpcode() == Mips::LUi && !MO.isRegister()
|
||||||
&& !MO.isImmediate()) {
|
&& !MO.isImmediate()) {
|
||||||
|
if ((isPIC) && (isCodeLarge))
|
||||||
|
O << "%call_hi(";
|
||||||
|
else
|
||||||
O << "%hi(";
|
O << "%hi(";
|
||||||
closeP = true;
|
closeP = true;
|
||||||
} else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()
|
} else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()
|
||||||
&& !MO.isImmediate()) {
|
&& !MO.isImmediate()) {
|
||||||
O << "%lo(";
|
O << "%lo(";
|
||||||
closeP = true;
|
closeP = true;
|
||||||
|
} else if ((isPIC) && (MI->getOpcode() == Mips::LW)
|
||||||
|
&& (!MO.isRegister()) && (!MO.isImmediate())) {
|
||||||
|
const MachineOperand &firstMO = MI->getOperand(opNum-1);
|
||||||
|
const MachineOperand &lastMO = MI->getOperand(opNum+1);
|
||||||
|
if ((firstMO.isRegister()) && (lastMO.isRegister())) {
|
||||||
|
if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() == Mips::GP)
|
||||||
|
&& (!isCodeLarge))
|
||||||
|
O << "%call16(";
|
||||||
|
else if ((firstMO.getReg() != Mips::T9) && (lastMO.getReg() == Mips::GP))
|
||||||
|
O << "%got(";
|
||||||
|
else if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() != Mips::GP)
|
||||||
|
&& (isCodeLarge))
|
||||||
|
O << "%call_lo(";
|
||||||
|
closeP = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (MO.getType())
|
switch (MO.getType())
|
||||||
@ -361,6 +388,7 @@ printOperand(const MachineInstr *MI, int opNum)
|
|||||||
O << MO.getSymbolName();
|
O << MO.getSymbolName();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// FIXME: Verify correct
|
||||||
case MachineOperand::MO_ConstantPoolIndex:
|
case MachineOperand::MO_ConstantPoolIndex:
|
||||||
O << TAI->getPrivateGlobalPrefix() << "CPI"
|
O << TAI->getPrivateGlobalPrefix() << "CPI"
|
||||||
<< getFunctionNumber() << "_" << MO.getConstantPoolIndex();
|
<< getFunctionNumber() << "_" << MO.getConstantPoolIndex();
|
||||||
@ -386,6 +414,8 @@ printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load/Store memory operands -- imm($reg)
|
// Load/Store memory operands -- imm($reg)
|
||||||
|
// If PIC target the target is loaded as the
|
||||||
|
// pattern lw $25,%call16($28)
|
||||||
printOperand(MI, opNum);
|
printOperand(MI, opNum);
|
||||||
O << "(";
|
O << "(";
|
||||||
printOperand(MI, opNum+1);
|
printOperand(MI, opNum+1);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "Mips.h"
|
#include "Mips.h"
|
||||||
#include "MipsISelLowering.h"
|
#include "MipsISelLowering.h"
|
||||||
|
#include "MipsMachineFunction.h"
|
||||||
#include "MipsRegisterInfo.h"
|
#include "MipsRegisterInfo.h"
|
||||||
#include "MipsSubtarget.h"
|
#include "MipsSubtarget.h"
|
||||||
#include "MipsTargetMachine.h"
|
#include "MipsTargetMachine.h"
|
||||||
@ -135,20 +136,24 @@ SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TargetExternalSymbol and TargetGlobalAddress are
|
// on PIC code Load GA
|
||||||
// lowered and their addresses go into registers, so
|
if (TM.getRelocationModel() == Reloc::PIC_) {
|
||||||
// they should not be touched here.
|
if (Addr.getOpcode() == ISD::TargetGlobalAddress) {
|
||||||
|
Base = CurDAG->getRegister(Mips::GP, MVT::i32);
|
||||||
|
Offset = Addr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
|
if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
|
||||||
Addr.getOpcode() == ISD::TargetGlobalAddress))
|
Addr.getOpcode() == ISD::TargetGlobalAddress))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Operand is a result from an ADD.
|
// Operand is a result from an ADD.
|
||||||
if (Addr.getOpcode() == ISD::ADD)
|
if (Addr.getOpcode() == ISD::ADD) {
|
||||||
{
|
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
|
||||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
|
if (Predicate_immSExt16(CN)) {
|
||||||
{
|
|
||||||
if (Predicate_immSExt16(CN))
|
|
||||||
{
|
|
||||||
// If the first operand is a FI, get the TargetFI Node
|
// If the first operand is a FI, get the TargetFI Node
|
||||||
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
|
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
|
||||||
(Addr.getOperand(0))) {
|
(Addr.getOperand(0))) {
|
||||||
@ -247,6 +252,51 @@ Select(SDOperand N)
|
|||||||
SDOperand MFInFlag = SDOperand(RemNode, 0);
|
SDOperand MFInFlag = SDOperand(RemNode, 0);
|
||||||
return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
|
return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle direct and indirect calls when using PIC. On PIC, when
|
||||||
|
/// GOT is smaller than about 64k (small code) the GA target is
|
||||||
|
/// loaded with only one instruction. Otherwise GA's target must
|
||||||
|
/// be loaded with 3 instructions.
|
||||||
|
case MipsISD::JmpLink: {
|
||||||
|
if (TM.getRelocationModel() == Reloc::PIC_) {
|
||||||
|
//bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large);
|
||||||
|
SDOperand Chain = Node->getOperand(0);
|
||||||
|
SDOperand Callee = Node->getOperand(1);
|
||||||
|
AddToISelQueue(Chain);
|
||||||
|
SDOperand T9Reg = CurDAG->getRegister(Mips::T9, MVT::i32);
|
||||||
|
SDOperand InFlag(0, 0);
|
||||||
|
|
||||||
|
if ( (isa<GlobalAddressSDNode>(Callee)) ||
|
||||||
|
(isa<ExternalSymbolSDNode>(Callee)) )
|
||||||
|
{
|
||||||
|
/// Direct call for global addresses and external symbols
|
||||||
|
SDOperand GPReg = CurDAG->getRegister(Mips::GP, MVT::i32);
|
||||||
|
|
||||||
|
// Use load to get GOT target
|
||||||
|
SDOperand Ops[] = { Callee, GPReg, Chain };
|
||||||
|
SDOperand Load = SDOperand(CurDAG->getTargetNode(Mips::LW, MVT::i32,
|
||||||
|
MVT::Other, Ops, 3), 0);
|
||||||
|
Chain = Load.getValue(1);
|
||||||
|
AddToISelQueue(Chain);
|
||||||
|
|
||||||
|
// Call target must be on T9
|
||||||
|
Chain = CurDAG->getCopyToReg(Chain, T9Reg, Load, InFlag);
|
||||||
|
} else
|
||||||
|
/// Indirect call
|
||||||
|
Chain = CurDAG->getCopyToReg(Chain, T9Reg, Callee, InFlag);
|
||||||
|
|
||||||
|
AddToISelQueue(Chain);
|
||||||
|
|
||||||
|
// Emit Jump and Link Register
|
||||||
|
SDNode *ResNode = CurDAG->getTargetNode(Mips::JALR, MVT::Other,
|
||||||
|
MVT::Flag, T9Reg, Chain);
|
||||||
|
Chain = SDOperand(ResNode, 0);
|
||||||
|
InFlag = SDOperand(ResNode, 1);
|
||||||
|
ReplaceUses(SDOperand(Node, 0), Chain);
|
||||||
|
ReplaceUses(SDOperand(Node, 1), InFlag);
|
||||||
|
return ResNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select the default instruction
|
// Select the default instruction
|
||||||
|
@ -43,8 +43,6 @@ getTargetNodeName(unsigned Opcode) const
|
|||||||
case MipsISD::Hi : return "MipsISD::Hi";
|
case MipsISD::Hi : return "MipsISD::Hi";
|
||||||
case MipsISD::Lo : return "MipsISD::Lo";
|
case MipsISD::Lo : return "MipsISD::Lo";
|
||||||
case MipsISD::Ret : return "MipsISD::Ret";
|
case MipsISD::Ret : return "MipsISD::Ret";
|
||||||
case MipsISD::Add : return "MipsISD::Add";
|
|
||||||
case MipsISD::LoadAddr : return "MipsISD::LoadAddr";
|
|
||||||
default : return NULL;
|
default : return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,21 +147,24 @@ LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG)
|
|||||||
{
|
{
|
||||||
SDOperand ResNode;
|
SDOperand ResNode;
|
||||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||||
|
|
||||||
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
|
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
|
||||||
|
bool isPIC = (getTargetMachine().getRelocationModel() == Reloc::PIC_);
|
||||||
|
|
||||||
// On PIC code global addresses are loaded with "la" instruction
|
SDOperand HiPart;
|
||||||
if (!(getTargetMachine().getRelocationModel() == Reloc::PIC_)) {
|
if (!isPIC) {
|
||||||
const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32, MVT::Flag);
|
const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32);
|
||||||
SDOperand Ops[] = { GA };
|
SDOperand Ops[] = { GA };
|
||||||
|
HiPart = DAG.getNode(MipsISD::Hi, VTs, 1, Ops, 1);
|
||||||
|
} else // Emit Load from Global Pointer
|
||||||
|
HiPart = DAG.getLoad(MVT::i32, DAG.getEntryNode(), GA, NULL, 0);
|
||||||
|
|
||||||
|
// On functions and global targets not internal linked only
|
||||||
|
// a load from got/GP is necessary for PIC to work.
|
||||||
|
if ((isPIC) && ((!GV->hasInternalLinkage()) || (isa<Function>(GV))))
|
||||||
|
return HiPart;
|
||||||
|
|
||||||
SDOperand Hi = DAG.getNode(MipsISD::Hi, VTs, 2, Ops, 1);
|
|
||||||
SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
|
SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
|
||||||
|
ResNode = DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo);
|
||||||
SDOperand InFlag = Hi.getValue(1);
|
|
||||||
ResNode = DAG.getNode(MipsISD::Add, MVT::i32, Lo, Hi, InFlag);
|
|
||||||
} else
|
|
||||||
ResNode = DAG.getNode(MipsISD::LoadAddr, MVT::i32, GA);
|
|
||||||
|
|
||||||
return ResNode;
|
return ResNode;
|
||||||
}
|
}
|
||||||
@ -211,7 +212,7 @@ LowerCALL(SDOperand Op, SelectionDAG &DAG)
|
|||||||
/// LowerCCCCallTo - functions arguments are copied from virtual
|
/// LowerCCCCallTo - functions arguments are copied from virtual
|
||||||
/// regs to (physical regs)/(stack frame), CALLSEQ_START and
|
/// regs to (physical regs)/(stack frame), CALLSEQ_START and
|
||||||
/// CALLSEQ_END are emitted.
|
/// CALLSEQ_END are emitted.
|
||||||
/// TODO: isVarArg, isTailCall, sret, GOT, linkage types.
|
/// TODO: isVarArg, isTailCall, sret.
|
||||||
SDOperand MipsTargetLowering::
|
SDOperand MipsTargetLowering::
|
||||||
LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
||||||
{
|
{
|
||||||
@ -244,7 +245,7 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
|||||||
SmallVector<SDOperand, 8> MemOpChains;
|
SmallVector<SDOperand, 8> MemOpChains;
|
||||||
|
|
||||||
SDOperand StackPtr;
|
SDOperand StackPtr;
|
||||||
unsigned LastStackLoc=0;
|
int LastStackLoc=0;
|
||||||
|
|
||||||
// Walk the register/memloc assignments, inserting copies/loads.
|
// Walk the register/memloc assignments, inserting copies/loads.
|
||||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
||||||
@ -268,8 +269,8 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arguments that can be passed on register,
|
// Arguments that can be passed on register must be kept at
|
||||||
// must be kept at RegsToPass vector
|
// RegsToPass vector
|
||||||
if (VA.isRegLoc()) {
|
if (VA.isRegLoc()) {
|
||||||
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
|
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
|
||||||
} else {
|
} else {
|
||||||
@ -294,14 +295,6 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a stack location to hold GP when PIC is used
|
|
||||||
if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
|
|
||||||
LastStackLoc = (!LastStackLoc) ? (16) : (LastStackLoc+4);
|
|
||||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
|
||||||
MFI->CreateFixedObject(4, LastStackLoc);
|
|
||||||
MipsFI->setGPStackOffset(LastStackLoc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform all store nodes into one single node because
|
// Transform all store nodes into one single node because
|
||||||
// all store nodes are independent of each other.
|
// all store nodes are independent of each other.
|
||||||
if (!MemOpChains.empty())
|
if (!MemOpChains.empty())
|
||||||
@ -321,13 +314,13 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
|||||||
|
|
||||||
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
|
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
|
||||||
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
|
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
|
||||||
// node so that legalize doesn't hack it. Otherwise we have an indirect call,
|
// node so that legalize doesn't hack it.
|
||||||
// if PIC is used, the call must use register GP
|
|
||||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
|
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
|
||||||
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
|
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
|
||||||
else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
|
else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
|
||||||
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
|
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
|
||||||
|
|
||||||
|
|
||||||
// MipsJmpLink = #chain, #target_address, #opt_in_flags...
|
// MipsJmpLink = #chain, #target_address, #opt_in_flags...
|
||||||
// = Chain, Callee, Reg#1, Reg#2, ...
|
// = Chain, Callee, Reg#1, Reg#2, ...
|
||||||
//
|
//
|
||||||
@ -349,6 +342,37 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
|||||||
Chain = DAG.getNode(MipsISD::JmpLink, NodeTys, &Ops[0], Ops.size());
|
Chain = DAG.getNode(MipsISD::JmpLink, NodeTys, &Ops[0], Ops.size());
|
||||||
InFlag = Chain.getValue(1);
|
InFlag = Chain.getValue(1);
|
||||||
|
|
||||||
|
// Create a stack location to hold GP when PIC is used. This stack
|
||||||
|
// location is used on function prologue to save GP and also after all
|
||||||
|
// emited CALL's to restore GP.
|
||||||
|
if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
|
||||||
|
|
||||||
|
// Function can have an arbitrary number of calls, so
|
||||||
|
// hold the LastStackLoc with the biggest offset.
|
||||||
|
int FI;
|
||||||
|
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
||||||
|
if (LastStackLoc >= MipsFI->getGPStackOffset()) {
|
||||||
|
|
||||||
|
LastStackLoc = (!LastStackLoc) ? (16) : (LastStackLoc+4);
|
||||||
|
// Create the frame index only once. SPOffset here can be anything
|
||||||
|
// (this will be fixed on processFunctionBeforeFrameFinalized)
|
||||||
|
if (MipsFI->getGPStackOffset() == -1) {
|
||||||
|
FI = MFI->CreateFixedObject(4, 0);
|
||||||
|
MipsFI->setGPFI(FI);
|
||||||
|
}
|
||||||
|
MipsFI->setGPStackOffset(LastStackLoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reload GP value.
|
||||||
|
FI = MipsFI->getGPFI();
|
||||||
|
SDOperand FIN = DAG.getFrameIndex(FI,getPointerTy());
|
||||||
|
SDOperand GPLoad = DAG.getLoad(MVT::i32, Chain, FIN, NULL, 0);
|
||||||
|
Chain = GPLoad.getValue(1);
|
||||||
|
Chain = DAG.getCopyToReg(Chain, DAG.getRegister(Mips::GP, MVT::i32),
|
||||||
|
GPLoad, SDOperand(0,0));
|
||||||
|
}
|
||||||
|
|
||||||
// Create the CALLSEQ_END node.
|
// Create the CALLSEQ_END node.
|
||||||
NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
|
NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
|
||||||
Ops.clear();
|
Ops.clear();
|
||||||
@ -389,8 +413,9 @@ LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall,
|
|||||||
ResultVals.push_back(Chain.getValue(0));
|
ResultVals.push_back(Chain.getValue(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge everything together with a MERGE_VALUES node.
|
|
||||||
ResultVals.push_back(Chain);
|
ResultVals.push_back(Chain);
|
||||||
|
|
||||||
|
// Merge everything together with a MERGE_VALUES node.
|
||||||
return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(),
|
return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(),
|
||||||
&ResultVals[0], ResultVals.size()).Val;
|
&ResultVals[0], ResultVals.size()).Val;
|
||||||
}
|
}
|
||||||
|
@ -38,13 +38,7 @@ namespace llvm {
|
|||||||
Lo,
|
Lo,
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
Ret,
|
Ret
|
||||||
|
|
||||||
// Need to support addition with a input flag
|
|
||||||
Add,
|
|
||||||
|
|
||||||
// Used on PIC Code to load global addresses
|
|
||||||
LoadAddr
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,21 +22,12 @@ def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
|
|||||||
def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
|
def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
|
||||||
SDNPOutFlag]>;
|
SDNPOutFlag]>;
|
||||||
|
|
||||||
// Hi and Lo nodes are created to let easy manipulation of 16-bit when
|
// Hi and Lo nodes are used to handle global addresses. Used on
|
||||||
// handling 32-bit immediates. They are used on MipsISelLowering to
|
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
|
||||||
// lower stuff like GlobalAddress, ExternalSymbol, ... on static model
|
// static model. (nothing to do with Mips Registers Hi and Lo)
|
||||||
// This two nodes have nothing to do with Mips Registers Hi and Lo.
|
|
||||||
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
|
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
|
||||||
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
|
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
|
||||||
|
|
||||||
// Necessary to generate glued instructions when loading GlobalAddress
|
|
||||||
// into registers.
|
|
||||||
def MipsAdd : SDNode<"MipsISD::Add", SDTIntBinOp, [SDNPCommutative,
|
|
||||||
SDNPAssociative, SDNPOptInFlag]>;
|
|
||||||
|
|
||||||
// Used to Load Addresses on PIC code.
|
|
||||||
def MipsLoadAddr: SDNode<"MipsISD::LoadAddr", SDTIntUnaryOp>;
|
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
||||||
def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain,
|
def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain,
|
||||||
@ -371,15 +362,9 @@ def IMPLICIT_DEF_CPURegs : PseudoInstMips<(outs CPURegs:$dst), (ins),
|
|||||||
// are used, we have the same behavior, but get also a bunch of warnings
|
// are used, we have the same behavior, but get also a bunch of warnings
|
||||||
// from the assembler.
|
// from the assembler.
|
||||||
def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg),
|
def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg),
|
||||||
".set noreorder\n\t.cpload $reg\n\t.set reorder", []>;
|
".set noreorder\n\t.cpload $reg\n\t.set reorder\n", []>;
|
||||||
def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc),
|
def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc),
|
||||||
".cprestore $loc", []>;
|
".cprestore $loc\n", []>;
|
||||||
|
|
||||||
// Used on PIC code only, it loads the address of label into register reg. The
|
|
||||||
// address is calculated from the global pointer ($gp) and is expanded by the
|
|
||||||
// assembler into two instructions "lw" and "addiu".
|
|
||||||
def LA: PseudoInstMips<(outs CPURegs:$dst), (ins addrlabel:$label),
|
|
||||||
"la $dst, $label", []>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Instruction definition
|
// Instruction definition
|
||||||
@ -393,17 +378,13 @@ def LA: PseudoInstMips<(outs CPURegs:$dst), (ins addrlabel:$label),
|
|||||||
|
|
||||||
// ADDiu just accept 16-bit immediates but we handle this on Pat's.
|
// ADDiu just accept 16-bit immediates but we handle this on Pat's.
|
||||||
// immZExt32 is used here so it can match GlobalAddress immediates.
|
// immZExt32 is used here so it can match GlobalAddress immediates.
|
||||||
def ADDiu : ArithI<0x09, "addiu", MipsAdd, uimm16, immZExt16>;
|
def ADDiu : ArithI<0x09, "addiu", add, uimm16, immZExt16>;
|
||||||
def ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>;
|
def ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>;
|
||||||
def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>;
|
def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>;
|
||||||
def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>;
|
def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>;
|
||||||
def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>;
|
def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>;
|
||||||
def ADD : ArithOverflowR<0x00, 0x20, "add">;
|
def ADD : ArithOverflowR<0x00, 0x20, "add">;
|
||||||
def SUB : ArithOverflowR<0x00, 0x22, "sub">;
|
def SUB : ArithOverflowR<0x00, 0x22, "sub">;
|
||||||
def MADD : MArithR<0x00, "madd">;
|
|
||||||
def MADDU : MArithR<0x01, "maddu">;
|
|
||||||
def MSUB : MArithR<0x04, "msub">;
|
|
||||||
def MSUBU : MArithR<0x05, "msubu">;
|
|
||||||
|
|
||||||
// Logical
|
// Logical
|
||||||
def AND : LogicR<0x24, "and", and>;
|
def AND : LogicR<0x24, "and", and>;
|
||||||
@ -485,6 +466,12 @@ def MTLO : MoveFromTo<0x13, "mtlo">;
|
|||||||
//def CLO : CountLeading<0x21, "clo">;
|
//def CLO : CountLeading<0x21, "clo">;
|
||||||
//def CLZ : CountLeading<0x20, "clz">;
|
//def CLZ : CountLeading<0x20, "clz">;
|
||||||
|
|
||||||
|
// MADD*/MSUB* are not part of MipsI either.
|
||||||
|
//def MADD : MArithR<0x00, "madd">;
|
||||||
|
//def MADDU : MArithR<0x01, "maddu">;
|
||||||
|
//def MSUB : MArithR<0x04, "msub">;
|
||||||
|
//def MSUBU : MArithR<0x05, "msubu">;
|
||||||
|
|
||||||
// No operation
|
// No operation
|
||||||
let addr=0 in
|
let addr=0 in
|
||||||
def NOP : FJ<0, (outs), (ins), "nop", [], IIAlu>;
|
def NOP : FJ<0, (outs), (ins), "nop", [], IIAlu>;
|
||||||
@ -529,9 +516,8 @@ def : Pat<(MipsJmpLink CPURegs:$dst),
|
|||||||
// GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable
|
// GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable
|
||||||
def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
|
def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
|
||||||
def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
|
def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
|
||||||
def : Pat<(MipsAdd CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
|
def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
|
||||||
(ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
|
(ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
|
||||||
def : Pat<(MipsLoadAddr tglobaladdr:$in), (LA tglobaladdr:$in)>;
|
|
||||||
|
|
||||||
// Mips does not have not, so we increase the operation
|
// Mips does not have not, so we increase the operation
|
||||||
def : Pat<(not CPURegs:$in),
|
def : Pat<(not CPURegs:$in),
|
||||||
@ -544,6 +530,9 @@ def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
|
|||||||
def : Pat<(truncstorei1 CPURegs:$src, addr:$addr),
|
def : Pat<(truncstorei1 CPURegs:$src, addr:$addr),
|
||||||
(SB CPURegs:$src, addr:$addr)>;
|
(SB CPURegs:$src, addr:$addr)>;
|
||||||
|
|
||||||
|
// some peepholes
|
||||||
|
def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// brcond patterns
|
/// brcond patterns
|
||||||
///
|
///
|
||||||
|
@ -33,11 +33,6 @@ private:
|
|||||||
/// the Return Address must be saved
|
/// the Return Address must be saved
|
||||||
int RAStackOffset;
|
int RAStackOffset;
|
||||||
|
|
||||||
/// When PIC is used the GP must be saved on the stack
|
|
||||||
/// on the function prologue, so a reference to its stack
|
|
||||||
/// location must be kept.
|
|
||||||
int GPStackOffset;
|
|
||||||
|
|
||||||
/// MipsFIHolder - Holds a FrameIndex and it's Stack Pointer Offset
|
/// MipsFIHolder - Holds a FrameIndex and it's Stack Pointer Offset
|
||||||
struct MipsFIHolder {
|
struct MipsFIHolder {
|
||||||
|
|
||||||
@ -48,6 +43,13 @@ private:
|
|||||||
: FI(FrameIndex), SPOffset(StackPointerOffset) {}
|
: FI(FrameIndex), SPOffset(StackPointerOffset) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// When PIC is used the GP must be saved on the stack
|
||||||
|
/// on the function prologue and must be reloaded from this
|
||||||
|
/// stack location after every call. A reference to its stack
|
||||||
|
/// location and frame index must be kept to be used on
|
||||||
|
/// emitPrologue and processFunctionBeforeFrameFinalized.
|
||||||
|
MipsFIHolder GPHolder;
|
||||||
|
|
||||||
// On LowerFORMAL_ARGUMENTS the stack size is unknown,
|
// On LowerFORMAL_ARGUMENTS the stack size is unknown,
|
||||||
// so the Stack Pointer Offset calculation of "not in
|
// so the Stack Pointer Offset calculation of "not in
|
||||||
// register arguments" must be postponed to emitPrologue.
|
// register arguments" must be postponed to emitPrologue.
|
||||||
@ -64,7 +66,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
MipsFunctionInfo(MachineFunction& MF)
|
MipsFunctionInfo(MachineFunction& MF)
|
||||||
: FPStackOffset(0), RAStackOffset(0),
|
: FPStackOffset(0), RAStackOffset(0), GPHolder(-1,-1),
|
||||||
HasLoadArgs(false), HasStoreVarArgs(false)
|
HasLoadArgs(false), HasStoreVarArgs(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -74,8 +76,10 @@ public:
|
|||||||
int getRAStackOffset() const { return RAStackOffset; }
|
int getRAStackOffset() const { return RAStackOffset; }
|
||||||
void setRAStackOffset(int Off) { RAStackOffset = Off; }
|
void setRAStackOffset(int Off) { RAStackOffset = Off; }
|
||||||
|
|
||||||
int getGPStackOffset() const { return GPStackOffset; }
|
int getGPStackOffset() const { return GPHolder.SPOffset; }
|
||||||
void setGPStackOffset(int Off) { GPStackOffset = Off; }
|
int getGPFI() const { return GPHolder.FI; }
|
||||||
|
void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; }
|
||||||
|
void setGPFI(int FI) { GPHolder.FI = FI; }
|
||||||
|
|
||||||
int getTopSavedRegOffset() const {
|
int getTopSavedRegOffset() const {
|
||||||
return (RAStackOffset > FPStackOffset) ?
|
return (RAStackOffset > FPStackOffset) ?
|
||||||
|
@ -203,6 +203,12 @@ foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const
|
|||||||
return NewMI;
|
return NewMI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MachineInstr *MipsRegisterInfo::
|
||||||
|
foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
||||||
|
MachineInstr* LoadMI) const {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// Callee Saved Registers methods
|
// Callee Saved Registers methods
|
||||||
@ -359,7 +365,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
MI.getOperand(i-1).ChangeToImmediate(Offset);
|
MI.getOperand(i-1).ChangeToImmediate(Offset);
|
||||||
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF),false);
|
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MipsRegisterInfo::
|
void MipsRegisterInfo::
|
||||||
@ -453,7 +459,6 @@ emitPrologue(MachineFunction &MF) const
|
|||||||
if ((isPIC) && (MFI->hasCalls()))
|
if ((isPIC) && (MFI->hasCalls()))
|
||||||
BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE))
|
BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE))
|
||||||
.addImm(MipsFI->getGPStackOffset());
|
.addImm(MipsFI->getGPStackOffset());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MipsRegisterInfo::
|
void MipsRegisterInfo::
|
||||||
@ -498,6 +503,17 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
|
|||||||
|
|
||||||
void MipsRegisterInfo::
|
void MipsRegisterInfo::
|
||||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
||||||
|
// Set the SPOffset on the FI where GP must be saved/loaded.
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
if (MFI->hasCalls()) {
|
||||||
|
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
||||||
|
#ifndef NDEBUG
|
||||||
|
DOUT << "processFunctionBeforeFrameFinalized\n";
|
||||||
|
DOUT << "GPOffset :" << MipsFI->getGPStackOffset() << "\n";
|
||||||
|
DOUT << "FI :" << MipsFI->getGPFI() << "\n";
|
||||||
|
#endif
|
||||||
|
MFI->setObjectOffset(MipsFI->getGPFI(), MipsFI->getGPStackOffset());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned MipsRegisterInfo::
|
unsigned MipsRegisterInfo::
|
||||||
|
@ -59,9 +59,7 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo {
|
|||||||
int FrameIndex) const;
|
int FrameIndex) const;
|
||||||
|
|
||||||
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
||||||
MachineInstr* LoadMI) const {
|
MachineInstr* LoadMI) const;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||||
unsigned DestReg, unsigned SrcReg,
|
unsigned DestReg, unsigned SrcReg,
|
||||||
|
@ -35,6 +35,9 @@ createTargetAsmInfo() const
|
|||||||
// On function prologue, the stack is created by decrementing
|
// On function prologue, the stack is created by decrementing
|
||||||
// its pointer. Once decremented, all references are done with positive
|
// its pointer. Once decremented, all references are done with positive
|
||||||
// offset from the stack/frame pointer, so StackGrowsUp is used.
|
// offset from the stack/frame pointer, so StackGrowsUp is used.
|
||||||
|
// When using CodeModel::Large the behaviour
|
||||||
|
//
|
||||||
|
//
|
||||||
MipsTargetMachine::
|
MipsTargetMachine::
|
||||||
MipsTargetMachine(const Module &M, const std::string &FS):
|
MipsTargetMachine(const Module &M, const std::string &FS):
|
||||||
Subtarget(*this, M, FS), DataLayout("E-p:32:32:32"),
|
Subtarget(*this, M, FS), DataLayout("E-p:32:32:32"),
|
||||||
@ -43,6 +46,8 @@ MipsTargetMachine(const Module &M, const std::string &FS):
|
|||||||
{
|
{
|
||||||
if (getRelocationModel() != Reloc::Static)
|
if (getRelocationModel() != Reloc::Static)
|
||||||
setRelocationModel(Reloc::PIC_);
|
setRelocationModel(Reloc::PIC_);
|
||||||
|
if (getCodeModel() == CodeModel::Default)
|
||||||
|
setCodeModel(CodeModel::Small);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return 0 and must specify -march to gen MIPS code.
|
// return 0 and must specify -march to gen MIPS code.
|
||||||
|
Loading…
Reference in New Issue
Block a user