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
M68kCallLowering(const M68kTargetLowering & TLI)28 M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI)
29 : CallLowering(&TLI) {}
30
31 struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler {
M68kOutgoingArgHandlerM68kOutgoingArgHandler32 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
assignValueToRegM68kOutgoingArgHandler38 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
assignValueToAddressM68kOutgoingArgHandler45 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
getStackAddressM68kOutgoingArgHandler55 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 };
lowerReturn(MachineIRBuilder & MIRBuilder,const Value * Val,ArrayRef<Register> VRegs,FunctionLoweringInfo & FLI,Register SwiftErrorVReg) const71 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
lowerFormalArguments(MachineIRBuilder & MIRBuilder,const Function & F,ArrayRef<ArrayRef<Register>> VRegs,FunctionLoweringInfo & FLI) const100 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
assignValueToReg(Register ValVReg,Register PhysReg,CCValAssign VA)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
assignValueToAddress(Register ValVReg,Register Addr,LLT MemTy,MachinePointerInfo & MPO,CCValAssign & VA)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
getStackAddress(uint64_t Size,int64_t Offset,MachinePointerInfo & MPO,ISD::ArgFlagsTy Flags)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
assignValueToReg(Register ValVReg,Register PhysReg,CCValAssign VA)163 void CallReturnHandler::assignValueToReg(Register ValVReg, Register PhysReg,
164 CCValAssign VA) {
165 MIB.addDef(PhysReg, RegState::Implicit);
166 MIRBuilder.buildCopy(ValVReg, PhysReg);
167 }
168
lowerCall(MachineIRBuilder & MIRBuilder,CallLoweringInfo & Info) const169 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.StackOffset).addImm(0);
225
226 unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
227 MIRBuilder.buildInstr(AdjStackUp).addImm(Assigner.StackOffset).addImm(0);
228
229 return true;
230 }
231
enableBigEndian() const232 bool M68kCallLowering::enableBigEndian() const { return true; }
233