aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Mips
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2010-02-16 09:30:23 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2010-02-16 09:30:23 +0000
commit6fe5c7aa327e188b7176daa5595bbf075a6b94df (patch)
tree4cfca640904d1896e25032757a61f8959c066919 /lib/Target/Mips
parent989df958a10f0beb90b89ccadd8351cbe51d90b1 (diff)
Notes
Diffstat (limited to 'lib/Target/Mips')
-rw-r--r--lib/Target/Mips/AsmPrinter/Makefile1
-rw-r--r--lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp134
-rw-r--r--lib/Target/Mips/Makefile1
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp7
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp210
-rw-r--r--lib/Target/Mips/MipsISelLowering.h5
-rw-r--r--lib/Target/Mips/MipsInstrFPU.td6
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td2
-rw-r--r--lib/Target/Mips/MipsMCAsmInfo.cpp4
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp28
-rw-r--r--lib/Target/Mips/MipsTargetObjectFile.h2
-rw-r--r--lib/Target/Mips/TargetInfo/Makefile1
12 files changed, 225 insertions, 176 deletions
diff --git a/lib/Target/Mips/AsmPrinter/Makefile b/lib/Target/Mips/AsmPrinter/Makefile
index aed801e5668b..a2fecf44e8e1 100644
--- a/lib/Target/Mips/AsmPrinter/Makefile
+++ b/lib/Target/Mips/AsmPrinter/Makefile
@@ -9,7 +9,6 @@
LEVEL = ../../../..
LIBRARYNAME = LLVMMipsAsmPrinter
-CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' Mips target directory to grab
# private headers
diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
index 9af9bd8b4e7f..b8641c309762 100644
--- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
@@ -37,7 +37,6 @@
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/CommandLine.h"
@@ -46,15 +45,14 @@
#include <cctype>
using namespace llvm;
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
namespace {
class MipsAsmPrinter : public AsmPrinter {
const MipsSubtarget *Subtarget;
public:
explicit MipsAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
- const MCAsmInfo *T, bool V)
- : AsmPrinter(O, TM, T, V) {
+ MCContext &Ctx, MCStreamer &Streamer,
+ const MCAsmInfo *T)
+ : AsmPrinter(O, TM, Ctx, Streamer, T) {
Subtarget = &TM.getSubtarget<MipsSubtarget>();
}
@@ -70,18 +68,22 @@ namespace {
const char *Modifier = 0);
void printFCCOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
- void printSavedRegsBitmask(MachineFunction &MF);
+ void printSavedRegsBitmask();
void printHex32(unsigned int Value);
const char *emitCurrentABIString();
- void emitFunctionStart(MachineFunction &MF);
- void emitFunctionEnd(MachineFunction &MF);
- void emitFrameDirective(MachineFunction &MF);
+ void emitFrameDirective();
void printInstruction(const MachineInstr *MI); // autogenerated.
+ void EmitInstruction(const MachineInstr *MI) {
+ printInstruction(MI);
+ OutStreamer.AddBlankLine();
+ }
+ virtual void EmitFunctionBodyStart();
+ virtual void EmitFunctionBodyEnd();
static const char *getRegisterName(unsigned RegNo);
- bool runOnMachineFunction(MachineFunction &F);
+ virtual void EmitFunctionEntryLabel();
void EmitStartOfAsmFile(Module &M);
};
} // end of anonymous namespace
@@ -125,18 +127,16 @@ namespace {
// Create a bitmask with all callee saved registers for CPU or Floating Point
// registers. For CPU registers consider RA, GP and FP for saving if necessary.
-void MipsAsmPrinter::
-printSavedRegsBitmask(MachineFunction &MF)
-{
+void MipsAsmPrinter::printSavedRegsBitmask() {
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
- MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
+ const MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>();
// CPU and FPU Saved Registers Bitmasks
unsigned int CPUBitmask = 0;
unsigned int FPUBitmask = 0;
// Set the CPU and FPU Bitmasks
- MachineFrameInfo *MFI = MF.getFrameInfo();
+ const MachineFrameInfo *MFI = MF->getFrameInfo();
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(CSI[i].getReg());
@@ -147,11 +147,11 @@ printSavedRegsBitmask(MachineFunction &MF)
}
// Return Address and Frame registers must also be set in CPUBitmask.
- if (RI.hasFP(MF))
+ if (RI.hasFP(*MF))
CPUBitmask |= (1 << MipsRegisterInfo::
- getRegisterNumbering(RI.getFrameRegister(MF)));
+ getRegisterNumbering(RI.getFrameRegister(*MF)));
- if (MF.getFrameInfo()->hasCalls())
+ if (MFI->hasCalls())
CPUBitmask |= (1 << MipsRegisterInfo::
getRegisterNumbering(RI.getRARegister()));
@@ -178,12 +178,12 @@ printHex32(unsigned int Value)
//===----------------------------------------------------------------------===//
/// Frame Directive
-void MipsAsmPrinter::emitFrameDirective(MachineFunction &MF) {
+void MipsAsmPrinter::emitFrameDirective() {
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
- unsigned stackReg = RI.getFrameRegister(MF);
+ unsigned stackReg = RI.getFrameRegister(*MF);
unsigned returnReg = RI.getRARegister();
- unsigned stackSize = MF.getFrameInfo()->getStackSize();
+ unsigned stackSize = MF->getFrameInfo()->getStackSize();
O << "\t.frame\t" << '$' << LowercaseString(getRegisterName(stackReg))
@@ -207,96 +207,30 @@ const char *MipsAsmPrinter::emitCurrentABIString() {
return NULL;
}
-/// Emit the directives used by GAS on the start of functions
-void MipsAsmPrinter::emitFunctionStart(MachineFunction &MF) {
- // Print out the label for the function.
- const Function *F = MF.getFunction();
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
-
- // 2 bits aligned
- EmitAlignment(MF.getAlignment(), F);
-
- O << "\t.globl\t" << *CurrentFnSym << '\n';
+void MipsAsmPrinter::EmitFunctionEntryLabel() {
O << "\t.ent\t" << *CurrentFnSym << '\n';
+ OutStreamer.EmitLabel(CurrentFnSym);
+}
- printVisibility(CurrentFnSym, F->getVisibility());
-
- if ((MAI->hasDotTypeDotSizeDirective()) && Subtarget->isLinux())
- O << "\t.type\t" << *CurrentFnSym << ", @function\n";
-
- O << *CurrentFnSym << ":\n";
-
- emitFrameDirective(MF);
- printSavedRegsBitmask(MF);
-
- O << '\n';
+/// EmitFunctionBodyStart - Targets can override this to emit stuff before
+/// the first basic block in the function.
+void MipsAsmPrinter::EmitFunctionBodyStart() {
+ emitFrameDirective();
+ printSavedRegsBitmask();
}
-/// Emit the directives used by GAS on the end of functions
-void MipsAsmPrinter::emitFunctionEnd(MachineFunction &MF) {
+/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
+/// the last basic block in the function.
+void MipsAsmPrinter::EmitFunctionBodyEnd() {
// There are instruction for this macros, but they must
// always be at the function end, and we can't emit and
// break with BB logic.
O << "\t.set\tmacro\n";
O << "\t.set\treorder\n";
-
+
O << "\t.end\t" << *CurrentFnSym << '\n';
- if (MAI->hasDotTypeDotSizeDirective() && !Subtarget->isLinux())
- O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
}
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
-bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- this->MF = &MF;
-
- SetupMachineFunction(MF);
-
- // Print out constants referenced by the function
- EmitConstantPool(MF.getConstantPool());
-
- // Print out jump tables referenced by the function
- EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
-
- O << "\n\n";
-
- // Emit the function start directives
- emitFunctionStart(MF);
-
- // Print out code for the function.
- for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
- I != E; ++I) {
-
- // Print a label for the basic block.
- if (I != MF.begin()) {
- EmitBasicBlockStart(I);
- }
-
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II) {
- processDebugLoc(II, true);
-
- // Print the assembly for the instruction.
- printInstruction(II);
-
- if (VerboseAsm)
- EmitComments(*II);
- O << '\n';
-
- processDebugLoc(II, false);
- ++EmittedInsts;
- }
-
- // Each Basic Block is separated by a newline
- O << '\n';
- }
-
- // Emit function end directives
- emitFunctionEnd(MF);
-
- // We didn't modify anything.
- return false;
-}
// Print out an operand for an inline asm expression.
bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@@ -343,7 +277,7 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
break;
case MachineOperand::MO_MachineBasicBlock:
- O << *GetMBBSymbol(MO.getMBB()->getNumber());
+ O << *MO.getMBB()->getSymbol(OutContext);
return;
case MachineOperand::MO_GlobalAddress:
diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile
index 4e4d87439ab2..2ed8d77b85b2 100644
--- a/lib/Target/Mips/Makefile
+++ b/lib/Target/Mips/Makefile
@@ -10,7 +10,6 @@
LEVEL = ../../..
LIBRARYNAME = LLVMMipsCodeGen
TARGET = Mips
-CXXFLAGS = -fno-rtti
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index e3a45d2ed49b..f1d4a67c81a2 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -245,7 +245,7 @@ SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) {
// lwc $f1, X+4($3)
SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32,
MVT::Other, Offset0, Base, Chain);
- SDValue Undef = SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF,
+ SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
dl, NVT), 0);
SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::SUBREG_FPEVEN, dl,
MVT::f64, Undef, SDValue(LD0, 0));
@@ -426,7 +426,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
SDValue InFlag = SDValue(MulNode, 0);
- if (MulOp == ISD::MUL)
+ if (Opcode == ISD::MUL)
return CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, InFlag);
else
return CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag);
@@ -464,8 +464,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
Mips::ZERO, MVT::i32);
SDValue Undef = SDValue(
- CurDAG->getMachineNode(
- TargetInstrInfo::IMPLICIT_DEF, dl, MVT::f64), 0);
+ CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::f64), 0);
SDNode *MTC = CurDAG->getMachineNode(Mips::MTC1, dl, MVT::f32, Zero);
SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::SUBREG_FPEVEN, dl,
MVT::f64, Undef, SDValue(MTC, 0));
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index ced8b939336e..584b8875eef7 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -60,9 +60,6 @@ MipsTargetLowering(MipsTargetMachine &TM)
// setcc operations results (slt, sgt, ...).
setBooleanContents(ZeroOrOneBooleanContent);
- // JumpTable targets must use GOT when using PIC_
- setUsesGlobalOffsetTable(true);
-
// Set up the register classes
addRegisterClass(MVT::i32, Mips::CPURegsRegisterClass);
addRegisterClass(MVT::f32, Mips::FGR32RegisterClass);
@@ -100,6 +97,8 @@ MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::BRCOND, MVT::Other, Custom);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
+ setOperationAction(ISD::VASTART, MVT::Other, Custom);
+
// We custom lower AND/OR to handle the case where the DAG contain 'ands/ors'
// with operands comming from setcc fp comparions. This is necessary since
@@ -182,6 +181,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG)
case ISD::OR: return LowerANDOR(Op, DAG);
case ISD::SELECT: return LowerSELECT(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
+ case ISD::VASTART: return LowerVASTART(Op, DAG);
}
return SDValue();
}
@@ -510,7 +510,8 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) {
SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32, 0,
MipsII::MO_GOT);
SDValue ResNode = DAG.getLoad(MVT::i32, dl,
- DAG.getEntryNode(), GA, NULL, 0);
+ DAG.getEntryNode(), GA, NULL, 0,
+ false, false, 0);
// On functions and global targets not internal linked only
// a load from got/GP is necessary for PIC to work.
if (!GV->hasLocalLinkage() || isa<Function>(GV))
@@ -549,7 +550,8 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG)
SDValue Ops[] = { JTI };
HiPart = DAG.getNode(MipsISD::Hi, dl, DAG.getVTList(MVT::i32), Ops, 1);
} else // Emit Load from Global Pointer
- HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, NULL, 0);
+ HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, NULL, 0,
+ false, false, 0);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, JTI);
ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo);
@@ -586,7 +588,7 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG)
SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(),
N->getOffset(), MipsII::MO_GOT);
SDValue Load = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(),
- CP, NULL, 0);
+ CP, NULL, 0, false, false, 0);
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CP);
ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, Load, Lo);
}
@@ -594,6 +596,17 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG)
return ResNode;
}
+SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) {
+ DebugLoc dl = Op.getDebugLoc();
+ SDValue FI = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy());
+
+ // vastart just stores the address of the VarArgsFrameIndex slot into the
+ // memory location argument.
+ const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+ return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0,
+ false, false, 0);
+}
+
//===----------------------------------------------------------------------===//
// Calling Convention Implementation
//===----------------------------------------------------------------------===//
@@ -679,21 +692,86 @@ static bool CC_MipsO32(unsigned ValNo, EVT ValVT,
return false; // CC must always match
}
+static bool CC_MipsO32_VarArgs(unsigned ValNo, EVT ValVT,
+ EVT LocVT, CCValAssign::LocInfo LocInfo,
+ ISD::ArgFlagsTy ArgFlags, CCState &State) {
+
+ static const unsigned IntRegsSize=4;
+
+ static const unsigned IntRegs[] = {
+ Mips::A0, Mips::A1, Mips::A2, Mips::A3
+ };
+
+ // Promote i8 and i16
+ if (LocVT == MVT::i8 || LocVT == MVT::i16) {
+ LocVT = MVT::i32;
+ if (ArgFlags.isSExt())
+ LocInfo = CCValAssign::SExt;
+ else if (ArgFlags.isZExt())
+ LocInfo = CCValAssign::ZExt;
+ else
+ LocInfo = CCValAssign::AExt;
+ }
+
+ if (ValVT == MVT::i32 || ValVT == MVT::f32) {
+ if (unsigned Reg = State.AllocateReg(IntRegs, IntRegsSize)) {
+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, MVT::i32, LocInfo));
+ return false;
+ }
+ unsigned Off = State.AllocateStack(4, 4);
+ State.addLoc(CCValAssign::getMem(ValNo, ValVT, Off, LocVT, LocInfo));
+ return false;
+ }
+
+ unsigned UnallocIntReg = State.getFirstUnallocated(IntRegs, IntRegsSize);
+ if (ValVT == MVT::f64) {
+ if (IntRegs[UnallocIntReg] == (unsigned (Mips::A1))) {
+ // A1 can't be used anymore, because 64 bit arguments
+ // must be aligned when copied back to the caller stack
+ State.AllocateReg(IntRegs, IntRegsSize);
+ UnallocIntReg++;
+ }
+
+ if (IntRegs[UnallocIntReg] == (unsigned (Mips::A0)) ||
+ IntRegs[UnallocIntReg] == (unsigned (Mips::A2))) {
+ unsigned Reg = State.AllocateReg(IntRegs, IntRegsSize);
+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, MVT::i32, LocInfo));
+ // Shadow the next register so it can be used
+ // later to get the other 32bit part.
+ State.AllocateReg(IntRegs, IntRegsSize);
+ return false;
+ }
+
+ // Register is shadowed to preserve alignment, and the
+ // argument goes to a stack location.
+ if (UnallocIntReg != IntRegsSize)
+ State.AllocateReg(IntRegs, IntRegsSize);
+
+ unsigned Off = State.AllocateStack(8, 8);
+ State.addLoc(CCValAssign::getMem(ValNo, ValVT, Off, LocVT, LocInfo));
+ return false;
+ }
+
+ return true; // CC didn't match
+}
+
//===----------------------------------------------------------------------===//
// Call Calling Convention Implementation
//===----------------------------------------------------------------------===//
/// LowerCall - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
-/// TODO: isVarArg, isTailCall.
+/// TODO: isTailCall.
SDValue
MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
CallingConv::ID CallConv, bool isVarArg,
- bool isTailCall,
+ bool &isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) {
+ // MIPs target does not yet support tail call optimization.
+ isTailCall = false;
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
@@ -709,7 +787,8 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
if (Subtarget->isABI_O32()) {
int VTsize = EVT(MVT::i32).getSizeInBits()/8;
MFI->CreateFixedObject(VTsize, (VTsize*3), true, false);
- CCInfo.AnalyzeCallOperands(Outs, CC_MipsO32);
+ CCInfo.AnalyzeCallOperands(Outs,
+ isVarArg ? CC_MipsO32_VarArgs : CC_MipsO32);
} else
CCInfo.AnalyzeCallOperands(Outs, CC_Mips);
@@ -783,7 +862,8 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
// emit ISD::STORE whichs stores the
// parameter value to a stack Location
- MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0));
+ MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0,
+ false, false, 0));
}
// Transform all store nodes into one single node because all store
@@ -835,11 +915,6 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
Chain = DAG.getNode(MipsISD::JmpLink, dl, NodeTys, &Ops[0], Ops.size());
InFlag = Chain.getValue(1);
- // Create the CALLSEQ_END node.
- Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
- DAG.getIntPtrConstant(0, true), InFlag);
- 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.
@@ -862,13 +937,19 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
// Reload GP value.
FI = MipsFI->getGPFI();
SDValue FIN = DAG.getFrameIndex(FI,getPointerTy());
- SDValue GPLoad = DAG.getLoad(MVT::i32, dl, Chain, FIN, NULL, 0);
+ SDValue GPLoad = DAG.getLoad(MVT::i32, dl, Chain, FIN, NULL, 0,
+ false, false, 0);
Chain = GPLoad.getValue(1);
Chain = DAG.getCopyToReg(Chain, dl, DAG.getRegister(Mips::GP, MVT::i32),
GPLoad, SDValue(0,0));
InFlag = Chain.getValue(1);
}
+ // Create the CALLSEQ_END node.
+ Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
+ DAG.getIntPtrConstant(0, true), InFlag);
+ InFlag = Chain.getValue(1);
+
// Handle result values, copying them out of physregs into vregs that we
// return.
return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
@@ -906,23 +987,28 @@ MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
// Formal Arguments Calling Convention Implementation
//===----------------------------------------------------------------------===//
-/// LowerFormalArguments - transform physical registers into
-/// virtual registers and generate load operations for
-/// arguments places on the stack.
-/// TODO: isVarArg
+/// LowerFormalArguments - transform physical registers into virtual registers
+/// and generate load operations for arguments places on the stack.
SDValue
MipsTargetLowering::LowerFormalArguments(SDValue Chain,
- CallingConv::ID CallConv, bool isVarArg,
- const SmallVectorImpl<ISD::InputArg>
- &Ins,
- DebugLoc dl, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals) {
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg>
+ &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF);
+ VarArgsFrameIndex = 0;
+
+ // Used with vargs to acumulate store chains.
+ std::vector<SDValue> OutChains;
+
+ // Keep track of the last register used for arguments
+ unsigned ArgRegEnd = 0;
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
@@ -930,7 +1016,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
ArgLocs, *DAG.getContext());
if (Subtarget->isABI_O32())
- CCInfo.AnalyzeFormalArguments(Ins, CC_MipsO32);
+ CCInfo.AnalyzeFormalArguments(Ins,
+ isVarArg ? CC_MipsO32_VarArgs : CC_MipsO32);
else
CCInfo.AnalyzeFormalArguments(Ins, CC_Mips);
@@ -944,6 +1031,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
// Arguments stored on registers
if (VA.isRegLoc()) {
EVT RegVT = VA.getLocVT();
+ ArgRegEnd = VA.getLocReg();
TargetRegisterClass *RC = 0;
if (RegVT == MVT::i32)
@@ -954,11 +1042,11 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
if (!Subtarget->isSingleFloat())
RC = Mips::AFGR64RegisterClass;
} else
- llvm_unreachable("RegVT not supported by LowerFormalArguments Lowering");
+ llvm_unreachable("RegVT not supported by FormalArguments Lowering");
// Transform the arguments stored on
// physical registers into virtual ones
- unsigned Reg = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC);
+ unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegEnd, RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
// If this is an 8 or 16-bit value, it has been passed promoted
@@ -991,34 +1079,13 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
}
InVals.push_back(ArgValue);
-
- // To meet ABI, when VARARGS are passed on registers, the registers
- // must have their values written to the caller stack frame.
- if ((isVarArg) && (Subtarget->isABI_O32())) {
- if (StackPtr.getNode() == 0)
- StackPtr = DAG.getRegister(StackReg, getPointerTy());
-
- // The stack pointer offset is relative to the caller stack frame.
- // Since the real stack size is unknown here, a negative SPOffset
- // is used so there's a way to adjust these offsets when the stack
- // size get known (on EliminateFrameIndex). A dummy SPOffset is
- // used instead of a direct negative address (which is recorded to
- // be used on emitPrologue) to avoid mis-calc of the first stack
- // offset on PEI::calculateFrameObjectOffsets.
- // Arguments are always 32-bit.
- int FI = MFI->CreateFixedObject(4, 0, true, false);
- MipsFI->recordStoreVarArgsFI(FI, -(4+(i*4)));
- SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy());
-
- // emit ISD::STORE whichs stores the
- // parameter value to a stack Location
- InVals.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0));
- }
-
} else { // VA.isRegLoc()
// sanity check
assert(VA.isMemLoc());
+
+ // The last argument is not a register anymore
+ ArgRegEnd = 0;
// The stack pointer offset is relative to the caller stack frame.
// Since the real stack size is unknown here, a negative SPOffset
@@ -1035,7 +1102,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
// Create load nodes to retrieve arguments from the stack
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
- InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0));
+ InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0,
+ false, false, 0));
}
}
@@ -1052,6 +1120,42 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
}
+ // To meet ABI, when VARARGS are passed on registers, the registers
+ // must have their values written to the caller stack frame. If the last
+ // argument was placed in the stack, there's no need to save any register.
+ if ((isVarArg) && (Subtarget->isABI_O32() && ArgRegEnd)) {
+ if (StackPtr.getNode() == 0)
+ StackPtr = DAG.getRegister(StackReg, getPointerTy());
+
+ // The last register argument that must be saved is Mips::A3
+ TargetRegisterClass *RC = Mips::CPURegsRegisterClass;
+ unsigned StackLoc = ArgLocs.size()-1;
+
+ for (++ArgRegEnd; ArgRegEnd <= Mips::A3; ++ArgRegEnd, ++StackLoc) {
+ unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegEnd, RC);
+ SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, MVT::i32);
+
+ int FI = MFI->CreateFixedObject(4, 0, true, false);
+ MipsFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4)));
+ SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy());
+ OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0,
+ false, false, 0));
+
+ // Record the frame index of the first variable argument
+ // which is a value necessary to VASTART.
+ if (!VarArgsFrameIndex)
+ VarArgsFrameIndex = FI;
+ }
+ }
+
+ // All stores are grouped in one node to allow the matching between
+ // the size of Ins and InVals. This only happens when on varg functions
+ if (!OutChains.empty()) {
+ OutChains.push_back(Chain);
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ &OutChains[0], OutChains.size());
+ }
+
return Chain;
}
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
index cacf4b59fcb7..7256617242fa 100644
--- a/lib/Target/Mips/MipsISelLowering.h
+++ b/lib/Target/Mips/MipsISelLowering.h
@@ -68,6 +68,8 @@ namespace llvm {
//===--------------------------------------------------------------------===//
class MipsTargetLowering : public TargetLowering {
+ int VarArgsFrameIndex; // FrameIndex for start of varargs area.
+
public:
explicit MipsTargetLowering(MipsTargetMachine &TM);
@@ -107,6 +109,7 @@ namespace llvm {
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);
SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG);
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG);
+ SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG);
virtual SDValue
LowerFormalArguments(SDValue Chain,
@@ -118,7 +121,7 @@ namespace llvm {
virtual SDValue
LowerCall(SDValue Chain, SDValue Callee,
CallingConv::ID CallConv, bool isVarArg,
- bool isTailCall,
+ bool &isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td
index ce89cfd7d747..fa4518d732f1 100644
--- a/lib/Target/Mips/MipsInstrFPU.td
+++ b/lib/Target/Mips/MipsInstrFPU.td
@@ -113,7 +113,6 @@ let ft = 0 in {
defm ROUND_W : FFR1_1<0b001100, "round.w">;
defm TRUNC_W : FFR1_1<0b001101, "trunc.w">;
defm CVTW : FFR1_1<0b100100, "cvt.w">;
- defm FMOV : FFR1_1<0b000110, "mov">;
defm FABS : FFR1_2<0b000101, "abs", fabs>;
defm FNEG : FFR1_2<0b000111, "neg", fneg>;
@@ -173,6 +172,11 @@ let fd = 0 in {
"mtc1 $rt, $fs", []>;
}
+def FMOV_S32 : FFR<0x11, 0b000110, 0x0, (outs FGR32:$fd), (ins FGR32:$fs),
+ "mov.s $fd, $fs", []>;
+def FMOV_D32 : FFR<0x11, 0b000110, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs),
+ "mov.d $fd, $fs", []>;
+
/// Floating Point Memory Instructions
let Predicates = [IsNotSingleFloat, IsNotMipsI] in {
def LDC1 : FFI<0b110101, (outs AFGR64:$ft), (ins mem:$addr),
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index e67bcbfc1771..f16a8053358d 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -120,7 +120,7 @@ def immZExt5 : PatLeaf<(imm), [{
// Mips Address Mode! SDNode frameindex could possibily be a match
// since load and store instructions from stack used it.
-def addr : ComplexPattern<i32, 2, "SelectAddr", [frameindex], []>;
+def addr : ComplexPattern<iPTR, 2, "SelectAddr", [frameindex], []>;
//===----------------------------------------------------------------------===//
// Instructions specific format
diff --git a/lib/Target/Mips/MipsMCAsmInfo.cpp b/lib/Target/Mips/MipsMCAsmInfo.cpp
index 60ef1c9e4fef..89e3e11b0a7c 100644
--- a/lib/Target/Mips/MipsMCAsmInfo.cpp
+++ b/lib/Target/Mips/MipsMCAsmInfo.cpp
@@ -16,12 +16,12 @@ using namespace llvm;
MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, const StringRef &TT) {
AlignmentIsInBytes = false;
- COMMDirectiveTakesAlignment = true;
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
Data64bitsDirective = 0;
PrivateGlobalPrefix = "$";
CommentString = "#";
ZeroDirective = "\t.space\t";
- PICJumpTableDirective = "\t.gpword\t";
+ GPRel32Directive = "\t.gpword\t";
+ HasSetDirective = false;
}
diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp
index 80fd9170f1f7..f923bedb1a5a 100644
--- a/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -223,6 +223,8 @@ void MipsRegisterInfo::adjustMipsStackFrame(MachineFunction &MF) const
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
unsigned StackAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
+ unsigned RegSize = Subtarget.isGP32bit() ? 4 : 8;
+ bool HasGP = MipsFI->needGPSaveRestore();
// Min and Max CSI FrameIndex.
int MinCSFI = -1, MaxCSFI = -1;
@@ -248,6 +250,9 @@ void MipsRegisterInfo::adjustMipsStackFrame(MachineFunction &MF) const
for (unsigned i = 0, e = CSI.size(); i != e; ++i)
CalleeSavedAreaSize += MFI->getObjectAlignment(CSI[i].getFrameIdx());
+ unsigned StackOffset = HasGP ? (MipsFI->getGPStackOffset()+RegSize)
+ : (Subtarget.isABI_O32() ? 16 : 0);
+
// Adjust local variables. They should come on the stack right
// after the arguments.
int LastOffsetFI = -1;
@@ -256,7 +261,8 @@ void MipsRegisterInfo::adjustMipsStackFrame(MachineFunction &MF) const
continue;
if (MFI->isDeadObjectIndex(i))
continue;
- unsigned Offset = MFI->getObjectOffset(i) - CalleeSavedAreaSize;
+ unsigned Offset =
+ StackOffset + MFI->getObjectOffset(i) - CalleeSavedAreaSize;
if (LastOffsetFI == -1)
LastOffsetFI = i;
if (Offset > MFI->getObjectOffset(LastOffsetFI))
@@ -265,11 +271,8 @@ void MipsRegisterInfo::adjustMipsStackFrame(MachineFunction &MF) const
}
// Adjust CPU Callee Saved Registers Area. Registers RA and FP must
- // be saved in this CPU Area there is the need. This whole Area must
- // be aligned to the default Stack Alignment requirements.
- unsigned StackOffset = 0;
- unsigned RegSize = Subtarget.isGP32bit() ? 4 : 8;
-
+ // be saved in this CPU Area. This whole area must be aligned to the
+ // default Stack Alignment requirements.
if (LastOffsetFI >= 0)
StackOffset = MFI->getObjectOffset(LastOffsetFI)+
MFI->getObjectSize(LastOffsetFI);
@@ -283,21 +286,26 @@ void MipsRegisterInfo::adjustMipsStackFrame(MachineFunction &MF) const
StackOffset += MFI->getObjectAlignment(CSI[i].getFrameIdx());
}
- if (hasFP(MF)) {
+ // Stack locations for FP and RA. If only one of them is used,
+ // the space must be allocated for both, otherwise no space at all.
+ if (hasFP(MF) || MFI->hasCalls()) {
+ // FP stack location
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
StackOffset);
MipsFI->setFPStackOffset(StackOffset);
TopCPUSavedRegOff = StackOffset;
StackOffset += RegSize;
- }
- if (MFI->hasCalls()) {
+ // SP stack location
MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true),
StackOffset);
MipsFI->setRAStackOffset(StackOffset);
- TopCPUSavedRegOff = StackOffset;
StackOffset += RegSize;
+
+ if (MFI->hasCalls())
+ TopCPUSavedRegOff += RegSize;
}
+
StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign);
// Adjust FPU Callee Saved Registers Area. This Area must be
diff --git a/lib/Target/Mips/MipsTargetObjectFile.h b/lib/Target/Mips/MipsTargetObjectFile.h
index 32e0436f0c97..237b1602cf3d 100644
--- a/lib/Target/Mips/MipsTargetObjectFile.h
+++ b/lib/Target/Mips/MipsTargetObjectFile.h
@@ -10,7 +10,7 @@
#ifndef LLVM_TARGET_MIPS_TARGETOBJECTFILE_H
#define LLVM_TARGET_MIPS_TARGETOBJECTFILE_H
-#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
namespace llvm {
diff --git a/lib/Target/Mips/TargetInfo/Makefile b/lib/Target/Mips/TargetInfo/Makefile
index f27d49e51302..32f4e1695b1d 100644
--- a/lib/Target/Mips/TargetInfo/Makefile
+++ b/lib/Target/Mips/TargetInfo/Makefile
@@ -8,7 +8,6 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMMipsInfo
-CXXFLAGS = -fno-rtti
# Hack: we need to include 'main' target directory to grab private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..