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 "PPCISelLowering.h"
17 #include "PPCSubtarget.h"
18 #include "PPCTargetMachine.h"
19 #include "llvm/CodeGen/CallingConvLower.h"
20 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
21 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
22 #include "llvm/CodeGen/MachineFrameInfo.h"
23 #include "llvm/CodeGen/TargetCallingConv.h"
24 #include "llvm/Support/Debug.h"
25 
26 #define DEBUG_TYPE "ppc-call-lowering"
27 
28 using namespace llvm;
29 
30 PPCCallLowering::PPCCallLowering(const PPCTargetLowering &TLI)
31     : CallLowering(&TLI) {}
32 
33 bool PPCCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
34                                   const Value *Val, ArrayRef<Register> VRegs,
35                                   FunctionLoweringInfo &FLI,
36                                   Register SwiftErrorVReg) const {
37   assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
38          "Return value without a vreg");
39   if (VRegs.size() > 0)
40     return false;
41 
42   MIRBuilder.buildInstr(PPC::BLR8);
43   return true;
44 }
45 
46 bool PPCCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
47                                 CallLoweringInfo &Info) const {
48   return false;
49 }
50 
51 bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
52                                            const Function &F,
53                                            ArrayRef<ArrayRef<Register>> VRegs,
54                                            FunctionLoweringInfo &FLI) const {
55   MachineFunction &MF = MIRBuilder.getMF();
56   MachineRegisterInfo &MRI = MF.getRegInfo();
57   const auto &DL = F.getParent()->getDataLayout();
58   auto &TLI = *getTLI<PPCTargetLowering>();
59 
60   // Loop over each arg, set flags and split to single value types
61   SmallVector<ArgInfo, 8> SplitArgs;
62   unsigned I = 0;
63   for (const auto &Arg : F.args()) {
64     if (DL.getTypeStoreSize(Arg.getType()).isZero())
65       continue;
66 
67     ArgInfo OrigArg{VRegs[I], Arg, I};
68     setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F);
69     splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
70     ++I;
71   }
72 
73   CCAssignFn *AssignFn =
74       TLI.ccAssignFnForCall(F.getCallingConv(), false, F.isVarArg());
75   IncomingValueAssigner ArgAssigner(AssignFn);
76   FormalArgHandler ArgHandler(MIRBuilder, MRI);
77   return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
78                                        MIRBuilder, F.getCallingConv(),
79                                        F.isVarArg());
80 }
81 
82 void PPCIncomingValueHandler::assignValueToReg(Register ValVReg,
83                                                Register PhysReg,
84                                                CCValAssign VA) {
85   markPhysRegUsed(PhysReg);
86   IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
87 }
88 
89 void PPCIncomingValueHandler::assignValueToAddress(Register ValVReg,
90                                                    Register Addr, LLT MemTy,
91                                                    MachinePointerInfo &MPO,
92                                                    CCValAssign &VA) {
93   // define a lambda expression to load value
94   auto BuildLoad = [](MachineIRBuilder &MIRBuilder, MachinePointerInfo &MPO,
95                       LLT MemTy, const DstOp &Res, Register Addr) {
96     MachineFunction &MF = MIRBuilder.getMF();
97     auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
98                                         inferAlignFromPtrInfo(MF, MPO));
99     return MIRBuilder.buildLoad(Res, Addr, *MMO);
100   };
101 
102   BuildLoad(MIRBuilder, MPO, MemTy, ValVReg, Addr);
103 }
104 
105 Register PPCIncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset,
106                                                   MachinePointerInfo &MPO,
107                                                   ISD::ArgFlagsTy Flags) {
108   auto &MFI = MIRBuilder.getMF().getFrameInfo();
109   const bool IsImmutable = !Flags.isByVal();
110   int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable);
111   MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
112 
113   // Build Frame Index based on whether the machine is 32-bit or 64-bit
114   llvm::LLT FramePtr = LLT::pointer(
115       0, MIRBuilder.getMF().getDataLayout().getPointerSizeInBits());
116   MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(FramePtr, FI);
117   StackUsed = std::max(StackUsed, Size + Offset);
118   return AddrReg.getReg(0);
119 }
120 
121 void FormalArgHandler::markPhysRegUsed(unsigned PhysReg) {
122   MIRBuilder.getMRI()->addLiveIn(PhysReg);
123   MIRBuilder.getMBB().addLiveIn(PhysReg);
124 }
125