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