1 //===- 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"
17 #include "MipsCCState.h"
18 #include "MipsTargetMachine.h"
19 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
20
21 using namespace llvm;
22
MipsCallLowering(const MipsTargetLowering & TLI)23 MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
24 : CallLowering(&TLI) {}
25
assign(const CCValAssign & VA,unsigned vreg)26 bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA,
27 unsigned vreg) {
28 if (VA.isRegLoc()) {
29 assignValueToReg(vreg, VA.getLocReg());
30 } 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);
36 } else {
37 return false;
38 }
39 return true;
40 }
41
42 namespace {
43 class IncomingValueHandler : public MipsCallLowering::MipsHandler {
44 public:
IncomingValueHandler(MachineIRBuilder & MIRBuilder,MachineRegisterInfo & MRI)45 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
46 : MipsHandler(MIRBuilder, MRI) {}
47
48 bool handle(ArrayRef<CCValAssign> ArgLocs,
49 ArrayRef<CallLowering::ArgInfo> Args);
50
51 private:
52 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;
59
markPhysRegUsed(unsigned PhysReg)60 virtual void markPhysRegUsed(unsigned PhysReg) {
61 MIRBuilder.getMBB().addLiveIn(PhysReg);
62 }
63
buildLoad(unsigned Val,unsigned Addr,uint64_t Size,unsigned Alignment,MachinePointerInfo & MPO)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 }
70 };
71
72 class CallReturnHandler : public IncomingValueHandler {
73 public:
CallReturnHandler(MachineIRBuilder & MIRBuilder,MachineRegisterInfo & MRI,MachineInstrBuilder & MIB)74 CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
75 MachineInstrBuilder &MIB)
76 : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
77
78 private:
markPhysRegUsed(unsigned PhysReg)79 void markPhysRegUsed(unsigned PhysReg) override {
80 MIB.addDef(PhysReg, RegState::Implicit);
81 }
82
83 MachineInstrBuilder &MIB;
84 };
85
86 } // end anonymous namespace
87
assignValueToReg(unsigned ValVReg,unsigned PhysReg)88 void IncomingValueHandler::assignValueToReg(unsigned ValVReg,
89 unsigned PhysReg) {
90 MIRBuilder.buildCopy(ValVReg, PhysReg);
91 markPhysRegUsed(PhysReg);
92 }
93
getStackAddress(uint64_t Size,int64_t Offset,MachinePointerInfo & MPO)94 unsigned 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
assignValueToAddress(unsigned ValVReg,unsigned Addr,uint64_t Size,MachinePointerInfo & MPO)107 void 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
handle(ArrayRef<CCValAssign> ArgLocs,ArrayRef<CallLowering::ArgInfo> Args)114 bool 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
123 namespace {
124 class OutgoingValueHandler : public MipsCallLowering::MipsHandler {
125 public:
OutgoingValueHandler(MachineIRBuilder & MIRBuilder,MachineRegisterInfo & MRI,MachineInstrBuilder & MIB)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
133 private:
134 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;
141
142 MachineInstrBuilder &MIB;
143 };
144 } // end anonymous namespace
145
assignValueToReg(unsigned ValVReg,unsigned PhysReg)146 void OutgoingValueHandler::assignValueToReg(unsigned ValVReg,
147 unsigned PhysReg) {
148 MIRBuilder.buildCopy(PhysReg, ValVReg);
149 MIB.addUse(PhysReg, RegState::Implicit);
150 }
151
getStackAddress(uint64_t Size,int64_t Offset,MachinePointerInfo & MPO)152 unsigned 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
assignValueToAddress(unsigned ValVReg,unsigned Addr,uint64_t Size,MachinePointerInfo & MPO)169 void 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
handle(ArrayRef<CCValAssign> ArgLocs,ArrayRef<CallLowering::ArgInfo> Args)177 bool 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
isSupportedType(Type * T)186 static bool isSupportedType(Type *T) {
187 if (T->isIntegerTy() && T->getScalarSizeInBits() == 32)
188 return true;
189 if (T->isPointerTy())
190 return true;
191 return false;
192 }
193
lowerReturn(MachineIRBuilder & MIRBuilder,const Value * Val,unsigned VReg) const194 bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
195 const Value *Val, unsigned VReg) const {
196
197 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
198
199 if (Val != nullptr) {
200 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 }
232 }
233 MIRBuilder.insertInstr(Ret);
234 return true;
235 }
236
lowerFormalArguments(MachineIRBuilder & MIRBuilder,const Function & F,ArrayRef<unsigned> VRegs) const237 bool 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
245 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
280 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);
285 CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall());
286
287 IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
288 if (!Handler.handle(ArgLocs, ArgInfos))
289 return false;
290
291 return true;
292 }
293
lowerCall(MachineIRBuilder & MIRBuilder,CallingConv::ID CallConv,const MachineOperand & Callee,const ArgInfo & OrigRet,ArrayRef<ArgInfo> OrigArgs) const294 bool 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
361 CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1);
362 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
370 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
376 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
404 MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0);
405
406 return true;
407 }
408
subTargetRegTypeForCallingConv(MachineIRBuilder & MIRBuilder,ArrayRef<ArgInfo> Args,ArrayRef<unsigned> OrigArgIndices,const FunTy & PushBack) const409 void 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);
421 MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(),
422 F.getCallingConv(), VT);
423
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
splitToValueTypes(const ArgInfo & OrigArg,unsigned OriginalIndex,SmallVectorImpl<ArgInfo> & SplitArgs,SmallVectorImpl<unsigned> & SplitArgsOrigIndices) const433 void 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);
442 }
443