SDValue BlackfinTargetLowering::LowerFormalArguments(SDValue Chain, unsigned CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AllocateStack(12, 4); // ABI requires 12 bytes stack space CCInfo.AnalyzeFormalArguments(Ins, CC_Blackfin); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; if (VA.isRegLoc()) { EVT RegVT = VA.getLocVT(); TargetRegisterClass *RC = VA.getLocReg() == BF::P0 ? BF::PRegisterClass : BF::DRegisterClass; assert(RC->contains(VA.getLocReg()) && "Unexpected regclass in CCState"); assert(RC->hasType(RegVT) && "Unexpected regclass in CCState"); unsigned Reg = MF.getRegInfo().createVirtualRegister(RC); MF.getRegInfo().addLiveIn(VA.getLocReg(), Reg); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); // If this is an 8 or 16-bit value, it is really passed promoted to 32 // bits. Insert an assert[sz]ext to capture this, then truncate to the // right size. if (VA.getLocInfo() == CCValAssign::SExt) ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); else if (VA.getLocInfo() == CCValAssign::ZExt) ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); if (VA.getLocInfo() != CCValAssign::Full) ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); InVals.push_back(ArgValue); } else { assert(VA.isMemLoc() && "CCValAssign must be RegLoc or MemLoc"); unsigned ObjSize = VA.getLocVT().getStoreSizeInBits()/8; int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset()); SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0)); } } return Chain; }
void MBlazeFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineFrameInfo *MFI = MF.getFrameInfo(); MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR; if (MFI->adjustsStack() || requiresRA) { MBlazeFI->setRAStackOffset(0); MFI->CreateFixedObject(4,0,true); } if (hasFP(MF)) { MBlazeFI->setFPStackOffset(4); MFI->CreateFixedObject(4,4,true); } interruptFrameLayout(MF); analyzeFrameIndexes(MF); }
void X86FrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineFrameInfo *MFI = MF.getFrameInfo(); const X86RegisterInfo *RegInfo = TM.getRegisterInfo(); unsigned SlotSize = RegInfo->getSlotSize(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); int32_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); if (TailCallReturnAddrDelta < 0) { // create RETURNADDR area // arg // arg // RETADDR // { ... // RETADDR area // ... // } // [EBP] MFI->CreateFixedObject(-TailCallReturnAddrDelta, (-1U*SlotSize)+TailCallReturnAddrDelta, true); } if (hasFP(MF)) { assert((TailCallReturnAddrDelta <= 0) && "The Delta should always be zero or negative"); const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo(); // Create a frame entry for the EBP register that must be saved. int FrameIdx = MFI->CreateFixedObject(SlotSize, -(int)SlotSize + TFI.getOffsetOfLocalArea() + TailCallReturnAddrDelta, true); assert(FrameIdx == MFI->getObjectIndexBegin() && "Slot for EBP register must be last in order to be found!"); FrameIdx = 0; } }
void LanaiFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const { TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); MachineFrameInfo *MFI = MF.getFrameInfo(); const LanaiRegisterInfo *LRI = static_cast<const LanaiRegisterInfo *>(STI.getRegisterInfo()); int Offset = -4; // Reserve 4 bytes for the saved RCA MFI->CreateFixedObject(4, Offset, true); Offset -= 4; // Reserve 4 bytes for the saved FP MFI->CreateFixedObject(4, Offset, true); Offset -= 4; if (LRI->hasBasePointer(MF)) { MFI->CreateFixedObject(4, Offset, true); SavedRegs.reset(LRI->getBaseRegister()); } }
int XCoreFunctionInfo::createLRSpillSlot(MachineFunction &MF) { if (LRSpillSlotSet) { return LRSpillSlot; } const TargetRegisterClass *RC = &XCore::GRRegsRegClass; MachineFrameInfo *MFI = MF.getFrameInfo(); if (! MF.getFunction()->isVarArg()) { // A fixed offset of 0 allows us to save / restore LR using entsp / retsp. LRSpillSlot = MFI->CreateFixedObject(RC->getSize(), 0, true); } else { LRSpillSlot = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), true); } LRSpillSlotSet = true; return LRSpillSlot; }
void XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineFrameInfo *MFI = MF.getFrameInfo(); const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR); const TargetRegisterClass *RC = &XCore::GRRegsRegClass; XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); if (LRUsed) { MF.getRegInfo().setPhysRegUnused(XCore::LR); bool isVarArg = MF.getFunction()->isVarArg(); int FrameIdx; if (! isVarArg) { // A fixed offset of 0 allows us to save / restore LR using entsp / retsp. FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true); } else { FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), false); } XFI->setUsesLR(FrameIdx); XFI->setLRSpillSlot(FrameIdx); } if (RegInfo->requiresRegisterScavenging(MF)) { // Reserve a slot close to SP or frame pointer. RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), false)); } if (hasFP(MF)) { // A callee save register is used to hold the FP. // This needs saving / restoring in the epilogue / prologue. XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), false)); } }
// LowerCCCArguments - transform physical registers into virtual registers and // generate load operations for arguments places on the stack. SDValue LanaiTargetLowering::LowerCCCArguments( SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); LanaiMachineFunctionInfo *LanaiMFI = MF.getInfo<LanaiMachineFunctionInfo>(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext()); if (CallConv == CallingConv::Fast) { CCInfo.AnalyzeFormalArguments(Ins, CC_Lanai32_Fast); } else { CCInfo.AnalyzeFormalArguments(Ins, CC_Lanai32); } for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; if (VA.isRegLoc()) { // Arguments passed in registers EVT RegVT = VA.getLocVT(); switch (RegVT.getSimpleVT().SimpleTy) { case MVT::i32: { unsigned VReg = RegInfo.createVirtualRegister(&Lanai::GPRRegClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, VReg, RegVT); // If this is an 8/16-bit value, it is really passed promoted to 32 // bits. Insert an assert[sz]ext to capture this, then truncate to the // right size. if (VA.getLocInfo() == CCValAssign::SExt) ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); else if (VA.getLocInfo() == CCValAssign::ZExt) ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); if (VA.getLocInfo() != CCValAssign::Full) ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue); InVals.push_back(ArgValue); break; } default: DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: " << RegVT.getSimpleVT().SimpleTy << "\n"); llvm_unreachable("unhandled argument type"); } } else { // Sanity check assert(VA.isMemLoc()); // Load the argument to a virtual register unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8; // Check that the argument fits in stack slot if (ObjSize > 4) { errs() << "LowerFormalArguments Unhandled argument type: " << EVT(VA.getLocVT()).getEVTString() << "\n"; } // Create the frame index object for this incoming parameter... int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); // Create the SelectionDAG nodes corresponding to a load // from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); InVals.push_back(DAG.getLoad( VA.getLocVT(), DL, Chain, FIN, MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), false, false, false, 0)); } } // The Lanai ABI for returning structs by value requires that we copy // the sret argument into rv for the return. Save the argument into // a virtual register so that we can access it from the return points. if (MF.getFunction()->hasStructRetAttr()) { unsigned Reg = LanaiMFI->getSRetReturnReg(); if (!Reg) { Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i32)); LanaiMFI->setSRetReturnReg(Reg); } SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[0]); Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain); } if (IsVarArg) { // Record the frame index of the first variable argument // which is a value necessary to VASTART. int FI = MFI->CreateFixedObject(4, CCInfo.getNextStackOffset(), true); LanaiMFI->setVarArgsFrameIndex(FI); } return Chain; }
SDValue AlphaTargetLowering::LowerFormalArguments(SDValue Chain, unsigned CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); unsigned args_int[] = { Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21}; unsigned args_float[] = { Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21}; for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) { SDValue argt; EVT ObjectVT = Ins[ArgNo].VT; SDValue ArgVal; if (ArgNo < 6) { switch (ObjectVT.getSimpleVT().SimpleTy) { default: assert(false && "Invalid value type!"); case MVT::f64: args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], &Alpha::F8RCRegClass); ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT); break; case MVT::f32: args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], &Alpha::F4RCRegClass); ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT); break; case MVT::i64: args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo], &Alpha::GPRCRegClass); ArgVal = DAG.getCopyFromReg(Chain, dl, args_int[ArgNo], MVT::i64); break; } } else { //more args // Create the frame index object for this incoming parameter... int FI = MFI->CreateFixedObject(8, 8 * (ArgNo - 6)); // Create the SelectionDAG nodes corresponding to a load //from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i64); ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0); } InVals.push_back(ArgVal); } // If the functions takes variable number of arguments, copy all regs to stack if (isVarArg) { VarArgsOffset = Ins.size() * 8; std::vector<SDValue> LS; for (int i = 0; i < 6; ++i) { if (TargetRegisterInfo::isPhysicalRegister(args_int[i])) args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass); SDValue argt = DAG.getCopyFromReg(Chain, dl, args_int[i], MVT::i64); int FI = MFI->CreateFixedObject(8, -8 * (6 - i)); if (i == 0) VarArgsBase = FI; SDValue SDFI = DAG.getFrameIndex(FI, MVT::i64); LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0)); if (TargetRegisterInfo::isPhysicalRegister(args_float[i])) args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass); argt = DAG.getCopyFromReg(Chain, dl, args_float[i], MVT::f64); FI = MFI->CreateFixedObject(8, - 8 * (12 - i)); SDFI = DAG.getFrameIndex(FI, MVT::i64); LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0)); } //Set up a token factor with all the stack traffic Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &LS[0], LS.size()); } return Chain; }
/// LowerFormalArguments - transform physical registers into /// virtual registers and generate load operations for /// arguments places on the stack. SDValue MBlazeTargetLowering:: LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF); MBlazeFI->setVarArgsFrameIndex(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); SDValue StackPtr; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; // Arguments stored on registers if (VA.isRegLoc()) { MVT RegVT = VA.getLocVT(); ArgRegEnd = VA.getLocReg(); TargetRegisterClass *RC = 0; if (RegVT == MVT::i32) RC = MBlaze::GPRRegisterClass; else if (RegVT == MVT::f32) RC = MBlaze::GPRRegisterClass; else llvm_unreachable("RegVT not supported by LowerFormalArguments"); // Transform the arguments stored on // physical registers into virtual ones 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. 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) Opcode = ISD::AssertSext; else if (VA.getLocInfo() == CCValAssign::ZExt) Opcode = ISD::AssertZext; if (Opcode) ArgValue = DAG.getNode(Opcode, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); } InVals.push_back(ArgValue); } 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 // 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. unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; unsigned StackLoc = VA.getLocMemOffset() + 4; int FI = MFI->CreateFixedObject(ArgSize, 0, true); MBlazeFI->recordLoadArgsFI(FI, -StackLoc); // 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, MachinePointerInfo::getFixedStack(FI), false, false, 0)); } } // 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::GPRRegisterClass; unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5); unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1); unsigned End = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10); unsigned StackLoc = Start - Begin + 1; 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); MBlazeFI->recordStoreVarArgsFI(FI, -(StackLoc*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 (!MBlazeFI->getVarArgsFrameIndex()) MBlazeFI->setVarArgsFrameIndex(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; }
/// LowerCall - functions arguments are copied from virtual regs to /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. /// TODO: isVarArg, isTailCall. SDValue MBlazeTargetLowering:: LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, bool &isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { // MBlaze does not yet support tail call optimization isTailCall = false; // The MBlaze requires stack slots for arguments passed to var arg // functions even if they are passed in registers. bool needsRegArgSlots = isVarArg; MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo(); // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze); // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); // Variable argument function calls require a minimum of 24-bytes of stack if (isVarArg && NumBytes < 24) NumBytes = 24; Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; SmallVector<SDValue, 8> MemOpChains; // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; MVT RegVT = VA.getLocVT(); SDValue Arg = OutVals[i]; // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: break; case CCValAssign::SExt: Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, RegVT, Arg); break; case CCValAssign::ZExt: Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, RegVT, Arg); break; case CCValAssign::AExt: Arg = DAG.getNode(ISD::ANY_EXTEND, dl, RegVT, Arg); break; } // Arguments that can be passed on register must be kept at // RegsToPass vector if (VA.isRegLoc()) { RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); } else { // Register can't get to this point... assert(VA.isMemLoc()); // Since we are alread passing values on the stack we don't // need to worry about creating additional slots for the // values passed via registers. needsRegArgSlots = false; // Create the frame index object for this incoming parameter unsigned ArgSize = VA.getValVT().getSizeInBits()/8; unsigned StackLoc = VA.getLocMemOffset() + 4; int FI = MFI->CreateFixedObject(ArgSize, StackLoc, true); SDValue PtrOff = DAG.getFrameIndex(FI,getPointerTy()); // emit ISD::STORE whichs stores the // parameter value to a stack Location MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo(), false, false, 0)); } } // If we need to reserve stack space for the arguments passed via registers // then create a fixed stack object at the beginning of the stack. if (needsRegArgSlots && TFI.hasReservedCallFrame(MF)) MFI->CreateFixedObject(28,0,true); // Transform all store nodes into one single node because all store // nodes are independent of each other. if (!MemOpChains.empty()) Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], MemOpChains.size()); // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. // The InFlag in necessary since all emited instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, RegsToPass[i].second, InFlag); InFlag = Chain.getValue(1); } // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, 0); else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(), 0); // MBlazeJmpLink = #chain, #target_address, #opt_in_flags... // = Chain, Callee, Reg#1, Reg#2, ... // // Returns a chain & a flag for retval copy to use. SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); SmallVector<SDValue, 8> Ops; Ops.push_back(Chain); Ops.push_back(Callee); // Add argument registers to the end of the list so that they are // known live into the call. for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { Ops.push_back(DAG.getRegister(RegsToPass[i].first, RegsToPass[i].second.getValueType())); } if (InFlag.getNode()) Ops.push_back(InFlag); Chain = DAG.getNode(MBlazeISD::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); if (!Ins.empty()) InFlag = Chain.getValue(1); // Handle result values, copying them out of physregs into vregs that we // return. return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG, InVals); }
static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG, int &VarArgsBase, int &VarArgsOffset) { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); std::vector<SDOperand> ArgValues; SDOperand Root = Op.getOperand(0); AddLiveIn(MF, Alpha::R29, &Alpha::GPRCRegClass); //GP AddLiveIn(MF, Alpha::R26, &Alpha::GPRCRegClass); //RA unsigned args_int[] = { Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21}; unsigned args_float[] = { Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21}; for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) { SDOperand argt; MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); SDOperand ArgVal; if (ArgNo < 6) { switch (ObjectVT) { default: cerr << "Unknown Type " << ObjectVT << "\n"; abort(); case MVT::f64: args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], &Alpha::F8RCRegClass); ArgVal = DAG.getCopyFromReg(Root, args_float[ArgNo], ObjectVT); break; case MVT::f32: args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], &Alpha::F4RCRegClass); ArgVal = DAG.getCopyFromReg(Root, args_float[ArgNo], ObjectVT); break; case MVT::i64: args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo], &Alpha::GPRCRegClass); ArgVal = DAG.getCopyFromReg(Root, args_int[ArgNo], MVT::i64); break; } } else { //more args // Create the frame index object for this incoming parameter... int FI = MFI->CreateFixedObject(8, 8 * (ArgNo - 6)); // Create the SelectionDAG nodes corresponding to a load //from this parameter SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64); ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0); } ArgValues.push_back(ArgVal); } // If the functions takes variable number of arguments, copy all regs to stack bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; if (isVarArg) { VarArgsOffset = (Op.Val->getNumValues()-1) * 8; std::vector<SDOperand> LS; for (int i = 0; i < 6; ++i) { if (MRegisterInfo::isPhysicalRegister(args_int[i])) args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass); SDOperand argt = DAG.getCopyFromReg(Root, args_int[i], MVT::i64); int FI = MFI->CreateFixedObject(8, -8 * (6 - i)); if (i == 0) VarArgsBase = FI; SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64); LS.push_back(DAG.getStore(Root, argt, SDFI, NULL, 0)); if (MRegisterInfo::isPhysicalRegister(args_float[i])) args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass); argt = DAG.getCopyFromReg(Root, args_float[i], MVT::f64); FI = MFI->CreateFixedObject(8, - 8 * (12 - i)); SDFI = DAG.getFrameIndex(FI, MVT::i64); LS.push_back(DAG.getStore(Root, argt, SDFI, NULL, 0)); } //Set up a token factor with all the stack traffic Root = DAG.getNode(ISD::TokenFactor, MVT::Other, &LS[0], LS.size()); } ArgValues.push_back(Root); // Return the new list of results. std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(), Op.Val->value_end()); return DAG.getNode(ISD::MERGE_VALUES, RetVT, &ArgValues[0], ArgValues.size()); }
/// LowerFormalArguments - transform physical registers into virtual registers /// and generate load operations for arguments places on the stack. SDValue Cpu0TargetLowering::LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); Cpu0FunctionInfo *Cpu0FI = MF.getInfo<Cpu0FunctionInfo>(); Cpu0FI->setVarArgsFrameIndex(0); // Used with vargs to acumulate store chains. std::vector<SDValue> OutChains; // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_Cpu0); Function::const_arg_iterator FuncArg = DAG.getMachineFunction().getFunction()->arg_begin(); int LastFI = 0;// Cpu0FI->LastInArgFI is 0 at the entry of this function. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++FuncArg) { CCValAssign &VA = ArgLocs[i]; EVT ValVT = VA.getValVT(); ISD::ArgFlagsTy Flags = Ins[i].Flags; bool IsRegLoc = VA.isRegLoc(); if (Flags.isByVal()) { assert(Flags.getByValSize() && "ByVal args of size 0 should have been ignored by front-end."); continue; } { // VA.isRegLoc() // sanity check assert(VA.isMemLoc()); // The stack pointer offset is relative to the caller stack frame. LastFI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, VA.getLocMemOffset(), true); // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy()); InVals.push_back(DAG.getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo::getFixedStack(LastFI), false, false, false, 0)); } } Cpu0FI->setLastInArgFI(LastFI); #if 1 // 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()); } #endif return Chain; }
/// LowerCCCArguments - transform physical registers into virtual registers and /// generate load operations for arguments places on the stack. // FIXME: struct return stuff // FIXME: varargs SDValue SystemZTargetLowering::LowerCCCArguments(SDValue Chain, 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(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_SystemZ); if (isVarArg) report_fatal_error("Varargs not supported yet"); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { SDValue ArgValue; CCValAssign &VA = ArgLocs[i]; EVT LocVT = VA.getLocVT(); if (VA.isRegLoc()) { // Arguments passed in registers TargetRegisterClass *RC; switch (LocVT.getSimpleVT().SimpleTy) { default: #ifndef NDEBUG errs() << "LowerFormalArguments Unhandled argument type: " << LocVT.getSimpleVT().SimpleTy << "\n"; #endif llvm_unreachable(0); case MVT::i64: RC = SystemZ::GR64RegisterClass; break; case MVT::f32: RC = SystemZ::FP32RegisterClass; break; case MVT::f64: RC = SystemZ::FP64RegisterClass; break; } unsigned VReg = RegInfo.createVirtualRegister(RC); RegInfo.addLiveIn(VA.getLocReg(), VReg); ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, LocVT); } else { // Sanity check assert(VA.isMemLoc()); // Create the nodes corresponding to a load from this parameter slot. // Create the frame index object for this incoming parameter... int FI = MFI->CreateFixedObject(LocVT.getSizeInBits()/8, VA.getLocMemOffset(), true, false); // Create the SelectionDAG nodes corresponding to a load // from this parameter SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); ArgValue = DAG.getLoad(LocVT, dl, Chain, FIN, PseudoSourceValue::getFixedStack(FI), 0, false, false, 0); } // If this is an 8/16/32-bit value, it is really passed promoted to 64 // bits. Insert an assert[sz]ext to capture this, then truncate to the // right size. if (VA.getLocInfo() == CCValAssign::SExt) ArgValue = DAG.getNode(ISD::AssertSext, dl, LocVT, ArgValue, DAG.getValueType(VA.getValVT())); else if (VA.getLocInfo() == CCValAssign::ZExt) ArgValue = DAG.getNode(ISD::AssertZext, dl, LocVT, ArgValue, DAG.getValueType(VA.getValVT())); if (VA.getLocInfo() != CCValAssign::Full) ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); InVals.push_back(ArgValue); } return Chain; }
SDValue ARCompactTargetLowering::LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { //DEBUG(dbgs() << "ARCompactTargetLowering::LowerFormalArguments()\n"); //DEBUG(dbgs() << "isVarArg? " << isVarArg << "\n"); //DEBUG(Chain.getNode()->dump()); MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); ARCompactFunctionInfo *AFI = MF.getInfo<ARCompactFunctionInfo>(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_ARCompact32); // Push the arguments onto the InVals vector. SDValue ArgValue; for (unsigned int i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; if (VA.isRegLoc()) { // Arguments passed in registers. TargetRegisterClass *RC = ARC::CPURegsRegisterClass; unsigned int Register = MF.addLiveIn(VA.getLocReg(), RC); EVT RegisterValueType = VA.getLocVT(); ArgValue = DAG.getCopyFromReg(Chain, dl, Register, RegisterValueType); InVals.push_back(ArgValue); } else { // Sanity check assert(VA.isMemLoc()); // Load the argument to a virtual register unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; if (ObjSize != 4) { llvm_unreachable("Memory argument is wrong size - not 32 bit!"); } // Create the frame index object for this incoming parameter... int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); // Create the SelectionDAG nodes corresponding to a load from this // parameter. SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, MachinePointerInfo::getFixedStack(FI), false, false, false, 0)); } } // varargs if (isVarArg) { // For this, we need to declare any varargs that can fit into the unused // parameter registers (register r0-r7.) This involves updating the // ARCompactFunctionInfo with the size of the space needed (num_regs * 4), // and sticking the values into the registers. The remaining varargs are // the problem of the caller to deal with. // Work out how many varargs we can fit into registers. unsigned FirstFreeIndex = CCInfo.getFirstUnallocated(ArgumentRegisters, sizeof(ArgumentRegisters) / sizeof(ArgumentRegisters[0])); unsigned NumFreeRegisters = (FirstFreeIndex <= 7) ? (8 - FirstFreeIndex) : 0; //dbgs() << "NumFreeRegisters: " << NumFreeRegisters << "\n"; // We must make sure to preserve the alignment. unsigned Align = MF.getTarget().getFrameLowering()->getStackAlignment(); unsigned VARegSize = NumFreeRegisters * 4; unsigned VARegSaveSize = (VARegSize + Align - 1) & ~(Align - 1); //dbgs() << "VARegSize: " << VARegSize << "\n"; //dbgs() << "VARegSaveSize: " << VARegSaveSize << "\n"; // Update the ARCompactFunctionInfo with the details about the varargs. AFI->setVarArgsRegSaveSize(VARegSaveSize); int64_t offset = CCInfo.getNextStackOffset() + VARegSaveSize - VARegSize; // Adjust the offset for the fact that the save locations starts at least 8 // above the FP, not at the FP. offset += 8; //dbgs() << "offset: " << offset << "\n"; AFI->setVarArgsFrameIndex(MFI->CreateFixedObject(VARegSaveSize, offset, false)); // Create a frame index for the varargs area. SDValue FIN = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(), getPointerTy()); // Now place as many varargs into the registers as we can. SmallVector<SDValue, 8> MemOps; for (; FirstFreeIndex < 8; ++FirstFreeIndex) { TargetRegisterClass *RC = ARC::CPURegsRegisterClass; unsigned VReg = MF.addLiveIn(ArgumentRegisters[FirstFreeIndex], RC); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo::getFixedStack(AFI->getVarArgsFrameIndex()), false, false, 0); MemOps.push_back(Store); // Increment the frame pointer location. FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN, DAG.getConstant(4, getPointerTy())); } // If we added any varargs, update the chain. if (!MemOps.empty()) { Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOps[0], MemOps.size()); } } return Chain; }
SDValue Y86TargetLowering:: LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); // Gather info about the formals. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_Y86); // Push corresponding SDValues for the arguments. SDValue ArgValue; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; if (VA.isRegLoc()) { EVT RegVT = VA.getLocVT(); const TargetRegisterClass *RC; if (RegVT == MVT::i32) RC = &Y86::GPRRegClass; else llvm_unreachable("Unknown EVT"); unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); } else { assert(VA.isMemLoc()); EVT ValVT; if (VA.getLocInfo() == CCValAssign::Indirect) ValVT = VA.getLocVT(); else ValVT = VA.getValVT(); // Create space in the stack (and an associated frame index) // accordingly: Either the complete size of the object is it's // a call by value or a pointer size otherwise. MachineFrameInfo *MFI = MF.getFrameInfo(); ISD::ArgFlagsTy Flags = Ins[i].Flags; if (Flags.isByVal()) { unsigned Bytes = Flags.getByValSize(); if (Bytes == 0) Bytes = 1; // Don't create zero-sized stack objects. int FI = MFI->CreateFixedObject(Bytes, VA.getLocMemOffset(), false); ArgValue = DAG.getFrameIndex(FI, getPointerTy()); } else { int FI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, VA.getLocMemOffset(), true); SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); ArgValue = DAG.getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo::getFixedStack(FI), false, false, false, 0); } } InVals.push_back(ArgValue); } return Chain; }
/// LowerCCCArguments - transform physical registers into virtual registers and /// generate load operations for arguments places on the stack. // FIXME: struct return stuff // FIXME: varargs SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Op, SelectionDAG &DAG) { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); SDValue Root = Op.getOperand(0); bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0; unsigned CC = MF.getFunction()->getCallingConv(); DebugLoc dl = Op.getDebugLoc(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs); CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_MSP430); assert(!isVarArg && "Varargs not supported yet"); SmallVector<SDValue, 16> ArgValues; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; if (VA.isRegLoc()) { // Arguments passed in registers MVT RegVT = VA.getLocVT(); switch (RegVT.getSimpleVT()) { default: cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: " << RegVT.getSimpleVT() << "\n"; abort(); case MVT::i16: unsigned VReg = RegInfo.createVirtualRegister(MSP430::GR16RegisterClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); SDValue ArgValue = DAG.getCopyFromReg(Root, dl, VReg, RegVT); // If this is an 8-bit value, it is really passed promoted to 16 // bits. Insert an assert[sz]ext to capture this, then truncate to the // right size. if (VA.getLocInfo() == CCValAssign::SExt) ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); else if (VA.getLocInfo() == CCValAssign::ZExt) ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); if (VA.getLocInfo() != CCValAssign::Full) ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); ArgValues.push_back(ArgValue); } } else { // Sanity check assert(VA.isMemLoc()); // Load the argument to a virtual register unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; if (ObjSize > 2) { cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: " << VA.getLocVT().getSimpleVT() << "\n"; } // Create the frame index object for this incoming parameter... int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset()); // Create the SelectionDAG nodes corresponding to a load //from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); ArgValues.push_back(DAG.getLoad(VA.getLocVT(), dl, Root, FIN, PseudoSourceValue::getFixedStack(FI), 0)); } } ArgValues.push_back(Root); // Return the new list of results. return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(), &ArgValues[0], ArgValues.size()).getValue(Op.getResNo()); }
std::vector<SDOperand> IA64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { std::vector<SDOperand> ArgValues; // // add beautiful description of IA64 stack frame format // here (from intel 24535803.pdf most likely) // MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); GP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64)); SP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64)); RP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64)); MachineBasicBlock& BB = MF.front(); unsigned args_int[] = {IA64::r32, IA64::r33, IA64::r34, IA64::r35, IA64::r36, IA64::r37, IA64::r38, IA64::r39}; unsigned args_FP[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11, IA64::F12,IA64::F13,IA64::F14, IA64::F15}; unsigned argVreg[8]; unsigned argPreg[8]; unsigned argOpc[8]; unsigned used_FPArgs = 0; // how many FP args have been used so far? unsigned ArgOffset = 0; int count = 0; for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { SDOperand newroot, argt; if(count < 8) { // need to fix this logic? maybe. switch (getValueType(I->getType())) { default: assert(0 && "ERROR in LowerArgs: can't lower this type of arg.\n"); case MVT::f32: // fixme? (well, will need to for weird FP structy stuff, // see intel ABI docs) case MVT::f64: //XXX BuildMI(&BB, IA64::IDEF, 0, args_FP[used_FPArgs]); MF.getRegInfo().addLiveIn(args_FP[used_FPArgs]); // mark this reg as liveIn // floating point args go into f8..f15 as-needed, the increment argVreg[count] = // is below..: MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::f64)); // FP args go into f8..f15 as needed: (hence the ++) argPreg[count] = args_FP[used_FPArgs++]; argOpc[count] = IA64::FMOV; argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), argVreg[count], MVT::f64); if (I->getType() == Type::FloatTy) argt = DAG.getNode(ISD::FP_ROUND, MVT::f32, argt, DAG.getIntPtrConstant(0)); break; case MVT::i1: // NOTE: as far as C abi stuff goes, // bools are just boring old ints case MVT::i8: case MVT::i16: case MVT::i32: case MVT::i64: //XXX BuildMI(&BB, IA64::IDEF, 0, args_int[count]); MF.getRegInfo().addLiveIn(args_int[count]); // mark this register as liveIn argVreg[count] = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64)); argPreg[count] = args_int[count]; argOpc[count] = IA64::MOV; argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), argVreg[count], MVT::i64); if ( getValueType(I->getType()) != MVT::i64) argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot); break; } } else { // more than 8 args go into the frame // Create the frame index object for this incoming parameter... ArgOffset = 16 + 8 * (count - 8); int FI = MFI->CreateFixedObject(8, ArgOffset); // Create the SelectionDAG nodes corresponding to a load //from this parameter SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64); argt = newroot = DAG.getLoad(getValueType(I->getType()), DAG.getEntryNode(), FIN, NULL, 0); } ++count; DAG.setRoot(newroot.getValue(1)); ArgValues.push_back(argt); } // Create a vreg to hold the output of (what will become) // the "alloc" instruction VirtGPR = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64)); BuildMI(&BB, TII->get(IA64::PSEUDO_ALLOC), VirtGPR); // we create a PSEUDO_ALLOC (pseudo)instruction for now /* BuildMI(&BB, IA64::IDEF, 0, IA64::r1); // hmm: BuildMI(&BB, IA64::IDEF, 0, IA64::r12); BuildMI(&BB, IA64::IDEF, 0, IA64::rp); // ..hmm. BuildMI(&BB, IA64::MOV, 1, GP).addReg(IA64::r1); // hmm: BuildMI(&BB, IA64::MOV, 1, SP).addReg(IA64::r12); BuildMI(&BB, IA64::MOV, 1, RP).addReg(IA64::rp); // ..hmm. */ unsigned tempOffset=0; // if this is a varargs function, we simply lower llvm.va_start by // pointing to the first entry if(F.isVarArg()) { tempOffset=0; VarArgsFrameIndex = MFI->CreateFixedObject(8, tempOffset); } // here we actually do the moving of args, and store them to the stack // too if this is a varargs function: for (int i = 0; i < count && i < 8; ++i) { BuildMI(&BB, TII->get(argOpc[i]), argVreg[i]).addReg(argPreg[i]); if(F.isVarArg()) { // if this is a varargs function, we copy the input registers to the stack int FI = MFI->CreateFixedObject(8, tempOffset); tempOffset+=8; //XXX: is it safe to use r22 like this? BuildMI(&BB, TII->get(IA64::MOV), IA64::r22).addFrameIndex(FI); // FIXME: we should use st8.spill here, one day BuildMI(&BB, TII->get(IA64::ST8), IA64::r22).addReg(argPreg[i]); } } // Finally, inform the code generator which regs we return values in. // (see the ISD::RET: case in the instruction selector) switch (getValueType(F.getReturnType())) { default: assert(0 && "i have no idea where to return this type!"); case MVT::isVoid: break; case MVT::i1: case MVT::i8: case MVT::i16: case MVT::i32: case MVT::i64: MF.getRegInfo().addLiveOut(IA64::r8); break; case MVT::f32: case MVT::f64: MF.getRegInfo().addLiveOut(IA64::F8); break; } return ArgValues; }
/// calculateCalleeSavedRegisters - Scan the function for modified callee saved /// registers. void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) { const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); const TargetFrameLowering *TFI = Fn.getTarget().getFrameLowering(); MachineFrameInfo *MFI = Fn.getFrameInfo(); // Get the callee saved register list... const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(&Fn); // These are used to keep track the callee-save area. Initialize them. MinCSFrameIndex = INT_MAX; MaxCSFrameIndex = 0; // Early exit for targets which have no callee saved registers. if (CSRegs == 0 || CSRegs[0] == 0) return; // In Naked functions we aren't going to save any registers. if (Fn.getFunction()->hasFnAttr(Attribute::Naked)) return; std::vector<CalleeSavedInfo> CSI; for (unsigned i = 0; CSRegs[i]; ++i) { unsigned Reg = CSRegs[i]; if (Fn.getRegInfo().isPhysRegUsed(Reg)) { // If the reg is modified, save it! CSI.push_back(CalleeSavedInfo(Reg)); } else { for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg); *AliasSet; ++AliasSet) { // Check alias registers too. if (Fn.getRegInfo().isPhysRegUsed(*AliasSet)) { CSI.push_back(CalleeSavedInfo(Reg)); break; } } } } if (CSI.empty()) return; // Early exit if no callee saved registers are modified! unsigned NumFixedSpillSlots; const TargetFrameLowering::SpillSlot *FixedSpillSlots = TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots); // Now that we know which registers need to be saved and restored, allocate // stack slots for them. for (std::vector<CalleeSavedInfo>::iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { unsigned Reg = I->getReg(); const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg); int FrameIdx; if (RegInfo->hasReservedSpillSlot(Fn, Reg, FrameIdx)) { I->setFrameIdx(FrameIdx); continue; } // Check to see if this physreg must be spilled to a particular stack slot // on this target. const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots; while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots && FixedSlot->Reg != Reg) ++FixedSlot; if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { // Nope, just spill it anywhere convenient. unsigned Align = RC->getAlignment(); unsigned StackAlign = TFI->getStackAlignment(); // We may not be able to satisfy the desired alignment specification of // the TargetRegisterClass if the stack alignment is smaller. Use the // min. Align = std::min(Align, StackAlign); FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true); if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; } else { // Spill it to the stack where we must. FrameIdx = MFI->CreateFixedObject(RC->getSize(), FixedSlot->Offset, true); } I->setFrameIdx(FrameIdx); } MFI->setCalleeSavedInfo(CSI); }
SDValue Cpu0TargetLowering::LowerCall(SDValue InChain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, bool doesNotRet, bool &isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { #if 1 // Cpu0 target does not yet support tail call optimization. isTailCall = false; MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); const TargetFrameLowering *TFL = MF.getTarget().getFrameLowering(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; Cpu0FunctionInfo *Cpu0FI = MF.getInfo<Cpu0FunctionInfo>(); // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeCallOperands(Outs, CC_Cpu0); // Get a count of how many bytes are to be pushed on the stack. unsigned NextStackOffset = CCInfo.getNextStackOffset(); // Chain is the output chain of the last Load/Store or CopyToReg node. // ByValChain is the output chain of the last Memcpy node created for copying // byval arguments to the stack. SDValue Chain, CallSeqStart, ByValChain; SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true); Chain = CallSeqStart = DAG.getCALLSEQ_START(InChain, NextStackOffsetVal); ByValChain = InChain; #if 0 // If this is the first call, create a stack frame object that points to // a location to which .cprestore saves $gp. if (IsO32 && IsPIC && Cpu0FI->globalBaseRegFixed() && !Cpu0FI->getGPFI()) Cpu0FI->setGPFI(MFI->CreateFixedObject(4, 0, true)); #endif // Get the frame index of the stack frame object that points to the location // of dynamically allocated area on the stack. int DynAllocFI = Cpu0FI->getDynAllocFI(); #if 0 // Update size of the maximum argument space. // For O32, a minimum of four words (16 bytes) of argument space is // allocated. if (IsO32) NextStackOffset = std::max(NextStackOffset, (unsigned)16); #endif unsigned MaxCallFrameSize = Cpu0FI->getMaxCallFrameSize(); if (MaxCallFrameSize < NextStackOffset) { Cpu0FI->setMaxCallFrameSize(NextStackOffset); // Set the offsets relative to $sp of the $gp restore slot and dynamically // allocated stack space. These offsets must be aligned to a boundary // determined by the stack alignment of the ABI. unsigned StackAlignment = TFL->getStackAlignment(); NextStackOffset = (NextStackOffset + StackAlignment - 1) / StackAlignment * StackAlignment; if (Cpu0FI->needGPSaveRestore()) MFI->setObjectOffset(Cpu0FI->getGPFI(), NextStackOffset); MFI->setObjectOffset(DynAllocFI, NextStackOffset); } // With EABI is it possible to have 16 args on registers. SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass; SmallVector<SDValue, 8> MemOpChains; 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]; CCValAssign &VA = ArgLocs[i]; MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); ISD::ArgFlagsTy Flags = Outs[i].Flags; // ByVal Arg. if (Flags.isByVal()) { assert(Flags.getByValSize() && "ByVal args of size 0 should have been ignored by front-end."); #if 0 if (IsO32) WriteByValArg(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, DAG, Arg, VA, Flags, getPointerTy(), Subtarget->isLittle()); #endif #if 0 else PassByValArg64(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, DAG, Arg, VA, Flags, getPointerTy(), Subtarget->isLittle()); #endif continue; } // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: #if 0 if (VA.isRegLoc()) { if ((ValVT == MVT::f32 && LocVT == MVT::i32) || (ValVT == MVT::f64 && LocVT == MVT::i64)) Arg = DAG.getNode(ISD::BITCAST, dl, LocVT, Arg); else if (ValVT == MVT::f64 && LocVT == MVT::i32) { SDValue Lo = DAG.getNode(Cpu0ISD::ExtractElementF64, dl, MVT::i32, Arg, DAG.getConstant(0, MVT::i32)); SDValue Hi = DAG.getNode(Cpu0ISD::ExtractElementF64, dl, MVT::i32, Arg, DAG.getConstant(1, MVT::i32)); if (!Subtarget->isLittle()) std::swap(Lo, Hi); unsigned LocRegLo = VA.getLocReg(); unsigned LocRegHigh = getNextIntArgReg(LocRegLo); RegsToPass.push_back(std::make_pair(LocRegLo, Lo)); RegsToPass.push_back(std::make_pair(LocRegHigh, Hi)); continue; } } #else assert("CCValAssign::Full:"); // Gamma debug #endif break; case CCValAssign::SExt: Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, LocVT, Arg); break; case CCValAssign::ZExt: Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, LocVT, Arg); break; case CCValAssign::AExt: Arg = DAG.getNode(ISD::ANY_EXTEND, dl, LocVT, Arg); break; } // Arguments that can be passed on register must be kept at // RegsToPass vector if (VA.isRegLoc()) { RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); continue; } // Register can't get to this point... assert(VA.isMemLoc()); // Create the frame index object for this incoming parameter LastFI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, VA.getLocMemOffset(), true); SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy()); // emit ISD::STORE whichs stores the // parameter value to a stack Location MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo(), false, false, 0)); } // 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) Cpu0FI->extendOutArgFIRange(FirstFI, LastFI); // If a memcpy has been created to copy a byval arg to a stack, replace the // chain input of CallSeqStart with ByValChain. if (InChain != ByValChain) DAG.UpdateNodeOperands(CallSeqStart.getNode(), ByValChain, NextStackOffsetVal); // Transform all store nodes into one single node because all store // nodes are independent of each other. if (!MemOpChains.empty()) Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], MemOpChains.size()); // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. unsigned char OpFlag; #if 0 // cpu0 int 32 only bool IsPICCall = (IsN64 || IsPIC); // true if calls are translated to jalr $25 #else bool IsPICCall = IsPIC; // true if calls are translated to jalr $25 #endif bool GlobalOrExternal = false; SDValue CalleeLo; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { if (IsPICCall && G->getGlobal()->hasInternalLinkage()) { OpFlag = Cpu0II::MO_GOT; #if 0 unsigned char LoFlag = IsO32 ? Cpu0II::MO_ABS_LO : Cpu0II::MO_GOT_OFST; #else unsigned char LoFlag = Cpu0II::MO_ABS_LO; #endif Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, OpFlag); CalleeLo = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, LoFlag); } else { OpFlag = IsPICCall ? Cpu0II::MO_GOT_CALL : Cpu0II::MO_NO_FLAG; Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, OpFlag); } GlobalOrExternal = true; } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { if (!IsPIC) // static OpFlag = Cpu0II::MO_NO_FLAG; else // O32 & PIC OpFlag = Cpu0II::MO_GOT_CALL; Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(), OpFlag); GlobalOrExternal = true; } SDValue InFlag; // Create nodes that load address of callee and copy it to T9 if (IsPICCall) { if (GlobalOrExternal) { // Load callee address Callee = DAG.getNode(Cpu0ISD::Wrapper, dl, getPointerTy(), GetGlobalReg(DAG, getPointerTy()), Callee); SDValue LoadValue = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Callee, MachinePointerInfo::getGOT(), false, false, false, 0); // Use GOT+LO if callee has internal linkage. if (CalleeLo.getNode()) { SDValue Lo = DAG.getNode(Cpu0ISD::Lo, dl, getPointerTy(), CalleeLo); Callee = DAG.getNode(ISD::ADD, dl, getPointerTy(), LoadValue, Lo); } else Callee = LoadValue; } } // T9 should contain the address of the callee function if // -reloction-model=pic or it is an indirect call. if (IsPICCall || !GlobalOrExternal) { // copy to T9 unsigned T9Reg = Cpu0::T9; Chain = DAG.getCopyToReg(Chain, dl, T9Reg, Callee, SDValue(0, 0)); InFlag = Chain.getValue(1); Callee = DAG.getRegister(T9Reg, getPointerTy()); } // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. // The InFlag in necessary since all emitted instructions must be // stuck together. for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, RegsToPass[i].second, InFlag); InFlag = Chain.getValue(1); } // Cpu0JmpLink = #chain, #target_address, #opt_in_flags... // = Chain, Callee, Reg#1, Reg#2, ... // // Returns a chain & a flag for retval copy to use. SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 8> Ops; Ops.push_back(Chain); Ops.push_back(Callee); // Add argument registers to the end of the list so that they are // known live into the call. for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) Ops.push_back(DAG.getRegister(RegsToPass[i].first, RegsToPass[i].second.getValueType())); // Add a register mask operand representing the call-preserved registers. const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); const uint32_t *Mask = TRI->getCallPreservedMask(CallConv); assert(Mask && "Missing call preserved mask for calling convention"); Ops.push_back(DAG.getRegisterMask(Mask)); if (InFlag.getNode()) Ops.push_back(InFlag); Chain = DAG.getNode(Cpu0ISD::JmpLink, dl, NodeTys, &Ops[0], Ops.size()); InFlag = Chain.getValue(1); // Create the CALLSEQ_END node. Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NextStackOffset, 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, Ins, dl, DAG, InVals); #else return InChain; #endif }
/// LowerCCCArguments - transform physical registers into virtual registers and /// generate load operations for arguments places on the stack. // FIXME: struct return stuff // FIXME: varargs SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_MSP430); assert(!isVarArg && "Varargs not supported yet"); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; if (VA.isRegLoc()) { // Arguments passed in registers EVT RegVT = VA.getLocVT(); switch (RegVT.getSimpleVT().SimpleTy) { default: { #ifndef NDEBUG errs() << "LowerFormalArguments Unhandled argument type: " << RegVT.getSimpleVT().SimpleTy << "\n"; #endif llvm_unreachable(0); } case MVT::i16: unsigned VReg = RegInfo.createVirtualRegister(MSP430::GR16RegisterClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); // If this is an 8-bit value, it is really passed promoted to 16 // bits. Insert an assert[sz]ext to capture this, then truncate to the // right size. if (VA.getLocInfo() == CCValAssign::SExt) ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); else if (VA.getLocInfo() == CCValAssign::ZExt) ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); if (VA.getLocInfo() != CCValAssign::Full) ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); InVals.push_back(ArgValue); } } else { // Sanity check assert(VA.isMemLoc()); // Load the argument to a virtual register unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; if (ObjSize > 2) { errs() << "LowerFormalArguments Unhandled argument type: " << EVT(VA.getLocVT()).getEVTString() << "\n"; } // Create the frame index object for this incoming parameter... int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); // Create the SelectionDAG nodes corresponding to a load //from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, MachinePointerInfo::getFixedStack(FI), false, false, 0)); } } return Chain; }
/// LowerFormalArguments - transform physical registers into virtual registers /// and generate load operations for arguments places on the stack. SDValue Cpu0TargetLowering::LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); Cpu0FunctionInfo *Cpu0FI = MF.getInfo<Cpu0FunctionInfo>(); Cpu0FI->setVarArgsFrameIndex(0); // Used with vargs to acumulate store chains. std::vector<SDValue> OutChains; // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_Cpu0); Function::const_arg_iterator FuncArg = DAG.getMachineFunction().getFunction()->arg_begin(); int LastFI = 0;// Cpu0FI->LastInArgFI is 0 at the entry of this function. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++FuncArg) { CCValAssign &VA = ArgLocs[i]; EVT ValVT = VA.getValVT(); ISD::ArgFlagsTy Flags = Ins[i].Flags; bool IsRegLoc = VA.isRegLoc(); if (Flags.isByVal()) { #if 0 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, &*FuncArg); continue; #else assert("ByVal args of size 0 should have been ignored by front-end."); #endif } // sanity check assert(VA.isMemLoc()); // The stack pointer offset is relative to the caller stack frame. LastFI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, VA.getLocMemOffset(), true); // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy()); InVals.push_back(DAG.getLoad(ValVT, DL, Chain, FIN, MachinePointerInfo::getFixedStack(LastFI), false, false, false, 0)); } #if 1 // Without this, it will use $3 instead of $2 as return register. // The cpu0 ABIs for returning structs by value requires that we copy // the sret argument into $v0 for the return. Save the argument into // a virtual register so that we can access it from the return points. if (DAG.getMachineFunction().getFunction()->hasStructRetAttr()) { unsigned Reg = Cpu0FI->getSRetReturnReg(); if (!Reg) { Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i32)); Cpu0FI->setSRetReturnReg(Reg); } SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[0]); Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain); } #endif if (isVarArg) { unsigned NumOfRegs = 0; int FirstRegSlotOffset = 0; // offset of $a0's slot. unsigned RegSize = Cpu0::CPURegsRegClass.getSize(); int RegSlotOffset = FirstRegSlotOffset + ArgLocs.size() * RegSize; // Offset of the first variable argument from stack pointer. int FirstVaArgOffset; FirstVaArgOffset = RegSlotOffset; // Record the frame index of the first variable argument // which is a value necessary to VASTART. LastFI = MFI->CreateFixedObject(RegSize, FirstVaArgOffset, true); Cpu0FI->setVarArgsFrameIndex(LastFI); } Cpu0FI->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()) { OutChains.push_back(Chain); Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, &OutChains[0], OutChains.size()); } return Chain; }