xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1bdd1243dSDimitry Andric //===-- RISCVCallLowering.cpp - Call lowering -------------------*- C++ -*-===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric //
9bdd1243dSDimitry Andric /// \file
10bdd1243dSDimitry Andric /// This file implements the lowering of LLVM calls to machine code calls for
11bdd1243dSDimitry Andric /// GlobalISel.
12bdd1243dSDimitry Andric //
13bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
14bdd1243dSDimitry Andric 
15bdd1243dSDimitry Andric #include "RISCVCallLowering.h"
16bdd1243dSDimitry Andric #include "RISCVISelLowering.h"
17*06c3fb27SDimitry Andric #include "RISCVSubtarget.h"
18*06c3fb27SDimitry Andric #include "llvm/CodeGen/Analysis.h"
19bdd1243dSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
20bdd1243dSDimitry Andric 
21bdd1243dSDimitry Andric using namespace llvm;
22bdd1243dSDimitry Andric 
23*06c3fb27SDimitry Andric namespace {
24*06c3fb27SDimitry Andric 
25*06c3fb27SDimitry Andric struct RISCVOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {
26*06c3fb27SDimitry Andric private:
27*06c3fb27SDimitry Andric   // The function used internally to assign args - we ignore the AssignFn stored
28*06c3fb27SDimitry Andric   // by OutgoingValueAssigner since RISC-V implements its CC using a custom
29*06c3fb27SDimitry Andric   // function with a different signature.
30*06c3fb27SDimitry Andric   RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn;
31*06c3fb27SDimitry Andric 
32*06c3fb27SDimitry Andric   // Whether this is assigning args for a return.
33*06c3fb27SDimitry Andric   bool IsRet;
34*06c3fb27SDimitry Andric 
35*06c3fb27SDimitry Andric public:
36*06c3fb27SDimitry Andric   RISCVOutgoingValueAssigner(
37*06c3fb27SDimitry Andric       RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)
38*06c3fb27SDimitry Andric       : CallLowering::OutgoingValueAssigner(nullptr),
39*06c3fb27SDimitry Andric         RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}
40*06c3fb27SDimitry Andric 
41*06c3fb27SDimitry Andric   bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
42*06c3fb27SDimitry Andric                  CCValAssign::LocInfo LocInfo,
43*06c3fb27SDimitry Andric                  const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
44*06c3fb27SDimitry Andric                  CCState &State) override {
45*06c3fb27SDimitry Andric     MachineFunction &MF = State.getMachineFunction();
46*06c3fb27SDimitry Andric     const DataLayout &DL = MF.getDataLayout();
47*06c3fb27SDimitry Andric     const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
48*06c3fb27SDimitry Andric 
49*06c3fb27SDimitry Andric     return RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
50*06c3fb27SDimitry Andric                          LocInfo, Flags, State, /*IsFixed=*/true, IsRet,
51*06c3fb27SDimitry Andric                          Info.Ty, *Subtarget.getTargetLowering(),
52*06c3fb27SDimitry Andric                          /*FirstMaskArgument=*/std::nullopt);
53*06c3fb27SDimitry Andric   }
54*06c3fb27SDimitry Andric };
55*06c3fb27SDimitry Andric 
56*06c3fb27SDimitry Andric struct RISCVOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
57*06c3fb27SDimitry Andric   RISCVOutgoingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,
58*06c3fb27SDimitry Andric                             MachineInstrBuilder MIB)
59*06c3fb27SDimitry Andric       : OutgoingValueHandler(B, MRI), MIB(MIB) {}
60*06c3fb27SDimitry Andric 
61*06c3fb27SDimitry Andric   MachineInstrBuilder MIB;
62*06c3fb27SDimitry Andric 
63*06c3fb27SDimitry Andric   Register getStackAddress(uint64_t MemSize, int64_t Offset,
64*06c3fb27SDimitry Andric                            MachinePointerInfo &MPO,
65*06c3fb27SDimitry Andric                            ISD::ArgFlagsTy Flags) override {
66*06c3fb27SDimitry Andric     llvm_unreachable("not implemented");
67*06c3fb27SDimitry Andric   }
68*06c3fb27SDimitry Andric 
69*06c3fb27SDimitry Andric   void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
70*06c3fb27SDimitry Andric                             MachinePointerInfo &MPO, CCValAssign &VA) override {
71*06c3fb27SDimitry Andric     llvm_unreachable("not implemented");
72*06c3fb27SDimitry Andric   }
73*06c3fb27SDimitry Andric 
74*06c3fb27SDimitry Andric   void assignValueToReg(Register ValVReg, Register PhysReg,
75*06c3fb27SDimitry Andric                         CCValAssign VA) override {
76*06c3fb27SDimitry Andric     Register ExtReg = extendRegister(ValVReg, VA);
77*06c3fb27SDimitry Andric     MIRBuilder.buildCopy(PhysReg, ExtReg);
78*06c3fb27SDimitry Andric     MIB.addUse(PhysReg, RegState::Implicit);
79*06c3fb27SDimitry Andric   }
80*06c3fb27SDimitry Andric };
81*06c3fb27SDimitry Andric 
82*06c3fb27SDimitry Andric struct RISCVIncomingValueAssigner : public CallLowering::IncomingValueAssigner {
83*06c3fb27SDimitry Andric private:
84*06c3fb27SDimitry Andric   // The function used internally to assign args - we ignore the AssignFn stored
85*06c3fb27SDimitry Andric   // by IncomingValueAssigner since RISC-V implements its CC using a custom
86*06c3fb27SDimitry Andric   // function with a different signature.
87*06c3fb27SDimitry Andric   RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn;
88*06c3fb27SDimitry Andric 
89*06c3fb27SDimitry Andric   // Whether this is assigning args from a return.
90*06c3fb27SDimitry Andric   bool IsRet;
91*06c3fb27SDimitry Andric 
92*06c3fb27SDimitry Andric public:
93*06c3fb27SDimitry Andric   RISCVIncomingValueAssigner(
94*06c3fb27SDimitry Andric       RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)
95*06c3fb27SDimitry Andric       : CallLowering::IncomingValueAssigner(nullptr),
96*06c3fb27SDimitry Andric         RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}
97*06c3fb27SDimitry Andric 
98*06c3fb27SDimitry Andric   bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
99*06c3fb27SDimitry Andric                  CCValAssign::LocInfo LocInfo,
100*06c3fb27SDimitry Andric                  const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
101*06c3fb27SDimitry Andric                  CCState &State) override {
102*06c3fb27SDimitry Andric     MachineFunction &MF = State.getMachineFunction();
103*06c3fb27SDimitry Andric     const DataLayout &DL = MF.getDataLayout();
104*06c3fb27SDimitry Andric     const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
105*06c3fb27SDimitry Andric 
106*06c3fb27SDimitry Andric     return RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
107*06c3fb27SDimitry Andric                          LocInfo, Flags, State, /*IsFixed=*/true, IsRet,
108*06c3fb27SDimitry Andric                          Info.Ty, *Subtarget.getTargetLowering(),
109*06c3fb27SDimitry Andric                          /*FirstMaskArgument=*/std::nullopt);
110*06c3fb27SDimitry Andric   }
111*06c3fb27SDimitry Andric };
112*06c3fb27SDimitry Andric 
113*06c3fb27SDimitry Andric struct RISCVIncomingValueHandler : public CallLowering::IncomingValueHandler {
114*06c3fb27SDimitry Andric   RISCVIncomingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)
115*06c3fb27SDimitry Andric       : IncomingValueHandler(B, MRI) {}
116*06c3fb27SDimitry Andric 
117*06c3fb27SDimitry Andric   Register getStackAddress(uint64_t MemSize, int64_t Offset,
118*06c3fb27SDimitry Andric                            MachinePointerInfo &MPO,
119*06c3fb27SDimitry Andric                            ISD::ArgFlagsTy Flags) override {
120*06c3fb27SDimitry Andric     llvm_unreachable("not implemented");
121*06c3fb27SDimitry Andric   }
122*06c3fb27SDimitry Andric 
123*06c3fb27SDimitry Andric   void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
124*06c3fb27SDimitry Andric                             MachinePointerInfo &MPO, CCValAssign &VA) override {
125*06c3fb27SDimitry Andric     llvm_unreachable("not implemented");
126*06c3fb27SDimitry Andric   }
127*06c3fb27SDimitry Andric 
128*06c3fb27SDimitry Andric   void assignValueToReg(Register ValVReg, Register PhysReg,
129*06c3fb27SDimitry Andric                         CCValAssign VA) override {
130*06c3fb27SDimitry Andric     // Copy argument received in physical register to desired VReg.
131*06c3fb27SDimitry Andric     MIRBuilder.getMBB().addLiveIn(PhysReg);
132*06c3fb27SDimitry Andric     MIRBuilder.buildCopy(ValVReg, PhysReg);
133*06c3fb27SDimitry Andric   }
134*06c3fb27SDimitry Andric };
135*06c3fb27SDimitry Andric 
136*06c3fb27SDimitry Andric struct RISCVCallReturnHandler : public RISCVIncomingValueHandler {
137*06c3fb27SDimitry Andric   RISCVCallReturnHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,
138*06c3fb27SDimitry Andric                          MachineInstrBuilder &MIB)
139*06c3fb27SDimitry Andric       : RISCVIncomingValueHandler(B, MRI), MIB(MIB) {}
140*06c3fb27SDimitry Andric 
141*06c3fb27SDimitry Andric   MachineInstrBuilder MIB;
142*06c3fb27SDimitry Andric 
143*06c3fb27SDimitry Andric   void assignValueToReg(Register ValVReg, Register PhysReg,
144*06c3fb27SDimitry Andric                         CCValAssign VA) override {
145*06c3fb27SDimitry Andric     // Copy argument received in physical register to desired VReg.
146*06c3fb27SDimitry Andric     MIB.addDef(PhysReg, RegState::Implicit);
147*06c3fb27SDimitry Andric     MIRBuilder.buildCopy(ValVReg, PhysReg);
148*06c3fb27SDimitry Andric   }
149*06c3fb27SDimitry Andric };
150*06c3fb27SDimitry Andric 
151*06c3fb27SDimitry Andric } // namespace
152*06c3fb27SDimitry Andric 
153bdd1243dSDimitry Andric RISCVCallLowering::RISCVCallLowering(const RISCVTargetLowering &TLI)
154bdd1243dSDimitry Andric     : CallLowering(&TLI) {}
155bdd1243dSDimitry Andric 
156*06c3fb27SDimitry Andric bool RISCVCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
157*06c3fb27SDimitry Andric                                        const Value *Val,
158*06c3fb27SDimitry Andric                                        ArrayRef<Register> VRegs,
159*06c3fb27SDimitry Andric                                        MachineInstrBuilder &Ret) const {
160*06c3fb27SDimitry Andric   if (!Val)
161*06c3fb27SDimitry Andric     return true;
162*06c3fb27SDimitry Andric 
163*06c3fb27SDimitry Andric   // TODO: Only integer, pointer and aggregate types are supported now.
164*06c3fb27SDimitry Andric   if (!Val->getType()->isIntOrPtrTy() && !Val->getType()->isAggregateType())
165*06c3fb27SDimitry Andric     return false;
166*06c3fb27SDimitry Andric 
167*06c3fb27SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
168*06c3fb27SDimitry Andric   const DataLayout &DL = MF.getDataLayout();
169*06c3fb27SDimitry Andric   const Function &F = MF.getFunction();
170*06c3fb27SDimitry Andric   CallingConv::ID CC = F.getCallingConv();
171*06c3fb27SDimitry Andric 
172*06c3fb27SDimitry Andric   ArgInfo OrigRetInfo(VRegs, Val->getType(), 0);
173*06c3fb27SDimitry Andric   setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F);
174*06c3fb27SDimitry Andric 
175*06c3fb27SDimitry Andric   SmallVector<ArgInfo, 4> SplitRetInfos;
176*06c3fb27SDimitry Andric   splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC);
177*06c3fb27SDimitry Andric 
178*06c3fb27SDimitry Andric   RISCVOutgoingValueAssigner Assigner(
179*06c3fb27SDimitry Andric       CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,
180*06c3fb27SDimitry Andric       /*IsRet=*/true);
181*06c3fb27SDimitry Andric   RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret);
182*06c3fb27SDimitry Andric   return determineAndHandleAssignments(Handler, Assigner, SplitRetInfos,
183*06c3fb27SDimitry Andric                                        MIRBuilder, CC, F.isVarArg());
184*06c3fb27SDimitry Andric }
185*06c3fb27SDimitry Andric 
186bdd1243dSDimitry Andric bool RISCVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
187bdd1243dSDimitry Andric                                     const Value *Val, ArrayRef<Register> VRegs,
188bdd1243dSDimitry Andric                                     FunctionLoweringInfo &FLI) const {
189*06c3fb27SDimitry Andric   assert(!Val == VRegs.empty() && "Return value without a vreg");
190bdd1243dSDimitry Andric   MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(RISCV::PseudoRET);
191bdd1243dSDimitry Andric 
192*06c3fb27SDimitry Andric   if (!lowerReturnVal(MIRBuilder, Val, VRegs, Ret))
193bdd1243dSDimitry Andric     return false;
194*06c3fb27SDimitry Andric 
195bdd1243dSDimitry Andric   MIRBuilder.insertInstr(Ret);
196bdd1243dSDimitry Andric   return true;
197bdd1243dSDimitry Andric }
198bdd1243dSDimitry Andric 
199bdd1243dSDimitry Andric bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
200bdd1243dSDimitry Andric                                              const Function &F,
201bdd1243dSDimitry Andric                                              ArrayRef<ArrayRef<Register>> VRegs,
202bdd1243dSDimitry Andric                                              FunctionLoweringInfo &FLI) const {
203*06c3fb27SDimitry Andric   // Early exit if there are no arguments.
204bdd1243dSDimitry Andric   if (F.arg_empty())
205bdd1243dSDimitry Andric     return true;
206bdd1243dSDimitry Andric 
207*06c3fb27SDimitry Andric   // TODO: Support vararg functions.
208*06c3fb27SDimitry Andric   if (F.isVarArg())
209bdd1243dSDimitry Andric     return false;
210*06c3fb27SDimitry Andric 
211*06c3fb27SDimitry Andric   // TODO: Support all argument types.
212*06c3fb27SDimitry Andric   for (auto &Arg : F.args()) {
213*06c3fb27SDimitry Andric     if (Arg.getType()->isIntegerTy())
214*06c3fb27SDimitry Andric       continue;
215*06c3fb27SDimitry Andric     if (Arg.getType()->isPointerTy())
216*06c3fb27SDimitry Andric       continue;
217*06c3fb27SDimitry Andric     return false;
218*06c3fb27SDimitry Andric   }
219*06c3fb27SDimitry Andric 
220*06c3fb27SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
221*06c3fb27SDimitry Andric   const DataLayout &DL = MF.getDataLayout();
222*06c3fb27SDimitry Andric   CallingConv::ID CC = F.getCallingConv();
223*06c3fb27SDimitry Andric 
224*06c3fb27SDimitry Andric   SmallVector<ArgInfo, 32> SplitArgInfos;
225*06c3fb27SDimitry Andric   unsigned Index = 0;
226*06c3fb27SDimitry Andric   for (auto &Arg : F.args()) {
227*06c3fb27SDimitry Andric     // Construct the ArgInfo object from destination register and argument type.
228*06c3fb27SDimitry Andric     ArgInfo AInfo(VRegs[Index], Arg.getType(), Index);
229*06c3fb27SDimitry Andric     setArgFlags(AInfo, Index + AttributeList::FirstArgIndex, DL, F);
230*06c3fb27SDimitry Andric 
231*06c3fb27SDimitry Andric     // Handle any required merging from split value types from physical
232*06c3fb27SDimitry Andric     // registers into the desired VReg. ArgInfo objects are constructed
233*06c3fb27SDimitry Andric     // correspondingly and appended to SplitArgInfos.
234*06c3fb27SDimitry Andric     splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
235*06c3fb27SDimitry Andric 
236*06c3fb27SDimitry Andric     ++Index;
237*06c3fb27SDimitry Andric   }
238*06c3fb27SDimitry Andric 
239*06c3fb27SDimitry Andric   RISCVIncomingValueAssigner Assigner(
240*06c3fb27SDimitry Andric       CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,
241*06c3fb27SDimitry Andric       /*IsRet=*/false);
242*06c3fb27SDimitry Andric   RISCVIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
243*06c3fb27SDimitry Andric 
244*06c3fb27SDimitry Andric   return determineAndHandleAssignments(Handler, Assigner, SplitArgInfos,
245*06c3fb27SDimitry Andric                                        MIRBuilder, CC, F.isVarArg());
246bdd1243dSDimitry Andric }
247bdd1243dSDimitry Andric 
248bdd1243dSDimitry Andric bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
249bdd1243dSDimitry Andric                                   CallLoweringInfo &Info) const {
250*06c3fb27SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
251*06c3fb27SDimitry Andric   const DataLayout &DL = MF.getDataLayout();
252*06c3fb27SDimitry Andric   const Function &F = MF.getFunction();
253*06c3fb27SDimitry Andric   CallingConv::ID CC = F.getCallingConv();
254*06c3fb27SDimitry Andric 
255*06c3fb27SDimitry Andric   // TODO: Support vararg functions.
256*06c3fb27SDimitry Andric   if (Info.IsVarArg)
257bdd1243dSDimitry Andric     return false;
258*06c3fb27SDimitry Andric 
259*06c3fb27SDimitry Andric   // TODO: Support all argument types.
260*06c3fb27SDimitry Andric   for (auto &AInfo : Info.OrigArgs) {
261*06c3fb27SDimitry Andric     if (AInfo.Ty->isIntegerTy())
262*06c3fb27SDimitry Andric       continue;
263*06c3fb27SDimitry Andric     if (AInfo.Ty->isPointerTy())
264*06c3fb27SDimitry Andric       continue;
265*06c3fb27SDimitry Andric     if (AInfo.Ty->isFloatingPointTy())
266*06c3fb27SDimitry Andric       continue;
267*06c3fb27SDimitry Andric     return false;
268*06c3fb27SDimitry Andric   }
269*06c3fb27SDimitry Andric 
270*06c3fb27SDimitry Andric   SmallVector<ArgInfo, 32> SplitArgInfos;
271*06c3fb27SDimitry Andric   SmallVector<ISD::OutputArg, 8> Outs;
272*06c3fb27SDimitry Andric   for (auto &AInfo : Info.OrigArgs) {
273*06c3fb27SDimitry Andric     // Handle any required unmerging of split value types from a given VReg into
274*06c3fb27SDimitry Andric     // physical registers. ArgInfo objects are constructed correspondingly and
275*06c3fb27SDimitry Andric     // appended to SplitArgInfos.
276*06c3fb27SDimitry Andric     splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
277*06c3fb27SDimitry Andric   }
278*06c3fb27SDimitry Andric 
279*06c3fb27SDimitry Andric   // TODO: Support tail calls.
280*06c3fb27SDimitry Andric   Info.IsTailCall = false;
281*06c3fb27SDimitry Andric 
282*06c3fb27SDimitry Andric   if (!Info.Callee.isReg())
283*06c3fb27SDimitry Andric     Info.Callee.setTargetFlags(RISCVII::MO_CALL);
284*06c3fb27SDimitry Andric 
285*06c3fb27SDimitry Andric   MachineInstrBuilder Call =
286*06c3fb27SDimitry Andric       MIRBuilder
287*06c3fb27SDimitry Andric           .buildInstrNoInsert(Info.Callee.isReg() ? RISCV::PseudoCALLIndirect
288*06c3fb27SDimitry Andric                                                   : RISCV::PseudoCALL)
289*06c3fb27SDimitry Andric           .add(Info.Callee);
290*06c3fb27SDimitry Andric 
291*06c3fb27SDimitry Andric   RISCVOutgoingValueAssigner ArgAssigner(
292*06c3fb27SDimitry Andric       CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,
293*06c3fb27SDimitry Andric       /*IsRet=*/false);
294*06c3fb27SDimitry Andric   RISCVOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), Call);
295*06c3fb27SDimitry Andric   if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos,
296*06c3fb27SDimitry Andric                                      MIRBuilder, CC, Info.IsVarArg))
297*06c3fb27SDimitry Andric     return false;
298*06c3fb27SDimitry Andric 
299*06c3fb27SDimitry Andric   MIRBuilder.insertInstr(Call);
300*06c3fb27SDimitry Andric 
301*06c3fb27SDimitry Andric   if (Info.OrigRet.Ty->isVoidTy())
302*06c3fb27SDimitry Andric     return true;
303*06c3fb27SDimitry Andric 
304*06c3fb27SDimitry Andric   // TODO: Only integer, pointer and aggregate types are supported now.
305*06c3fb27SDimitry Andric   if (!Info.OrigRet.Ty->isIntOrPtrTy() && !Info.OrigRet.Ty->isAggregateType())
306*06c3fb27SDimitry Andric     return false;
307*06c3fb27SDimitry Andric 
308*06c3fb27SDimitry Andric   SmallVector<ArgInfo, 4> SplitRetInfos;
309*06c3fb27SDimitry Andric   splitToValueTypes(Info.OrigRet, SplitRetInfos, DL, CC);
310*06c3fb27SDimitry Andric 
311*06c3fb27SDimitry Andric   // Assignments should be handled *before* the merging of values takes place.
312*06c3fb27SDimitry Andric   // To ensure this, the insert point is temporarily adjusted to just after the
313*06c3fb27SDimitry Andric   // call instruction.
314*06c3fb27SDimitry Andric   MachineBasicBlock::iterator CallInsertPt = Call;
315*06c3fb27SDimitry Andric   MIRBuilder.setInsertPt(MIRBuilder.getMBB(), std::next(CallInsertPt));
316*06c3fb27SDimitry Andric 
317*06c3fb27SDimitry Andric   RISCVIncomingValueAssigner RetAssigner(
318*06c3fb27SDimitry Andric       CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,
319*06c3fb27SDimitry Andric       /*IsRet=*/true);
320*06c3fb27SDimitry Andric   RISCVCallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Call);
321*06c3fb27SDimitry Andric   if (!determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos,
322*06c3fb27SDimitry Andric                                      MIRBuilder, CC, Info.IsVarArg))
323*06c3fb27SDimitry Andric     return false;
324*06c3fb27SDimitry Andric 
325*06c3fb27SDimitry Andric   // Readjust insert point to end of basic block.
326*06c3fb27SDimitry Andric   MIRBuilder.setMBB(MIRBuilder.getMBB());
327*06c3fb27SDimitry Andric 
328*06c3fb27SDimitry Andric   return true;
329bdd1243dSDimitry Andric }
330