SDValue XCoreSelectionDAGInfo:: EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const { unsigned SizeBitWidth = Size.getValueType().getSizeInBits(); // Call __memcpy_4 if the src, dst and size are all 4 byte aligned. if (!AlwaysInline && (Align & 3) == 0 && DAG.MaskedValueIsZero(Size, APInt(SizeBitWidth, 3))) { const TargetLowering &TLI = *DAG.getTarget().getTargetLowering(); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; Entry.Ty = TLI.getDataLayout()->getIntPtrType(*DAG.getContext()); Entry.Node = Dst; Args.push_back(Entry); Entry.Node = Src; Args.push_back(Entry); Entry.Node = Size; Args.push_back(Entry); TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(dl).setChain(Chain) .setCallee(TLI.getLibcallCallingConv(RTLIB::MEMCPY), Type::getVoidTy(*DAG.getContext()), DAG.getExternalSymbol("__memcpy_4", TLI.getPointerTy()), &Args, 0) .setDiscardResult(); std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI); return CallResult.second; } // Otherwise have the target-independent code call memcpy. return SDValue(); }
SDValue BPFTargetLowering::LowerCallResult( SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); // Assign locations to each value returned by this call. SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); if (Ins.size() >= 2) { DiagnosticInfoUnsupported Err(DL, *MF.getFunction(), "only small returns supported", SDValue()); DAG.getContext()->diagnose(Err); } CCInfo.AnalyzeCallResult(Ins, RetCC_BPF64); // Copy all of the result registers out of their specified physreg. for (auto &Val : RVLocs) { Chain = DAG.getCopyFromReg(Chain, DL, Val.getLocReg(), Val.getValVT(), InFlag).getValue(1); InFlag = Chain.getValue(2); InVals.push_back(Chain.getValue(0)); } return Chain; }
SDValue ARM64SelectionDAGInfo::EmitTargetCodeForMemset( SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVolatile, MachinePointerInfo DstPtrInfo) const { // Check to see if there is a specialized entry-point for memory zeroing. ConstantSDNode *V = dyn_cast<ConstantSDNode>(Src); ConstantSDNode *SizeValue = dyn_cast<ConstantSDNode>(Size); const char *bzeroEntry = (V && V->isNullValue()) ? Subtarget->getBZeroEntry() : 0; // For small size (< 256), it is not beneficial to use bzero // instead of memset. if (bzeroEntry && (!SizeValue || SizeValue->getZExtValue() > 256)) { const ARM64TargetLowering &TLI = *static_cast<const ARM64TargetLowering *>( DAG.getTarget().getTargetLowering()); EVT IntPtr = TLI.getPointerTy(); Type *IntPtrTy = getDataLayout()->getIntPtrType(*DAG.getContext()); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; Entry.Node = Dst; Entry.Ty = IntPtrTy; Args.push_back(Entry); Entry.Node = Size; Args.push_back(Entry); TargetLowering::CallLoweringInfo CLI( Chain, Type::getVoidTy(*DAG.getContext()), false, false, false, false, 0, CallingConv::C, /*isTailCall=*/false, /*doesNotRet=*/false, /*isReturnValueUsed=*/false, DAG.getExternalSymbol(bzeroEntry, IntPtr), Args, DAG, dl); std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI); return CallResult.second; } return SDValue(); }
// Adjust parameters for memset, EABI uses format (ptr, size, value), // GNU library uses (ptr, value, size) // See RTABI section 4.3.4 SDValue ARMSelectionDAGInfo:: EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVolatile, MachinePointerInfo DstPtrInfo) const { // Use default for non AAPCS (or Darwin) subtargets if (!Subtarget->isAAPCS_ABI() || Subtarget->isTargetDarwin()) return SDValue(); const ARMTargetLowering &TLI = *static_cast<const ARMTargetLowering*>(DAG.getTarget().getTargetLowering()); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; // First argument: data pointer Type *IntPtrTy = TLI.getDataLayout()->getIntPtrType(*DAG.getContext()); Entry.Node = Dst; Entry.Ty = IntPtrTy; Args.push_back(Entry); // Second argument: buffer size Entry.Node = Size; Entry.Ty = IntPtrTy; Entry.isSExt = false; Args.push_back(Entry); // Extend or truncate the argument to be an i32 value for the call. if (Src.getValueType().bitsGT(MVT::i32)) Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src); else Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src); // Third argument: value to fill Entry.Node = Src; Entry.Ty = Type::getInt32Ty(*DAG.getContext()); Entry.isSExt = true; Args.push_back(Entry); // Emit __eabi_memset call TargetLowering::CallLoweringInfo CLI(Chain, Type::getVoidTy(*DAG.getContext()), // return type false, // return sign ext false, // return zero ext false, // is var arg false, // is in regs 0, // number of fixed arguments TLI.getLibcallCallingConv(RTLIB::MEMSET), // call conv false, // is tail call false, // does not return false, // is return val used DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET), TLI.getPointerTy()), // callee Args, DAG, dl); std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI); return CallResult.second; }
SDValue BPFTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, SDLoc DL, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of the return value to a location SmallVector<CCValAssign, 16> RVLocs; MachineFunction &MF = DAG.getMachineFunction(); // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); if (MF.getFunction()->getReturnType()->isAggregateType()) { DiagnosticInfoUnsupported Err(DL, *MF.getFunction(), "only integer returns supported", SDValue()); DAG.getContext()->diagnose(Err); } // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_BPF64); SDValue Flag; SmallVector<SDValue, 4> RetOps(1, Chain); // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag); // Guarantee that all emitted copies are stuck together, // avoiding something bad. Flag = Chain.getValue(1); RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } unsigned Opc = BPFISD::RET_FLAG; RetOps[0] = Chain; // Update chain. // Add the flag if we have it. if (Flag.getNode()) RetOps.push_back(Flag); return DAG.getNode(Opc, DL, MVT::Other, RetOps); }
SDValue LanaiTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, SDLoc DL, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of the return value to a location SmallVector<CCValAssign, 16> RVLocs; // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, *DAG.getContext()); // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_Lanai32); SDValue Flag; SmallVector<SDValue, 4> RetOps(1, Chain); // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag); // Guarantee that all emitted copies are stuck together with flags. Flag = Chain.getValue(1); RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } // The Lanai ABI for returning structs by value requires that we copy // the sret argument into rv for the return. We saved the argument into // a virtual register in the entry block, so now we copy the value out // and into rv. if (DAG.getMachineFunction().getFunction()->hasStructRetAttr()) { MachineFunction &MF = DAG.getMachineFunction(); LanaiMachineFunctionInfo *LanaiMFI = MF.getInfo<LanaiMachineFunctionInfo>(); unsigned Reg = LanaiMFI->getSRetReturnReg(); assert(Reg && "SRetReturnReg should have been set in LowerFormalArguments()."); SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(DAG.getDataLayout())); Chain = DAG.getCopyToReg(Chain, DL, Lanai::RV, Val, Flag); Flag = Chain.getValue(1); RetOps.push_back( DAG.getRegister(Lanai::RV, getPointerTy(DAG.getDataLayout()))); } RetOps[0] = Chain; // Update chain unsigned Opc = LanaiISD::RET_FLAG; if (Flag.getNode()) RetOps.push_back(Flag); // Return Void return DAG.getNode(Opc, DL, MVT::Other, ArrayRef<SDValue>(&RetOps[0], RetOps.size())); }
SDValue Y86TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { // Assign locations to each value returned by this call. SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, *DAG.getContext()); CCInfo.AnalyzeCallResult(Ins, RetCC_Y86); // Copy all of the result registers out of their specified physreg. for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { CCValAssign &VA = RVLocs[i]; EVT CopyVT = VA.getValVT(); Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), CopyVT, InFlag).getValue(1); InFlag = Chain.getValue(2); InVals.push_back(Chain.getValue(0)); } return Chain; }
SDValue BlackfinTargetLowering::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(); SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 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().getStoreSize(); int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, MachinePointerInfo(), false, false, 0)); } } return Chain; }
SDValue BlackfinTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, DebugLoc dl, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of the return value to locations. SmallVector<CCValAssign, 16> RVLocs; // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), DAG.getTarget(), RVLocs, *DAG.getContext()); // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_Blackfin); // If this is the first return lowered for this function, add the regs to the // liveout set for the function. if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); } SDValue Flag; // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); SDValue Opi = OutVals[i]; // Expand to i32 if necessary switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: break; case CCValAssign::SExt: Opi = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Opi); break; case CCValAssign::ZExt: Opi = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Opi); break; case CCValAssign::AExt: Opi = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Opi); break; } Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Opi, SDValue()); // Guarantee that all emitted copies are stuck together with flags. Flag = Chain.getValue(1); } if (Flag.getNode()) { return DAG.getNode(BFISD::RET_FLAG, dl, MVT::Other, Chain, Flag); } else { return DAG.getNode(BFISD::RET_FLAG, dl, MVT::Other, Chain); } }
SDValue PTXTargetLowering:: LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, DebugLoc dl, SelectionDAG &DAG) const { if (isVarArg) llvm_unreachable("PTX does not support varargs"); switch (CallConv) { default: llvm_unreachable("Unsupported calling convention."); case CallingConv::PTX_Kernel: assert(Outs.size() == 0 && "Kernel must return void."); return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain); case CallingConv::PTX_Device: //assert(Outs.size() <= 1 && "Can at most return one value."); break; } MachineFunction& MF = DAG.getMachineFunction(); PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>(); SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), RVLocs, *DAG.getContext()); SDValue Flag; CCInfo.AnalyzeReturn(Outs, RetCC_PTX); for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { CCValAssign& VA = RVLocs[i]; assert(VA.isRegLoc() && "CCValAssign must be RegLoc"); unsigned Reg = VA.getLocReg(); DAG.getMachineFunction().getRegInfo().addLiveOut(Reg); Chain = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i], Flag); // Guarantee that all emitted copies are stuck together, // avoiding something bad Flag = Chain.getValue(1); MFI->addRetReg(Reg); } if (Flag.getNode() == 0) { return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain); } else { return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag); } }
static void fail(SDLoc DL, SelectionDAG &DAG, const char *Msg, SDValue Val) { MachineFunction &MF = DAG.getMachineFunction(); std::string Str; raw_string_ostream OS(Str); OS << Msg; Val->print(OS); OS.flush(); DAG.getContext()->diagnose( DiagnosticInfoUnsupported(*MF.getFunction(), Str, DL.getDebugLoc())); }
SDValue SystemZTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, DebugLoc dl, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of the return value to a location SmallVector<CCValAssign, 16> RVLocs; // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), RVLocs, *DAG.getContext()); // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_SystemZ); // If this is the first return lowered for this function, add the regs to the // liveout set for the function. if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) if (RVLocs[i].isRegLoc()) DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); } SDValue Flag; // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; SDValue ResValue = OutVals[i]; assert(VA.isRegLoc() && "Can only return in registers!"); // If this is an 8/16/32-bit value, it is really should be passed promoted // to 64 bits. if (VA.getLocInfo() == CCValAssign::SExt) ResValue = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), ResValue); else if (VA.getLocInfo() == CCValAssign::ZExt) ResValue = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), ResValue); else if (VA.getLocInfo() == CCValAssign::AExt) ResValue = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), ResValue); Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), ResValue, Flag); // Guarantee that all emitted copies are stuck together, // avoiding something bad. Flag = Chain.getValue(1); } if (Flag.getNode()) return DAG.getNode(SystemZISD::RET_FLAG, dl, MVT::Other, Chain, Flag); // Return Void return DAG.getNode(SystemZISD::RET_FLAG, dl, MVT::Other, Chain); }
SDValue MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, DebugLoc dl, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of the return value to a location SmallVector<CCValAssign, 16> RVLocs; // ISRs cannot return any value. if (CallConv == CallingConv::MSP430_INTR && !Outs.empty()) { report_fatal_error("ISRs cannot return any value"); return SDValue(); } // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext()); // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_MSP430); // If this is the first return lowered for this function, add the regs to the // liveout set for the function. if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) if (RVLocs[i].isRegLoc()) DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); } SDValue Flag; // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); // Guarantee that all emitted copies are stuck together, // avoiding something bad. Flag = Chain.getValue(1); } unsigned Opc = (CallConv == CallingConv::MSP430_INTR ? MSP430ISD::RETI_FLAG : MSP430ISD::RET_FLAG); if (Flag.getNode()) return DAG.getNode(Opc, dl, MVT::Other, Chain, Flag); // Return Void return DAG.getNode(Opc, dl, MVT::Other, Chain); }
SDValue HexagonSelectionDAGInfo::EmitTargetCodeForMemcpy( SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const { ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); if (AlwaysInline || (Align & 0x3) != 0 || !ConstantSize) return SDValue(); uint64_t SizeVal = ConstantSize->getZExtValue(); if (SizeVal < 32 || (SizeVal % 8) != 0) return SDValue(); // Special case aligned memcpys with size >= 32 bytes and a multiple of 8. // const TargetLowering &TLI = *DAG.getSubtarget().getTargetLowering(); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; Entry.Ty = DAG.getDataLayout().getIntPtrType(*DAG.getContext()); Entry.Node = Dst; Args.push_back(Entry); Entry.Node = Src; Args.push_back(Entry); Entry.Node = Size; Args.push_back(Entry); const char *SpecialMemcpyName = "__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes"; TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(dl) .setChain(Chain) .setCallee(TLI.getLibcallCallingConv(RTLIB::MEMCPY), Type::getVoidTy(*DAG.getContext()), DAG.getTargetExternalSymbol( SpecialMemcpyName, TLI.getPointerTy(DAG.getDataLayout())), std::move(Args)) .setDiscardResult(); std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI); return CallResult.second; }
SDValue VectorProcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, DebugLoc DL, SelectionDAG &DAG) const { MachineFunction &MF = DAG.getMachineFunction(); // CCValAssign - represent the assignment of the return value to locations. SmallVector<CCValAssign, 16> RVLocs; // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), DAG.getTarget(), RVLocs, *DAG.getContext()); // Analyze return values. CCInfo.AnalyzeReturn(Outs, RetCC_VectorProc32); SDValue Flag; SmallVector<SDValue, 4> RetOps(1, Chain); // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag); // Guarantee that all emitted copies are stuck together with flags. Flag = Chain.getValue(1); RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } if (MF.getFunction()->hasStructRetAttr()) { VectorProcMachineFunctionInfo *SFI = MF.getInfo<VectorProcMachineFunctionInfo>(); unsigned Reg = SFI->getSRetReturnReg(); if (!Reg) llvm_unreachable("sret virtual register not created in the entry block"); SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy()); Chain = DAG.getCopyToReg(Chain, DL, VectorProc::S0, Val, Flag); Flag = Chain.getValue(1); RetOps.push_back(DAG.getRegister(VectorProc::S0, getPointerTy())); } RetOps[0] = Chain; // Update chain. // Add the flag if we have it. if (Flag.getNode()) RetOps.push_back(Flag); return DAG.getNode(VectorProcISD::RET_FLAG, DL, MVT::Other, &RetOps[0], RetOps.size()); }
SDValue ARCompactTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, DebugLoc dl, SelectionDAG &DAG) const { //DEBUG(dbgs() << "ARCompactTargetLowering::LowerReturn()\n"); MachineFunction &MF = DAG.getMachineFunction(); // CCValAssign - represent the assignment of the return value to locations. SmallVector<CCValAssign, 16> RVLocs; // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), DAG.getTarget(), RVLocs, *DAG.getContext()); // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_ARCompact32); // If this is the first return lowered for this function, add the regs to the // liveout set for the function. if (MF.getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) if (RVLocs[i].isRegLoc()) { MF.getRegInfo().addLiveOut(RVLocs[i].getLocReg()); } } SDValue Flag; // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); // Guarantee that all emitted copies are stuck together with flags. Flag = Chain.getValue(1); } // TODO: Check this value. unsigned int RetAddrOffset = 8; // Call Instruction + Delay Slot SDValue RetAddrOffsetNode = DAG.getConstant(RetAddrOffset, MVT::i32); if (Flag.getNode()) { return DAG.getNode(ARCISD::RET_FLAG, dl, MVT::Other, Chain, RetAddrOffsetNode, Flag); } return DAG.getNode(ARCISD::RET_FLAG, dl, MVT::Other, Chain, RetAddrOffsetNode); }
SDValue MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of the return value to a location SmallVector<CCValAssign, 16> RVLocs; // ISRs cannot return any value. if (CallConv == CallingConv::MSP430_INTR && !Outs.empty()) report_fatal_error("ISRs cannot return any value"); // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, *DAG.getContext()); // Analize return values. AnalyzeReturnValues(CCInfo, RVLocs, Outs); SDValue Flag; SmallVector<SDValue, 4> RetOps(1, Chain); // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); // Guarantee that all emitted copies are stuck together, // avoiding something bad. Flag = Chain.getValue(1); RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } unsigned Opc = (CallConv == CallingConv::MSP430_INTR ? MSP430ISD::RETI_FLAG : MSP430ISD::RET_FLAG); RetOps[0] = Chain; // Update chain. // Add the flag if we have it. if (Flag.getNode()) RetOps.push_back(Flag); return DAG.getNode(Opc, dl, MVT::Other, RetOps); }
SDValue MBlazeTargetLowering:: LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, DebugLoc dl, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of // the return value to a location SmallVector<CCValAssign, 16> RVLocs; // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext()); // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_MBlaze); // If this is the first return lowered for this function, add // the regs to the liveout set for the function. if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) if (RVLocs[i].isRegLoc()) DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); } SDValue Flag; // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); // guarantee that all emitted copies are // stuck together, avoiding something bad Flag = Chain.getValue(1); } // Return on MBlaze is always a "rtsd R15, 8" if (Flag.getNode()) return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other, Chain, DAG.getRegister(MBlaze::R15, MVT::i32), Flag); else // Return Void return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other, Chain, DAG.getRegister(MBlaze::R15, MVT::i32)); }
void VDAGToDAGISel::LowerADDEForISel(SDNode *N, SelectionDAG &DAG) { SDValue LHS = N->getOperand(0), RHS = N->getOperand(1), C = N->getOperand(2); unsigned OpSize = VTargetLowering::computeSizeInBits(LHS); unsigned AddSize = OpSize + 1; DebugLoc dl = N->getDebugLoc(); LLVMContext &Cntx = *DAG.getContext(); EVT VT = LHS.getValueType(), NewVT = VTargetLowering::getRoundIntegerOrBitType(AddSize, Cntx); SDValue NewAdd = DAG.getNode(VTMISD::ADDCS, dl, NewVT, LHS, RHS, C); SDValue NewValues[] = { VTargetLowering::getBitSlice(DAG, dl, NewAdd, OpSize, 0), VTargetLowering::getBitSlice(DAG, dl, NewAdd, OpSize + 1, OpSize) }; DAG.ReplaceAllUsesWith(N, NewValues); }
void VDAGToDAGISel::LowerICmpForISel(SDNode *N, SelectionDAG &DAG) { CondCodeSDNode *CCNode = cast<CondCodeSDNode>(N->getOperand(2)); DebugLoc dl = N->getDebugLoc(); LLVMContext &Cntx = *DAG.getContext(); SDValue LHS = N->getOperand(0), RHS = N->getOperand(1); unsigned OpSize = VTargetLowering::computeSizeInBits(LHS); //assert(OpSize > 1 && "Unexpected 1bit comparison!"); EVT FUVT = EVT::getIntegerVT(Cntx, OpSize); ISD::CondCode CC = CCNode->get(); switch (CC) { case ISD::SETEQ: case ISD::SETNE: case ISD::SETGT: case ISD::SETGE: case ISD::SETUGT: case ISD::SETUGE: break; case ISD::SETLT: case ISD::SETLE: case ISD::SETULT: case ISD::SETULE: CC = ISD::getSetCCSwappedOperands(CC); std::swap(LHS, RHS); break; default: llvm_unreachable("Unexpected CondCode!"); } unsigned CCNum = (CC == ISD::SETEQ || CC == ISD::SETNE) ? VFUs::CmpEQ : (ISD::isSignedIntSetCC(CC) ? VFUs::CmpSigned : VFUs::CmpUnsigned); SDValue NewICmp = DAG.getNode(VTMISD::ICmp, dl, MVT::i8, LHS, RHS, DAG.getTargetConstant(CCNum, FUVT)); // Read the result from specific bit of the result. unsigned ResultPort = getICmpPort(CC); DAG.ReplaceAllUsesWith(SDValue(N, 0), VTargetLowering::getBitSlice(DAG, dl, NewICmp, ResultPort + 1, ResultPort, N->getValueSizeInBits(0))); }
/// LowerCallResult - Lower the result values of a call into the /// appropriate copies out of appropriate physical registers. /// SDValue SystemZTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) { // Assign locations to each value returned by this call. SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs, *DAG.getContext()); CCInfo.AnalyzeCallResult(Ins, RetCC_SystemZ); // Copy all of the result registers out of their specified physreg. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), InFlag).getValue(1); SDValue RetValue = Chain.getValue(0); InFlag = Chain.getValue(2); // 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) RetValue = DAG.getNode(ISD::AssertSext, dl, VA.getLocVT(), RetValue, DAG.getValueType(VA.getValVT())); else if (VA.getLocInfo() == CCValAssign::ZExt) RetValue = DAG.getNode(ISD::AssertZext, dl, VA.getLocVT(), RetValue, DAG.getValueType(VA.getValVT())); if (VA.getLocInfo() != CCValAssign::Full) RetValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RetValue); InVals.push_back(RetValue); } return Chain; }
SDValue SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, DebugLoc dl, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of the return value to locations. SmallVector<CCValAssign, 16> RVLocs; // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), RVLocs, *DAG.getContext()); // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32); // If this is the first return lowered for this function, add the regs to the // liveout set for the function. if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) if (RVLocs[i].isRegLoc()) DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); } SDValue Flag; // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Outs[i].Val, Flag); // Guarantee that all emitted copies are stuck together with flags. Flag = Chain.getValue(1); } if (Flag.getNode()) return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, Flag); return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain); }
void VDAGToDAGISel::LowerUMUL_LOHIForISel(SDNode *N, SelectionDAG &DAG){ SDValue LHS = N->getOperand(0), RHS = N->getOperand(1); unsigned OpSize = VTargetLowering::computeSizeInBits(LHS); unsigned MulSize = OpSize * 2; assert(MulSize <= 64 && "Unsupported multiplier width!"); DebugLoc dl = N->getDebugLoc(); LLVMContext &Cntx = *DAG.getContext(); EVT VT = LHS.getValueType(), NewVT = VTargetLowering::getRoundIntegerOrBitType(MulSize, Cntx); SDValue NewMul = DAG.getNode(VTMISD::MULHiLo, dl, NewVT, LHS, RHS); SDValue NewValues[] = { VTargetLowering::getBitSlice(DAG, dl, NewMul, OpSize, 0), VTargetLowering::getBitSlice(DAG, dl, NewMul, MulSize, OpSize) }; DAG.ReplaceAllUsesWith(N, NewValues); }
// LowerCallResult - Lower the result values of a call into the // appropriate copies out of appropriate physical registers. SDValue LanaiTargetLowering::LowerCallResult( SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { // Assign locations to each value returned by this call. SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, *DAG.getContext()); CCInfo.AnalyzeCallResult(Ins, RetCC_Lanai32); // Copy all of the result registers out of their specified physreg. for (unsigned I = 0; I != RVLocs.size(); ++I) { Chain = DAG.getCopyFromReg(Chain, DL, RVLocs[I].getLocReg(), RVLocs[I].getValVT(), InFlag) .getValue(1); InFlag = Chain.getValue(2); InVals.push_back(Chain.getValue(0)); } return Chain; }
SDValue Y86TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, SDLoc dl, SelectionDAG &DAG) const { MachineFunction &MF = DAG.getMachineFunction(); // Gather info about the return values. SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, isVarArg, MF, RVLocs, *DAG.getContext()); CCInfo.AnalyzeReturn(Outs, RetCC_Y86); SDValue Flag; SmallVector<SDValue, 6> RetOps(1, Chain); // Operand 0 is the chain. // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); SDValue ValToCopy = OutVals[i]; Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), ValToCopy, Flag); Flag = Chain.getValue(1); // Copies are glued together with flags. RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } RetOps[0] = Chain; // Update the chain. // Add the flag if we have it. if (Flag.getNode()) RetOps.push_back(Flag); return DAG.getNode(Y86ISD::RET_FLAG, dl, MVT::Other, RetOps); }
/// LowerCCCCallTo - functions arguments are copied from virtual regs to /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. /// TODO: sret. SDValue MSP430TargetLowering::LowerCCCCallTo(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 { // 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_MSP430); // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes, getPointerTy(), true)); SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; SmallVector<SDValue, 12> MemOpChains; SDValue StackPtr; // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; 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, VA.getLocVT(), Arg); break; case CCValAssign::ZExt: Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); break; case CCValAssign::AExt: Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), 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 { assert(VA.isMemLoc()); if (StackPtr.getNode() == 0) StackPtr = DAG.getCopyFromReg(Chain, dl, MSP430::SPW, getPointerTy()); SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, DAG.getIntPtrConstant(VA.getLocMemOffset())); MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo(),false, false, 0)); } } // 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 emitted 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 node (quite common, every direct call is) // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. // Likewise ExternalSymbol -> TargetExternalSymbol. if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i16); else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i16); // 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())); if (InFlag.getNode()) Ops.push_back(InFlag); Chain = DAG.getNode(MSP430ISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); InFlag = Chain.getValue(1); // Create the CALLSEQ_END node. Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, getPointerTy(), true), DAG.getConstant(0, getPointerTy(), 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); }
/// 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; }
/// 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 BPFTargetLowering::LowerFormalArguments( SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, 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.getSimpleVT().SimpleTy << '\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 { DiagnosticInfoUnsupported Err(DL, *MF.getFunction(), "defined with too many args", SDValue()); DAG.getContext()->diagnose(Err); } } if (IsVarArg || MF.getFunction()->hasStructRetAttr()) { DiagnosticInfoUnsupported Err( DL, *MF.getFunction(), "functions with VarArgs or StructRet are not supported", SDValue()); DAG.getContext()->diagnose(Err); } return Chain; }
// Emit, if possible, a specialized version of the given Libcall. Typically this // means selecting the appropriately aligned version, but we also convert memset // of 0 into memclr. SDValue ARMSelectionDAGInfo::EmitSpecializedLibcall( SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, RTLIB::Libcall LC) const { const ARMSubtarget &Subtarget = DAG.getMachineFunction().getSubtarget<ARMSubtarget>(); const ARMTargetLowering *TLI = Subtarget.getTargetLowering(); // Only use a specialized AEABI function if the default version of this // Libcall is an AEABI function. if (std::strncmp(TLI->getLibcallName(LC), "__aeabi", 7) != 0) return SDValue(); // Translate RTLIB::Libcall to AEABILibcall. We only do this in order to be // able to translate memset to memclr and use the value to index the function // name array. enum { AEABI_MEMCPY = 0, AEABI_MEMMOVE, AEABI_MEMSET, AEABI_MEMCLR } AEABILibcall; switch (LC) { case RTLIB::MEMCPY: AEABILibcall = AEABI_MEMCPY; break; case RTLIB::MEMMOVE: AEABILibcall = AEABI_MEMMOVE; break; case RTLIB::MEMSET: AEABILibcall = AEABI_MEMSET; if (ConstantSDNode *ConstantSrc = dyn_cast<ConstantSDNode>(Src)) if (ConstantSrc->getZExtValue() == 0) AEABILibcall = AEABI_MEMCLR; break; default: return SDValue(); } // Choose the most-aligned libcall variant that we can enum { ALIGN1 = 0, ALIGN4, ALIGN8 } AlignVariant; if ((Align & 7) == 0) AlignVariant = ALIGN8; else if ((Align & 3) == 0) AlignVariant = ALIGN4; else AlignVariant = ALIGN1; TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; Entry.Ty = DAG.getDataLayout().getIntPtrType(*DAG.getContext()); Entry.Node = Dst; Args.push_back(Entry); if (AEABILibcall == AEABI_MEMCLR) { Entry.Node = Size; Args.push_back(Entry); } else if (AEABILibcall == AEABI_MEMSET) { // Adjust parameters for memset, EABI uses format (ptr, size, value), // GNU library uses (ptr, value, size) // See RTABI section 4.3.4 Entry.Node = Size; Args.push_back(Entry); // Extend or truncate the argument to be an i32 value for the call. if (Src.getValueType().bitsGT(MVT::i32)) Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src); else if (Src.getValueType().bitsLT(MVT::i32)) Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src); Entry.Node = Src; Entry.Ty = Type::getInt32Ty(*DAG.getContext()); Entry.IsSExt = false; Args.push_back(Entry); } else { Entry.Node = Src; Args.push_back(Entry); Entry.Node = Size; Args.push_back(Entry); } char const *FunctionNames[4][3] = { { "__aeabi_memcpy", "__aeabi_memcpy4", "__aeabi_memcpy8" }, { "__aeabi_memmove", "__aeabi_memmove4", "__aeabi_memmove8" }, { "__aeabi_memset", "__aeabi_memset4", "__aeabi_memset8" }, { "__aeabi_memclr", "__aeabi_memclr4", "__aeabi_memclr8" } }; TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(dl) .setChain(Chain) .setLibCallee( TLI->getLibcallCallingConv(LC), Type::getVoidTy(*DAG.getContext()), DAG.getExternalSymbol(FunctionNames[AEABILibcall][AlignVariant], TLI->getPointerTy(DAG.getDataLayout())), std::move(Args)) .setDiscardResult(); std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI); return CallResult.second; }