//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "mips-lower"
+//#include <algorithm>
#include "MipsISelLowering.h"
#include "MipsMachineFunction.h"
#include "MipsTargetMachine.h"
const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
- case MipsISD::JmpLink : return "MipsISD::JmpLink";
- case MipsISD::Hi : return "MipsISD::Hi";
- case MipsISD::Lo : return "MipsISD::Lo";
- case MipsISD::GPRel : return "MipsISD::GPRel";
- case MipsISD::Ret : return "MipsISD::Ret";
- case MipsISD::FPBrcond : return "MipsISD::FPBrcond";
- case MipsISD::FPCmp : return "MipsISD::FPCmp";
- case MipsISD::CMovFP_T : return "MipsISD::CMovFP_T";
- case MipsISD::CMovFP_F : return "MipsISD::CMovFP_F";
- case MipsISD::FPRound : return "MipsISD::FPRound";
- case MipsISD::MAdd : return "MipsISD::MAdd";
- case MipsISD::MAddu : return "MipsISD::MAddu";
- case MipsISD::MSub : return "MipsISD::MSub";
- case MipsISD::MSubu : return "MipsISD::MSubu";
- case MipsISD::DivRem : return "MipsISD::DivRem";
- case MipsISD::DivRemU : return "MipsISD::DivRemU";
- case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64";
- case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64";
- default : return NULL;
+ case MipsISD::JmpLink: return "MipsISD::JmpLink";
+ case MipsISD::Hi: return "MipsISD::Hi";
+ case MipsISD::Lo: return "MipsISD::Lo";
+ case MipsISD::GPRel: return "MipsISD::GPRel";
+ case MipsISD::Ret: return "MipsISD::Ret";
+ case MipsISD::FPBrcond: return "MipsISD::FPBrcond";
+ case MipsISD::FPCmp: return "MipsISD::FPCmp";
+ case MipsISD::CMovFP_T: return "MipsISD::CMovFP_T";
+ case MipsISD::CMovFP_F: return "MipsISD::CMovFP_F";
+ case MipsISD::FPRound: return "MipsISD::FPRound";
+ case MipsISD::MAdd: return "MipsISD::MAdd";
+ case MipsISD::MAddu: return "MipsISD::MAddu";
+ case MipsISD::MSub: return "MipsISD::MSub";
+ case MipsISD::MSubu: return "MipsISD::MSubu";
+ case MipsISD::DivRem: return "MipsISD::DivRem";
+ case MipsISD::DivRemU: return "MipsISD::DivRemU";
+ case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64";
+ case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64";
+ default: return NULL;
}
}
setOperationAction(ISD::FCOS, MVT::f64, Expand);
setOperationAction(ISD::FPOWI, MVT::f32, Expand);
setOperationAction(ISD::FPOW, MVT::f32, Expand);
+ setOperationAction(ISD::FPOW, MVT::f64, Expand);
setOperationAction(ISD::FLOG, MVT::f32, Expand);
setOperationAction(ISD::FLOG2, MVT::f32, Expand);
setOperationAction(ISD::FLOG10, MVT::f32, Expand);
// insert MFHI
if (N->hasAnyUseOfValue(1)) {
SDValue CopyFromHi = DAG.getCopyFromReg(InChain, dl,
- Mips::HI, MVT::i32, InGlue);
+ Mips::HI, MVT::i32, InGlue);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi);
}
CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs,
*DAG.getContext());
- if (Subtarget->isABI_O32()) {
+ if (Subtarget->isABI_O32())
CCInfo.AnalyzeCallOperands(Outs, CC_MipsO32);
- } else
+ else
CCInfo.AnalyzeCallOperands(Outs, CC_Mips);
// Get a count of how many bytes are to be pushed on the stack.
// With EABI is it possible to have 16 args on registers.
SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass;
SmallVector<SDValue, 8> MemOpChains;
- unsigned NextStackOffset = (Subtarget->isABI_EABI() ? 0 : 16);
MipsFI->setHasCall();
+ // Create GP frame object if this is the first call.
+ // SPOffset will be updated after call frame size is known.
+ if (IsPIC && !MipsFI->getGPFI())
+ MipsFI->setGPFI(MFI->CreateFixedObject(4, 0, true));
+
+ int FirstFI = -MFI->getNumFixedObjects() - 1, LastFI = 0;
+
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
SDValue Arg = OutVals[i];
// This guarantees that when allocating Local Area the firsts
// 16 bytes which are alwayes reserved won't be overwritten
// if O32 ABI is used. For EABI the first address is zero.
- NextStackOffset = VA.getLocMemOffset();
- int FI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8,
- NextStackOffset, true);
- NextStackOffset += VA.getValVT().getSizeInBits()/8;
-
- SDValue PtrOff = DAG.getFrameIndex(FI,getPointerTy());
+ LastFI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8,
+ VA.getLocMemOffset(), true);
+ SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy());
// emit ISD::STORE whichs stores the
// parameter value to a stack Location
// location is used on function prologue to save GP and also after all
// emitted CALL's to restore GP.
if (IsPIC) {
- // Function can have an arbitrary number of calls, so
- // hold the LastArgStackLoc with the biggest offset.
- int FI;
- int MaxCallFrameSize = MipsFI->getMaxCallFrameSize();
-
- if (MaxCallFrameSize < (int)NextStackOffset) {
- MipsFI->setMaxCallFrameSize(NextStackOffset);
-
- if (MipsFI->getGPStackOffset() == -1) {
- FI = MFI->CreateFixedObject(4, 0, true);
- MipsFI->setGPFI(FI);
- }
-
- // $gp restore slot must be aligned.
- unsigned StackAlignment = TFL->getStackAlignment();
- NextStackOffset = (NextStackOffset + StackAlignment - 1) /
- StackAlignment * StackAlignment;
- MipsFI->setGPStackOffset(NextStackOffset);
- }
+ // Function can have an arbitrary number of calls, so
+ // hold the LastArgStackLoc with the biggest offset.
+ int MaxCallFrameSize = MipsFI->getMaxCallFrameSize();
+ unsigned NextStackOffset = CCInfo.getNextStackOffset();
+
+ // For O32, a minimum of four words (16 bytes) of argument space is
+ // allocated.
+ if (Subtarget->isABI_O32())
+ NextStackOffset = std::max(NextStackOffset, (unsigned)16);
+
+ if (MaxCallFrameSize < (int)NextStackOffset) {
+ MipsFI->setMaxCallFrameSize(NextStackOffset);
+
+ // $gp restore slot must be aligned.
+ unsigned StackAlignment = TFL->getStackAlignment();
+ NextStackOffset = (NextStackOffset + StackAlignment - 1) /
+ StackAlignment * StackAlignment;
+ int GPFI = MipsFI->getGPFI();
+ MFI->setObjectOffset(GPFI, NextStackOffset);
+ }
}
+ // Extend range of indices of frame objects for outgoing arguments that were
+ // created during this function call. Skip this step if no such objects were
+ // created.
+ if (LastFI)
+ MipsFI->extendOutArgFIRange(FirstFI, LastFI);
+
// Create the CALLSEQ_END node.
Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
DAG.getIntPtrConstant(0, true), InFlag);
// 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;
CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
else
CCInfo.AnalyzeFormalArguments(Ins, CC_Mips);
- unsigned NextStackOffset = (Subtarget->isABI_EABI() ? 0 : 16);
- EVT LastRegArgValVT;
+ int LastFI = 0;// MipsFI->LastInArgFI is 0 at the entry of this function.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
// Arguments stored on registers
if (VA.isRegLoc()) {
EVT RegVT = VA.getLocVT();
- ArgRegEnd = VA.getLocReg();
- LastRegArgValVT = VA.getValVT();
+ unsigned ArgReg = VA.getLocReg();
TargetRegisterClass *RC = 0;
if (RegVT == MVT::i32)
// Transform the arguments stored on
// physical registers into virtual ones
- unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegEnd, RC);
+ unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgReg, RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
// If this is an 8 or 16-bit value, it has been passed promoted
// 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
// is used so there's a way to adjust these offsets when the stack
// 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.
- unsigned ArgSize = VA.getValVT().getSizeInBits()/8;
- NextStackOffset = VA.getLocMemOffset() + ArgSize;
- int FI = MFI->CreateFixedObject(ArgSize, 0, true);
- MipsFI->recordLoadArgsFI(FI, -(4 + VA.getLocMemOffset()));
+ LastFI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8,
+ VA.getLocMemOffset(), true);
// Create load nodes to retrieve arguments from the stack
- SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
+ SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy());
InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN,
- MachinePointerInfo::getFixedStack(FI),
+ MachinePointerInfo::getFixedStack(LastFI),
false, false, 0));
}
}
// 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()) {
- if (ArgRegEnd) {
- // Last named formal argument is passed in register.
+ // Record the frame index of the first variable argument
+ // which is a value necessary to VASTART.
+ unsigned NextStackOffset = CCInfo.getNextStackOffset();
+ LastFI = MFI->CreateFixedObject(4, NextStackOffset, true);
+ MipsFI->setVarArgsFrameIndex(LastFI);
+
+ const unsigned O32IntRegs[] = {
+ Mips::A0, Mips::A1, Mips::A2, Mips::A3
+ };
- // The last register argument that must be saved is Mips::A3
+ // Copy variable arguments passed in registers to stack.
+ for (; NextStackOffset < 16; NextStackOffset += 4) {
TargetRegisterClass *RC = Mips::CPURegsRegisterClass;
- if (LastRegArgValVT == MVT::f64)
- ArgRegEnd++;
-
- if (ArgRegEnd < Mips::A3) {
- // Both the last named formal argument and the first variable
- // argument are passed in registers.
- for (++ArgRegEnd; ArgRegEnd <= Mips::A3; ++ArgRegEnd) {
- unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegEnd, RC);
- SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, MVT::i32);
-
- int FI = MFI->CreateFixedObject(4, 0, true);
- MipsFI->recordStoreVarArgsFI(FI, -(4+(ArgRegEnd-Mips::A0)*4));
- SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy());
- OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff,
- MachinePointerInfo(),
- false, false, 0));
-
- // Record the frame index of the first variable argument
- // which is a value necessary to VASTART.
- if (!MipsFI->getVarArgsFrameIndex()) {
- MFI->setObjectAlignment(FI, 4);
- MipsFI->setVarArgsFrameIndex(FI);
- }
- }
- } else {
- // Last named formal argument is in register Mips::A3, and the first
- // variable argument is on stack. Record the frame index of the first
- // variable argument.
- int FI = MFI->CreateFixedObject(4, 0, true);
- MFI->setObjectAlignment(FI, 4);
- MipsFI->recordStoreVarArgsFI(FI, -20);
- MipsFI->setVarArgsFrameIndex(FI);
- }
- } else {
- // Last named formal argument and all the variable arguments are passed
- // on stack. Record the frame index of the first variable argument.
- int FI = MFI->CreateFixedObject(4, 0, true);
- MFI->setObjectAlignment(FI, 4);
- MipsFI->recordStoreVarArgsFI(FI, -(4+NextStackOffset));
- MipsFI->setVarArgsFrameIndex(FI);
+ unsigned Idx = NextStackOffset / 4;
+ unsigned Reg = AddLiveIn(DAG.getMachineFunction(), O32IntRegs[Idx], RC);
+ SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, MVT::i32);
+ LastFI = MFI->CreateFixedObject(4, NextStackOffset, true);
+ SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy());
+ OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff,
+ MachinePointerInfo(),
+ false, false, 0));
}
}
+ MipsFI->setLastInArgFI(LastFI);
+
// 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()) {