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" 16*04eeddc0SDimitry Andric #include "CSKYConstantPoolValue.h" 17349cc55cSDimitry Andric #include "CSKYMachineFunctionInfo.h" 18349cc55cSDimitry Andric #include "CSKYRegisterInfo.h" 19349cc55cSDimitry Andric #include "CSKYSubtarget.h" 20349cc55cSDimitry Andric #include "llvm/ADT/Statistic.h" 21349cc55cSDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 22349cc55cSDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h" 23349cc55cSDimitry Andric #include "llvm/Support/Debug.h" 24349cc55cSDimitry Andric 25349cc55cSDimitry Andric using namespace llvm; 26349cc55cSDimitry Andric 27349cc55cSDimitry Andric #define DEBUG_TYPE "csky-isel-lowering" 28349cc55cSDimitry Andric 29349cc55cSDimitry Andric STATISTIC(NumTailCalls, "Number of tail calls"); 30349cc55cSDimitry Andric 31349cc55cSDimitry Andric #include "CSKYGenCallingConv.inc" 32349cc55cSDimitry Andric 33349cc55cSDimitry Andric static const MCPhysReg GPRArgRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3}; 34349cc55cSDimitry Andric 35349cc55cSDimitry Andric CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM, 36349cc55cSDimitry Andric const CSKYSubtarget &STI) 37349cc55cSDimitry Andric : TargetLowering(TM), Subtarget(STI) { 38349cc55cSDimitry Andric // Register Class 39349cc55cSDimitry Andric addRegisterClass(MVT::i32, &CSKY::GPRRegClass); 40349cc55cSDimitry Andric 41*04eeddc0SDimitry Andric if (STI.useHardFloat()) { 42*04eeddc0SDimitry Andric if (STI.hasFPUv2SingleFloat()) 43*04eeddc0SDimitry Andric addRegisterClass(MVT::f32, &CSKY::sFPR32RegClass); 44*04eeddc0SDimitry Andric else if (STI.hasFPUv3SingleFloat()) 45*04eeddc0SDimitry Andric addRegisterClass(MVT::f32, &CSKY::FPR32RegClass); 46*04eeddc0SDimitry Andric 47*04eeddc0SDimitry Andric if (STI.hasFPUv2DoubleFloat()) 48*04eeddc0SDimitry Andric addRegisterClass(MVT::f64, &CSKY::sFPR64RegClass); 49*04eeddc0SDimitry Andric else if (STI.hasFPUv3DoubleFloat()) 50*04eeddc0SDimitry Andric addRegisterClass(MVT::f64, &CSKY::FPR64RegClass); 51*04eeddc0SDimitry Andric } 52*04eeddc0SDimitry Andric 530eae32dcSDimitry Andric setOperationAction(ISD::ADDCARRY, MVT::i32, Legal); 540eae32dcSDimitry Andric setOperationAction(ISD::SUBCARRY, MVT::i32, Legal); 550eae32dcSDimitry Andric setOperationAction(ISD::BITREVERSE, MVT::i32, Legal); 560eae32dcSDimitry Andric 570eae32dcSDimitry Andric setOperationAction(ISD::SREM, MVT::i32, Expand); 580eae32dcSDimitry Andric setOperationAction(ISD::UREM, MVT::i32, Expand); 590eae32dcSDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i32, Expand); 600eae32dcSDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i32, Expand); 610eae32dcSDimitry Andric setOperationAction(ISD::CTTZ, MVT::i32, Expand); 620eae32dcSDimitry Andric setOperationAction(ISD::CTPOP, MVT::i32, Expand); 630eae32dcSDimitry Andric setOperationAction(ISD::ROTR, MVT::i32, Expand); 640eae32dcSDimitry Andric setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 650eae32dcSDimitry Andric setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 660eae32dcSDimitry Andric setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 670eae32dcSDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); 680eae32dcSDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); 69*04eeddc0SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); 70*04eeddc0SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i32, Expand); 71*04eeddc0SDimitry Andric setOperationAction(ISD::BR_JT, MVT::Other, Expand); 720eae32dcSDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); 730eae32dcSDimitry Andric setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 740eae32dcSDimitry Andric setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 750eae32dcSDimitry Andric setOperationAction(ISD::MULHS, MVT::i32, Expand); 760eae32dcSDimitry Andric setOperationAction(ISD::MULHU, MVT::i32, Expand); 77*04eeddc0SDimitry Andric setOperationAction(ISD::VAARG, MVT::Other, Expand); 78*04eeddc0SDimitry Andric setOperationAction(ISD::VACOPY, MVT::Other, Expand); 79*04eeddc0SDimitry Andric setOperationAction(ISD::VAEND, MVT::Other, Expand); 800eae32dcSDimitry Andric 810eae32dcSDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote); 820eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote); 830eae32dcSDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote); 840eae32dcSDimitry Andric 85*04eeddc0SDimitry Andric setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 86*04eeddc0SDimitry Andric setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom); 87*04eeddc0SDimitry Andric setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); 88*04eeddc0SDimitry Andric setOperationAction(ISD::BlockAddress, MVT::i32, Custom); 89*04eeddc0SDimitry Andric setOperationAction(ISD::JumpTable, MVT::i32, Custom); 90*04eeddc0SDimitry Andric setOperationAction(ISD::VASTART, MVT::Other, Custom); 91*04eeddc0SDimitry Andric 920eae32dcSDimitry Andric if (!Subtarget.hasE2()) { 930eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand); 940eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand); 950eae32dcSDimitry Andric setOperationAction(ISD::CTLZ, MVT::i32, Expand); 960eae32dcSDimitry Andric setOperationAction(ISD::BSWAP, MVT::i32, Expand); 970eae32dcSDimitry Andric } 980eae32dcSDimitry Andric 990eae32dcSDimitry Andric if (!Subtarget.has2E3()) { 1000eae32dcSDimitry Andric setOperationAction(ISD::ABS, MVT::i32, Expand); 1010eae32dcSDimitry Andric setOperationAction(ISD::BITREVERSE, MVT::i32, Expand); 1020eae32dcSDimitry Andric setOperationAction(ISD::SDIV, MVT::i32, Expand); 1030eae32dcSDimitry Andric setOperationAction(ISD::UDIV, MVT::i32, Expand); 1040eae32dcSDimitry Andric } 1050eae32dcSDimitry Andric 106*04eeddc0SDimitry Andric if (!Subtarget.has3r2E3r3()) { 107*04eeddc0SDimitry Andric setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); 108*04eeddc0SDimitry Andric } 109*04eeddc0SDimitry Andric 110*04eeddc0SDimitry Andric // Float 111*04eeddc0SDimitry Andric 112*04eeddc0SDimitry Andric ISD::CondCode FPCCToExtend[] = { 113*04eeddc0SDimitry Andric ISD::SETONE, ISD::SETUEQ, ISD::SETUGT, 114*04eeddc0SDimitry Andric ISD::SETUGE, ISD::SETULT, ISD::SETULE, 115*04eeddc0SDimitry Andric }; 116*04eeddc0SDimitry Andric 117*04eeddc0SDimitry Andric ISD::NodeType FPOpToExpand[] = {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, 118*04eeddc0SDimitry Andric ISD::FPOW, ISD::FREM, ISD::FCOPYSIGN}; 119*04eeddc0SDimitry Andric 120*04eeddc0SDimitry Andric if (STI.useHardFloat()) { 121*04eeddc0SDimitry Andric 122*04eeddc0SDimitry Andric MVT AllVTy[] = {MVT::f32, MVT::f64}; 123*04eeddc0SDimitry Andric 124*04eeddc0SDimitry Andric for (auto VT : AllVTy) { 125*04eeddc0SDimitry Andric setOperationAction(ISD::FREM, VT, Expand); 126*04eeddc0SDimitry Andric setOperationAction(ISD::SELECT_CC, VT, Expand); 127*04eeddc0SDimitry Andric setOperationAction(ISD::BR_CC, VT, Expand); 128*04eeddc0SDimitry Andric 129*04eeddc0SDimitry Andric for (auto CC : FPCCToExtend) 130*04eeddc0SDimitry Andric setCondCodeAction(CC, VT, Expand); 131*04eeddc0SDimitry Andric for (auto Op : FPOpToExpand) 132*04eeddc0SDimitry Andric setOperationAction(Op, VT, Expand); 133*04eeddc0SDimitry Andric } 134*04eeddc0SDimitry Andric 135*04eeddc0SDimitry Andric if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) { 136*04eeddc0SDimitry Andric setOperationAction(ISD::ConstantFP, MVT::f32, Legal); 137*04eeddc0SDimitry Andric } 138*04eeddc0SDimitry Andric if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) { 139*04eeddc0SDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); 140*04eeddc0SDimitry Andric setTruncStoreAction(MVT::f64, MVT::f32, Expand); 141*04eeddc0SDimitry Andric } 142*04eeddc0SDimitry Andric } 143*04eeddc0SDimitry Andric 144349cc55cSDimitry Andric // Compute derived properties from the register classes. 145349cc55cSDimitry Andric computeRegisterProperties(STI.getRegisterInfo()); 146349cc55cSDimitry Andric 147349cc55cSDimitry Andric setBooleanContents(UndefinedBooleanContent); 148349cc55cSDimitry Andric setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); 149349cc55cSDimitry Andric 150349cc55cSDimitry Andric // TODO: Add atomic support fully. 151349cc55cSDimitry Andric setMaxAtomicSizeInBitsSupported(0); 152349cc55cSDimitry Andric 153349cc55cSDimitry Andric setStackPointerRegisterToSaveRestore(CSKY::R14); 154349cc55cSDimitry Andric const Align FunctionAlignment(2); 155349cc55cSDimitry Andric setMinFunctionAlignment(FunctionAlignment); 156349cc55cSDimitry Andric setSchedulingPreference(Sched::Source); 157349cc55cSDimitry Andric } 158349cc55cSDimitry Andric 159*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerOperation(SDValue Op, 160*04eeddc0SDimitry Andric SelectionDAG &DAG) const { 161*04eeddc0SDimitry Andric switch (Op.getOpcode()) { 162*04eeddc0SDimitry Andric default: 163*04eeddc0SDimitry Andric llvm_unreachable("unimplemented op"); 164*04eeddc0SDimitry Andric case ISD::GlobalAddress: 165*04eeddc0SDimitry Andric return LowerGlobalAddress(Op, DAG); 166*04eeddc0SDimitry Andric case ISD::ExternalSymbol: 167*04eeddc0SDimitry Andric return LowerExternalSymbol(Op, DAG); 168*04eeddc0SDimitry Andric case ISD::GlobalTLSAddress: 169*04eeddc0SDimitry Andric return LowerGlobalTLSAddress(Op, DAG); 170*04eeddc0SDimitry Andric case ISD::JumpTable: 171*04eeddc0SDimitry Andric return LowerJumpTable(Op, DAG); 172*04eeddc0SDimitry Andric case ISD::BlockAddress: 173*04eeddc0SDimitry Andric return LowerBlockAddress(Op, DAG); 174*04eeddc0SDimitry Andric case ISD::VASTART: 175*04eeddc0SDimitry Andric return LowerVASTART(Op, DAG); 176*04eeddc0SDimitry Andric case ISD::FRAMEADDR: 177*04eeddc0SDimitry Andric return LowerFRAMEADDR(Op, DAG); 178*04eeddc0SDimitry Andric case ISD::RETURNADDR: 179*04eeddc0SDimitry Andric return LowerRETURNADDR(Op, DAG); 180*04eeddc0SDimitry Andric } 181*04eeddc0SDimitry Andric } 182*04eeddc0SDimitry Andric 183349cc55cSDimitry Andric EVT CSKYTargetLowering::getSetCCResultType(const DataLayout &DL, 184349cc55cSDimitry Andric LLVMContext &Context, EVT VT) const { 185349cc55cSDimitry Andric if (!VT.isVector()) 186349cc55cSDimitry Andric return MVT::i32; 187349cc55cSDimitry Andric 188349cc55cSDimitry Andric return VT.changeVectorElementTypeToInteger(); 189349cc55cSDimitry Andric } 190349cc55cSDimitry Andric 191349cc55cSDimitry Andric static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, 192349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 193349cc55cSDimitry Andric EVT LocVT = VA.getLocVT(); 194349cc55cSDimitry Andric 195349cc55cSDimitry Andric switch (VA.getLocInfo()) { 196349cc55cSDimitry Andric default: 197349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo"); 198349cc55cSDimitry Andric case CCValAssign::Full: 199349cc55cSDimitry Andric break; 200349cc55cSDimitry Andric case CCValAssign::BCvt: 201349cc55cSDimitry Andric Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val); 202349cc55cSDimitry Andric break; 203349cc55cSDimitry Andric } 204349cc55cSDimitry Andric return Val; 205349cc55cSDimitry Andric } 206349cc55cSDimitry Andric 207349cc55cSDimitry Andric static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, 208349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 209349cc55cSDimitry Andric switch (VA.getLocInfo()) { 210349cc55cSDimitry Andric default: 211349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo"); 212349cc55cSDimitry Andric case CCValAssign::Full: 213349cc55cSDimitry Andric break; 214349cc55cSDimitry Andric case CCValAssign::BCvt: 215349cc55cSDimitry Andric Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val); 216349cc55cSDimitry Andric break; 217349cc55cSDimitry Andric } 218349cc55cSDimitry Andric return Val; 219349cc55cSDimitry Andric } 220349cc55cSDimitry Andric 221349cc55cSDimitry Andric static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, 222349cc55cSDimitry Andric SelectionDAG &DAG, SDValue Chain, 223349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 224349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 225349cc55cSDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 226349cc55cSDimitry Andric EVT LocVT = VA.getLocVT(); 227349cc55cSDimitry Andric SDValue Val; 228349cc55cSDimitry Andric const TargetRegisterClass *RC; 229349cc55cSDimitry Andric 230349cc55cSDimitry Andric switch (LocVT.getSimpleVT().SimpleTy) { 231349cc55cSDimitry Andric default: 232349cc55cSDimitry Andric llvm_unreachable("Unexpected register type"); 233349cc55cSDimitry Andric case MVT::i32: 234349cc55cSDimitry Andric RC = &CSKY::GPRRegClass; 235349cc55cSDimitry Andric break; 236*04eeddc0SDimitry Andric case MVT::f32: 237*04eeddc0SDimitry Andric RC = Subtarget.hasFPUv2SingleFloat() ? &CSKY::sFPR32RegClass 238*04eeddc0SDimitry Andric : &CSKY::FPR32RegClass; 239*04eeddc0SDimitry Andric break; 240*04eeddc0SDimitry Andric case MVT::f64: 241*04eeddc0SDimitry Andric RC = Subtarget.hasFPUv2DoubleFloat() ? &CSKY::sFPR64RegClass 242*04eeddc0SDimitry Andric : &CSKY::FPR64RegClass; 243*04eeddc0SDimitry Andric break; 244349cc55cSDimitry Andric } 245349cc55cSDimitry Andric 246349cc55cSDimitry Andric Register VReg = RegInfo.createVirtualRegister(RC); 247349cc55cSDimitry Andric RegInfo.addLiveIn(VA.getLocReg(), VReg); 248349cc55cSDimitry Andric Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT); 249349cc55cSDimitry Andric 250349cc55cSDimitry Andric return convertLocVTToValVT(DAG, Val, VA, DL); 251349cc55cSDimitry Andric } 252349cc55cSDimitry Andric 253349cc55cSDimitry Andric static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, 254349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 255349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 256349cc55cSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 257349cc55cSDimitry Andric EVT LocVT = VA.getLocVT(); 258349cc55cSDimitry Andric EVT ValVT = VA.getValVT(); 259349cc55cSDimitry Andric EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0)); 260349cc55cSDimitry Andric int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8, 261349cc55cSDimitry Andric VA.getLocMemOffset(), /*Immutable=*/true); 262349cc55cSDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, PtrVT); 263349cc55cSDimitry Andric SDValue Val; 264349cc55cSDimitry Andric 265349cc55cSDimitry Andric ISD::LoadExtType ExtType; 266349cc55cSDimitry Andric switch (VA.getLocInfo()) { 267349cc55cSDimitry Andric default: 268349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo"); 269349cc55cSDimitry Andric case CCValAssign::Full: 270349cc55cSDimitry Andric case CCValAssign::BCvt: 271349cc55cSDimitry Andric ExtType = ISD::NON_EXTLOAD; 272349cc55cSDimitry Andric break; 273349cc55cSDimitry Andric } 274349cc55cSDimitry Andric Val = DAG.getExtLoad( 275349cc55cSDimitry Andric ExtType, DL, LocVT, Chain, FIN, 276349cc55cSDimitry Andric MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT); 277349cc55cSDimitry Andric return Val; 278349cc55cSDimitry Andric } 279349cc55cSDimitry Andric 280*04eeddc0SDimitry Andric static SDValue unpack64(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, 281*04eeddc0SDimitry Andric const SDLoc &DL) { 282*04eeddc0SDimitry Andric assert(VA.getLocVT() == MVT::i32 && 283*04eeddc0SDimitry Andric (VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::i64) && 284*04eeddc0SDimitry Andric "Unexpected VA"); 285*04eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 286*04eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 287*04eeddc0SDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 288*04eeddc0SDimitry Andric 289*04eeddc0SDimitry Andric if (VA.isMemLoc()) { 290*04eeddc0SDimitry Andric // f64/i64 is passed on the stack. 291*04eeddc0SDimitry Andric int FI = MFI.CreateFixedObject(8, VA.getLocMemOffset(), /*Immutable=*/true); 292*04eeddc0SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 293*04eeddc0SDimitry Andric return DAG.getLoad(VA.getValVT(), DL, Chain, FIN, 294*04eeddc0SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)); 295*04eeddc0SDimitry Andric } 296*04eeddc0SDimitry Andric 297*04eeddc0SDimitry Andric assert(VA.isRegLoc() && "Expected register VA assignment"); 298*04eeddc0SDimitry Andric 299*04eeddc0SDimitry Andric Register LoVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass); 300*04eeddc0SDimitry Andric RegInfo.addLiveIn(VA.getLocReg(), LoVReg); 301*04eeddc0SDimitry Andric SDValue Lo = DAG.getCopyFromReg(Chain, DL, LoVReg, MVT::i32); 302*04eeddc0SDimitry Andric SDValue Hi; 303*04eeddc0SDimitry Andric if (VA.getLocReg() == CSKY::R3) { 304*04eeddc0SDimitry Andric // Second half of f64/i64 is passed on the stack. 305*04eeddc0SDimitry Andric int FI = MFI.CreateFixedObject(4, 0, /*Immutable=*/true); 306*04eeddc0SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 307*04eeddc0SDimitry Andric Hi = DAG.getLoad(MVT::i32, DL, Chain, FIN, 308*04eeddc0SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)); 309*04eeddc0SDimitry Andric } else { 310*04eeddc0SDimitry Andric // Second half of f64/i64 is passed in another GPR. 311*04eeddc0SDimitry Andric Register HiVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass); 312*04eeddc0SDimitry Andric RegInfo.addLiveIn(VA.getLocReg() + 1, HiVReg); 313*04eeddc0SDimitry Andric Hi = DAG.getCopyFromReg(Chain, DL, HiVReg, MVT::i32); 314*04eeddc0SDimitry Andric } 315*04eeddc0SDimitry Andric return DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(), Lo, Hi); 316*04eeddc0SDimitry Andric } 317*04eeddc0SDimitry Andric 318349cc55cSDimitry Andric // Transform physical registers into virtual registers. 319349cc55cSDimitry Andric SDValue CSKYTargetLowering::LowerFormalArguments( 320349cc55cSDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 321349cc55cSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 322349cc55cSDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 323349cc55cSDimitry Andric 324349cc55cSDimitry Andric switch (CallConv) { 325349cc55cSDimitry Andric default: 326349cc55cSDimitry Andric report_fatal_error("Unsupported calling convention"); 327349cc55cSDimitry Andric case CallingConv::C: 328349cc55cSDimitry Andric case CallingConv::Fast: 329349cc55cSDimitry Andric break; 330349cc55cSDimitry Andric } 331349cc55cSDimitry Andric 332349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 333349cc55cSDimitry Andric 334349cc55cSDimitry Andric // Used with vargs to acumulate store chains. 335349cc55cSDimitry Andric std::vector<SDValue> OutChains; 336349cc55cSDimitry Andric 337349cc55cSDimitry Andric // Assign locations to all of the incoming arguments. 338349cc55cSDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 339349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 340349cc55cSDimitry Andric 341349cc55cSDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg)); 342349cc55cSDimitry Andric 343349cc55cSDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 344349cc55cSDimitry Andric CCValAssign &VA = ArgLocs[i]; 345349cc55cSDimitry Andric SDValue ArgValue; 346349cc55cSDimitry Andric 347*04eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 348*04eeddc0SDimitry Andric 349*04eeddc0SDimitry Andric if (IsF64OnCSKY) 350*04eeddc0SDimitry Andric ArgValue = unpack64(DAG, Chain, VA, DL); 351*04eeddc0SDimitry Andric else if (VA.isRegLoc()) 352349cc55cSDimitry Andric ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL); 353349cc55cSDimitry Andric else 354349cc55cSDimitry Andric ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL); 355349cc55cSDimitry Andric 356349cc55cSDimitry Andric InVals.push_back(ArgValue); 357349cc55cSDimitry Andric } 358349cc55cSDimitry Andric 359349cc55cSDimitry Andric if (IsVarArg) { 360349cc55cSDimitry Andric const unsigned XLenInBytes = 4; 361349cc55cSDimitry Andric const MVT XLenVT = MVT::i32; 362349cc55cSDimitry Andric 363349cc55cSDimitry Andric ArrayRef<MCPhysReg> ArgRegs = makeArrayRef(GPRArgRegs); 364349cc55cSDimitry Andric unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs); 365349cc55cSDimitry Andric const TargetRegisterClass *RC = &CSKY::GPRRegClass; 366349cc55cSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 367349cc55cSDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 368349cc55cSDimitry Andric CSKYMachineFunctionInfo *CSKYFI = MF.getInfo<CSKYMachineFunctionInfo>(); 369349cc55cSDimitry Andric 370349cc55cSDimitry Andric // Offset of the first variable argument from stack pointer, and size of 371349cc55cSDimitry Andric // the vararg save area. For now, the varargs save area is either zero or 372349cc55cSDimitry Andric // large enough to hold a0-a4. 373349cc55cSDimitry Andric int VaArgOffset, VarArgsSaveSize; 374349cc55cSDimitry Andric 375349cc55cSDimitry Andric // If all registers are allocated, then all varargs must be passed on the 376349cc55cSDimitry Andric // stack and we don't need to save any argregs. 377349cc55cSDimitry Andric if (ArgRegs.size() == Idx) { 378349cc55cSDimitry Andric VaArgOffset = CCInfo.getNextStackOffset(); 379349cc55cSDimitry Andric VarArgsSaveSize = 0; 380349cc55cSDimitry Andric } else { 381349cc55cSDimitry Andric VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx); 382349cc55cSDimitry Andric VaArgOffset = -VarArgsSaveSize; 383349cc55cSDimitry Andric } 384349cc55cSDimitry Andric 385349cc55cSDimitry Andric // Record the frame index of the first variable argument 386349cc55cSDimitry Andric // which is a value necessary to VASTART. 387349cc55cSDimitry Andric int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true); 388349cc55cSDimitry Andric CSKYFI->setVarArgsFrameIndex(FI); 389349cc55cSDimitry Andric 390349cc55cSDimitry Andric // Copy the integer registers that may have been used for passing varargs 391349cc55cSDimitry Andric // to the vararg save area. 392349cc55cSDimitry Andric for (unsigned I = Idx; I < ArgRegs.size(); 393349cc55cSDimitry Andric ++I, VaArgOffset += XLenInBytes) { 394349cc55cSDimitry Andric const Register Reg = RegInfo.createVirtualRegister(RC); 395349cc55cSDimitry Andric RegInfo.addLiveIn(ArgRegs[I], Reg); 396349cc55cSDimitry Andric SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT); 397349cc55cSDimitry Andric FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true); 398349cc55cSDimitry Andric SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); 399349cc55cSDimitry Andric SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff, 400349cc55cSDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)); 401349cc55cSDimitry Andric cast<StoreSDNode>(Store.getNode()) 402349cc55cSDimitry Andric ->getMemOperand() 403349cc55cSDimitry Andric ->setValue((Value *)nullptr); 404349cc55cSDimitry Andric OutChains.push_back(Store); 405349cc55cSDimitry Andric } 406349cc55cSDimitry Andric CSKYFI->setVarArgsSaveSize(VarArgsSaveSize); 407349cc55cSDimitry Andric } 408349cc55cSDimitry Andric 409349cc55cSDimitry Andric // All stores are grouped in one node to allow the matching between 410349cc55cSDimitry Andric // the size of Ins and InVals. This only happens for vararg functions. 411349cc55cSDimitry Andric if (!OutChains.empty()) { 412349cc55cSDimitry Andric OutChains.push_back(Chain); 413349cc55cSDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 414349cc55cSDimitry Andric } 415349cc55cSDimitry Andric 416349cc55cSDimitry Andric return Chain; 417349cc55cSDimitry Andric } 418349cc55cSDimitry Andric 419349cc55cSDimitry Andric bool CSKYTargetLowering::CanLowerReturn( 420349cc55cSDimitry Andric CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 421349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 422349cc55cSDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs; 423349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context); 424349cc55cSDimitry Andric return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)); 425349cc55cSDimitry Andric } 426349cc55cSDimitry Andric 427349cc55cSDimitry Andric SDValue 428349cc55cSDimitry Andric CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, 429349cc55cSDimitry Andric bool IsVarArg, 430349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 431349cc55cSDimitry Andric const SmallVectorImpl<SDValue> &OutVals, 432349cc55cSDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const { 433349cc55cSDimitry Andric // Stores the assignment of the return value to a location. 434349cc55cSDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs; 435349cc55cSDimitry Andric 436349cc55cSDimitry Andric // Info about the registers and stack slot. 437349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs, 438349cc55cSDimitry Andric *DAG.getContext()); 439349cc55cSDimitry Andric CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)); 440349cc55cSDimitry Andric 441349cc55cSDimitry Andric SDValue Glue; 442349cc55cSDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain); 443349cc55cSDimitry Andric 444349cc55cSDimitry Andric // Copy the result values into the output registers. 445349cc55cSDimitry Andric for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) { 446349cc55cSDimitry Andric SDValue Val = OutVals[i]; 447349cc55cSDimitry Andric CCValAssign &VA = CSKYLocs[i]; 448349cc55cSDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!"); 449349cc55cSDimitry Andric 450349cc55cSDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 451349cc55cSDimitry Andric 452349cc55cSDimitry Andric if (IsF64OnCSKY) { 453349cc55cSDimitry Andric 454349cc55cSDimitry Andric assert(VA.isRegLoc() && "Expected return via registers"); 455349cc55cSDimitry Andric SDValue Split64 = DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL, 456349cc55cSDimitry Andric DAG.getVTList(MVT::i32, MVT::i32), Val); 457349cc55cSDimitry Andric SDValue Lo = Split64.getValue(0); 458349cc55cSDimitry Andric SDValue Hi = Split64.getValue(1); 459349cc55cSDimitry Andric 460349cc55cSDimitry Andric Register RegLo = VA.getLocReg(); 461349cc55cSDimitry Andric assert(RegLo < CSKY::R31 && "Invalid register pair"); 462349cc55cSDimitry Andric Register RegHi = RegLo + 1; 463349cc55cSDimitry Andric 464349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue); 465349cc55cSDimitry Andric Glue = Chain.getValue(1); 466349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(RegLo, MVT::i32)); 467349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, RegHi, Hi, Glue); 468349cc55cSDimitry Andric Glue = Chain.getValue(1); 469349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(RegHi, MVT::i32)); 470349cc55cSDimitry Andric } else { 471349cc55cSDimitry Andric // Handle a 'normal' return. 472349cc55cSDimitry Andric Val = convertValVTToLocVT(DAG, Val, VA, DL); 473349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue); 474349cc55cSDimitry Andric 475349cc55cSDimitry Andric // Guarantee that all emitted copies are stuck together. 476349cc55cSDimitry Andric Glue = Chain.getValue(1); 477349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 478349cc55cSDimitry Andric } 479349cc55cSDimitry Andric } 480349cc55cSDimitry Andric 481349cc55cSDimitry Andric RetOps[0] = Chain; // Update chain. 482349cc55cSDimitry Andric 483349cc55cSDimitry Andric // Add the glue node if we have it. 484349cc55cSDimitry Andric if (Glue.getNode()) { 485349cc55cSDimitry Andric RetOps.push_back(Glue); 486349cc55cSDimitry Andric } 487349cc55cSDimitry Andric 488349cc55cSDimitry Andric // Interrupt service routines use different return instructions. 489349cc55cSDimitry Andric if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt")) 490349cc55cSDimitry Andric return DAG.getNode(CSKYISD::NIR, DL, MVT::Other, RetOps); 491349cc55cSDimitry Andric 492349cc55cSDimitry Andric return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps); 493349cc55cSDimitry Andric } 494349cc55cSDimitry Andric 495*04eeddc0SDimitry Andric // Lower a call to a callseq_start + CALL + callseq_end chain, and add input 496*04eeddc0SDimitry Andric // and output parameter nodes. 497*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI, 498*04eeddc0SDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 499*04eeddc0SDimitry Andric SelectionDAG &DAG = CLI.DAG; 500*04eeddc0SDimitry Andric SDLoc &DL = CLI.DL; 501*04eeddc0SDimitry Andric SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 502*04eeddc0SDimitry Andric SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 503*04eeddc0SDimitry Andric SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 504*04eeddc0SDimitry Andric SDValue Chain = CLI.Chain; 505*04eeddc0SDimitry Andric SDValue Callee = CLI.Callee; 506*04eeddc0SDimitry Andric bool &IsTailCall = CLI.IsTailCall; 507*04eeddc0SDimitry Andric CallingConv::ID CallConv = CLI.CallConv; 508*04eeddc0SDimitry Andric bool IsVarArg = CLI.IsVarArg; 509*04eeddc0SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout()); 510*04eeddc0SDimitry Andric MVT XLenVT = MVT::i32; 511*04eeddc0SDimitry Andric 512*04eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 513*04eeddc0SDimitry Andric 514*04eeddc0SDimitry Andric // Analyze the operands of the call, assigning locations to each operand. 515*04eeddc0SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 516*04eeddc0SDimitry Andric CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 517*04eeddc0SDimitry Andric 518*04eeddc0SDimitry Andric ArgCCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CallConv, IsVarArg)); 519*04eeddc0SDimitry Andric 520*04eeddc0SDimitry Andric // Check if it's really possible to do a tail call. 521*04eeddc0SDimitry Andric if (IsTailCall) 522*04eeddc0SDimitry Andric IsTailCall = false; // TODO: TailCallOptimization; 523*04eeddc0SDimitry Andric 524*04eeddc0SDimitry Andric if (IsTailCall) 525*04eeddc0SDimitry Andric ++NumTailCalls; 526*04eeddc0SDimitry Andric else if (CLI.CB && CLI.CB->isMustTailCall()) 527*04eeddc0SDimitry Andric report_fatal_error("failed to perform tail call elimination on a call " 528*04eeddc0SDimitry Andric "site marked musttail"); 529*04eeddc0SDimitry Andric 530*04eeddc0SDimitry Andric // Get a count of how many bytes are to be pushed on the stack. 531*04eeddc0SDimitry Andric unsigned NumBytes = ArgCCInfo.getNextStackOffset(); 532*04eeddc0SDimitry Andric 533*04eeddc0SDimitry Andric // Create local copies for byval args 534*04eeddc0SDimitry Andric SmallVector<SDValue, 8> ByValArgs; 535*04eeddc0SDimitry Andric for (unsigned i = 0, e = Outs.size(); i != e; ++i) { 536*04eeddc0SDimitry Andric ISD::ArgFlagsTy Flags = Outs[i].Flags; 537*04eeddc0SDimitry Andric if (!Flags.isByVal()) 538*04eeddc0SDimitry Andric continue; 539*04eeddc0SDimitry Andric 540*04eeddc0SDimitry Andric SDValue Arg = OutVals[i]; 541*04eeddc0SDimitry Andric unsigned Size = Flags.getByValSize(); 542*04eeddc0SDimitry Andric Align Alignment = Flags.getNonZeroByValAlign(); 543*04eeddc0SDimitry Andric 544*04eeddc0SDimitry Andric int FI = 545*04eeddc0SDimitry Andric MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/false); 546*04eeddc0SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); 547*04eeddc0SDimitry Andric SDValue SizeNode = DAG.getConstant(Size, DL, XLenVT); 548*04eeddc0SDimitry Andric 549*04eeddc0SDimitry Andric Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment, 550*04eeddc0SDimitry Andric /*IsVolatile=*/false, 551*04eeddc0SDimitry Andric /*AlwaysInline=*/false, IsTailCall, 552*04eeddc0SDimitry Andric MachinePointerInfo(), MachinePointerInfo()); 553*04eeddc0SDimitry Andric ByValArgs.push_back(FIPtr); 554*04eeddc0SDimitry Andric } 555*04eeddc0SDimitry Andric 556*04eeddc0SDimitry Andric if (!IsTailCall) 557*04eeddc0SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); 558*04eeddc0SDimitry Andric 559*04eeddc0SDimitry Andric // Copy argument values to their designated locations. 560*04eeddc0SDimitry Andric SmallVector<std::pair<Register, SDValue>, 8> RegsToPass; 561*04eeddc0SDimitry Andric SmallVector<SDValue, 8> MemOpChains; 562*04eeddc0SDimitry Andric SDValue StackPtr; 563*04eeddc0SDimitry Andric for (unsigned i = 0, j = 0, e = ArgLocs.size(); i != e; ++i) { 564*04eeddc0SDimitry Andric CCValAssign &VA = ArgLocs[i]; 565*04eeddc0SDimitry Andric SDValue ArgValue = OutVals[i]; 566*04eeddc0SDimitry Andric ISD::ArgFlagsTy Flags = Outs[i].Flags; 567*04eeddc0SDimitry Andric 568*04eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 569*04eeddc0SDimitry Andric 570*04eeddc0SDimitry Andric if (IsF64OnCSKY && VA.isRegLoc()) { 571*04eeddc0SDimitry Andric SDValue Split64 = 572*04eeddc0SDimitry Andric DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL, 573*04eeddc0SDimitry Andric DAG.getVTList(MVT::i32, MVT::i32), ArgValue); 574*04eeddc0SDimitry Andric SDValue Lo = Split64.getValue(0); 575*04eeddc0SDimitry Andric SDValue Hi = Split64.getValue(1); 576*04eeddc0SDimitry Andric 577*04eeddc0SDimitry Andric Register RegLo = VA.getLocReg(); 578*04eeddc0SDimitry Andric RegsToPass.push_back(std::make_pair(RegLo, Lo)); 579*04eeddc0SDimitry Andric 580*04eeddc0SDimitry Andric if (RegLo == CSKY::R3) { 581*04eeddc0SDimitry Andric // Second half of f64/i64 is passed on the stack. 582*04eeddc0SDimitry Andric // Work out the address of the stack slot. 583*04eeddc0SDimitry Andric if (!StackPtr.getNode()) 584*04eeddc0SDimitry Andric StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT); 585*04eeddc0SDimitry Andric // Emit the store. 586*04eeddc0SDimitry Andric MemOpChains.push_back( 587*04eeddc0SDimitry Andric DAG.getStore(Chain, DL, Hi, StackPtr, MachinePointerInfo())); 588*04eeddc0SDimitry Andric } else { 589*04eeddc0SDimitry Andric // Second half of f64/i64 is passed in another GPR. 590*04eeddc0SDimitry Andric assert(RegLo < CSKY::R31 && "Invalid register pair"); 591*04eeddc0SDimitry Andric Register RegHigh = RegLo + 1; 592*04eeddc0SDimitry Andric RegsToPass.push_back(std::make_pair(RegHigh, Hi)); 593*04eeddc0SDimitry Andric } 594*04eeddc0SDimitry Andric continue; 595*04eeddc0SDimitry Andric } 596*04eeddc0SDimitry Andric 597*04eeddc0SDimitry Andric ArgValue = convertValVTToLocVT(DAG, ArgValue, VA, DL); 598*04eeddc0SDimitry Andric 599*04eeddc0SDimitry Andric // Use local copy if it is a byval arg. 600*04eeddc0SDimitry Andric if (Flags.isByVal()) 601*04eeddc0SDimitry Andric ArgValue = ByValArgs[j++]; 602*04eeddc0SDimitry Andric 603*04eeddc0SDimitry Andric if (VA.isRegLoc()) { 604*04eeddc0SDimitry Andric // Queue up the argument copies and emit them at the end. 605*04eeddc0SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); 606*04eeddc0SDimitry Andric } else { 607*04eeddc0SDimitry Andric assert(VA.isMemLoc() && "Argument not register or memory"); 608*04eeddc0SDimitry Andric assert(!IsTailCall && "Tail call not allowed if stack is used " 609*04eeddc0SDimitry Andric "for passing parameters"); 610*04eeddc0SDimitry Andric 611*04eeddc0SDimitry Andric // Work out the address of the stack slot. 612*04eeddc0SDimitry Andric if (!StackPtr.getNode()) 613*04eeddc0SDimitry Andric StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT); 614*04eeddc0SDimitry Andric SDValue Address = 615*04eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, 616*04eeddc0SDimitry Andric DAG.getIntPtrConstant(VA.getLocMemOffset(), DL)); 617*04eeddc0SDimitry Andric 618*04eeddc0SDimitry Andric // Emit the store. 619*04eeddc0SDimitry Andric MemOpChains.push_back( 620*04eeddc0SDimitry Andric DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo())); 621*04eeddc0SDimitry Andric } 622*04eeddc0SDimitry Andric } 623*04eeddc0SDimitry Andric 624*04eeddc0SDimitry Andric // Join the stores, which are independent of one another. 625*04eeddc0SDimitry Andric if (!MemOpChains.empty()) 626*04eeddc0SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); 627*04eeddc0SDimitry Andric 628*04eeddc0SDimitry Andric SDValue Glue; 629*04eeddc0SDimitry Andric 630*04eeddc0SDimitry Andric // Build a sequence of copy-to-reg nodes, chained and glued together. 631*04eeddc0SDimitry Andric for (auto &Reg : RegsToPass) { 632*04eeddc0SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue); 633*04eeddc0SDimitry Andric Glue = Chain.getValue(1); 634*04eeddc0SDimitry Andric } 635*04eeddc0SDimitry Andric 636*04eeddc0SDimitry Andric SmallVector<SDValue, 8> Ops; 637*04eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout()); 638*04eeddc0SDimitry Andric bool IsRegCall = false; 639*04eeddc0SDimitry Andric 640*04eeddc0SDimitry Andric Ops.push_back(Chain); 641*04eeddc0SDimitry Andric 642*04eeddc0SDimitry Andric if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) { 643*04eeddc0SDimitry Andric const GlobalValue *GV = S->getGlobal(); 644*04eeddc0SDimitry Andric bool IsLocal = 645*04eeddc0SDimitry Andric getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); 646*04eeddc0SDimitry Andric 647*04eeddc0SDimitry Andric if (isPositionIndependent() || !Subtarget.has2E3()) { 648*04eeddc0SDimitry Andric IsRegCall = true; 649*04eeddc0SDimitry Andric Ops.push_back(getAddr<GlobalAddressSDNode, true>(S, DAG, IsLocal)); 650*04eeddc0SDimitry Andric } else { 651*04eeddc0SDimitry Andric Ops.push_back(getTargetNode(cast<GlobalAddressSDNode>(Callee), DL, Ty, 652*04eeddc0SDimitry Andric DAG, CSKYII::MO_None)); 653*04eeddc0SDimitry Andric Ops.push_back(getTargetConstantPoolValue( 654*04eeddc0SDimitry Andric cast<GlobalAddressSDNode>(Callee), Ty, DAG, CSKYII::MO_None)); 655*04eeddc0SDimitry Andric } 656*04eeddc0SDimitry Andric } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { 657*04eeddc0SDimitry Andric bool IsLocal = getTargetMachine().shouldAssumeDSOLocal( 658*04eeddc0SDimitry Andric *MF.getFunction().getParent(), nullptr); 659*04eeddc0SDimitry Andric 660*04eeddc0SDimitry Andric if (isPositionIndependent() || !Subtarget.has2E3()) { 661*04eeddc0SDimitry Andric IsRegCall = true; 662*04eeddc0SDimitry Andric Ops.push_back(getAddr<ExternalSymbolSDNode, true>(S, DAG, IsLocal)); 663*04eeddc0SDimitry Andric } else { 664*04eeddc0SDimitry Andric Ops.push_back(getTargetNode(cast<ExternalSymbolSDNode>(Callee), DL, Ty, 665*04eeddc0SDimitry Andric DAG, CSKYII::MO_None)); 666*04eeddc0SDimitry Andric Ops.push_back(getTargetConstantPoolValue( 667*04eeddc0SDimitry Andric cast<ExternalSymbolSDNode>(Callee), Ty, DAG, CSKYII::MO_None)); 668*04eeddc0SDimitry Andric } 669*04eeddc0SDimitry Andric } else { 670*04eeddc0SDimitry Andric IsRegCall = true; 671*04eeddc0SDimitry Andric Ops.push_back(Callee); 672*04eeddc0SDimitry Andric } 673*04eeddc0SDimitry Andric 674*04eeddc0SDimitry Andric // Add argument registers to the end of the list so that they are 675*04eeddc0SDimitry Andric // known live into the call. 676*04eeddc0SDimitry Andric for (auto &Reg : RegsToPass) 677*04eeddc0SDimitry Andric Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); 678*04eeddc0SDimitry Andric 679*04eeddc0SDimitry Andric if (!IsTailCall) { 680*04eeddc0SDimitry Andric // Add a register mask operand representing the call-preserved registers. 681*04eeddc0SDimitry Andric const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 682*04eeddc0SDimitry Andric const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); 683*04eeddc0SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 684*04eeddc0SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask)); 685*04eeddc0SDimitry Andric } 686*04eeddc0SDimitry Andric 687*04eeddc0SDimitry Andric // Glue the call to the argument copies, if any. 688*04eeddc0SDimitry Andric if (Glue.getNode()) 689*04eeddc0SDimitry Andric Ops.push_back(Glue); 690*04eeddc0SDimitry Andric 691*04eeddc0SDimitry Andric // Emit the call. 692*04eeddc0SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 693*04eeddc0SDimitry Andric 694*04eeddc0SDimitry Andric if (IsTailCall) { 695*04eeddc0SDimitry Andric MF.getFrameInfo().setHasTailCall(); 696*04eeddc0SDimitry Andric return DAG.getNode(IsRegCall ? CSKYISD::TAILReg : CSKYISD::TAIL, DL, 697*04eeddc0SDimitry Andric NodeTys, Ops); 698*04eeddc0SDimitry Andric } 699*04eeddc0SDimitry Andric 700*04eeddc0SDimitry Andric Chain = DAG.getNode(IsRegCall ? CSKYISD::CALLReg : CSKYISD::CALL, DL, NodeTys, 701*04eeddc0SDimitry Andric Ops); 702*04eeddc0SDimitry Andric DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); 703*04eeddc0SDimitry Andric Glue = Chain.getValue(1); 704*04eeddc0SDimitry Andric 705*04eeddc0SDimitry Andric // Mark the end of the call, which is glued to the call itself. 706*04eeddc0SDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true), 707*04eeddc0SDimitry Andric DAG.getConstant(0, DL, PtrVT, true), Glue, DL); 708*04eeddc0SDimitry Andric Glue = Chain.getValue(1); 709*04eeddc0SDimitry Andric 710*04eeddc0SDimitry Andric // Assign locations to each value returned by this call. 711*04eeddc0SDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs; 712*04eeddc0SDimitry Andric CCState RetCCInfo(CallConv, IsVarArg, MF, CSKYLocs, *DAG.getContext()); 713*04eeddc0SDimitry Andric RetCCInfo.AnalyzeCallResult(Ins, CCAssignFnForReturn(CallConv, IsVarArg)); 714*04eeddc0SDimitry Andric 715*04eeddc0SDimitry Andric // Copy all of the result registers out of their specified physreg. 716*04eeddc0SDimitry Andric for (auto &VA : CSKYLocs) { 717*04eeddc0SDimitry Andric // Copy the value out 718*04eeddc0SDimitry Andric SDValue RetValue = 719*04eeddc0SDimitry Andric DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue); 720*04eeddc0SDimitry Andric // Glue the RetValue to the end of the call sequence 721*04eeddc0SDimitry Andric Chain = RetValue.getValue(1); 722*04eeddc0SDimitry Andric Glue = RetValue.getValue(2); 723*04eeddc0SDimitry Andric 724*04eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 725*04eeddc0SDimitry Andric 726*04eeddc0SDimitry Andric if (IsF64OnCSKY) { 727*04eeddc0SDimitry Andric assert(VA.getLocReg() == GPRArgRegs[0] && "Unexpected reg assignment"); 728*04eeddc0SDimitry Andric SDValue RetValue2 = 729*04eeddc0SDimitry Andric DAG.getCopyFromReg(Chain, DL, GPRArgRegs[1], MVT::i32, Glue); 730*04eeddc0SDimitry Andric Chain = RetValue2.getValue(1); 731*04eeddc0SDimitry Andric Glue = RetValue2.getValue(2); 732*04eeddc0SDimitry Andric RetValue = DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(), 733*04eeddc0SDimitry Andric RetValue, RetValue2); 734*04eeddc0SDimitry Andric } 735*04eeddc0SDimitry Andric 736*04eeddc0SDimitry Andric RetValue = convertLocVTToValVT(DAG, RetValue, VA, DL); 737*04eeddc0SDimitry Andric 738*04eeddc0SDimitry Andric InVals.push_back(RetValue); 739*04eeddc0SDimitry Andric } 740*04eeddc0SDimitry Andric 741*04eeddc0SDimitry Andric return Chain; 742*04eeddc0SDimitry Andric } 743*04eeddc0SDimitry Andric 744349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC, 745349cc55cSDimitry Andric bool IsVarArg) const { 746349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI()) 747349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_SOFT; 748349cc55cSDimitry Andric else 749349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_FP; 750349cc55cSDimitry Andric } 751349cc55cSDimitry Andric 752349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC, 753349cc55cSDimitry Andric bool IsVarArg) const { 754349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI()) 755349cc55cSDimitry Andric return CC_CSKY_ABIV2_SOFT; 756349cc55cSDimitry Andric else 757349cc55cSDimitry Andric return CC_CSKY_ABIV2_FP; 758349cc55cSDimitry Andric } 759349cc55cSDimitry Andric 760*04eeddc0SDimitry Andric static CSKYCP::CSKYCPModifier getModifier(unsigned Flags) { 761*04eeddc0SDimitry Andric 762*04eeddc0SDimitry Andric if (Flags == CSKYII::MO_ADDR32) 763*04eeddc0SDimitry Andric return CSKYCP::ADDR; 764*04eeddc0SDimitry Andric else if (Flags == CSKYII::MO_GOT32) 765*04eeddc0SDimitry Andric return CSKYCP::GOT; 766*04eeddc0SDimitry Andric else if (Flags == CSKYII::MO_GOTOFF) 767*04eeddc0SDimitry Andric return CSKYCP::GOTOFF; 768*04eeddc0SDimitry Andric else if (Flags == CSKYII::MO_PLT32) 769*04eeddc0SDimitry Andric return CSKYCP::PLT; 770*04eeddc0SDimitry Andric else if (Flags == CSKYII::MO_None) 771*04eeddc0SDimitry Andric return CSKYCP::NO_MOD; 772*04eeddc0SDimitry Andric else 773*04eeddc0SDimitry Andric assert(0 && "unknown CSKYII Modifier"); 774*04eeddc0SDimitry Andric return CSKYCP::NO_MOD; 775*04eeddc0SDimitry Andric } 776*04eeddc0SDimitry Andric 777*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(GlobalAddressSDNode *N, 778*04eeddc0SDimitry Andric EVT Ty, 779*04eeddc0SDimitry Andric SelectionDAG &DAG, 780*04eeddc0SDimitry Andric unsigned Flags) const { 781*04eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( 782*04eeddc0SDimitry Andric N->getGlobal(), CSKYCP::CPValue, 0, getModifier(Flags), false); 783*04eeddc0SDimitry Andric 784*04eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 785*04eeddc0SDimitry Andric } 786*04eeddc0SDimitry Andric 787*04eeddc0SDimitry Andric static MachineBasicBlock * 788*04eeddc0SDimitry Andric emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode) { 789*04eeddc0SDimitry Andric 790*04eeddc0SDimitry Andric const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); 791*04eeddc0SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 792*04eeddc0SDimitry Andric 793*04eeddc0SDimitry Andric // To "insert" a SELECT instruction, we actually have to insert the 794*04eeddc0SDimitry Andric // diamond control-flow pattern. The incoming instruction knows the 795*04eeddc0SDimitry Andric // destination vreg to set, the condition code register to branch on, the 796*04eeddc0SDimitry Andric // true/false values to select between, and a branch opcode to use. 797*04eeddc0SDimitry Andric const BasicBlock *LLVM_BB = BB->getBasicBlock(); 798*04eeddc0SDimitry Andric MachineFunction::iterator It = ++BB->getIterator(); 799*04eeddc0SDimitry Andric 800*04eeddc0SDimitry Andric // thisMBB: 801*04eeddc0SDimitry Andric // ... 802*04eeddc0SDimitry Andric // TrueVal = ... 803*04eeddc0SDimitry Andric // bt32 c, sinkMBB 804*04eeddc0SDimitry Andric // fallthrough --> copyMBB 805*04eeddc0SDimitry Andric MachineBasicBlock *thisMBB = BB; 806*04eeddc0SDimitry Andric MachineFunction *F = BB->getParent(); 807*04eeddc0SDimitry Andric MachineBasicBlock *copyMBB = F->CreateMachineBasicBlock(LLVM_BB); 808*04eeddc0SDimitry Andric MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 809*04eeddc0SDimitry Andric F->insert(It, copyMBB); 810*04eeddc0SDimitry Andric F->insert(It, sinkMBB); 811*04eeddc0SDimitry Andric 812*04eeddc0SDimitry Andric // Transfer the remainder of BB and its successor edges to sinkMBB. 813*04eeddc0SDimitry Andric sinkMBB->splice(sinkMBB->begin(), BB, 814*04eeddc0SDimitry Andric std::next(MachineBasicBlock::iterator(MI)), BB->end()); 815*04eeddc0SDimitry Andric sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 816*04eeddc0SDimitry Andric 817*04eeddc0SDimitry Andric // Next, add the true and fallthrough blocks as its successors. 818*04eeddc0SDimitry Andric BB->addSuccessor(copyMBB); 819*04eeddc0SDimitry Andric BB->addSuccessor(sinkMBB); 820*04eeddc0SDimitry Andric 821*04eeddc0SDimitry Andric // bt32 condition, sinkMBB 822*04eeddc0SDimitry Andric BuildMI(BB, DL, TII.get(Opcode)) 823*04eeddc0SDimitry Andric .addReg(MI.getOperand(1).getReg()) 824*04eeddc0SDimitry Andric .addMBB(sinkMBB); 825*04eeddc0SDimitry Andric 826*04eeddc0SDimitry Andric // copyMBB: 827*04eeddc0SDimitry Andric // %FalseValue = ... 828*04eeddc0SDimitry Andric // # fallthrough to sinkMBB 829*04eeddc0SDimitry Andric BB = copyMBB; 830*04eeddc0SDimitry Andric 831*04eeddc0SDimitry Andric // Update machine-CFG edges 832*04eeddc0SDimitry Andric BB->addSuccessor(sinkMBB); 833*04eeddc0SDimitry Andric 834*04eeddc0SDimitry Andric // sinkMBB: 835*04eeddc0SDimitry Andric // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copyMBB ] 836*04eeddc0SDimitry Andric // ... 837*04eeddc0SDimitry Andric BB = sinkMBB; 838*04eeddc0SDimitry Andric 839*04eeddc0SDimitry Andric BuildMI(*BB, BB->begin(), DL, TII.get(CSKY::PHI), MI.getOperand(0).getReg()) 840*04eeddc0SDimitry Andric .addReg(MI.getOperand(2).getReg()) 841*04eeddc0SDimitry Andric .addMBB(thisMBB) 842*04eeddc0SDimitry Andric .addReg(MI.getOperand(3).getReg()) 843*04eeddc0SDimitry Andric .addMBB(copyMBB); 844*04eeddc0SDimitry Andric 845*04eeddc0SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now. 846*04eeddc0SDimitry Andric 847*04eeddc0SDimitry Andric return BB; 848*04eeddc0SDimitry Andric } 849*04eeddc0SDimitry Andric 850*04eeddc0SDimitry Andric MachineBasicBlock * 851*04eeddc0SDimitry Andric CSKYTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, 852*04eeddc0SDimitry Andric MachineBasicBlock *BB) const { 853*04eeddc0SDimitry Andric switch (MI.getOpcode()) { 854*04eeddc0SDimitry Andric default: 855*04eeddc0SDimitry Andric llvm_unreachable("Unexpected instr type to insert"); 856*04eeddc0SDimitry Andric case CSKY::ISEL32: 857*04eeddc0SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT32); 858*04eeddc0SDimitry Andric case CSKY::ISEL16: 859*04eeddc0SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT16); 860*04eeddc0SDimitry Andric } 861*04eeddc0SDimitry Andric } 862*04eeddc0SDimitry Andric 863*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(ExternalSymbolSDNode *N, 864*04eeddc0SDimitry Andric EVT Ty, 865*04eeddc0SDimitry Andric SelectionDAG &DAG, 866*04eeddc0SDimitry Andric unsigned Flags) const { 867*04eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 868*04eeddc0SDimitry Andric CSKYConstantPoolSymbol::Create(Type::getInt32Ty(*DAG.getContext()), 869*04eeddc0SDimitry Andric N->getSymbol(), 0, getModifier(Flags)); 870*04eeddc0SDimitry Andric 871*04eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 872*04eeddc0SDimitry Andric } 873*04eeddc0SDimitry Andric 874*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(JumpTableSDNode *N, 875*04eeddc0SDimitry Andric EVT Ty, 876*04eeddc0SDimitry Andric SelectionDAG &DAG, 877*04eeddc0SDimitry Andric unsigned Flags) const { 878*04eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 879*04eeddc0SDimitry Andric CSKYConstantPoolJT::Create(Type::getInt32Ty(*DAG.getContext()), 880*04eeddc0SDimitry Andric N->getIndex(), 0, getModifier(Flags)); 881*04eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 882*04eeddc0SDimitry Andric } 883*04eeddc0SDimitry Andric 884*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(BlockAddressSDNode *N, 885*04eeddc0SDimitry Andric EVT Ty, 886*04eeddc0SDimitry Andric SelectionDAG &DAG, 887*04eeddc0SDimitry Andric unsigned Flags) const { 888*04eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( 889*04eeddc0SDimitry Andric N->getBlockAddress(), CSKYCP::CPBlockAddress, 0, getModifier(Flags), 890*04eeddc0SDimitry Andric false); 891*04eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 892*04eeddc0SDimitry Andric } 893*04eeddc0SDimitry Andric 894*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(GlobalAddressSDNode *N, SDLoc DL, 895*04eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG, 896*04eeddc0SDimitry Andric unsigned Flags) const { 897*04eeddc0SDimitry Andric return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags); 898*04eeddc0SDimitry Andric } 899*04eeddc0SDimitry Andric 900*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(ExternalSymbolSDNode *N, SDLoc DL, 901*04eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG, 902*04eeddc0SDimitry Andric unsigned Flags) const { 903*04eeddc0SDimitry Andric return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flags); 904*04eeddc0SDimitry Andric } 905*04eeddc0SDimitry Andric 906*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty, 907*04eeddc0SDimitry Andric SelectionDAG &DAG, 908*04eeddc0SDimitry Andric unsigned Flags) const { 909*04eeddc0SDimitry Andric return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags); 910*04eeddc0SDimitry Andric } 911*04eeddc0SDimitry Andric 912*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(BlockAddressSDNode *N, SDLoc DL, 913*04eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG, 914*04eeddc0SDimitry Andric unsigned Flags) const { 915*04eeddc0SDimitry Andric return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(), 916*04eeddc0SDimitry Andric Flags); 917*04eeddc0SDimitry Andric } 918*04eeddc0SDimitry Andric 919349cc55cSDimitry Andric const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const { 920349cc55cSDimitry Andric switch (Opcode) { 921349cc55cSDimitry Andric default: 922349cc55cSDimitry Andric llvm_unreachable("unknown CSKYISD node"); 923349cc55cSDimitry Andric case CSKYISD::NIE: 924349cc55cSDimitry Andric return "CSKYISD::NIE"; 925349cc55cSDimitry Andric case CSKYISD::NIR: 926349cc55cSDimitry Andric return "CSKYISD::NIR"; 927349cc55cSDimitry Andric case CSKYISD::RET: 928349cc55cSDimitry Andric return "CSKYISD::RET"; 929*04eeddc0SDimitry Andric case CSKYISD::CALL: 930*04eeddc0SDimitry Andric return "CSKYISD::CALL"; 931*04eeddc0SDimitry Andric case CSKYISD::CALLReg: 932*04eeddc0SDimitry Andric return "CSKYISD::CALLReg"; 933*04eeddc0SDimitry Andric case CSKYISD::TAIL: 934*04eeddc0SDimitry Andric return "CSKYISD::TAIL"; 935*04eeddc0SDimitry Andric case CSKYISD::TAILReg: 936*04eeddc0SDimitry Andric return "CSKYISD::TAILReg"; 937*04eeddc0SDimitry Andric case CSKYISD::LOAD_ADDR: 938*04eeddc0SDimitry Andric return "CSKYISD::LOAD_ADDR"; 939349cc55cSDimitry Andric case CSKYISD::BITCAST_TO_LOHI: 940349cc55cSDimitry Andric return "CSKYISD::BITCAST_TO_LOHI"; 941*04eeddc0SDimitry Andric case CSKYISD::BITCAST_FROM_LOHI: 942*04eeddc0SDimitry Andric return "CSKYISD::BITCAST_FROM_LOHI"; 943349cc55cSDimitry Andric } 944349cc55cSDimitry Andric } 945*04eeddc0SDimitry Andric 946*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerGlobalAddress(SDValue Op, 947*04eeddc0SDimitry Andric SelectionDAG &DAG) const { 948*04eeddc0SDimitry Andric SDLoc DL(Op); 949*04eeddc0SDimitry Andric EVT Ty = Op.getValueType(); 950*04eeddc0SDimitry Andric GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); 951*04eeddc0SDimitry Andric int64_t Offset = N->getOffset(); 952*04eeddc0SDimitry Andric 953*04eeddc0SDimitry Andric const GlobalValue *GV = N->getGlobal(); 954*04eeddc0SDimitry Andric bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); 955*04eeddc0SDimitry Andric SDValue Addr = getAddr<GlobalAddressSDNode, false>(N, DAG, IsLocal); 956*04eeddc0SDimitry Andric 957*04eeddc0SDimitry Andric // In order to maximise the opportunity for common subexpression elimination, 958*04eeddc0SDimitry Andric // emit a separate ADD node for the global address offset instead of folding 959*04eeddc0SDimitry Andric // it in the global address node. Later peephole optimisations may choose to 960*04eeddc0SDimitry Andric // fold it back in when profitable. 961*04eeddc0SDimitry Andric if (Offset != 0) 962*04eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Addr, 963*04eeddc0SDimitry Andric DAG.getConstant(Offset, DL, MVT::i32)); 964*04eeddc0SDimitry Andric return Addr; 965*04eeddc0SDimitry Andric } 966*04eeddc0SDimitry Andric 967*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerExternalSymbol(SDValue Op, 968*04eeddc0SDimitry Andric SelectionDAG &DAG) const { 969*04eeddc0SDimitry Andric ExternalSymbolSDNode *N = cast<ExternalSymbolSDNode>(Op); 970*04eeddc0SDimitry Andric 971*04eeddc0SDimitry Andric return getAddr(N, DAG, false); 972*04eeddc0SDimitry Andric } 973*04eeddc0SDimitry Andric 974*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerJumpTable(SDValue Op, 975*04eeddc0SDimitry Andric SelectionDAG &DAG) const { 976*04eeddc0SDimitry Andric JumpTableSDNode *N = cast<JumpTableSDNode>(Op); 977*04eeddc0SDimitry Andric 978*04eeddc0SDimitry Andric return getAddr<JumpTableSDNode, false>(N, DAG); 979*04eeddc0SDimitry Andric } 980*04eeddc0SDimitry Andric 981*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerBlockAddress(SDValue Op, 982*04eeddc0SDimitry Andric SelectionDAG &DAG) const { 983*04eeddc0SDimitry Andric BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); 984*04eeddc0SDimitry Andric 985*04eeddc0SDimitry Andric return getAddr(N, DAG); 986*04eeddc0SDimitry Andric } 987*04eeddc0SDimitry Andric 988*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { 989*04eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 990*04eeddc0SDimitry Andric CSKYMachineFunctionInfo *FuncInfo = MF.getInfo<CSKYMachineFunctionInfo>(); 991*04eeddc0SDimitry Andric 992*04eeddc0SDimitry Andric SDLoc DL(Op); 993*04eeddc0SDimitry Andric SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), 994*04eeddc0SDimitry Andric getPointerTy(MF.getDataLayout())); 995*04eeddc0SDimitry Andric 996*04eeddc0SDimitry Andric // vastart just stores the address of the VarArgsFrameIndex slot into the 997*04eeddc0SDimitry Andric // memory location argument. 998*04eeddc0SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 999*04eeddc0SDimitry Andric return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1), 1000*04eeddc0SDimitry Andric MachinePointerInfo(SV)); 1001*04eeddc0SDimitry Andric } 1002*04eeddc0SDimitry Andric 1003*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerFRAMEADDR(SDValue Op, 1004*04eeddc0SDimitry Andric SelectionDAG &DAG) const { 1005*04eeddc0SDimitry Andric const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo(); 1006*04eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 1007*04eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 1008*04eeddc0SDimitry Andric MFI.setFrameAddressIsTaken(true); 1009*04eeddc0SDimitry Andric 1010*04eeddc0SDimitry Andric EVT VT = Op.getValueType(); 1011*04eeddc0SDimitry Andric SDLoc dl(Op); 1012*04eeddc0SDimitry Andric unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 1013*04eeddc0SDimitry Andric Register FrameReg = RI.getFrameRegister(MF); 1014*04eeddc0SDimitry Andric SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); 1015*04eeddc0SDimitry Andric while (Depth--) 1016*04eeddc0SDimitry Andric FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, 1017*04eeddc0SDimitry Andric MachinePointerInfo()); 1018*04eeddc0SDimitry Andric return FrameAddr; 1019*04eeddc0SDimitry Andric } 1020*04eeddc0SDimitry Andric 1021*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerRETURNADDR(SDValue Op, 1022*04eeddc0SDimitry Andric SelectionDAG &DAG) const { 1023*04eeddc0SDimitry Andric const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo(); 1024*04eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 1025*04eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 1026*04eeddc0SDimitry Andric MFI.setReturnAddressIsTaken(true); 1027*04eeddc0SDimitry Andric 1028*04eeddc0SDimitry Andric if (verifyReturnAddressArgumentIsConstant(Op, DAG)) 1029*04eeddc0SDimitry Andric return SDValue(); 1030*04eeddc0SDimitry Andric 1031*04eeddc0SDimitry Andric EVT VT = Op.getValueType(); 1032*04eeddc0SDimitry Andric SDLoc dl(Op); 1033*04eeddc0SDimitry Andric unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 1034*04eeddc0SDimitry Andric if (Depth) { 1035*04eeddc0SDimitry Andric SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); 1036*04eeddc0SDimitry Andric SDValue Offset = DAG.getConstant(4, dl, MVT::i32); 1037*04eeddc0SDimitry Andric return DAG.getLoad(VT, dl, DAG.getEntryNode(), 1038*04eeddc0SDimitry Andric DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset), 1039*04eeddc0SDimitry Andric MachinePointerInfo()); 1040*04eeddc0SDimitry Andric } 1041*04eeddc0SDimitry Andric // Return the value of the return address register, marking it an implicit 1042*04eeddc0SDimitry Andric // live-in. 1043*04eeddc0SDimitry Andric unsigned Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(MVT::i32)); 1044*04eeddc0SDimitry Andric return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT); 1045*04eeddc0SDimitry Andric } 1046*04eeddc0SDimitry Andric 1047*04eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionPointerRegister( 1048*04eeddc0SDimitry Andric const Constant *PersonalityFn) const { 1049*04eeddc0SDimitry Andric return CSKY::R0; 1050*04eeddc0SDimitry Andric } 1051*04eeddc0SDimitry Andric 1052*04eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionSelectorRegister( 1053*04eeddc0SDimitry Andric const Constant *PersonalityFn) const { 1054*04eeddc0SDimitry Andric return CSKY::R1; 1055*04eeddc0SDimitry Andric } 1056*04eeddc0SDimitry Andric 1057*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerGlobalTLSAddress(SDValue Op, 1058*04eeddc0SDimitry Andric SelectionDAG &DAG) const { 1059*04eeddc0SDimitry Andric SDLoc DL(Op); 1060*04eeddc0SDimitry Andric EVT Ty = Op.getValueType(); 1061*04eeddc0SDimitry Andric GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); 1062*04eeddc0SDimitry Andric int64_t Offset = N->getOffset(); 1063*04eeddc0SDimitry Andric MVT XLenVT = MVT::i32; 1064*04eeddc0SDimitry Andric 1065*04eeddc0SDimitry Andric TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal()); 1066*04eeddc0SDimitry Andric SDValue Addr; 1067*04eeddc0SDimitry Andric switch (Model) { 1068*04eeddc0SDimitry Andric case TLSModel::LocalExec: 1069*04eeddc0SDimitry Andric Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false); 1070*04eeddc0SDimitry Andric break; 1071*04eeddc0SDimitry Andric case TLSModel::InitialExec: 1072*04eeddc0SDimitry Andric Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true); 1073*04eeddc0SDimitry Andric break; 1074*04eeddc0SDimitry Andric case TLSModel::LocalDynamic: 1075*04eeddc0SDimitry Andric case TLSModel::GeneralDynamic: 1076*04eeddc0SDimitry Andric Addr = getDynamicTLSAddr(N, DAG); 1077*04eeddc0SDimitry Andric break; 1078*04eeddc0SDimitry Andric } 1079*04eeddc0SDimitry Andric 1080*04eeddc0SDimitry Andric // In order to maximise the opportunity for common subexpression elimination, 1081*04eeddc0SDimitry Andric // emit a separate ADD node for the global address offset instead of folding 1082*04eeddc0SDimitry Andric // it in the global address node. Later peephole optimisations may choose to 1083*04eeddc0SDimitry Andric // fold it back in when profitable. 1084*04eeddc0SDimitry Andric if (Offset != 0) 1085*04eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Addr, 1086*04eeddc0SDimitry Andric DAG.getConstant(Offset, DL, XLenVT)); 1087*04eeddc0SDimitry Andric return Addr; 1088*04eeddc0SDimitry Andric } 1089*04eeddc0SDimitry Andric 1090*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N, 1091*04eeddc0SDimitry Andric SelectionDAG &DAG, 1092*04eeddc0SDimitry Andric bool UseGOT) const { 1093*04eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 1094*04eeddc0SDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 1095*04eeddc0SDimitry Andric 1096*04eeddc0SDimitry Andric unsigned CSKYPCLabelIndex = CFI->createPICLabelUId(); 1097*04eeddc0SDimitry Andric 1098*04eeddc0SDimitry Andric SDLoc DL(N); 1099*04eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout()); 1100*04eeddc0SDimitry Andric 1101*04eeddc0SDimitry Andric CSKYCP::CSKYCPModifier Flag = UseGOT ? CSKYCP::TLSIE : CSKYCP::TLSLE; 1102*04eeddc0SDimitry Andric bool AddCurrentAddr = UseGOT ? true : false; 1103*04eeddc0SDimitry Andric unsigned char PCAjust = UseGOT ? 4 : 0; 1104*04eeddc0SDimitry Andric 1105*04eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 1106*04eeddc0SDimitry Andric CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, PCAjust, 1107*04eeddc0SDimitry Andric Flag, AddCurrentAddr, CSKYPCLabelIndex); 1108*04eeddc0SDimitry Andric SDValue CAddr = DAG.getTargetConstantPool(CPV, Ty); 1109*04eeddc0SDimitry Andric 1110*04eeddc0SDimitry Andric SDValue Load; 1111*04eeddc0SDimitry Andric if (UseGOT) { 1112*04eeddc0SDimitry Andric SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32); 1113*04eeddc0SDimitry Andric auto *LRWGRS = DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, 1114*04eeddc0SDimitry Andric {CAddr, PICLabel}); 1115*04eeddc0SDimitry Andric auto LRWADDGRS = 1116*04eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1)); 1117*04eeddc0SDimitry Andric Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), LRWADDGRS, 1118*04eeddc0SDimitry Andric MachinePointerInfo(N->getGlobal())); 1119*04eeddc0SDimitry Andric } else { 1120*04eeddc0SDimitry Andric Load = SDValue(DAG.getMachineNode(CSKY::LRW32, DL, Ty, CAddr), 0); 1121*04eeddc0SDimitry Andric } 1122*04eeddc0SDimitry Andric 1123*04eeddc0SDimitry Andric // Add the thread pointer. 1124*04eeddc0SDimitry Andric SDValue TPReg = DAG.getRegister(CSKY::R31, MVT::i32); 1125*04eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Load, TPReg); 1126*04eeddc0SDimitry Andric } 1127*04eeddc0SDimitry Andric 1128*04eeddc0SDimitry Andric SDValue CSKYTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N, 1129*04eeddc0SDimitry Andric SelectionDAG &DAG) const { 1130*04eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 1131*04eeddc0SDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 1132*04eeddc0SDimitry Andric 1133*04eeddc0SDimitry Andric unsigned CSKYPCLabelIndex = CFI->createPICLabelUId(); 1134*04eeddc0SDimitry Andric 1135*04eeddc0SDimitry Andric SDLoc DL(N); 1136*04eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout()); 1137*04eeddc0SDimitry Andric IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits()); 1138*04eeddc0SDimitry Andric 1139*04eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 1140*04eeddc0SDimitry Andric CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, 4, 1141*04eeddc0SDimitry Andric CSKYCP::TLSGD, true, CSKYPCLabelIndex); 1142*04eeddc0SDimitry Andric SDValue Addr = DAG.getTargetConstantPool(CPV, Ty); 1143*04eeddc0SDimitry Andric SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32); 1144*04eeddc0SDimitry Andric 1145*04eeddc0SDimitry Andric auto *LRWGRS = 1146*04eeddc0SDimitry Andric DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, {Addr, PICLabel}); 1147*04eeddc0SDimitry Andric 1148*04eeddc0SDimitry Andric auto Load = 1149*04eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1)); 1150*04eeddc0SDimitry Andric 1151*04eeddc0SDimitry Andric // Prepare argument list to generate call. 1152*04eeddc0SDimitry Andric ArgListTy Args; 1153*04eeddc0SDimitry Andric ArgListEntry Entry; 1154*04eeddc0SDimitry Andric Entry.Node = Load; 1155*04eeddc0SDimitry Andric Entry.Ty = CallTy; 1156*04eeddc0SDimitry Andric Args.push_back(Entry); 1157*04eeddc0SDimitry Andric 1158*04eeddc0SDimitry Andric // Setup call to __tls_get_addr. 1159*04eeddc0SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG); 1160*04eeddc0SDimitry Andric CLI.setDebugLoc(DL) 1161*04eeddc0SDimitry Andric .setChain(DAG.getEntryNode()) 1162*04eeddc0SDimitry Andric .setLibCallee(CallingConv::C, CallTy, 1163*04eeddc0SDimitry Andric DAG.getExternalSymbol("__tls_get_addr", Ty), 1164*04eeddc0SDimitry Andric std::move(Args)); 1165*04eeddc0SDimitry Andric SDValue V = LowerCallTo(CLI).first; 1166*04eeddc0SDimitry Andric 1167*04eeddc0SDimitry Andric return V; 1168*04eeddc0SDimitry Andric } 1169