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