blob: a705ebb6b193bc9e6d27fd4a2b87fb2c6b62fd2c [file] [log] [blame]
Petar Jovanovicfac93e22018-02-23 11:06:40 +00001//===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10/// \file
11/// This file implements the lowering of LLVM calls to machine code calls for
12/// GlobalISel.
13//
14//===----------------------------------------------------------------------===//
15
16#include "MipsCallLowering.h"
Petar Jovanovic366857a2018-04-11 15:12:32 +000017#include "MipsCCState.h"
Petar Jovanovic326ec322018-06-06 07:24:52 +000018#include "MipsTargetMachine.h"
Petar Jovanovicfac93e22018-02-23 11:06:40 +000019#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
20
21using namespace llvm;
22
23MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
24 : CallLowering(&TLI) {}
25
Petar Jovanovic366857a2018-04-11 15:12:32 +000026bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA,
27 unsigned vreg) {
28 if (VA.isRegLoc()) {
29 assignValueToReg(vreg, VA.getLocReg());
Petar Jovanovic226e6112018-07-03 09:31:48 +000030 } else if (VA.isMemLoc()) {
31 unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8;
32 unsigned Offset = VA.getLocMemOffset();
33 MachinePointerInfo MPO;
34 unsigned StackAddr = getStackAddress(Size, Offset, MPO);
35 assignValueToAddress(vreg, StackAddr, Size, MPO);
Petar Jovanovic366857a2018-04-11 15:12:32 +000036 } else {
37 return false;
38 }
39 return true;
40}
41
42namespace {
43class IncomingValueHandler : public MipsCallLowering::MipsHandler {
44public:
45 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
46 : MipsHandler(MIRBuilder, MRI) {}
47
48 bool handle(ArrayRef<CCValAssign> ArgLocs,
49 ArrayRef<CallLowering::ArgInfo> Args);
50
51private:
Petar Jovanovic226e6112018-07-03 09:31:48 +000052 void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override;
53
54 unsigned getStackAddress(uint64_t Size, int64_t Offset,
55 MachinePointerInfo &MPO) override;
56
57 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
58 MachinePointerInfo &MPO) override;
Petar Jovanovic366857a2018-04-11 15:12:32 +000059
Petar Jovanovic326ec322018-06-06 07:24:52 +000060 virtual void markPhysRegUsed(unsigned PhysReg) {
Petar Jovanovic366857a2018-04-11 15:12:32 +000061 MIRBuilder.getMBB().addLiveIn(PhysReg);
62 }
Petar Jovanovic226e6112018-07-03 09:31:48 +000063
64 void buildLoad(unsigned Val, unsigned Addr, uint64_t Size, unsigned Alignment,
65 MachinePointerInfo &MPO) {
66 MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand(
67 MPO, MachineMemOperand::MOLoad, Size, Alignment);
68 MIRBuilder.buildLoad(Val, Addr, *MMO);
69 }
Petar Jovanovic366857a2018-04-11 15:12:32 +000070};
Petar Jovanovic326ec322018-06-06 07:24:52 +000071
72class CallReturnHandler : public IncomingValueHandler {
73public:
74 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
75 MachineInstrBuilder &MIB)
76 : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
77
78private:
Petar Jovanovic226e6112018-07-03 09:31:48 +000079 void markPhysRegUsed(unsigned PhysReg) override {
Petar Jovanovic326ec322018-06-06 07:24:52 +000080 MIB.addDef(PhysReg, RegState::Implicit);
81 }
82
83 MachineInstrBuilder &MIB;
84};
85
Petar Jovanovic366857a2018-04-11 15:12:32 +000086} // end anonymous namespace
87
88void IncomingValueHandler::assignValueToReg(unsigned ValVReg,
89 unsigned PhysReg) {
90 MIRBuilder.buildCopy(ValVReg, PhysReg);
91 markPhysRegUsed(PhysReg);
92}
93
Petar Jovanovic226e6112018-07-03 09:31:48 +000094unsigned IncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset,
95 MachinePointerInfo &MPO) {
96 MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo();
97
98 int FI = MFI.CreateFixedObject(Size, Offset, true);
99 MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
100
101 unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32));
102 MIRBuilder.buildFrameIndex(AddrReg, FI);
103
104 return AddrReg;
105}
106
107void IncomingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr,
108 uint64_t Size,
109 MachinePointerInfo &MPO) {
110 // If the value is not extended, a simple load will suffice.
111 buildLoad(ValVReg, Addr, Size, /* Alignment */ 0, MPO);
112}
113
Petar Jovanovic366857a2018-04-11 15:12:32 +0000114bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
115 ArrayRef<CallLowering::ArgInfo> Args) {
116 for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) {
117 if (!assign(ArgLocs[i], Args[i].Reg))
118 return false;
119 }
120 return true;
121}
122
123namespace {
124class OutgoingValueHandler : public MipsCallLowering::MipsHandler {
125public:
126 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
127 MachineInstrBuilder &MIB)
128 : MipsHandler(MIRBuilder, MRI), MIB(MIB) {}
129
130 bool handle(ArrayRef<CCValAssign> ArgLocs,
131 ArrayRef<CallLowering::ArgInfo> Args);
132
133private:
Petar Jovanovic226e6112018-07-03 09:31:48 +0000134 void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override;
135
136 unsigned getStackAddress(uint64_t Size, int64_t Offset,
137 MachinePointerInfo &MPO) override;
138
139 void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
140 MachinePointerInfo &MPO) override;
Petar Jovanovic366857a2018-04-11 15:12:32 +0000141
142 MachineInstrBuilder &MIB;
143};
144} // end anonymous namespace
145
146void OutgoingValueHandler::assignValueToReg(unsigned ValVReg,
147 unsigned PhysReg) {
148 MIRBuilder.buildCopy(PhysReg, ValVReg);
149 MIB.addUse(PhysReg, RegState::Implicit);
150}
151
Petar Jovanovic226e6112018-07-03 09:31:48 +0000152unsigned OutgoingValueHandler::getStackAddress(uint64_t Size, int64_t Offset,
153 MachinePointerInfo &MPO) {
154 LLT p0 = LLT::pointer(0, 32);
155 LLT s32 = LLT::scalar(32);
156 unsigned SPReg = MRI.createGenericVirtualRegister(p0);
157 MIRBuilder.buildCopy(SPReg, Mips::SP);
158
159 unsigned OffsetReg = MRI.createGenericVirtualRegister(s32);
160 MIRBuilder.buildConstant(OffsetReg, Offset);
161
162 unsigned AddrReg = MRI.createGenericVirtualRegister(p0);
163 MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg);
164
165 MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
166 return AddrReg;
167}
168
169void OutgoingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr,
170 uint64_t Size,
171 MachinePointerInfo &MPO) {
172 MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand(
173 MPO, MachineMemOperand::MOStore, Size, /* Alignment */ 0);
174 MIRBuilder.buildStore(ValVReg, Addr, *MMO);
175}
176
Petar Jovanovic366857a2018-04-11 15:12:32 +0000177bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
178 ArrayRef<CallLowering::ArgInfo> Args) {
179 for (unsigned i = 0; i < Args.size(); ++i) {
180 if (!assign(ArgLocs[i], Args[i].Reg))
181 return false;
182 }
183 return true;
184}
185
186static bool isSupportedType(Type *T) {
187 if (T->isIntegerTy() && T->getScalarSizeInBits() == 32)
188 return true;
Petar Jovanovic58c02102018-07-25 12:35:01 +0000189 if (T->isPointerTy())
190 return true;
Petar Jovanovic366857a2018-04-11 15:12:32 +0000191 return false;
192}
193
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000194bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
195 const Value *Val, unsigned VReg) const {
196
197 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
198
199 if (Val != nullptr) {
Petar Jovanovic366857a2018-04-11 15:12:32 +0000200 if (!isSupportedType(Val->getType()))
201 return false;
202
203 MachineFunction &MF = MIRBuilder.getMF();
204 const Function &F = MF.getFunction();
205 const DataLayout &DL = MF.getDataLayout();
206 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
207
208 SmallVector<ArgInfo, 8> RetInfos;
209 SmallVector<unsigned, 8> OrigArgIndices;
210
211 ArgInfo ArgRetInfo(VReg, Val->getType());
212 setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);
213 splitToValueTypes(ArgRetInfo, 0, RetInfos, OrigArgIndices);
214
215 SmallVector<ISD::OutputArg, 8> Outs;
216 subTargetRegTypeForCallingConv(
217 MIRBuilder, RetInfos, OrigArgIndices,
218 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
219 unsigned origIdx, unsigned partOffs) {
220 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
221 });
222
223 SmallVector<CCValAssign, 16> ArgLocs;
224 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
225 F.getContext());
226 CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn());
227
228 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
229 if (!RetHandler.handle(ArgLocs, RetInfos)) {
230 return false;
231 }
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000232 }
233 MIRBuilder.insertInstr(Ret);
234 return true;
235}
236
237bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
238 const Function &F,
239 ArrayRef<unsigned> VRegs) const {
240
241 // Quick exit if there aren't any args.
242 if (F.arg_empty())
243 return true;
244
Petar Jovanovic366857a2018-04-11 15:12:32 +0000245 if (F.isVarArg()) {
246 return false;
247 }
248
249 for (auto &Arg : F.args()) {
250 if (!isSupportedType(Arg.getType()))
251 return false;
252 }
253
254 MachineFunction &MF = MIRBuilder.getMF();
255 const DataLayout &DL = MF.getDataLayout();
256 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
257
258 SmallVector<ArgInfo, 8> ArgInfos;
259 SmallVector<unsigned, 8> OrigArgIndices;
260 unsigned i = 0;
261 for (auto &Arg : F.args()) {
262 ArgInfo AInfo(VRegs[i], Arg.getType());
263 setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);
264 splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices);
265 ++i;
266 }
267
268 SmallVector<ISD::InputArg, 8> Ins;
269 subTargetRegTypeForCallingConv(
270 MIRBuilder, ArgInfos, OrigArgIndices,
271 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx,
272 unsigned partOffs) {
273 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
274 });
275
276 SmallVector<CCValAssign, 16> ArgLocs;
277 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
278 F.getContext());
279
Petar Jovanovic226e6112018-07-03 09:31:48 +0000280 const MipsTargetMachine &TM =
281 static_cast<const MipsTargetMachine &>(MF.getTarget());
282 const MipsABIInfo &ABI = TM.getABI();
283 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()),
284 1);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000285 CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall());
286
Petar Jovanovic667e2132018-04-12 17:01:46 +0000287 IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
Petar Jovanovic366857a2018-04-11 15:12:32 +0000288 if (!Handler.handle(ArgLocs, ArgInfos))
289 return false;
290
291 return true;
292}
293
Petar Jovanovic326ec322018-06-06 07:24:52 +0000294bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
295 CallingConv::ID CallConv,
296 const MachineOperand &Callee,
297 const ArgInfo &OrigRet,
298 ArrayRef<ArgInfo> OrigArgs) const {
299
300 if (CallConv != CallingConv::C)
301 return false;
302
303 for (auto &Arg : OrigArgs) {
304 if (!isSupportedType(Arg.Ty))
305 return false;
306 if (Arg.Flags.isByVal() || Arg.Flags.isSRet())
307 return false;
308 }
309 if (OrigRet.Reg && !isSupportedType(OrigRet.Ty))
310 return false;
311
312 MachineFunction &MF = MIRBuilder.getMF();
313 const Function &F = MF.getFunction();
314 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
315 const MipsTargetMachine &TM =
316 static_cast<const MipsTargetMachine &>(MF.getTarget());
317 const MipsABIInfo &ABI = TM.getABI();
318
319 MachineInstrBuilder CallSeqStart =
320 MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN);
321
322 // FIXME: Add support for pic calling sequences, long call sequences for O32,
323 // N32 and N64. First handle the case when Callee.isReg().
324 if (Callee.isReg())
325 return false;
326
327 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Mips::JAL);
328 MIB.addDef(Mips::SP, RegState::Implicit);
329 MIB.add(Callee);
330 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
331 MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));
332
333 TargetLowering::ArgListTy FuncOrigArgs;
334 FuncOrigArgs.reserve(OrigArgs.size());
335
336 SmallVector<ArgInfo, 8> ArgInfos;
337 SmallVector<unsigned, 8> OrigArgIndices;
338 unsigned i = 0;
339 for (auto &Arg : OrigArgs) {
340
341 TargetLowering::ArgListEntry Entry;
342 Entry.Ty = Arg.Ty;
343 FuncOrigArgs.push_back(Entry);
344
345 splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices);
346 ++i;
347 }
348
349 SmallVector<ISD::OutputArg, 8> Outs;
350 subTargetRegTypeForCallingConv(
351 MIRBuilder, ArgInfos, OrigArgIndices,
352 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx,
353 unsigned partOffs) {
354 Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
355 });
356
357 SmallVector<CCValAssign, 8> ArgLocs;
358 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
359 F.getContext());
360
Petar Jovanovic226e6112018-07-03 09:31:48 +0000361 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1);
Petar Jovanovic326ec322018-06-06 07:24:52 +0000362 const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr;
363 CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call);
364
365 OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB);
366 if (!RetHandler.handle(ArgLocs, ArgInfos)) {
367 return false;
368 }
369
Petar Jovanovic226e6112018-07-03 09:31:48 +0000370 unsigned NextStackOffset = CCInfo.getNextStackOffset();
371 const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering();
372 unsigned StackAlignment = TFL->getStackAlignment();
373 NextStackOffset = alignTo(NextStackOffset, StackAlignment);
374 CallSeqStart.addImm(NextStackOffset).addImm(0);
375
Petar Jovanovic326ec322018-06-06 07:24:52 +0000376 MIRBuilder.insertInstr(MIB);
377
378 if (OrigRet.Reg) {
379
380 ArgInfos.clear();
381 SmallVector<unsigned, 8> OrigRetIndices;
382
383 splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices);
384
385 SmallVector<ISD::InputArg, 8> Ins;
386 subTargetRegTypeForCallingConv(
387 MIRBuilder, ArgInfos, OrigRetIndices,
388 [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
389 unsigned origIdx, unsigned partOffs) {
390 Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
391 });
392
393 SmallVector<CCValAssign, 8> ArgLocs;
394 MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
395 F.getContext());
396
397 CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call);
398
399 CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB);
400 if (!Handler.handle(ArgLocs, ArgInfos))
401 return false;
402 }
403
Petar Jovanovic226e6112018-07-03 09:31:48 +0000404 MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0);
Petar Jovanovic326ec322018-06-06 07:24:52 +0000405
406 return true;
407}
408
Petar Jovanovic366857a2018-04-11 15:12:32 +0000409void MipsCallLowering::subTargetRegTypeForCallingConv(
410 MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args,
411 ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const {
412 MachineFunction &MF = MIRBuilder.getMF();
413 const Function &F = MF.getFunction();
414 const DataLayout &DL = F.getParent()->getDataLayout();
415 const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
416
417 unsigned ArgNo = 0;
418 for (auto &Arg : Args) {
419
420 EVT VT = TLI.getValueType(DL, Arg.Ty);
Matt Arsenault81920b02018-07-28 13:25:19 +0000421 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(),
422 F.getCallingConv(), VT);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000423
424 ISD::ArgFlagsTy Flags = Arg.Flags;
425 Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL));
426
427 PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0);
428
429 ++ArgNo;
430 }
431}
432
433void MipsCallLowering::splitToValueTypes(
434 const ArgInfo &OrigArg, unsigned OriginalIndex,
435 SmallVectorImpl<ArgInfo> &SplitArgs,
436 SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const {
437
438 // TODO : perform structure and array split. For now we only deal with
439 // types that pass isSupportedType check.
440 SplitArgs.push_back(OrigArg);
441 SplitArgsOrigIndices.push_back(OriginalIndex);
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000442}