diff options
Diffstat (limited to 'lib/Target/MBlaze/MBlazeISelLowering.cpp')
-rw-r--r-- | lib/Target/MBlaze/MBlazeISelLowering.cpp | 166 |
1 files changed, 130 insertions, 36 deletions
diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp index 7790248..f0864d0 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -138,6 +138,13 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) setOperationAction(ISD::JumpTable, MVT::i32, Custom); setOperationAction(ISD::ConstantPool, MVT::i32, Custom); + // Variable Argument support + setOperationAction(ISD::VASTART, MVT::Other, Custom); + setOperationAction(ISD::VAEND, MVT::Other, Expand); + setOperationAction(ISD::VAARG, MVT::Other, Expand); + setOperationAction(ISD::VACOPY, MVT::Other, Expand); + + // Operations not directly supported by MBlaze. setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); setOperationAction(ISD::BR_JT, MVT::Other, Expand); @@ -186,6 +193,7 @@ SDValue MBlazeTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + case ISD::VASTART: return LowerVASTART(Op, DAG); } return SDValue(); } @@ -440,7 +448,6 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) { ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); Constant *C = N->getConstVal(); SDValue Zero = DAG.getConstant(0, PtrVT); - // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), @@ -448,12 +455,71 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) { return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, CP); } +SDValue MBlazeTargetLowering::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 //===----------------------------------------------------------------------===// #include "MBlazeGenCallingConv.inc" +static bool CC_MBlaze2(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + static const unsigned RegsSize=6; + static const unsigned IntRegs[] = { + MBlaze::R5, MBlaze::R6, MBlaze::R7, + MBlaze::R8, MBlaze::R9, MBlaze::R10 + }; + + static const unsigned FltRegs[] = { + MBlaze::F5, MBlaze::F6, MBlaze::F7, + MBlaze::F8, MBlaze::F9, MBlaze::F10 + }; + + unsigned Reg=0; + + // 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) { + Reg = State.AllocateReg(IntRegs, RegsSize); + LocVT = MVT::i32; + } else if (ValVT == MVT::f32) { + Reg = State.AllocateReg(FltRegs, RegsSize); + LocVT = MVT::f32; + } + + if (!Reg) { + unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; + unsigned Offset = State.AllocateStack(SizeInBytes, SizeInBytes); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + } else { + unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; + State.AllocateStack(SizeInBytes, SizeInBytes); + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + } + + return false; // CC must always match +} + //===----------------------------------------------------------------------===// // Call Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -468,6 +534,9 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) { + // MBlaze does not yet support tail call optimization + isTailCall = false; + MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -475,7 +544,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); - CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze); + CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze2); // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); @@ -487,7 +556,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // First/LastArgStackLoc contains the first/last // "at stack" argument location. int LastArgStackLoc = 0; - unsigned FirstStackArgLoc = 4; + unsigned FirstStackArgLoc = 0; // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { @@ -508,9 +577,6 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, case CCValAssign::AExt: Arg = DAG.getNode(ISD::ANY_EXTEND, dl, RegVT, Arg); break; - case CCValAssign::BCvt: - Arg = DAG.getNode(ISD::BIT_CONVERT, dl, RegVT, Arg); - break; } // Arguments that can be passed on register must be kept at @@ -617,7 +683,7 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, RVLocs[i].getValVT(), InFlag).getValue(1); InFlag = Chain.getValue(2); InVals.push_back(Chain.getValue(0)); - } + } return Chain; } @@ -629,7 +695,6 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, /// LowerFormalArguments - transform physical registers into /// virtual registers and generate load operations for /// arguments places on the stack. -/// TODO: isVarArg SDValue MBlazeTargetLowering:: LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, @@ -640,16 +705,23 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); 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; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); - CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze); + CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze2); SDValue StackPtr; - unsigned FirstStackArgLoc = 4; + unsigned FirstStackArgLoc = 0; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -657,6 +729,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, // Arguments stored on registers if (VA.isRegLoc()) { EVT RegVT = VA.getLocVT(); + ArgRegEnd = VA.getLocReg(); TargetRegisterClass *RC = 0; if (RegVT == MVT::i32) @@ -668,12 +741,13 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, // Transform the arguments stored on // physical registers into virtual ones - unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); + unsigned Reg = MF.addLiveIn(ArgRegEnd, RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); // If this is an 8 or 16-bit value, it has been passed promoted // to 32 bits. Insert an assert[sz]ext to capture this, then - // truncate to the right size. + // truncate to the right size. If if is a floating point value + // then convert to the correct type. if (VA.getLocInfo() != CCValAssign::Full) { unsigned Opcode = 0; if (VA.getLocInfo() == CCValAssign::SExt) @@ -688,35 +762,14 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, 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) { - 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); - MBlazeFI->recordStoreVarArgsFI(FI, -(FirstStackArgLoc+(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, - false, false, 0)); - } - } else { // VA.isRegLoc() // sanity check assert(VA.isMemLoc()); + // The last argument is not a register + 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 @@ -737,6 +790,47 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, } } + // 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) && ArgRegEnd) { + if (StackPtr.getNode() == 0) + StackPtr = DAG.getRegister(StackReg, getPointerTy()); + + // The last register argument that must be saved is MBlaze::R10 + TargetRegisterClass *RC = MBlaze::CPURegsRegisterClass; + + unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5); + unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1); + unsigned End = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10); + unsigned StackLoc = ArgLocs.size()-1 + (Start - Begin); + + for (; Start <= End; ++Start, ++StackLoc) { + unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start); + unsigned LiveReg = MF.addLiveIn(Reg, RC); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32); + + int FI = MFI->CreateFixedObject(4, 0, true, false); + MBlazeFI->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; } |