xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp (revision 2f9966ff63d65bd474478888c9088eeae3f9c669)
1 //===-- M68kCallLowering.cpp - Call lowering --------------------*- 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 "M68kCallLowering.h"
16 #include "M68kISelLowering.h"
17 #include "M68kInstrInfo.h"
18 #include "M68kSubtarget.h"
19 #include "M68kTargetMachine.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 
26 using namespace llvm;
27 
28 namespace {
29 
30 struct M68kFormalArgHandler : public M68kIncomingValueHandler {
31   M68kFormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
32       : M68kIncomingValueHandler(MIRBuilder, MRI) {}
33 };
34 
35 struct CallReturnHandler : public M68kIncomingValueHandler {
36   CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
37                     MachineInstrBuilder &MIB)
38       : M68kIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
39 
40 private:
41   void assignValueToReg(Register ValVReg, Register PhysReg,
42                         const CCValAssign &VA) override;
43 
44   MachineInstrBuilder &MIB;
45 };
46 
47 } // end anonymous namespace
48 
49 M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI)
50     : CallLowering(&TLI) {}
51 
52 struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler {
53   M68kOutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
54                          MachineInstrBuilder MIB)
55       : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB),
56         DL(MIRBuilder.getMF().getDataLayout()),
57         STI(MIRBuilder.getMF().getSubtarget<M68kSubtarget>()) {}
58 
59   void assignValueToReg(Register ValVReg, Register PhysReg,
60                         const CCValAssign &VA) override {
61     MIB.addUse(PhysReg, RegState::Implicit);
62     Register ExtReg = extendRegister(ValVReg, VA);
63     MIRBuilder.buildCopy(PhysReg, ExtReg);
64   }
65 
66   void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
67                             const MachinePointerInfo &MPO,
68                             const CCValAssign &VA) override {
69     MachineFunction &MF = MIRBuilder.getMF();
70     Register ExtReg = extendRegister(ValVReg, VA);
71 
72     auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy,
73                                         inferAlignFromPtrInfo(MF, MPO));
74     MIRBuilder.buildStore(ExtReg, Addr, *MMO);
75   }
76 
77   Register getStackAddress(uint64_t Size, int64_t Offset,
78                            MachinePointerInfo &MPO,
79                            ISD::ArgFlagsTy Flags) override {
80     LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0));
81     LLT SType = LLT::scalar(DL.getPointerSizeInBits(0));
82     Register StackReg = STI.getRegisterInfo()->getStackRegister();
83     auto SPReg = MIRBuilder.buildCopy(p0, StackReg).getReg(0);
84     auto OffsetReg = MIRBuilder.buildConstant(SType, Offset);
85     auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
86     MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
87     return AddrReg.getReg(0);
88   }
89   MachineInstrBuilder MIB;
90   const DataLayout &DL;
91   const M68kSubtarget &STI;
92 };
93 bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
94                                    const Value *Val, ArrayRef<Register> VRegs,
95                                    FunctionLoweringInfo &FLI,
96                                    Register SwiftErrorVReg) const {
97 
98   auto MIB = MIRBuilder.buildInstrNoInsert(M68k::RTS);
99   bool Success = true;
100   MachineFunction &MF = MIRBuilder.getMF();
101   const Function &F = MF.getFunction();
102   MachineRegisterInfo &MRI = MF.getRegInfo();
103   const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>();
104   CCAssignFn *AssignFn =
105       TLI.getCCAssignFn(F.getCallingConv(), true, F.isVarArg());
106   auto &DL = F.getParent()->getDataLayout();
107   if (!VRegs.empty()) {
108     SmallVector<ArgInfo, 8> SplitArgs;
109     ArgInfo OrigArg{VRegs, Val->getType(), 0};
110     setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F);
111     splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
112     OutgoingValueAssigner ArgAssigner(AssignFn);
113     M68kOutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB);
114     Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
115                                             MIRBuilder, F.getCallingConv(),
116                                             F.isVarArg());
117   }
118   MIRBuilder.insertInstr(MIB);
119   return Success;
120 }
121 
122 bool M68kCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
123                                             const Function &F,
124                                             ArrayRef<ArrayRef<Register>> VRegs,
125                                             FunctionLoweringInfo &FLI) const {
126   MachineFunction &MF = MIRBuilder.getMF();
127   MachineRegisterInfo &MRI = MF.getRegInfo();
128   const auto &DL = F.getParent()->getDataLayout();
129   auto &TLI = *getTLI<M68kTargetLowering>();
130 
131   SmallVector<ArgInfo, 8> SplitArgs;
132   unsigned I = 0;
133   for (const auto &Arg : F.args()) {
134     ArgInfo OrigArg{VRegs[I], Arg.getType(), I};
135     setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F);
136     splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
137     ++I;
138   }
139 
140   CCAssignFn *AssignFn =
141       TLI.getCCAssignFn(F.getCallingConv(), false, F.isVarArg());
142   IncomingValueAssigner ArgAssigner(AssignFn);
143   M68kFormalArgHandler ArgHandler(MIRBuilder, MRI);
144   return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
145                                        MIRBuilder, F.getCallingConv(),
146                                        F.isVarArg());
147 }
148 
149 void M68kIncomingValueHandler::assignValueToReg(Register ValVReg,
150                                                 Register PhysReg,
151                                                 const CCValAssign &VA) {
152   MIRBuilder.getMRI()->addLiveIn(PhysReg);
153   MIRBuilder.getMBB().addLiveIn(PhysReg);
154   IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
155 }
156 
157 void M68kIncomingValueHandler::assignValueToAddress(
158     Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,
159     const CCValAssign &VA) {
160   MachineFunction &MF = MIRBuilder.getMF();
161   auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
162                                       inferAlignFromPtrInfo(MF, MPO));
163   MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
164 }
165 
166 Register M68kIncomingValueHandler::getStackAddress(uint64_t Size,
167                                                    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
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 CallReturnHandler::assignValueToReg(Register ValVReg, Register PhysReg,
184                                          const CCValAssign &VA) {
185   MIB.addDef(PhysReg, RegState::Implicit);
186   MIRBuilder.buildCopy(ValVReg, PhysReg);
187 }
188 
189 bool M68kCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
190                                  CallLoweringInfo &Info) const {
191   MachineFunction &MF = MIRBuilder.getMF();
192   Function &F = MF.getFunction();
193   MachineRegisterInfo &MRI = MF.getRegInfo();
194   auto &DL = F.getParent()->getDataLayout();
195   const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>();
196   const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
197   const TargetInstrInfo &TII = *STI.getInstrInfo();
198   const M68kRegisterInfo *TRI = STI.getRegisterInfo();
199 
200   SmallVector<ArgInfo, 8> OutArgs;
201   for (auto &OrigArg : Info.OrigArgs)
202     splitToValueTypes(OrigArg, OutArgs, DL, Info.CallConv);
203 
204   SmallVector<ArgInfo, 8> InArgs;
205   if (!Info.OrigRet.Ty->isVoidTy())
206     splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv);
207 
208   unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
209   auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown);
210 
211   unsigned Opc = TLI.getTargetMachine().isPositionIndependent() ? M68k::CALLq
212                  : Info.Callee.isReg()                          ? M68k::CALLj
213                                                                 : M68k::CALLb;
214 
215   auto MIB = MIRBuilder.buildInstrNoInsert(Opc)
216                  .add(Info.Callee)
217                  .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
218 
219   CCAssignFn *AssignFn = TLI.getCCAssignFn(Info.CallConv, false, Info.IsVarArg);
220   OutgoingValueAssigner Assigner(AssignFn);
221   M68kOutgoingArgHandler Handler(MIRBuilder, MRI, MIB);
222   if (!determineAndHandleAssignments(Handler, Assigner, OutArgs, MIRBuilder,
223                                      Info.CallConv, Info.IsVarArg))
224     return false;
225 
226   if (Info.Callee.isReg())
227     constrainOperandRegClass(MF, *TRI, MRI, *STI.getInstrInfo(),
228                              *STI.getRegBankInfo(), *MIB, MIB->getDesc(),
229                              Info.Callee, 0);
230 
231   MIRBuilder.insertInstr(MIB);
232 
233   if (!Info.OrigRet.Ty->isVoidTy()) {
234     CCAssignFn *RetAssignFn =
235         TLI.getCCAssignFn(Info.CallConv, true, Info.IsVarArg);
236 
237     OutgoingValueAssigner Assigner(RetAssignFn, RetAssignFn);
238     CallReturnHandler Handler(MIRBuilder, MRI, MIB);
239     if (!determineAndHandleAssignments(Handler, Assigner, InArgs, MIRBuilder,
240                                        Info.CallConv, Info.IsVarArg))
241       return false;
242   }
243 
244   CallSeqStart.addImm(Assigner.StackSize).addImm(0);
245 
246   unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
247   MIRBuilder.buildInstr(AdjStackUp).addImm(Assigner.StackSize).addImm(0);
248 
249   return true;
250 }
251 
252 bool M68kCallLowering::enableBigEndian() const { return true; }
253