File: | lib/Target/Mips/MipsCallLowering.cpp |
Warning: | line 415, column 24 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- MipsCallLowering.cpp -------------------------------------*- 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 "MipsCallLowering.h" | |||
16 | #include "MipsCCState.h" | |||
17 | #include "MipsMachineFunction.h" | |||
18 | #include "MipsTargetMachine.h" | |||
19 | #include "llvm/CodeGen/Analysis.h" | |||
20 | #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" | |||
21 | ||||
22 | using namespace llvm; | |||
23 | ||||
24 | MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) | |||
25 | : CallLowering(&TLI) {} | |||
26 | ||||
27 | bool MipsCallLowering::MipsHandler::assign(Register VReg, const CCValAssign &VA, | |||
28 | const EVT &VT) { | |||
29 | if (VA.isRegLoc()) { | |||
30 | assignValueToReg(VReg, VA, VT); | |||
31 | } else if (VA.isMemLoc()) { | |||
32 | assignValueToAddress(VReg, VA); | |||
33 | } else { | |||
34 | return false; | |||
35 | } | |||
36 | return true; | |||
37 | } | |||
38 | ||||
39 | bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef<Register> VRegs, | |||
40 | ArrayRef<CCValAssign> ArgLocs, | |||
41 | unsigned ArgLocsStartIndex, | |||
42 | const EVT &VT) { | |||
43 | for (unsigned i = 0; i < VRegs.size(); ++i) | |||
44 | if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i], VT)) | |||
45 | return false; | |||
46 | return true; | |||
47 | } | |||
48 | ||||
49 | void MipsCallLowering::MipsHandler::setLeastSignificantFirst( | |||
50 | SmallVectorImpl<Register> &VRegs) { | |||
51 | if (!MIRBuilder.getMF().getDataLayout().isLittleEndian()) | |||
52 | std::reverse(VRegs.begin(), VRegs.end()); | |||
53 | } | |||
54 | ||||
55 | bool MipsCallLowering::MipsHandler::handle( | |||
56 | ArrayRef<CCValAssign> ArgLocs, ArrayRef<CallLowering::ArgInfo> Args) { | |||
57 | SmallVector<Register, 4> VRegs; | |||
58 | unsigned SplitLength; | |||
59 | const Function &F = MIRBuilder.getMF().getFunction(); | |||
60 | const DataLayout &DL = F.getParent()->getDataLayout(); | |||
61 | const MipsTargetLowering &TLI = *static_cast<const MipsTargetLowering *>( | |||
62 | MIRBuilder.getMF().getSubtarget().getTargetLowering()); | |||
63 | ||||
64 | for (unsigned ArgsIndex = 0, ArgLocsIndex = 0; ArgsIndex < Args.size(); | |||
65 | ++ArgsIndex, ArgLocsIndex += SplitLength) { | |||
66 | EVT VT = TLI.getValueType(DL, Args[ArgsIndex].Ty); | |||
67 | SplitLength = TLI.getNumRegistersForCallingConv(F.getContext(), | |||
68 | F.getCallingConv(), VT); | |||
69 | assert(Args[ArgsIndex].Regs.size() == 1 && "Can't handle multple regs yet")((Args[ArgsIndex].Regs.size() == 1 && "Can't handle multple regs yet" ) ? static_cast<void> (0) : __assert_fail ("Args[ArgsIndex].Regs.size() == 1 && \"Can't handle multple regs yet\"" , "/build/llvm-toolchain-snapshot-10~svn372774/lib/Target/Mips/MipsCallLowering.cpp" , 69, __PRETTY_FUNCTION__)); | |||
70 | ||||
71 | if (SplitLength > 1) { | |||
72 | VRegs.clear(); | |||
73 | MVT RegisterVT = TLI.getRegisterTypeForCallingConv( | |||
74 | F.getContext(), F.getCallingConv(), VT); | |||
75 | for (unsigned i = 0; i < SplitLength; ++i) | |||
76 | VRegs.push_back(MRI.createGenericVirtualRegister(LLT{RegisterVT})); | |||
77 | ||||
78 | if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Regs[0], | |||
79 | VT)) | |||
80 | return false; | |||
81 | } else { | |||
82 | if (!assign(Args[ArgsIndex].Regs[0], ArgLocs[ArgLocsIndex], VT)) | |||
83 | return false; | |||
84 | } | |||
85 | } | |||
86 | return true; | |||
87 | } | |||
88 | ||||
89 | namespace { | |||
90 | class IncomingValueHandler : public MipsCallLowering::MipsHandler { | |||
91 | public: | |||
92 | IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) | |||
93 | : MipsHandler(MIRBuilder, MRI) {} | |||
94 | ||||
95 | private: | |||
96 | void assignValueToReg(Register ValVReg, const CCValAssign &VA, | |||
97 | const EVT &VT) override; | |||
98 | ||||
99 | Register getStackAddress(const CCValAssign &VA, | |||
100 | MachineMemOperand *&MMO) override; | |||
101 | ||||
102 | void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; | |||
103 | ||||
104 | bool handleSplit(SmallVectorImpl<Register> &VRegs, | |||
105 | ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, | |||
106 | Register ArgsReg, const EVT &VT) override; | |||
107 | ||||
108 | virtual void markPhysRegUsed(unsigned PhysReg) { | |||
109 | MIRBuilder.getMRI()->addLiveIn(PhysReg); | |||
110 | MIRBuilder.getMBB().addLiveIn(PhysReg); | |||
111 | } | |||
112 | ||||
113 | void buildLoad(Register Val, const CCValAssign &VA) { | |||
114 | MachineMemOperand *MMO; | |||
115 | Register Addr = getStackAddress(VA, MMO); | |||
116 | MIRBuilder.buildLoad(Val, Addr, *MMO); | |||
117 | } | |||
118 | }; | |||
119 | ||||
120 | class CallReturnHandler : public IncomingValueHandler { | |||
121 | public: | |||
122 | CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, | |||
123 | MachineInstrBuilder &MIB) | |||
124 | : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} | |||
125 | ||||
126 | private: | |||
127 | void markPhysRegUsed(unsigned PhysReg) override { | |||
128 | MIB.addDef(PhysReg, RegState::Implicit); | |||
129 | } | |||
130 | ||||
131 | MachineInstrBuilder &MIB; | |||
132 | }; | |||
133 | ||||
134 | } // end anonymous namespace | |||
135 | ||||
136 | void IncomingValueHandler::assignValueToReg(Register ValVReg, | |||
137 | const CCValAssign &VA, | |||
138 | const EVT &VT) { | |||
139 | const MipsSubtarget &STI = | |||
140 | static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); | |||
141 | Register PhysReg = VA.getLocReg(); | |||
142 | if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { | |||
143 | const MipsSubtarget &STI = | |||
144 | static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); | |||
145 | ||||
146 | MIRBuilder | |||
147 | .buildInstr(STI.isFP64bit() ? Mips::BuildPairF64_64 | |||
148 | : Mips::BuildPairF64) | |||
149 | .addDef(ValVReg) | |||
150 | .addUse(PhysReg + (STI.isLittle() ? 0 : 1)) | |||
151 | .addUse(PhysReg + (STI.isLittle() ? 1 : 0)) | |||
152 | .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), | |||
153 | *STI.getRegBankInfo()); | |||
154 | markPhysRegUsed(PhysReg); | |||
155 | markPhysRegUsed(PhysReg + 1); | |||
156 | } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { | |||
157 | MIRBuilder.buildInstr(Mips::MTC1) | |||
158 | .addDef(ValVReg) | |||
159 | .addUse(PhysReg) | |||
160 | .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), | |||
161 | *STI.getRegBankInfo()); | |||
162 | markPhysRegUsed(PhysReg); | |||
163 | } else { | |||
164 | switch (VA.getLocInfo()) { | |||
165 | case CCValAssign::LocInfo::SExt: | |||
166 | case CCValAssign::LocInfo::ZExt: | |||
167 | case CCValAssign::LocInfo::AExt: { | |||
168 | auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); | |||
169 | MIRBuilder.buildTrunc(ValVReg, Copy); | |||
170 | break; | |||
171 | } | |||
172 | default: | |||
173 | MIRBuilder.buildCopy(ValVReg, PhysReg); | |||
174 | break; | |||
175 | } | |||
176 | markPhysRegUsed(PhysReg); | |||
177 | } | |||
178 | } | |||
179 | ||||
180 | Register IncomingValueHandler::getStackAddress(const CCValAssign &VA, | |||
181 | MachineMemOperand *&MMO) { | |||
182 | MachineFunction &MF = MIRBuilder.getMF(); | |||
183 | unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; | |||
184 | unsigned Offset = VA.getLocMemOffset(); | |||
185 | MachineFrameInfo &MFI = MF.getFrameInfo(); | |||
186 | ||||
187 | int FI = MFI.CreateFixedObject(Size, Offset, true); | |||
188 | MachinePointerInfo MPO = | |||
189 | MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); | |||
190 | ||||
191 | const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); | |||
192 | unsigned Align = MinAlign(TFL->getStackAlignment(), Offset); | |||
193 | MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, Size, Align); | |||
194 | ||||
195 | Register AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); | |||
196 | MIRBuilder.buildFrameIndex(AddrReg, FI); | |||
197 | ||||
198 | return AddrReg; | |||
199 | } | |||
200 | ||||
201 | void IncomingValueHandler::assignValueToAddress(Register ValVReg, | |||
202 | const CCValAssign &VA) { | |||
203 | if (VA.getLocInfo() == CCValAssign::SExt || | |||
204 | VA.getLocInfo() == CCValAssign::ZExt || | |||
205 | VA.getLocInfo() == CCValAssign::AExt) { | |||
206 | Register LoadReg = MRI.createGenericVirtualRegister(LLT::scalar(32)); | |||
207 | buildLoad(LoadReg, VA); | |||
208 | MIRBuilder.buildTrunc(ValVReg, LoadReg); | |||
209 | } else | |||
210 | buildLoad(ValVReg, VA); | |||
211 | } | |||
212 | ||||
213 | bool IncomingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs, | |||
214 | ArrayRef<CCValAssign> ArgLocs, | |||
215 | unsigned ArgLocsStartIndex, | |||
216 | Register ArgsReg, const EVT &VT) { | |||
217 | if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) | |||
218 | return false; | |||
219 | setLeastSignificantFirst(VRegs); | |||
220 | MIRBuilder.buildMerge(ArgsReg, VRegs); | |||
221 | return true; | |||
222 | } | |||
223 | ||||
224 | namespace { | |||
225 | class OutgoingValueHandler : public MipsCallLowering::MipsHandler { | |||
226 | public: | |||
227 | OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, | |||
228 | MachineInstrBuilder &MIB) | |||
229 | : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} | |||
230 | ||||
231 | private: | |||
232 | void assignValueToReg(Register ValVReg, const CCValAssign &VA, | |||
233 | const EVT &VT) override; | |||
234 | ||||
235 | Register getStackAddress(const CCValAssign &VA, | |||
236 | MachineMemOperand *&MMO) override; | |||
237 | ||||
238 | void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; | |||
239 | ||||
240 | bool handleSplit(SmallVectorImpl<Register> &VRegs, | |||
241 | ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, | |||
242 | Register ArgsReg, const EVT &VT) override; | |||
243 | ||||
244 | Register extendRegister(Register ValReg, const CCValAssign &VA); | |||
245 | ||||
246 | MachineInstrBuilder &MIB; | |||
247 | }; | |||
248 | } // end anonymous namespace | |||
249 | ||||
250 | void OutgoingValueHandler::assignValueToReg(Register ValVReg, | |||
251 | const CCValAssign &VA, | |||
252 | const EVT &VT) { | |||
253 | Register PhysReg = VA.getLocReg(); | |||
254 | const MipsSubtarget &STI = | |||
255 | static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); | |||
256 | ||||
257 | if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { | |||
258 | MIRBuilder | |||
259 | .buildInstr(STI.isFP64bit() ? Mips::ExtractElementF64_64 | |||
260 | : Mips::ExtractElementF64) | |||
261 | .addDef(PhysReg + (STI.isLittle() ? 1 : 0)) | |||
262 | .addUse(ValVReg) | |||
263 | .addImm(1) | |||
264 | .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), | |||
265 | *STI.getRegBankInfo()); | |||
266 | MIRBuilder | |||
267 | .buildInstr(STI.isFP64bit() ? Mips::ExtractElementF64_64 | |||
268 | : Mips::ExtractElementF64) | |||
269 | .addDef(PhysReg + (STI.isLittle() ? 0 : 1)) | |||
270 | .addUse(ValVReg) | |||
271 | .addImm(0) | |||
272 | .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), | |||
273 | *STI.getRegBankInfo()); | |||
274 | } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { | |||
275 | MIRBuilder.buildInstr(Mips::MFC1) | |||
276 | .addDef(PhysReg) | |||
277 | .addUse(ValVReg) | |||
278 | .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), | |||
279 | *STI.getRegBankInfo()); | |||
280 | } else { | |||
281 | Register ExtReg = extendRegister(ValVReg, VA); | |||
282 | MIRBuilder.buildCopy(PhysReg, ExtReg); | |||
283 | MIB.addUse(PhysReg, RegState::Implicit); | |||
284 | } | |||
285 | } | |||
286 | ||||
287 | Register OutgoingValueHandler::getStackAddress(const CCValAssign &VA, | |||
288 | MachineMemOperand *&MMO) { | |||
289 | MachineFunction &MF = MIRBuilder.getMF(); | |||
290 | const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); | |||
291 | ||||
292 | LLT p0 = LLT::pointer(0, 32); | |||
293 | LLT s32 = LLT::scalar(32); | |||
294 | Register SPReg = MRI.createGenericVirtualRegister(p0); | |||
295 | MIRBuilder.buildCopy(SPReg, Register(Mips::SP)); | |||
296 | ||||
297 | Register OffsetReg = MRI.createGenericVirtualRegister(s32); | |||
298 | unsigned Offset = VA.getLocMemOffset(); | |||
299 | MIRBuilder.buildConstant(OffsetReg, Offset); | |||
300 | ||||
301 | Register AddrReg = MRI.createGenericVirtualRegister(p0); | |||
302 | MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); | |||
303 | ||||
304 | MachinePointerInfo MPO = | |||
305 | MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); | |||
306 | unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; | |||
307 | unsigned Align = MinAlign(TFL->getStackAlignment(), Offset); | |||
308 | MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, Size, Align); | |||
309 | ||||
310 | return AddrReg; | |||
311 | } | |||
312 | ||||
313 | void OutgoingValueHandler::assignValueToAddress(Register ValVReg, | |||
314 | const CCValAssign &VA) { | |||
315 | MachineMemOperand *MMO; | |||
316 | Register Addr = getStackAddress(VA, MMO); | |||
317 | Register ExtReg = extendRegister(ValVReg, VA); | |||
318 | MIRBuilder.buildStore(ExtReg, Addr, *MMO); | |||
319 | } | |||
320 | ||||
321 | Register OutgoingValueHandler::extendRegister(Register ValReg, | |||
322 | const CCValAssign &VA) { | |||
323 | LLT LocTy{VA.getLocVT()}; | |||
324 | switch (VA.getLocInfo()) { | |||
325 | case CCValAssign::SExt: { | |||
326 | Register ExtReg = MRI.createGenericVirtualRegister(LocTy); | |||
327 | MIRBuilder.buildSExt(ExtReg, ValReg); | |||
328 | return ExtReg; | |||
329 | } | |||
330 | case CCValAssign::ZExt: { | |||
331 | Register ExtReg = MRI.createGenericVirtualRegister(LocTy); | |||
332 | MIRBuilder.buildZExt(ExtReg, ValReg); | |||
333 | return ExtReg; | |||
334 | } | |||
335 | case CCValAssign::AExt: { | |||
336 | Register ExtReg = MRI.createGenericVirtualRegister(LocTy); | |||
337 | MIRBuilder.buildAnyExt(ExtReg, ValReg); | |||
338 | return ExtReg; | |||
339 | } | |||
340 | // TODO : handle upper extends | |||
341 | case CCValAssign::Full: | |||
342 | return ValReg; | |||
343 | default: | |||
344 | break; | |||
345 | } | |||
346 | llvm_unreachable("unable to extend register")::llvm::llvm_unreachable_internal("unable to extend register" , "/build/llvm-toolchain-snapshot-10~svn372774/lib/Target/Mips/MipsCallLowering.cpp" , 346); | |||
347 | } | |||
348 | ||||
349 | bool OutgoingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs, | |||
350 | ArrayRef<CCValAssign> ArgLocs, | |||
351 | unsigned ArgLocsStartIndex, | |||
352 | Register ArgsReg, const EVT &VT) { | |||
353 | MIRBuilder.buildUnmerge(VRegs, ArgsReg); | |||
354 | setLeastSignificantFirst(VRegs); | |||
355 | if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) | |||
356 | return false; | |||
357 | ||||
358 | return true; | |||
359 | } | |||
360 | ||||
361 | static bool isSupportedType(Type *T) { | |||
362 | if (T->isIntegerTy()) | |||
363 | return true; | |||
364 | if (T->isPointerTy()) | |||
365 | return true; | |||
366 | if (T->isFloatingPointTy()) | |||
367 | return true; | |||
368 | return false; | |||
369 | } | |||
370 | ||||
371 | static CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT, | |||
372 | const ISD::ArgFlagsTy &Flags) { | |||
373 | // > does not mean loss of information as type RegisterVT can't hold type VT, | |||
374 | // it means that type VT is split into multiple registers of type RegisterVT | |||
375 | if (VT.getSizeInBits() >= RegisterVT.getSizeInBits()) | |||
376 | return CCValAssign::LocInfo::Full; | |||
377 | if (Flags.isSExt()) | |||
378 | return CCValAssign::LocInfo::SExt; | |||
379 | if (Flags.isZExt()) | |||
380 | return CCValAssign::LocInfo::ZExt; | |||
381 | return CCValAssign::LocInfo::AExt; | |||
382 | } | |||
383 | ||||
384 | template <typename T> | |||
385 | static void setLocInfo(SmallVectorImpl<CCValAssign> &ArgLocs, | |||
386 | const SmallVectorImpl<T> &Arguments) { | |||
387 | for (unsigned i = 0; i < ArgLocs.size(); ++i) { | |||
388 | const CCValAssign &VA = ArgLocs[i]; | |||
389 | CCValAssign::LocInfo LocInfo = determineLocInfo( | |||
390 | Arguments[i].VT, Arguments[i].ArgVT, Arguments[i].Flags); | |||
391 | if (VA.isMemLoc()) | |||
392 | ArgLocs[i] = | |||
393 | CCValAssign::getMem(VA.getValNo(), VA.getValVT(), | |||
394 | VA.getLocMemOffset(), VA.getLocVT(), LocInfo); | |||
395 | else | |||
396 | ArgLocs[i] = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), | |||
397 | VA.getLocReg(), VA.getLocVT(), LocInfo); | |||
398 | } | |||
399 | } | |||
400 | ||||
401 | bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, | |||
402 | const Value *Val, | |||
403 | ArrayRef<Register> VRegs) const { | |||
404 | ||||
405 | MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); | |||
406 | ||||
407 | if (Val != nullptr && !isSupportedType(Val->getType())) | |||
| ||||
408 | return false; | |||
409 | ||||
410 | if (!VRegs.empty()) { | |||
411 | MachineFunction &MF = MIRBuilder.getMF(); | |||
412 | const Function &F = MF.getFunction(); | |||
413 | const DataLayout &DL = MF.getDataLayout(); | |||
414 | const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); | |||
415 | LLVMContext &Ctx = Val->getType()->getContext(); | |||
| ||||
416 | ||||
417 | SmallVector<EVT, 4> SplitEVTs; | |||
418 | ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs); | |||
419 | assert(VRegs.size() == SplitEVTs.size() &&((VRegs.size() == SplitEVTs.size() && "For each split Type there should be exactly one VReg." ) ? static_cast<void> (0) : __assert_fail ("VRegs.size() == SplitEVTs.size() && \"For each split Type there should be exactly one VReg.\"" , "/build/llvm-toolchain-snapshot-10~svn372774/lib/Target/Mips/MipsCallLowering.cpp" , 420, __PRETTY_FUNCTION__)) | |||
420 | "For each split Type there should be exactly one VReg.")((VRegs.size() == SplitEVTs.size() && "For each split Type there should be exactly one VReg." ) ? static_cast<void> (0) : __assert_fail ("VRegs.size() == SplitEVTs.size() && \"For each split Type there should be exactly one VReg.\"" , "/build/llvm-toolchain-snapshot-10~svn372774/lib/Target/Mips/MipsCallLowering.cpp" , 420, __PRETTY_FUNCTION__)); | |||
421 | ||||
422 | SmallVector<ArgInfo, 8> RetInfos; | |||
423 | SmallVector<unsigned, 8> OrigArgIndices; | |||
424 | ||||
425 | for (unsigned i = 0; i < SplitEVTs.size(); ++i) { | |||
426 | ArgInfo CurArgInfo = ArgInfo{VRegs[i], SplitEVTs[i].getTypeForEVT(Ctx)}; | |||
427 | setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F); | |||
428 | splitToValueTypes(CurArgInfo, 0, RetInfos, OrigArgIndices); | |||
429 | } | |||
430 | ||||
431 | SmallVector<ISD::OutputArg, 8> Outs; | |||
432 | subTargetRegTypeForCallingConv(F, RetInfos, OrigArgIndices, Outs); | |||
433 | ||||
434 | SmallVector<CCValAssign, 16> ArgLocs; | |||
435 | MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, | |||
436 | F.getContext()); | |||
437 | CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); | |||
438 | setLocInfo(ArgLocs, Outs); | |||
439 | ||||
440 | OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); | |||
441 | if (!RetHandler.handle(ArgLocs, RetInfos)) { | |||
442 | return false; | |||
443 | } | |||
444 | } | |||
445 | MIRBuilder.insertInstr(Ret); | |||
446 | return true; | |||
447 | } | |||
448 | ||||
449 | bool MipsCallLowering::lowerFormalArguments( | |||
450 | MachineIRBuilder &MIRBuilder, const Function &F, | |||
451 | ArrayRef<ArrayRef<Register>> VRegs) const { | |||
452 | ||||
453 | // Quick exit if there aren't any args. | |||
454 | if (F.arg_empty()) | |||
455 | return true; | |||
456 | ||||
457 | for (auto &Arg : F.args()) { | |||
458 | if (!isSupportedType(Arg.getType())) | |||
459 | return false; | |||
460 | } | |||
461 | ||||
462 | MachineFunction &MF = MIRBuilder.getMF(); | |||
463 | const DataLayout &DL = MF.getDataLayout(); | |||
464 | const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); | |||
465 | ||||
466 | SmallVector<ArgInfo, 8> ArgInfos; | |||
467 | SmallVector<unsigned, 8> OrigArgIndices; | |||
468 | unsigned i = 0; | |||
469 | for (auto &Arg : F.args()) { | |||
470 | ArgInfo AInfo(VRegs[i], Arg.getType()); | |||
471 | setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F); | |||
472 | splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices); | |||
473 | ++i; | |||
474 | } | |||
475 | ||||
476 | SmallVector<ISD::InputArg, 8> Ins; | |||
477 | subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Ins); | |||
478 | ||||
479 | SmallVector<CCValAssign, 16> ArgLocs; | |||
480 | MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, | |||
481 | F.getContext()); | |||
482 | ||||
483 | const MipsTargetMachine &TM = | |||
484 | static_cast<const MipsTargetMachine &>(MF.getTarget()); | |||
485 | const MipsABIInfo &ABI = TM.getABI(); | |||
486 | CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), | |||
487 | 1); | |||
488 | CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); | |||
489 | setLocInfo(ArgLocs, Ins); | |||
490 | ||||
491 | IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); | |||
492 | if (!Handler.handle(ArgLocs, ArgInfos)) | |||
493 | return false; | |||
494 | ||||
495 | if (F.isVarArg()) { | |||
496 | ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs(); | |||
497 | unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs); | |||
498 | ||||
499 | int VaArgOffset; | |||
500 | unsigned RegSize = 4; | |||
501 | if (ArgRegs.size() == Idx) | |||
502 | VaArgOffset = alignTo(CCInfo.getNextStackOffset(), RegSize); | |||
503 | else { | |||
504 | VaArgOffset = | |||
505 | (int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) - | |||
506 | (int)(RegSize * (ArgRegs.size() - Idx)); | |||
507 | } | |||
508 | ||||
509 | MachineFrameInfo &MFI = MF.getFrameInfo(); | |||
510 | int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true); | |||
511 | MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI); | |||
512 | ||||
513 | for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) { | |||
514 | MIRBuilder.getMBB().addLiveIn(ArgRegs[I]); | |||
515 | ||||
516 | MachineInstrBuilder Copy = | |||
517 | MIRBuilder.buildCopy(LLT::scalar(RegSize * 8), Register(ArgRegs[I])); | |||
518 | FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true); | |||
519 | MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI); | |||
520 | MachineInstrBuilder FrameIndex = | |||
521 | MIRBuilder.buildFrameIndex(LLT::pointer(MPO.getAddrSpace(), 32), FI); | |||
522 | MachineMemOperand *MMO = | |||
523 | MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, RegSize, | |||
524 | /* Alignment */ RegSize); | |||
525 | MIRBuilder.buildStore(Copy, FrameIndex, *MMO); | |||
526 | } | |||
527 | } | |||
528 | ||||
529 | return true; | |||
530 | } | |||
531 | ||||
532 | bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, | |||
533 | CallLoweringInfo &Info) const { | |||
534 | ||||
535 | if (Info.CallConv != CallingConv::C) | |||
536 | return false; | |||
537 | ||||
538 | for (auto &Arg : Info.OrigArgs) { | |||
539 | if (!isSupportedType(Arg.Ty)) | |||
540 | return false; | |||
541 | if (Arg.Flags[0].isByVal()) | |||
542 | return false; | |||
543 | if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy()) | |||
544 | return false; | |||
545 | } | |||
546 | ||||
547 | if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedType(Info.OrigRet.Ty)) | |||
548 | return false; | |||
549 | ||||
550 | MachineFunction &MF = MIRBuilder.getMF(); | |||
551 | const Function &F = MF.getFunction(); | |||
552 | const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); | |||
553 | const MipsTargetMachine &TM = | |||
554 | static_cast<const MipsTargetMachine &>(MF.getTarget()); | |||
555 | const MipsABIInfo &ABI = TM.getABI(); | |||
556 | ||||
557 | MachineInstrBuilder CallSeqStart = | |||
558 | MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); | |||
559 | ||||
560 | const bool IsCalleeGlobalPIC = | |||
561 | Info.Callee.isGlobal() && TM.isPositionIndependent(); | |||
562 | ||||
563 | MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert( | |||
564 | Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL); | |||
565 | MIB.addDef(Mips::SP, RegState::Implicit); | |||
566 | if (IsCalleeGlobalPIC) { | |||
567 | Register CalleeReg = | |||
568 | MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32)); | |||
569 | MachineInstr *CalleeGlobalValue = | |||
570 | MIRBuilder.buildGlobalValue(CalleeReg, Info.Callee.getGlobal()); | |||
571 | if (!Info.Callee.getGlobal()->hasLocalLinkage()) | |||
572 | CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL); | |||
573 | MIB.addUse(CalleeReg); | |||
574 | } else | |||
575 | MIB.add(Info.Callee); | |||
576 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); | |||
577 | MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv())); | |||
578 | ||||
579 | TargetLowering::ArgListTy FuncOrigArgs; | |||
580 | FuncOrigArgs.reserve(Info.OrigArgs.size()); | |||
581 | ||||
582 | SmallVector<ArgInfo, 8> ArgInfos; | |||
583 | SmallVector<unsigned, 8> OrigArgIndices; | |||
584 | unsigned i = 0; | |||
585 | for (auto &Arg : Info.OrigArgs) { | |||
586 | ||||
587 | TargetLowering::ArgListEntry Entry; | |||
588 | Entry.Ty = Arg.Ty; | |||
589 | FuncOrigArgs.push_back(Entry); | |||
590 | ||||
591 | splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices); | |||
592 | ++i; | |||
593 | } | |||
594 | ||||
595 | SmallVector<ISD::OutputArg, 8> Outs; | |||
596 | subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs); | |||
597 | ||||
598 | SmallVector<CCValAssign, 8> ArgLocs; | |||
599 | bool IsCalleeVarArg = false; | |||
600 | if (Info.Callee.isGlobal()) { | |||
601 | const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal()); | |||
602 | IsCalleeVarArg = CF->isVarArg(); | |||
603 | } | |||
604 | MipsCCState CCInfo(F.getCallingConv(), IsCalleeVarArg, MF, ArgLocs, | |||
605 | F.getContext()); | |||
606 | ||||
607 | CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv), 1); | |||
608 | const char *Call = | |||
609 | Info.Callee.isSymbol() ? Info.Callee.getSymbolName() : nullptr; | |||
610 | CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); | |||
611 | setLocInfo(ArgLocs, Outs); | |||
612 | ||||
613 | OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); | |||
614 | if (!RetHandler.handle(ArgLocs, ArgInfos)) { | |||
615 | return false; | |||
616 | } | |||
617 | ||||
618 | unsigned NextStackOffset = CCInfo.getNextStackOffset(); | |||
619 | const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); | |||
620 | unsigned StackAlignment = TFL->getStackAlignment(); | |||
621 | NextStackOffset = alignTo(NextStackOffset, StackAlignment); | |||
622 | CallSeqStart.addImm(NextStackOffset).addImm(0); | |||
623 | ||||
624 | if (IsCalleeGlobalPIC) { | |||
625 | MIRBuilder.buildCopy( | |||
626 | Register(Mips::GP), | |||
627 | MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel()); | |||
628 | MIB.addDef(Mips::GP, RegState::Implicit); | |||
629 | } | |||
630 | MIRBuilder.insertInstr(MIB); | |||
631 | if (MIB->getOpcode() == Mips::JALRPseudo) { | |||
632 | const MipsSubtarget &STI = | |||
633 | static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); | |||
634 | MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), | |||
635 | *STI.getRegBankInfo()); | |||
636 | } | |||
637 | ||||
638 | if (!Info.OrigRet.Ty->isVoidTy()) { | |||
639 | ArgInfos.clear(); | |||
640 | SmallVector<unsigned, 8> OrigRetIndices; | |||
641 | ||||
642 | splitToValueTypes(Info.OrigRet, 0, ArgInfos, OrigRetIndices); | |||
643 | ||||
644 | SmallVector<ISD::InputArg, 8> Ins; | |||
645 | subTargetRegTypeForCallingConv(F, ArgInfos, OrigRetIndices, Ins); | |||
646 | ||||
647 | SmallVector<CCValAssign, 8> ArgLocs; | |||
648 | MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, | |||
649 | F.getContext()); | |||
650 | ||||
651 | CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), Info.OrigRet.Ty, Call); | |||
652 | setLocInfo(ArgLocs, Ins); | |||
653 | ||||
654 | CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); | |||
655 | if (!Handler.handle(ArgLocs, ArgInfos)) | |||
656 | return false; | |||
657 | } | |||
658 | ||||
659 | MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0); | |||
660 | ||||
661 | return true; | |||
662 | } | |||
663 | ||||
664 | template <typename T> | |||
665 | void MipsCallLowering::subTargetRegTypeForCallingConv( | |||
666 | const Function &F, ArrayRef<ArgInfo> Args, | |||
667 | ArrayRef<unsigned> OrigArgIndices, SmallVectorImpl<T> &ISDArgs) const { | |||
668 | const DataLayout &DL = F.getParent()->getDataLayout(); | |||
669 | const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); | |||
670 | ||||
671 | unsigned ArgNo = 0; | |||
672 | for (auto &Arg : Args) { | |||
673 | ||||
674 | EVT VT = TLI.getValueType(DL, Arg.Ty); | |||
675 | MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), | |||
676 | F.getCallingConv(), VT); | |||
677 | unsigned NumRegs = TLI.getNumRegistersForCallingConv( | |||
678 | F.getContext(), F.getCallingConv(), VT); | |||
679 | ||||
680 | for (unsigned i = 0; i < NumRegs; ++i) { | |||
681 | ISD::ArgFlagsTy Flags = Arg.Flags[0]; | |||
682 | ||||
683 | if (i == 0) | |||
684 | Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); | |||
685 | else | |||
686 | Flags.setOrigAlign(1); | |||
687 | ||||
688 | ISDArgs.emplace_back(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], | |||
689 | 0); | |||
690 | } | |||
691 | ++ArgNo; | |||
692 | } | |||
693 | } | |||
694 | ||||
695 | void MipsCallLowering::splitToValueTypes( | |||
696 | const ArgInfo &OrigArg, unsigned OriginalIndex, | |||
697 | SmallVectorImpl<ArgInfo> &SplitArgs, | |||
698 | SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const { | |||
699 | ||||
700 | // TODO : perform structure and array split. For now we only deal with | |||
701 | // types that pass isSupportedType check. | |||
702 | SplitArgs.push_back(OrigArg); | |||
703 | SplitArgsOrigIndices.push_back(OriginalIndex); | |||
704 | } |