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