X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsISelLowering.cpp;h=9efd0f757b7af11c885497a3078d544efc52002f;hb=edacba83dc6b34676fe2be60e0bac487a6d1152d;hp=63bafa16e67ebfdcc71a8170f2e954ef47492c90;hpb=46da136ec79f484decce7c6cfeef42fb25888996;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 63bafa16e67..9efd0f757b7 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "mips-lower" +//#include #include "MipsISelLowering.h" #include "MipsMachineFunction.h" #include "MipsTargetMachine.h" @@ -691,6 +692,13 @@ LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const SDValue MipsTargetLowering:: LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const { + unsigned StackAlignment = + getTargetMachine().getFrameLowering()->getStackAlignment(); + assert(StackAlignment >= + cast(Op.getOperand(2).getNode())->getZExtValue() && + "Cannot lower if the alignment of the allocated space is larger than \ + that of the stack."); + SDValue Chain = Op.getOperand(0); SDValue Size = Op.getOperand(1); DebugLoc dl = Op.getDebugLoc(); @@ -704,11 +712,25 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const // The Sub result contains the new stack start address, so it // must be placed in the stack pointer register. - Chain = DAG.getCopyToReg(StackPointer.getValue(1), dl, Mips::SP, Sub); + Chain = DAG.getCopyToReg(StackPointer.getValue(1), dl, Mips::SP, Sub, + SDValue()); + // Retrieve updated $sp. There is a glue input to prevent instructions that + // clobber $sp from being inserted between copytoreg and copyfromreg. + SDValue NewSP = DAG.getCopyFromReg(Chain, dl, Mips::SP, MVT::i32, + Chain.getValue(1)); + + // The stack space reserved by alloca is located right above the argument + // area. It is aligned on a boundary that is a multiple of StackAlignment. + MachineFunction &MF = DAG.getMachineFunction(); + MipsFunctionInfo *MipsFI = MF.getInfo(); + unsigned SPOffset = (MipsFI->getMaxCallFrameSize() + StackAlignment - 1) / + StackAlignment * StackAlignment; + SDValue AllocPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, NewSP, + DAG.getConstant(SPOffset, MVT::i32)); // This node always has two return values: a new stack pointer // value and a chain - SDValue Ops[2] = { Sub, Chain }; + SDValue Ops[2] = { AllocPtr, NewSP.getValue(1) }; return DAG.getMergeValues(Ops, 2, dl); } @@ -958,6 +980,17 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, Mips::D6, Mips::D7 }; + // ByVal Args + if (ArgFlags.isByVal()) { + State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, + 1 /*MinSize*/, 4 /*MinAlign*/, ArgFlags); + unsigned NextReg = (State.getNextStackOffset() + 3) / 4; + for (unsigned r = State.getFirstUnallocated(IntRegs, IntRegsSize); + r < std::min(IntRegsSize, NextReg); ++r) + State.AllocateReg(IntRegs[r]); + return false; + } + // Promote i8 and i16 if (LocVT == MVT::i8 || LocVT == MVT::i16) { LocVT = MVT::i32; @@ -1026,6 +1059,56 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, // Call Calling Convention Implementation //===----------------------------------------------------------------------===// +static const unsigned O32IntRegsSize = 4; + +static const unsigned O32IntRegs[] = { + Mips::A0, Mips::A1, Mips::A2, Mips::A3 +}; + +// Write ByVal Arg to arg registers and stack. +static void +WriteByValArg(SDValue& Chain, DebugLoc dl, + SmallVector, 16>& RegsToPass, + SmallVector& MemOpChains, int& LastFI, + MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, + const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, + MVT PtrType) { + unsigned FirstWord = VA.getLocMemOffset() / 4; + unsigned NumWords = (Flags.getByValSize() + 3) / 4; + unsigned LastWord = FirstWord + NumWords; + unsigned CurWord; + + // copy the first 4 words of byval arg to registers A0 - A3 + for (CurWord = FirstWord; CurWord < std::min(LastWord, O32IntRegsSize); + ++CurWord) { + SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, + DAG.getConstant((CurWord - FirstWord) * 4, + MVT::i32)); + SDValue LoadVal = DAG.getLoad(MVT::i32, dl, Chain, LoadPtr, + MachinePointerInfo(), + false, false, 0); + MemOpChains.push_back(LoadVal.getValue(1)); + unsigned DstReg = O32IntRegs[CurWord]; + RegsToPass.push_back(std::make_pair(DstReg, LoadVal)); + } + + // copy remaining part of byval arg to stack. + if (CurWord < LastWord) { + unsigned SizeInBytes = (LastWord - CurWord) * 4; + SDValue Src = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, + DAG.getConstant((CurWord - FirstWord) * 4, + MVT::i32)); + LastFI = MFI->CreateFixedObject(SizeInBytes, CurWord * 4, true); + SDValue Dst = DAG.getFrameIndex(LastFI, PtrType); + Chain = DAG.getMemcpy(Chain, dl, Dst, Src, + DAG.getConstant(SizeInBytes, MVT::i32), + /*Align*/4, + /*isVolatile=*/false, /*AlwaysInline=*/false, + MachinePointerInfo(0), MachinePointerInfo(0)); + MemOpChains.push_back(Chain); + } +} + /// LowerCall - functions arguments are copied from virtual regs to /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. /// TODO: isTailCall. @@ -1064,12 +1147,13 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // With EABI is it possible to have 16 args on registers. SmallVector, 16> RegsToPass; SmallVector 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 this is the first call, create a stack frame object that points to + // a location to which .cprestore saves $gp. The offset of this frame object + // is set to 0, since we know nothing about the size of the argument area at + // this point. if (IsPIC && !MipsFI->getGPFI()) MipsFI->setGPFI(MFI->CreateFixedObject(4, 0, true)); @@ -1121,15 +1205,21 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Register can't get to this point... assert(VA.isMemLoc()); - // Create the frame index object for this incoming parameter - // 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. - unsigned ArgSize = VA.getValVT().getSizeInBits()/8; - NextStackOffset = VA.getLocMemOffset(); - LastFI = MFI->CreateFixedObject(ArgSize, NextStackOffset, true); - NextStackOffset += ArgSize; + // ByVal Arg. + ISD::ArgFlagsTy Flags = Outs[i].Flags; + if (Flags.isByVal()) { + assert(Subtarget->isABI_O32() && + "No support for ByVal args by ABIs other than O32 yet."); + assert(Flags.getByValSize() && + "ByVal args of size 0 should have been ignored by front-end."); + WriteByValArg(Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, DAG, Arg, + VA, Flags, getPointerTy()); + continue; + } + // Create the frame index object for this incoming parameter + LastFI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, + VA.getLocMemOffset(), true); SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy()); // emit ISD::STORE whichs stores the @@ -1229,13 +1319,16 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, Chain = DAG.getNode(MipsISD::JmpLink, dl, NodeTys, &Ops[0], Ops.size()); 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 - // 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 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); @@ -1296,6 +1389,29 @@ MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, //===----------------------------------------------------------------------===// // Formal Arguments Calling Convention Implementation //===----------------------------------------------------------------------===// +static void ReadByValArg(MachineFunction &MF, SDValue Chain, DebugLoc dl, + std::vector& OutChains, + SelectionDAG &DAG, unsigned NumWords, SDValue FIN, + const CCValAssign &VA, const ISD::ArgFlagsTy& Flags) { + unsigned LocMem = VA.getLocMemOffset(); + unsigned FirstWord = LocMem / 4; + + // copy register A0 - A3 to frame object + for (unsigned i = 0; i < NumWords; ++i) { + unsigned CurWord = FirstWord + i; + if (CurWord >= O32IntRegsSize) + break; + + unsigned SrcReg = O32IntRegs[CurWord]; + unsigned Reg = AddLiveIn(MF, SrcReg, Mips::CPURegsRegisterClass); + SDValue StorePtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN, + DAG.getConstant(i * 4, MVT::i32)); + SDValue Store = DAG.getStore(Chain, dl, DAG.getRegister(Reg, MVT::i32), + StorePtr, MachinePointerInfo(), false, + false, 0); + OutChains.push_back(Store); + } +} /// LowerFormalArguments - transform physical registers into virtual registers /// and generate load operations for arguments places on the stack. @@ -1308,7 +1424,6 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl &InVals) const { - MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo(); @@ -1318,9 +1433,6 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // Used with vargs to acumulate store chains. std::vector OutChains; - // Keep track of the last register used for arguments - unsigned ArgRegEnd = 0; - // Assign locations to all of the incoming arguments. SmallVector ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), @@ -1331,8 +1443,6 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, 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) { @@ -1341,8 +1451,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // 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) @@ -1357,7 +1466,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // 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 @@ -1396,20 +1505,26 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // sanity check assert(VA.isMemLoc()); - // The last argument is not a register anymore - ArgRegEnd = 0; + ISD::ArgFlagsTy Flags = Ins[i].Flags; + + if (Flags.isByVal()) { + assert(Subtarget->isABI_O32() && + "No support for ByVal args by ABIs other than O32 yet."); + assert(Flags.getByValSize() && + "ByVal args of size 0 should have been ignored by front-end."); + unsigned NumWords = (Flags.getByValSize() + 3) / 4; + LastFI = MFI->CreateFixedObject(NumWords * 4, VA.getLocMemOffset(), + true); + SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy()); + InVals.push_back(FIN); + ReadByValArg(MF, Chain, dl, OutChains, DAG, NumWords, FIN, VA, Flags); + + continue; + } // 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. - unsigned ArgSize = VA.getValVT().getSizeInBits()/8; - NextStackOffset = VA.getLocMemOffset(); - LastFI = MFI->CreateFixedObject(ArgSize, NextStackOffset, true); - NextStackOffset += ArgSize; + LastFI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, + VA.getLocMemOffset(), true); // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy()); @@ -1432,48 +1547,28 @@ 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()) { - if (ArgRegEnd) { - // Last named formal argument is passed in register. - - // The last register argument that must be saved is Mips::A3 + // Record the frame index of the first variable argument + // which is a value necessary to VASTART. + unsigned NextStackOffset = CCInfo.getNextStackOffset(); + assert(NextStackOffset % 4 == 0 && + "NextStackOffset must be aligned to 4-byte boundaries."); + LastFI = MFI->CreateFixedObject(4, NextStackOffset, true); + MipsFI->setVarArgsFrameIndex(LastFI); + + // If NextStackOffset is smaller than o32's 16-byte reserved argument area, + // copy the integer registers that have not been used for argument passing + // to the caller's stack frame. + 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); - - LastFI = MFI->CreateFixedObject(4, (ArgRegEnd-Mips::A0)*4, true); - SDValue PtrOff = DAG.getFrameIndex(LastFI, 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()) - MipsFI->setVarArgsFrameIndex(LastFI); - } - } 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. - LastFI = MFI->CreateFixedObject(4, 16, true); - MipsFI->setVarArgsFrameIndex(LastFI); - } - } else { - // Last named formal argument and all the variable arguments are passed - // on stack. Record the frame index of the first variable argument. + 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); - MipsFI->setVarArgsFrameIndex(LastFI); + SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy()); + OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, + MachinePointerInfo(), + false, false, 0)); } }