xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYISelLowering.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
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