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