1349cc55cSDimitry Andric //===-- CSKYISelLowering.cpp - CSKY DAG Lowering Implementation ----------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric // 9349cc55cSDimitry Andric // This file defines the interfaces that CSKY uses to lower LLVM code into a 10349cc55cSDimitry Andric // selection DAG. 11349cc55cSDimitry Andric // 12349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 13349cc55cSDimitry Andric 14349cc55cSDimitry Andric #include "CSKYISelLowering.h" 15349cc55cSDimitry Andric #include "CSKYCallingConv.h" 16349cc55cSDimitry Andric #include "CSKYMachineFunctionInfo.h" 17349cc55cSDimitry Andric #include "CSKYRegisterInfo.h" 18349cc55cSDimitry Andric #include "CSKYSubtarget.h" 19349cc55cSDimitry Andric #include "llvm/ADT/Statistic.h" 20349cc55cSDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 21349cc55cSDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h" 22349cc55cSDimitry Andric #include "llvm/Support/Debug.h" 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric using namespace llvm; 25349cc55cSDimitry Andric 26349cc55cSDimitry Andric #define DEBUG_TYPE "csky-isel-lowering" 27349cc55cSDimitry Andric 28349cc55cSDimitry Andric STATISTIC(NumTailCalls, "Number of tail calls"); 29349cc55cSDimitry Andric 30349cc55cSDimitry Andric #include "CSKYGenCallingConv.inc" 31349cc55cSDimitry Andric 32349cc55cSDimitry Andric static const MCPhysReg GPRArgRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3}; 33349cc55cSDimitry Andric 34349cc55cSDimitry Andric CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM, 35349cc55cSDimitry Andric const CSKYSubtarget &STI) 36349cc55cSDimitry Andric : TargetLowering(TM), Subtarget(STI) { 37349cc55cSDimitry Andric // Register Class 38349cc55cSDimitry Andric addRegisterClass(MVT::i32, &CSKY::GPRRegClass); 39349cc55cSDimitry Andric 40*0eae32dcSDimitry Andric setOperationAction(ISD::ADDCARRY, MVT::i32, Legal); 41*0eae32dcSDimitry Andric setOperationAction(ISD::SUBCARRY, MVT::i32, Legal); 42*0eae32dcSDimitry Andric setOperationAction(ISD::BITREVERSE, MVT::i32, Legal); 43*0eae32dcSDimitry Andric 44*0eae32dcSDimitry Andric setOperationAction(ISD::SREM, MVT::i32, Expand); 45*0eae32dcSDimitry Andric setOperationAction(ISD::UREM, MVT::i32, Expand); 46*0eae32dcSDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i32, Expand); 47*0eae32dcSDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i32, Expand); 48*0eae32dcSDimitry Andric setOperationAction(ISD::CTTZ, MVT::i32, Expand); 49*0eae32dcSDimitry Andric setOperationAction(ISD::CTPOP, MVT::i32, Expand); 50*0eae32dcSDimitry Andric setOperationAction(ISD::ROTR, MVT::i32, Expand); 51*0eae32dcSDimitry Andric setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 52*0eae32dcSDimitry Andric setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 53*0eae32dcSDimitry Andric setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 54*0eae32dcSDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); 55*0eae32dcSDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); 56*0eae32dcSDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); 57*0eae32dcSDimitry Andric setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 58*0eae32dcSDimitry Andric setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 59*0eae32dcSDimitry Andric setOperationAction(ISD::MULHS, MVT::i32, Expand); 60*0eae32dcSDimitry Andric setOperationAction(ISD::MULHU, MVT::i32, Expand); 61*0eae32dcSDimitry Andric 62*0eae32dcSDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote); 63*0eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote); 64*0eae32dcSDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote); 65*0eae32dcSDimitry Andric 66*0eae32dcSDimitry Andric if (!Subtarget.hasE2()) { 67*0eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand); 68*0eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand); 69*0eae32dcSDimitry Andric setOperationAction(ISD::CTLZ, MVT::i32, Expand); 70*0eae32dcSDimitry Andric setOperationAction(ISD::BSWAP, MVT::i32, Expand); 71*0eae32dcSDimitry Andric } 72*0eae32dcSDimitry Andric 73*0eae32dcSDimitry Andric if (!Subtarget.has2E3()) { 74*0eae32dcSDimitry Andric setOperationAction(ISD::ABS, MVT::i32, Expand); 75*0eae32dcSDimitry Andric setOperationAction(ISD::BITREVERSE, MVT::i32, Expand); 76*0eae32dcSDimitry Andric setOperationAction(ISD::SDIV, MVT::i32, Expand); 77*0eae32dcSDimitry Andric setOperationAction(ISD::UDIV, MVT::i32, Expand); 78*0eae32dcSDimitry Andric } 79*0eae32dcSDimitry Andric 80349cc55cSDimitry Andric // Compute derived properties from the register classes. 81349cc55cSDimitry Andric computeRegisterProperties(STI.getRegisterInfo()); 82349cc55cSDimitry Andric 83349cc55cSDimitry Andric setBooleanContents(UndefinedBooleanContent); 84349cc55cSDimitry Andric setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); 85349cc55cSDimitry Andric 86349cc55cSDimitry Andric // TODO: Add atomic support fully. 87349cc55cSDimitry Andric setMaxAtomicSizeInBitsSupported(0); 88349cc55cSDimitry Andric 89349cc55cSDimitry Andric setStackPointerRegisterToSaveRestore(CSKY::R14); 90349cc55cSDimitry Andric const Align FunctionAlignment(2); 91349cc55cSDimitry Andric setMinFunctionAlignment(FunctionAlignment); 92349cc55cSDimitry Andric setSchedulingPreference(Sched::Source); 93349cc55cSDimitry Andric } 94349cc55cSDimitry Andric 95349cc55cSDimitry Andric EVT CSKYTargetLowering::getSetCCResultType(const DataLayout &DL, 96349cc55cSDimitry Andric LLVMContext &Context, EVT VT) const { 97349cc55cSDimitry Andric if (!VT.isVector()) 98349cc55cSDimitry Andric return MVT::i32; 99349cc55cSDimitry Andric 100349cc55cSDimitry Andric return VT.changeVectorElementTypeToInteger(); 101349cc55cSDimitry Andric } 102349cc55cSDimitry Andric 103349cc55cSDimitry Andric static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, 104349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 105349cc55cSDimitry Andric EVT LocVT = VA.getLocVT(); 106349cc55cSDimitry Andric 107349cc55cSDimitry Andric switch (VA.getLocInfo()) { 108349cc55cSDimitry Andric default: 109349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo"); 110349cc55cSDimitry Andric case CCValAssign::Full: 111349cc55cSDimitry Andric break; 112349cc55cSDimitry Andric case CCValAssign::BCvt: 113349cc55cSDimitry Andric Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val); 114349cc55cSDimitry Andric break; 115349cc55cSDimitry Andric } 116349cc55cSDimitry Andric return Val; 117349cc55cSDimitry Andric } 118349cc55cSDimitry Andric 119349cc55cSDimitry Andric static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, 120349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 121349cc55cSDimitry Andric switch (VA.getLocInfo()) { 122349cc55cSDimitry Andric default: 123349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo"); 124349cc55cSDimitry Andric case CCValAssign::Full: 125349cc55cSDimitry Andric break; 126349cc55cSDimitry Andric case CCValAssign::BCvt: 127349cc55cSDimitry Andric Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val); 128349cc55cSDimitry Andric break; 129349cc55cSDimitry Andric } 130349cc55cSDimitry Andric return Val; 131349cc55cSDimitry Andric } 132349cc55cSDimitry Andric 133349cc55cSDimitry Andric static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, 134349cc55cSDimitry Andric SelectionDAG &DAG, SDValue Chain, 135349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 136349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 137349cc55cSDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 138349cc55cSDimitry Andric EVT LocVT = VA.getLocVT(); 139349cc55cSDimitry Andric SDValue Val; 140349cc55cSDimitry Andric const TargetRegisterClass *RC; 141349cc55cSDimitry Andric 142349cc55cSDimitry Andric switch (LocVT.getSimpleVT().SimpleTy) { 143349cc55cSDimitry Andric default: 144349cc55cSDimitry Andric llvm_unreachable("Unexpected register type"); 145349cc55cSDimitry Andric case MVT::i32: 146349cc55cSDimitry Andric RC = &CSKY::GPRRegClass; 147349cc55cSDimitry Andric break; 148349cc55cSDimitry Andric } 149349cc55cSDimitry Andric 150349cc55cSDimitry Andric Register VReg = RegInfo.createVirtualRegister(RC); 151349cc55cSDimitry Andric RegInfo.addLiveIn(VA.getLocReg(), VReg); 152349cc55cSDimitry Andric Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT); 153349cc55cSDimitry Andric 154349cc55cSDimitry Andric return convertLocVTToValVT(DAG, Val, VA, DL); 155349cc55cSDimitry Andric } 156349cc55cSDimitry Andric 157349cc55cSDimitry Andric static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, 158349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 159349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 160349cc55cSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 161349cc55cSDimitry Andric EVT LocVT = VA.getLocVT(); 162349cc55cSDimitry Andric EVT ValVT = VA.getValVT(); 163349cc55cSDimitry Andric EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0)); 164349cc55cSDimitry Andric int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8, 165349cc55cSDimitry Andric VA.getLocMemOffset(), /*Immutable=*/true); 166349cc55cSDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, PtrVT); 167349cc55cSDimitry Andric SDValue Val; 168349cc55cSDimitry Andric 169349cc55cSDimitry Andric ISD::LoadExtType ExtType; 170349cc55cSDimitry Andric switch (VA.getLocInfo()) { 171349cc55cSDimitry Andric default: 172349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo"); 173349cc55cSDimitry Andric case CCValAssign::Full: 174349cc55cSDimitry Andric case CCValAssign::BCvt: 175349cc55cSDimitry Andric ExtType = ISD::NON_EXTLOAD; 176349cc55cSDimitry Andric break; 177349cc55cSDimitry Andric } 178349cc55cSDimitry Andric Val = DAG.getExtLoad( 179349cc55cSDimitry Andric ExtType, DL, LocVT, Chain, FIN, 180349cc55cSDimitry Andric MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT); 181349cc55cSDimitry Andric return Val; 182349cc55cSDimitry Andric } 183349cc55cSDimitry Andric 184349cc55cSDimitry Andric // Transform physical registers into virtual registers. 185349cc55cSDimitry Andric SDValue CSKYTargetLowering::LowerFormalArguments( 186349cc55cSDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 187349cc55cSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 188349cc55cSDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 189349cc55cSDimitry Andric 190349cc55cSDimitry Andric switch (CallConv) { 191349cc55cSDimitry Andric default: 192349cc55cSDimitry Andric report_fatal_error("Unsupported calling convention"); 193349cc55cSDimitry Andric case CallingConv::C: 194349cc55cSDimitry Andric case CallingConv::Fast: 195349cc55cSDimitry Andric break; 196349cc55cSDimitry Andric } 197349cc55cSDimitry Andric 198349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 199349cc55cSDimitry Andric 200349cc55cSDimitry Andric // Used with vargs to acumulate store chains. 201349cc55cSDimitry Andric std::vector<SDValue> OutChains; 202349cc55cSDimitry Andric 203349cc55cSDimitry Andric // Assign locations to all of the incoming arguments. 204349cc55cSDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 205349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 206349cc55cSDimitry Andric 207349cc55cSDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg)); 208349cc55cSDimitry Andric 209349cc55cSDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 210349cc55cSDimitry Andric CCValAssign &VA = ArgLocs[i]; 211349cc55cSDimitry Andric SDValue ArgValue; 212349cc55cSDimitry Andric 213349cc55cSDimitry Andric if (VA.isRegLoc()) 214349cc55cSDimitry Andric ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL); 215349cc55cSDimitry Andric else 216349cc55cSDimitry Andric ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL); 217349cc55cSDimitry Andric 218349cc55cSDimitry Andric InVals.push_back(ArgValue); 219349cc55cSDimitry Andric } 220349cc55cSDimitry Andric 221349cc55cSDimitry Andric if (IsVarArg) { 222349cc55cSDimitry Andric const unsigned XLenInBytes = 4; 223349cc55cSDimitry Andric const MVT XLenVT = MVT::i32; 224349cc55cSDimitry Andric 225349cc55cSDimitry Andric ArrayRef<MCPhysReg> ArgRegs = makeArrayRef(GPRArgRegs); 226349cc55cSDimitry Andric unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs); 227349cc55cSDimitry Andric const TargetRegisterClass *RC = &CSKY::GPRRegClass; 228349cc55cSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 229349cc55cSDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 230349cc55cSDimitry Andric CSKYMachineFunctionInfo *CSKYFI = MF.getInfo<CSKYMachineFunctionInfo>(); 231349cc55cSDimitry Andric 232349cc55cSDimitry Andric // Offset of the first variable argument from stack pointer, and size of 233349cc55cSDimitry Andric // the vararg save area. For now, the varargs save area is either zero or 234349cc55cSDimitry Andric // large enough to hold a0-a4. 235349cc55cSDimitry Andric int VaArgOffset, VarArgsSaveSize; 236349cc55cSDimitry Andric 237349cc55cSDimitry Andric // If all registers are allocated, then all varargs must be passed on the 238349cc55cSDimitry Andric // stack and we don't need to save any argregs. 239349cc55cSDimitry Andric if (ArgRegs.size() == Idx) { 240349cc55cSDimitry Andric VaArgOffset = CCInfo.getNextStackOffset(); 241349cc55cSDimitry Andric VarArgsSaveSize = 0; 242349cc55cSDimitry Andric } else { 243349cc55cSDimitry Andric VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx); 244349cc55cSDimitry Andric VaArgOffset = -VarArgsSaveSize; 245349cc55cSDimitry Andric } 246349cc55cSDimitry Andric 247349cc55cSDimitry Andric // Record the frame index of the first variable argument 248349cc55cSDimitry Andric // which is a value necessary to VASTART. 249349cc55cSDimitry Andric int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true); 250349cc55cSDimitry Andric CSKYFI->setVarArgsFrameIndex(FI); 251349cc55cSDimitry Andric 252349cc55cSDimitry Andric // Copy the integer registers that may have been used for passing varargs 253349cc55cSDimitry Andric // to the vararg save area. 254349cc55cSDimitry Andric for (unsigned I = Idx; I < ArgRegs.size(); 255349cc55cSDimitry Andric ++I, VaArgOffset += XLenInBytes) { 256349cc55cSDimitry Andric const Register Reg = RegInfo.createVirtualRegister(RC); 257349cc55cSDimitry Andric RegInfo.addLiveIn(ArgRegs[I], Reg); 258349cc55cSDimitry Andric SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT); 259349cc55cSDimitry Andric FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true); 260349cc55cSDimitry Andric SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); 261349cc55cSDimitry Andric SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff, 262349cc55cSDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)); 263349cc55cSDimitry Andric cast<StoreSDNode>(Store.getNode()) 264349cc55cSDimitry Andric ->getMemOperand() 265349cc55cSDimitry Andric ->setValue((Value *)nullptr); 266349cc55cSDimitry Andric OutChains.push_back(Store); 267349cc55cSDimitry Andric } 268349cc55cSDimitry Andric CSKYFI->setVarArgsSaveSize(VarArgsSaveSize); 269349cc55cSDimitry Andric } 270349cc55cSDimitry Andric 271349cc55cSDimitry Andric // All stores are grouped in one node to allow the matching between 272349cc55cSDimitry Andric // the size of Ins and InVals. This only happens for vararg functions. 273349cc55cSDimitry Andric if (!OutChains.empty()) { 274349cc55cSDimitry Andric OutChains.push_back(Chain); 275349cc55cSDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 276349cc55cSDimitry Andric } 277349cc55cSDimitry Andric 278349cc55cSDimitry Andric return Chain; 279349cc55cSDimitry Andric } 280349cc55cSDimitry Andric 281349cc55cSDimitry Andric bool CSKYTargetLowering::CanLowerReturn( 282349cc55cSDimitry Andric CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 283349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 284349cc55cSDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs; 285349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context); 286349cc55cSDimitry Andric return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)); 287349cc55cSDimitry Andric } 288349cc55cSDimitry Andric 289349cc55cSDimitry Andric SDValue 290349cc55cSDimitry Andric CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, 291349cc55cSDimitry Andric bool IsVarArg, 292349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 293349cc55cSDimitry Andric const SmallVectorImpl<SDValue> &OutVals, 294349cc55cSDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const { 295349cc55cSDimitry Andric // Stores the assignment of the return value to a location. 296349cc55cSDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs; 297349cc55cSDimitry Andric 298349cc55cSDimitry Andric // Info about the registers and stack slot. 299349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs, 300349cc55cSDimitry Andric *DAG.getContext()); 301349cc55cSDimitry Andric CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)); 302349cc55cSDimitry Andric 303349cc55cSDimitry Andric SDValue Glue; 304349cc55cSDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain); 305349cc55cSDimitry Andric 306349cc55cSDimitry Andric // Copy the result values into the output registers. 307349cc55cSDimitry Andric for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) { 308349cc55cSDimitry Andric SDValue Val = OutVals[i]; 309349cc55cSDimitry Andric CCValAssign &VA = CSKYLocs[i]; 310349cc55cSDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!"); 311349cc55cSDimitry Andric 312349cc55cSDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 313349cc55cSDimitry Andric 314349cc55cSDimitry Andric if (IsF64OnCSKY) { 315349cc55cSDimitry Andric 316349cc55cSDimitry Andric assert(VA.isRegLoc() && "Expected return via registers"); 317349cc55cSDimitry Andric SDValue Split64 = DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL, 318349cc55cSDimitry Andric DAG.getVTList(MVT::i32, MVT::i32), Val); 319349cc55cSDimitry Andric SDValue Lo = Split64.getValue(0); 320349cc55cSDimitry Andric SDValue Hi = Split64.getValue(1); 321349cc55cSDimitry Andric 322349cc55cSDimitry Andric Register RegLo = VA.getLocReg(); 323349cc55cSDimitry Andric assert(RegLo < CSKY::R31 && "Invalid register pair"); 324349cc55cSDimitry Andric Register RegHi = RegLo + 1; 325349cc55cSDimitry Andric 326349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue); 327349cc55cSDimitry Andric Glue = Chain.getValue(1); 328349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(RegLo, MVT::i32)); 329349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, RegHi, Hi, Glue); 330349cc55cSDimitry Andric Glue = Chain.getValue(1); 331349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(RegHi, MVT::i32)); 332349cc55cSDimitry Andric } else { 333349cc55cSDimitry Andric // Handle a 'normal' return. 334349cc55cSDimitry Andric Val = convertValVTToLocVT(DAG, Val, VA, DL); 335349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue); 336349cc55cSDimitry Andric 337349cc55cSDimitry Andric // Guarantee that all emitted copies are stuck together. 338349cc55cSDimitry Andric Glue = Chain.getValue(1); 339349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 340349cc55cSDimitry Andric } 341349cc55cSDimitry Andric } 342349cc55cSDimitry Andric 343349cc55cSDimitry Andric RetOps[0] = Chain; // Update chain. 344349cc55cSDimitry Andric 345349cc55cSDimitry Andric // Add the glue node if we have it. 346349cc55cSDimitry Andric if (Glue.getNode()) { 347349cc55cSDimitry Andric RetOps.push_back(Glue); 348349cc55cSDimitry Andric } 349349cc55cSDimitry Andric 350349cc55cSDimitry Andric // Interrupt service routines use different return instructions. 351349cc55cSDimitry Andric if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt")) 352349cc55cSDimitry Andric return DAG.getNode(CSKYISD::NIR, DL, MVT::Other, RetOps); 353349cc55cSDimitry Andric 354349cc55cSDimitry Andric return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps); 355349cc55cSDimitry Andric } 356349cc55cSDimitry Andric 357349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC, 358349cc55cSDimitry Andric bool IsVarArg) const { 359349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI()) 360349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_SOFT; 361349cc55cSDimitry Andric else 362349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_FP; 363349cc55cSDimitry Andric } 364349cc55cSDimitry Andric 365349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC, 366349cc55cSDimitry Andric bool IsVarArg) const { 367349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI()) 368349cc55cSDimitry Andric return CC_CSKY_ABIV2_SOFT; 369349cc55cSDimitry Andric else 370349cc55cSDimitry Andric return CC_CSKY_ABIV2_FP; 371349cc55cSDimitry Andric } 372349cc55cSDimitry Andric 373349cc55cSDimitry Andric const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const { 374349cc55cSDimitry Andric switch (Opcode) { 375349cc55cSDimitry Andric default: 376349cc55cSDimitry Andric llvm_unreachable("unknown CSKYISD node"); 377349cc55cSDimitry Andric case CSKYISD::NIE: 378349cc55cSDimitry Andric return "CSKYISD::NIE"; 379349cc55cSDimitry Andric case CSKYISD::NIR: 380349cc55cSDimitry Andric return "CSKYISD::NIR"; 381349cc55cSDimitry Andric case CSKYISD::RET: 382349cc55cSDimitry Andric return "CSKYISD::RET"; 383349cc55cSDimitry Andric case CSKYISD::BITCAST_TO_LOHI: 384349cc55cSDimitry Andric return "CSKYISD::BITCAST_TO_LOHI"; 385349cc55cSDimitry Andric } 386349cc55cSDimitry Andric } 387