xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
104eeddc0SDimitry Andric //===-- M68kCallLowering.cpp - Call lowering --------------------*- C++ -*-===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric //
9349cc55cSDimitry Andric /// \file
10349cc55cSDimitry Andric /// This file implements the lowering of LLVM calls to machine code calls for
11349cc55cSDimitry Andric /// GlobalISel.
12349cc55cSDimitry Andric //
13349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
14349cc55cSDimitry Andric 
15349cc55cSDimitry Andric #include "M68kCallLowering.h"
16349cc55cSDimitry Andric #include "M68kISelLowering.h"
17349cc55cSDimitry Andric #include "M68kInstrInfo.h"
18349cc55cSDimitry Andric #include "M68kSubtarget.h"
19349cc55cSDimitry Andric #include "M68kTargetMachine.h"
20349cc55cSDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
21349cc55cSDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h"
22349cc55cSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
23*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
24349cc55cSDimitry Andric #include "llvm/CodeGen/TargetCallingConv.h"
25349cc55cSDimitry Andric 
26349cc55cSDimitry Andric using namespace llvm;
27349cc55cSDimitry Andric 
28349cc55cSDimitry Andric M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI)
29349cc55cSDimitry Andric     : CallLowering(&TLI) {}
30349cc55cSDimitry Andric 
31*81ad6265SDimitry Andric struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler {
32*81ad6265SDimitry Andric   M68kOutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
33349cc55cSDimitry Andric                          MachineInstrBuilder MIB)
34*81ad6265SDimitry Andric       : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB),
35*81ad6265SDimitry Andric         DL(MIRBuilder.getMF().getDataLayout()),
36*81ad6265SDimitry Andric         STI(MIRBuilder.getMF().getSubtarget<M68kSubtarget>()) {}
37349cc55cSDimitry Andric 
38349cc55cSDimitry Andric   void assignValueToReg(Register ValVReg, Register PhysReg,
39349cc55cSDimitry Andric                         CCValAssign VA) override {
40349cc55cSDimitry Andric     MIB.addUse(PhysReg, RegState::Implicit);
41349cc55cSDimitry Andric     Register ExtReg = extendRegister(ValVReg, VA);
42349cc55cSDimitry Andric     MIRBuilder.buildCopy(PhysReg, ExtReg);
43349cc55cSDimitry Andric   }
44349cc55cSDimitry Andric 
45349cc55cSDimitry Andric   void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
46349cc55cSDimitry Andric                             MachinePointerInfo &MPO, CCValAssign &VA) override {
47*81ad6265SDimitry Andric     MachineFunction &MF = MIRBuilder.getMF();
48*81ad6265SDimitry Andric     Register ExtReg = extendRegister(ValVReg, VA);
49*81ad6265SDimitry Andric 
50*81ad6265SDimitry Andric     auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy,
51*81ad6265SDimitry Andric                                         inferAlignFromPtrInfo(MF, MPO));
52*81ad6265SDimitry Andric     MIRBuilder.buildStore(ExtReg, Addr, *MMO);
53349cc55cSDimitry Andric   }
54349cc55cSDimitry Andric 
55349cc55cSDimitry Andric   Register getStackAddress(uint64_t Size, int64_t Offset,
56349cc55cSDimitry Andric                            MachinePointerInfo &MPO,
57349cc55cSDimitry Andric                            ISD::ArgFlagsTy Flags) override {
58*81ad6265SDimitry Andric     LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0));
59*81ad6265SDimitry Andric     LLT SType = LLT::scalar(DL.getPointerSizeInBits(0));
60*81ad6265SDimitry Andric     Register StackReg = STI.getRegisterInfo()->getStackRegister();
61*81ad6265SDimitry Andric     auto SPReg = MIRBuilder.buildCopy(p0, StackReg).getReg(0);
62*81ad6265SDimitry Andric     auto OffsetReg = MIRBuilder.buildConstant(SType, Offset);
63*81ad6265SDimitry Andric     auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
64*81ad6265SDimitry Andric     MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
65*81ad6265SDimitry Andric     return AddrReg.getReg(0);
66349cc55cSDimitry Andric   }
67349cc55cSDimitry Andric   MachineInstrBuilder MIB;
68*81ad6265SDimitry Andric   const DataLayout &DL;
69*81ad6265SDimitry Andric   const M68kSubtarget &STI;
70349cc55cSDimitry Andric };
71349cc55cSDimitry Andric bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
72349cc55cSDimitry Andric                                    const Value *Val, ArrayRef<Register> VRegs,
73349cc55cSDimitry Andric                                    FunctionLoweringInfo &FLI,
74349cc55cSDimitry Andric                                    Register SwiftErrorVReg) const {
75349cc55cSDimitry Andric 
76349cc55cSDimitry Andric   auto MIB = MIRBuilder.buildInstrNoInsert(M68k::RTS);
77349cc55cSDimitry Andric   bool Success = true;
78349cc55cSDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
79349cc55cSDimitry Andric   const Function &F = MF.getFunction();
80349cc55cSDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
81349cc55cSDimitry Andric   const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>();
82349cc55cSDimitry Andric   CCAssignFn *AssignFn =
83349cc55cSDimitry Andric       TLI.getCCAssignFn(F.getCallingConv(), true, F.isVarArg());
84349cc55cSDimitry Andric   auto &DL = F.getParent()->getDataLayout();
85349cc55cSDimitry Andric   if (!VRegs.empty()) {
86349cc55cSDimitry Andric     SmallVector<ArgInfo, 8> SplitArgs;
87349cc55cSDimitry Andric     ArgInfo OrigArg{VRegs, Val->getType(), 0};
88349cc55cSDimitry Andric     setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F);
89349cc55cSDimitry Andric     splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
90349cc55cSDimitry Andric     OutgoingValueAssigner ArgAssigner(AssignFn);
91*81ad6265SDimitry Andric     M68kOutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB);
92349cc55cSDimitry Andric     Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
93349cc55cSDimitry Andric                                             MIRBuilder, F.getCallingConv(),
94349cc55cSDimitry Andric                                             F.isVarArg());
95349cc55cSDimitry Andric   }
96349cc55cSDimitry Andric   MIRBuilder.insertInstr(MIB);
97349cc55cSDimitry Andric   return Success;
98349cc55cSDimitry Andric }
99349cc55cSDimitry Andric 
100349cc55cSDimitry Andric bool M68kCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
101349cc55cSDimitry Andric                                             const Function &F,
102349cc55cSDimitry Andric                                             ArrayRef<ArrayRef<Register>> VRegs,
103349cc55cSDimitry Andric                                             FunctionLoweringInfo &FLI) const {
104349cc55cSDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
105349cc55cSDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
106349cc55cSDimitry Andric   const auto &DL = F.getParent()->getDataLayout();
107349cc55cSDimitry Andric   auto &TLI = *getTLI<M68kTargetLowering>();
108349cc55cSDimitry Andric 
109349cc55cSDimitry Andric   SmallVector<ArgInfo, 8> SplitArgs;
110349cc55cSDimitry Andric   unsigned I = 0;
111349cc55cSDimitry Andric   for (const auto &Arg : F.args()) {
112349cc55cSDimitry Andric     ArgInfo OrigArg{VRegs[I], Arg.getType(), I};
113349cc55cSDimitry Andric     setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F);
114349cc55cSDimitry Andric     splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
115349cc55cSDimitry Andric     ++I;
116349cc55cSDimitry Andric   }
117349cc55cSDimitry Andric 
118349cc55cSDimitry Andric   CCAssignFn *AssignFn =
119349cc55cSDimitry Andric       TLI.getCCAssignFn(F.getCallingConv(), false, F.isVarArg());
120349cc55cSDimitry Andric   IncomingValueAssigner ArgAssigner(AssignFn);
121349cc55cSDimitry Andric   FormalArgHandler ArgHandler(MIRBuilder, MRI);
122349cc55cSDimitry Andric   return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
123349cc55cSDimitry Andric                                        MIRBuilder, F.getCallingConv(),
124349cc55cSDimitry Andric                                        F.isVarArg());
125349cc55cSDimitry Andric }
126349cc55cSDimitry Andric 
127349cc55cSDimitry Andric void M68kIncomingValueHandler::assignValueToReg(Register ValVReg,
128349cc55cSDimitry Andric                                                 Register PhysReg,
129349cc55cSDimitry Andric                                                 CCValAssign VA) {
130349cc55cSDimitry Andric   MIRBuilder.getMRI()->addLiveIn(PhysReg);
131349cc55cSDimitry Andric   MIRBuilder.getMBB().addLiveIn(PhysReg);
132349cc55cSDimitry Andric   IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
133349cc55cSDimitry Andric }
134349cc55cSDimitry Andric 
135349cc55cSDimitry Andric void M68kIncomingValueHandler::assignValueToAddress(Register ValVReg,
136349cc55cSDimitry Andric                                                     Register Addr,
137349cc55cSDimitry Andric                                                     LLT MemTy,
138349cc55cSDimitry Andric                                                     MachinePointerInfo &MPO,
139349cc55cSDimitry Andric                                                     CCValAssign &VA) {
140349cc55cSDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
141349cc55cSDimitry Andric   auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
142349cc55cSDimitry Andric                                       inferAlignFromPtrInfo(MF, MPO));
143349cc55cSDimitry Andric   MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
144349cc55cSDimitry Andric }
145349cc55cSDimitry Andric 
146349cc55cSDimitry Andric Register M68kIncomingValueHandler::getStackAddress(uint64_t Size,
147349cc55cSDimitry Andric                                                    int64_t Offset,
148349cc55cSDimitry Andric                                                    MachinePointerInfo &MPO,
149349cc55cSDimitry Andric                                                    ISD::ArgFlagsTy Flags) {
150349cc55cSDimitry Andric   auto &MFI = MIRBuilder.getMF().getFrameInfo();
151349cc55cSDimitry Andric   const bool IsImmutable = !Flags.isByVal();
152349cc55cSDimitry Andric   int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable);
153349cc55cSDimitry Andric   MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
154349cc55cSDimitry Andric 
155349cc55cSDimitry Andric   // Build Frame Index
156349cc55cSDimitry Andric   llvm::LLT FramePtr = LLT::pointer(
157349cc55cSDimitry Andric       0, MIRBuilder.getMF().getDataLayout().getPointerSizeInBits());
158349cc55cSDimitry Andric   MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(FramePtr, FI);
159349cc55cSDimitry Andric   StackUsed = std::max(StackUsed, Size + Offset);
160349cc55cSDimitry Andric   return AddrReg.getReg(0);
161349cc55cSDimitry Andric }
162349cc55cSDimitry Andric 
163*81ad6265SDimitry Andric void CallReturnHandler::assignValueToReg(Register ValVReg, Register PhysReg,
164*81ad6265SDimitry Andric                                          CCValAssign VA) {
165*81ad6265SDimitry Andric   MIB.addDef(PhysReg, RegState::Implicit);
166*81ad6265SDimitry Andric   MIRBuilder.buildCopy(ValVReg, PhysReg);
167*81ad6265SDimitry Andric }
168*81ad6265SDimitry Andric 
169349cc55cSDimitry Andric bool M68kCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
170349cc55cSDimitry Andric                                  CallLoweringInfo &Info) const {
171*81ad6265SDimitry Andric   MachineFunction &MF = MIRBuilder.getMF();
172*81ad6265SDimitry Andric   Function &F = MF.getFunction();
173*81ad6265SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
174*81ad6265SDimitry Andric   auto &DL = F.getParent()->getDataLayout();
175*81ad6265SDimitry Andric   const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>();
176*81ad6265SDimitry Andric   const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
177*81ad6265SDimitry Andric   const TargetInstrInfo &TII = *STI.getInstrInfo();
178*81ad6265SDimitry Andric   const M68kRegisterInfo *TRI = STI.getRegisterInfo();
179*81ad6265SDimitry Andric 
180*81ad6265SDimitry Andric   SmallVector<ArgInfo, 8> OutArgs;
181*81ad6265SDimitry Andric   for (auto &OrigArg : Info.OrigArgs)
182*81ad6265SDimitry Andric     splitToValueTypes(OrigArg, OutArgs, DL, Info.CallConv);
183*81ad6265SDimitry Andric 
184*81ad6265SDimitry Andric   SmallVector<ArgInfo, 8> InArgs;
185*81ad6265SDimitry Andric   if (!Info.OrigRet.Ty->isVoidTy())
186*81ad6265SDimitry Andric     splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv);
187*81ad6265SDimitry Andric 
188*81ad6265SDimitry Andric   unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
189*81ad6265SDimitry Andric   auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown);
190*81ad6265SDimitry Andric 
191*81ad6265SDimitry Andric   unsigned Opc = TLI.getTargetMachine().isPositionIndependent() ? M68k::CALLq
192*81ad6265SDimitry Andric                  : Info.Callee.isReg()                          ? M68k::CALLj
193*81ad6265SDimitry Andric                                                                 : M68k::CALLb;
194*81ad6265SDimitry Andric 
195*81ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstrNoInsert(Opc)
196*81ad6265SDimitry Andric                  .add(Info.Callee)
197*81ad6265SDimitry Andric                  .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
198*81ad6265SDimitry Andric 
199*81ad6265SDimitry Andric   CCAssignFn *AssignFn = TLI.getCCAssignFn(Info.CallConv, false, Info.IsVarArg);
200*81ad6265SDimitry Andric   OutgoingValueAssigner Assigner(AssignFn);
201*81ad6265SDimitry Andric   M68kOutgoingArgHandler Handler(MIRBuilder, MRI, MIB);
202*81ad6265SDimitry Andric   if (!determineAndHandleAssignments(Handler, Assigner, OutArgs, MIRBuilder,
203*81ad6265SDimitry Andric                                      Info.CallConv, Info.IsVarArg))
204349cc55cSDimitry Andric     return false;
205*81ad6265SDimitry Andric 
206*81ad6265SDimitry Andric   if (Info.Callee.isReg())
207*81ad6265SDimitry Andric     constrainOperandRegClass(MF, *TRI, MRI, *STI.getInstrInfo(),
208*81ad6265SDimitry Andric                              *STI.getRegBankInfo(), *MIB, MIB->getDesc(),
209*81ad6265SDimitry Andric                              Info.Callee, 0);
210*81ad6265SDimitry Andric 
211*81ad6265SDimitry Andric   MIRBuilder.insertInstr(MIB);
212*81ad6265SDimitry Andric 
213*81ad6265SDimitry Andric   if (!Info.OrigRet.Ty->isVoidTy()) {
214*81ad6265SDimitry Andric     CCAssignFn *RetAssignFn =
215*81ad6265SDimitry Andric         TLI.getCCAssignFn(Info.CallConv, true, Info.IsVarArg);
216*81ad6265SDimitry Andric 
217*81ad6265SDimitry Andric     OutgoingValueAssigner Assigner(RetAssignFn, RetAssignFn);
218*81ad6265SDimitry Andric     CallReturnHandler Handler(MIRBuilder, MRI, MIB);
219*81ad6265SDimitry Andric     if (!determineAndHandleAssignments(Handler, Assigner, InArgs, MIRBuilder,
220*81ad6265SDimitry Andric                                        Info.CallConv, Info.IsVarArg))
221*81ad6265SDimitry Andric       return false;
222*81ad6265SDimitry Andric   }
223*81ad6265SDimitry Andric 
224*81ad6265SDimitry Andric   CallSeqStart.addImm(Assigner.StackOffset).addImm(0);
225*81ad6265SDimitry Andric 
226*81ad6265SDimitry Andric   unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
227*81ad6265SDimitry Andric   MIRBuilder.buildInstr(AdjStackUp).addImm(Assigner.StackOffset).addImm(0);
228*81ad6265SDimitry Andric 
229*81ad6265SDimitry Andric   return true;
230349cc55cSDimitry Andric }
231349cc55cSDimitry Andric 
232349cc55cSDimitry Andric bool M68kCallLowering::enableBigEndian() const { return true; }
233