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
29using namespace llvm;
30
31namespace {
32
33struct 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
50void 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
57void OutgoingArgHandler::assignValueToAddress(Register ValVReg, Register Addr,
58                                              LLT MemTy,
59                                              MachinePointerInfo &MPO,
60                                              CCValAssign &VA) {
61  llvm_unreachable("unimplemented");
62}
63
64Register OutgoingArgHandler::getStackAddress(uint64_t Size, int64_t Offset,
65                                             MachinePointerInfo &MPO,
66                                             ISD::ArgFlagsTy Flags) {
67  llvm_unreachable("unimplemented");
68}
69
70PPCCallLowering::PPCCallLowering(const PPCTargetLowering &TLI)
71    : CallLowering(&TLI) {}
72
73bool 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
108bool PPCCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
109                                CallLoweringInfo &Info) const {
110  return false;
111}
112
113bool 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
144void PPCIncomingValueHandler::assignValueToReg(Register ValVReg,
145                                               Register PhysReg,
146                                               CCValAssign VA) {
147  markPhysRegUsed(PhysReg);
148  IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
149}
150
151void 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
167Register 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
183void FormalArgHandler::markPhysRegUsed(unsigned PhysReg) {
184  MIRBuilder.getMRI()->addLiveIn(PhysReg);
185  MIRBuilder.getMBB().addLiveIn(PhysReg);
186}
187