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