/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node, /// incorporating info about the formals into this state. void Hexagon_CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, Hexagon_CCAssignFn Fn, unsigned SretValueInRegs) { unsigned NumArgs = Ins.size(); unsigned i = 0; // If the function returns a small struct in registers, skip // over the first (dummy) argument. if (SretValueInRegs != 0) { ++i; } for (; i != NumArgs; ++i) { EVT ArgVT = Ins[i].VT; ISD::ArgFlagsTy ArgFlags = Ins[i].Flags; if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, 0, 0, false)) { dbgs() << "Formal argument #" << i << " has unhandled type " << ArgVT.getEVTString() << "\n"; abort(); } } }
/// AnalyzeReturn - Analyze the returned values of an ISD::RET node, /// incorporating info about the result values into this state. void Hexagon_CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, Hexagon_CCAssignFn Fn, unsigned SretValueInRegs) { // For Hexagon, Return small structures in registers. if (SretValueInRegs != 0) { if (SretValueInRegs <= 32) { unsigned Reg = Hexagon::R0; addLoc(CCValAssign::getReg(0, MVT::i32, Reg, MVT::i32, CCValAssign::Full)); return; } if (SretValueInRegs <= 64) { unsigned Reg = Hexagon::D0; addLoc(CCValAssign::getReg(0, MVT::i64, Reg, MVT::i64, CCValAssign::Full)); return; } } // Determine which register each value should be copied into. for (unsigned i = 0, e = Outs.size(); i != e; ++i) { EVT VT = Outs[i].VT; ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this, -1, -1, false)){ dbgs() << "Return operand #" << i << " has unhandled type " << VT.getEVTString() << "\n"; abort(); } } }
/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info /// about the passed values into this state. void Hexagon_CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, Hexagon_CCAssignFn Fn, int NonVarArgsParams, unsigned SretValueSize) { unsigned NumOps = Outs.size(); unsigned i = 0; // If the called function returns a small struct in registers, skip // the first actual parameter. We do not want to pass a pointer to // the stack location. if (SretValueSize != 0) { ++i; } for (; i != NumOps; ++i) { EVT ArgVT = Outs[i].VT; ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, NonVarArgsParams, i+1, false)) { dbgs() << "Call operand #" << i << " has unhandled type " << ArgVT.getEVTString() << "\n"; abort(); } } }
/// AnalyzeCallResult - Same as above except it's specialized for calls which /// produce a single value. void Hexagon_CCState::AnalyzeCallResult(EVT VT, Hexagon_CCAssignFn Fn) { if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this, -1, -1, false)) { dbgs() << "Call result has unhandled type " << VT.getEVTString() << "\n"; abort(); } }
/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node, /// incorporating info about the passed values into this state. void Hexagon_CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, Hexagon_CCAssignFn Fn, unsigned SretValueInRegs) { for (unsigned i = 0, e = Ins.size(); i != e; ++i) { EVT VT = Ins[i].VT; ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this, -1, -1, false)) { dbgs() << "Call result #" << i << " has unhandled type " << VT.getEVTString() << "\n"; abort(); } } }
/// AnalyzeCallOperands - Same as above except it takes vectors of types /// and argument flags. void Hexagon_CCState::AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs, SmallVectorImpl<ISD::ArgFlagsTy> &Flags, Hexagon_CCAssignFn Fn) { unsigned NumOps = ArgVTs.size(); for (unsigned i = 0; i != NumOps; ++i) { EVT ArgVT = ArgVTs[i]; ISD::ArgFlagsTy ArgFlags = Flags[i]; if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, -1, -1, false)) { dbgs() << "Call operand #" << i << " has unhandled type " << ArgVT.getEVTString() << "\n"; abort(); } } }
/// LowerCCCArguments - transform physical registers into virtual registers and /// generate load operations for arguments places on the stack. // FIXME: struct return stuff SDValue MSP430TargetLowering::LowerCCCArguments( SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext()); AnalyzeArguments(CCInfo, ArgLocs, Ins); // Create frame index for the start of the first vararg value if (isVarArg) { unsigned Offset = CCInfo.getNextStackOffset(); FuncInfo->setVarArgsFrameIndex(MFI->CreateFixedObject(1, Offset, true)); } 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.getEVTString() << "\n"; #endif llvm_unreachable(nullptr); } case MVT::i16: unsigned VReg = RegInfo.createVirtualRegister(&MSP430::GR16RegClass); 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()); SDValue InVal; ISD::ArgFlagsTy Flags = Ins[i].Flags; if (Flags.isByVal()) { int FI = MFI->CreateFixedObject(Flags.getByValSize(), VA.getLocMemOffset(), true); InVal = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); } else { // 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); InVal = DAG.getLoad( VA.getLocVT(), dl, Chain, FIN, MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), false, false, false, 0); } InVals.push_back(InVal); } } return Chain; }
SDValue BPFTargetLowering::LowerFormalArguments( SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { switch (CallConv) { default: llvm_unreachable("Unsupported calling convention"); case CallingConv::C: case CallingConv::Fast: break; } MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_BPF64); for (auto &VA : ArgLocs) { if (VA.isRegLoc()) { // Arguments passed in registers EVT RegVT = VA.getLocVT(); switch (RegVT.getSimpleVT().SimpleTy) { default: { errs() << "LowerFormalArguments Unhandled argument type: " << RegVT.getEVTString() << '\n'; llvm_unreachable(0); } case MVT::i64: unsigned VReg = RegInfo.createVirtualRegister(&BPF::GPRRegClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, VReg, RegVT); // 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, 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 { fail(DL, DAG, "defined with too many args"); InVals.push_back(DAG.getConstant(0, DL, VA.getLocVT())); } } if (IsVarArg || MF.getFunction()->hasStructRetAttr()) { fail(DL, DAG, "functions with VarArgs or StructRet are not supported"); } return Chain; }
// 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, const 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.getEVTString() << "\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; }