xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1e8d8bef9SDimitry Andric //===-- PPCCallLowering.h - Call lowering for GlobalISel -------*- C++ -*-===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric ///
9e8d8bef9SDimitry Andric /// \file
10e8d8bef9SDimitry Andric /// This file implements the lowering of LLVM calls to machine code calls for
11e8d8bef9SDimitry Andric /// GlobalISel.
12e8d8bef9SDimitry Andric ///
13e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
14e8d8bef9SDimitry Andric 
15e8d8bef9SDimitry Andric #include "PPCCallLowering.h"
16bdd1243dSDimitry Andric #include "PPCCallingConv.h"
17fe6060f1SDimitry Andric #include "PPCISelLowering.h"
18fe6060f1SDimitry Andric #include "PPCSubtarget.h"
19fe6060f1SDimitry Andric #include "PPCTargetMachine.h"
20fe6060f1SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
21fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h"
22e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
2381ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
24fe6060f1SDimitry Andric #include "llvm/CodeGen/TargetCallingConv.h"
25e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h"
26e8d8bef9SDimitry Andric 
27e8d8bef9SDimitry Andric #define DEBUG_TYPE "ppc-call-lowering"
28e8d8bef9SDimitry Andric 
29e8d8bef9SDimitry Andric using namespace llvm;
30e8d8bef9SDimitry Andric 
31bdd1243dSDimitry Andric namespace {
32bdd1243dSDimitry Andric 
33bdd1243dSDimitry Andric struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler {
34bdd1243dSDimitry Andric   OutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
35bdd1243dSDimitry Andric                      MachineInstrBuilder MIB)
36bdd1243dSDimitry Andric       : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
37bdd1243dSDimitry Andric 
38bdd1243dSDimitry Andric   void assignValueToReg(Register ValVReg, Register PhysReg,
395f757f3fSDimitry Andric                         const CCValAssign &VA) override;
40bdd1243dSDimitry Andric   void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
415f757f3fSDimitry Andric                             const MachinePointerInfo &MPO,
425f757f3fSDimitry Andric                             const CCValAssign &VA) override;
43bdd1243dSDimitry Andric   Register getStackAddress(uint64_t Size, int64_t Offset,
44bdd1243dSDimitry Andric                            MachinePointerInfo &MPO,
45bdd1243dSDimitry Andric                            ISD::ArgFlagsTy Flags) override;
46bdd1243dSDimitry Andric 
47bdd1243dSDimitry Andric   MachineInstrBuilder MIB;
48bdd1243dSDimitry Andric };
49bdd1243dSDimitry Andric } // namespace
50bdd1243dSDimitry Andric 
51bdd1243dSDimitry Andric void OutgoingArgHandler::assignValueToReg(Register ValVReg, Register PhysReg,
525f757f3fSDimitry Andric                                           const CCValAssign &VA) {
53bdd1243dSDimitry Andric   MIB.addUse(PhysReg, RegState::Implicit);
54bdd1243dSDimitry Andric   Register ExtReg = extendRegister(ValVReg, VA);
55bdd1243dSDimitry Andric   MIRBuilder.buildCopy(PhysReg, ExtReg);
56bdd1243dSDimitry Andric }
57bdd1243dSDimitry Andric 
58bdd1243dSDimitry Andric void OutgoingArgHandler::assignValueToAddress(Register ValVReg, Register Addr,
59bdd1243dSDimitry Andric                                               LLT MemTy,
605f757f3fSDimitry Andric                                               const MachinePointerInfo &MPO,
615f757f3fSDimitry Andric                                               const CCValAssign &VA) {
62bdd1243dSDimitry Andric   llvm_unreachable("unimplemented");
63bdd1243dSDimitry Andric }
64bdd1243dSDimitry Andric 
65bdd1243dSDimitry Andric Register OutgoingArgHandler::getStackAddress(uint64_t Size, int64_t Offset,
66bdd1243dSDimitry Andric                                              MachinePointerInfo &MPO,
67bdd1243dSDimitry Andric                                              ISD::ArgFlagsTy Flags) {
68bdd1243dSDimitry Andric   llvm_unreachable("unimplemented");
69bdd1243dSDimitry Andric }
70bdd1243dSDimitry Andric 
71e8d8bef9SDimitry Andric PPCCallLowering::PPCCallLowering(const PPCTargetLowering &TLI)
72e8d8bef9SDimitry Andric     : CallLowering(&TLI) {}
73e8d8bef9SDimitry Andric 
74e8d8bef9SDimitry Andric bool PPCCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
75e8d8bef9SDimitry Andric                                   const Value *Val, ArrayRef<Register> VRegs,
76e8d8bef9SDimitry Andric                                   FunctionLoweringInfo &FLI,
77e8d8bef9SDimitry Andric                                   Register SwiftErrorVReg) const {
78bdd1243dSDimitry Andric   auto MIB = MIRBuilder.buildInstrNoInsert(PPC::BLR8);
79bdd1243dSDimitry Andric   bool Success = true;
80bdd1243dSDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
81bdd1243dSDimitry Andric   const Function &F = MF.getFunction();
82bdd1243dSDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
83*0fca6ea1SDimitry Andric   auto &DL = F.getDataLayout();
84bdd1243dSDimitry Andric   if (!VRegs.empty()) {
85bdd1243dSDimitry Andric     // Setup the information about the return value.
86bdd1243dSDimitry Andric     ArgInfo OrigArg{VRegs, Val->getType(), 0};
87bdd1243dSDimitry Andric     setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F);
88e8d8bef9SDimitry Andric 
89bdd1243dSDimitry Andric     // Split the return value into consecutive registers if needed.
90bdd1243dSDimitry Andric     SmallVector<ArgInfo, 8> SplitArgs;
91bdd1243dSDimitry Andric     splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
92bdd1243dSDimitry Andric 
93bdd1243dSDimitry Andric     // Use the calling convention callback to determine type and location of
94bdd1243dSDimitry Andric     // return value.
95bdd1243dSDimitry Andric     OutgoingValueAssigner ArgAssigner(RetCC_PPC);
96bdd1243dSDimitry Andric 
97bdd1243dSDimitry Andric     // Handler to move the return value into the correct location.
98bdd1243dSDimitry Andric     OutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB);
99bdd1243dSDimitry Andric 
100bdd1243dSDimitry Andric     // Iterate over all return values, and move them to the assigned location.
101bdd1243dSDimitry Andric     Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
102bdd1243dSDimitry Andric                                             MIRBuilder, F.getCallingConv(),
103bdd1243dSDimitry Andric                                             F.isVarArg());
104bdd1243dSDimitry Andric   }
105bdd1243dSDimitry Andric   MIRBuilder.insertInstr(MIB);
106bdd1243dSDimitry Andric   return Success;
107e8d8bef9SDimitry Andric }
108e8d8bef9SDimitry Andric 
109fe6060f1SDimitry Andric bool PPCCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
110fe6060f1SDimitry Andric                                 CallLoweringInfo &Info) const {
111fe6060f1SDimitry Andric   return false;
112fe6060f1SDimitry Andric }
113fe6060f1SDimitry Andric 
114e8d8bef9SDimitry Andric bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
115e8d8bef9SDimitry Andric                                            const Function &F,
116e8d8bef9SDimitry Andric                                            ArrayRef<ArrayRef<Register>> VRegs,
117e8d8bef9SDimitry Andric                                            FunctionLoweringInfo &FLI) const {
118fe6060f1SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
119fe6060f1SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
120*0fca6ea1SDimitry Andric   const auto &DL = F.getDataLayout();
121fe6060f1SDimitry Andric   auto &TLI = *getTLI<PPCTargetLowering>();
122e8d8bef9SDimitry Andric 
123fe6060f1SDimitry Andric   // Loop over each arg, set flags and split to single value types
124fe6060f1SDimitry Andric   SmallVector<ArgInfo, 8> SplitArgs;
125fe6060f1SDimitry Andric   unsigned I = 0;
126fe6060f1SDimitry Andric   for (const auto &Arg : F.args()) {
127fe6060f1SDimitry Andric     if (DL.getTypeStoreSize(Arg.getType()).isZero())
128fe6060f1SDimitry Andric       continue;
129fe6060f1SDimitry Andric 
130fe6060f1SDimitry Andric     ArgInfo OrigArg{VRegs[I], Arg, I};
131fe6060f1SDimitry Andric     setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F);
132fe6060f1SDimitry Andric     splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
133fe6060f1SDimitry Andric     ++I;
134e8d8bef9SDimitry Andric   }
135e8d8bef9SDimitry Andric 
136fe6060f1SDimitry Andric   CCAssignFn *AssignFn =
137fe6060f1SDimitry Andric       TLI.ccAssignFnForCall(F.getCallingConv(), false, F.isVarArg());
138fe6060f1SDimitry Andric   IncomingValueAssigner ArgAssigner(AssignFn);
139fe6060f1SDimitry Andric   FormalArgHandler ArgHandler(MIRBuilder, MRI);
140fe6060f1SDimitry Andric   return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
141fe6060f1SDimitry Andric                                        MIRBuilder, F.getCallingConv(),
142fe6060f1SDimitry Andric                                        F.isVarArg());
143fe6060f1SDimitry Andric }
144fe6060f1SDimitry Andric 
145fe6060f1SDimitry Andric void PPCIncomingValueHandler::assignValueToReg(Register ValVReg,
146fe6060f1SDimitry Andric                                                Register PhysReg,
1475f757f3fSDimitry Andric                                                const CCValAssign &VA) {
148fe6060f1SDimitry Andric   markPhysRegUsed(PhysReg);
149fe6060f1SDimitry Andric   IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
150fe6060f1SDimitry Andric }
151fe6060f1SDimitry Andric 
1525f757f3fSDimitry Andric void PPCIncomingValueHandler::assignValueToAddress(
1535f757f3fSDimitry Andric     Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,
1545f757f3fSDimitry Andric     const CCValAssign &VA) {
155fe6060f1SDimitry Andric   // define a lambda expression to load value
1565f757f3fSDimitry Andric   auto BuildLoad = [](MachineIRBuilder &MIRBuilder,
1575f757f3fSDimitry Andric                       const MachinePointerInfo &MPO, LLT MemTy,
1585f757f3fSDimitry Andric                       const DstOp &Res, Register Addr) {
159fe6060f1SDimitry Andric     MachineFunction &MF = MIRBuilder.getMF();
160fe6060f1SDimitry Andric     auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
161fe6060f1SDimitry Andric                                         inferAlignFromPtrInfo(MF, MPO));
162fe6060f1SDimitry Andric     return MIRBuilder.buildLoad(Res, Addr, *MMO);
163fe6060f1SDimitry Andric   };
164fe6060f1SDimitry Andric 
165fe6060f1SDimitry Andric   BuildLoad(MIRBuilder, MPO, MemTy, ValVReg, Addr);
166fe6060f1SDimitry Andric }
167fe6060f1SDimitry Andric 
168fe6060f1SDimitry Andric Register PPCIncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset,
169fe6060f1SDimitry Andric                                                   MachinePointerInfo &MPO,
170fe6060f1SDimitry Andric                                                   ISD::ArgFlagsTy Flags) {
171fe6060f1SDimitry Andric   auto &MFI = MIRBuilder.getMF().getFrameInfo();
172fe6060f1SDimitry Andric   const bool IsImmutable = !Flags.isByVal();
173fe6060f1SDimitry Andric   int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable);
174fe6060f1SDimitry Andric   MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
175fe6060f1SDimitry Andric 
176fe6060f1SDimitry Andric   // Build Frame Index based on whether the machine is 32-bit or 64-bit
177fe6060f1SDimitry Andric   llvm::LLT FramePtr = LLT::pointer(
178fe6060f1SDimitry Andric       0, MIRBuilder.getMF().getDataLayout().getPointerSizeInBits());
179fe6060f1SDimitry Andric   MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(FramePtr, FI);
180fe6060f1SDimitry Andric   StackUsed = std::max(StackUsed, Size + Offset);
181fe6060f1SDimitry Andric   return AddrReg.getReg(0);
182fe6060f1SDimitry Andric }
183fe6060f1SDimitry Andric 
184fe6060f1SDimitry Andric void FormalArgHandler::markPhysRegUsed(unsigned PhysReg) {
185fe6060f1SDimitry Andric   MIRBuilder.getMRI()->addLiveIn(PhysReg);
186fe6060f1SDimitry Andric   MIRBuilder.getMBB().addLiveIn(PhysReg);
187e8d8bef9SDimitry Andric }
188