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