File: | build/source/llvm/lib/Target/Mips/MipsCallLowering.cpp |
Warning: | line 332, column 13 Forming reference to null pointer |
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 | #include "llvm/CodeGen/MachineFrameInfo.h" | |||
22 | ||||
23 | using namespace llvm; | |||
24 | ||||
25 | MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) | |||
26 | : CallLowering(&TLI) {} | |||
27 | ||||
28 | namespace { | |||
29 | struct MipsOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner { | |||
30 | /// This is the name of the function being called | |||
31 | /// FIXME: Relying on this is unsound | |||
32 | const char *Func = nullptr; | |||
33 | ||||
34 | /// Is this a return value, or an outgoing call operand. | |||
35 | bool IsReturn; | |||
36 | ||||
37 | MipsOutgoingValueAssigner(CCAssignFn *AssignFn_, const char *Func, | |||
38 | bool IsReturn) | |||
39 | : OutgoingValueAssigner(AssignFn_), Func(Func), IsReturn(IsReturn) {} | |||
40 | ||||
41 | bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, | |||
42 | CCValAssign::LocInfo LocInfo, | |||
43 | const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags, | |||
44 | CCState &State_) override { | |||
45 | MipsCCState &State = static_cast<MipsCCState &>(State_); | |||
46 | ||||
47 | if (IsReturn) | |||
48 | State.PreAnalyzeReturnValue(EVT::getEVT(Info.Ty)); | |||
49 | else | |||
50 | State.PreAnalyzeCallOperand(Info.Ty, Info.IsFixed, Func); | |||
51 | ||||
52 | return CallLowering::OutgoingValueAssigner::assignArg( | |||
53 | ValNo, OrigVT, ValVT, LocVT, LocInfo, Info, Flags, State); | |||
54 | } | |||
55 | }; | |||
56 | ||||
57 | struct MipsIncomingValueAssigner : public CallLowering::IncomingValueAssigner { | |||
58 | /// This is the name of the function being called | |||
59 | /// FIXME: Relying on this is unsound | |||
60 | const char *Func = nullptr; | |||
61 | ||||
62 | /// Is this a call return value, or an incoming function argument. | |||
63 | bool IsReturn; | |||
64 | ||||
65 | MipsIncomingValueAssigner(CCAssignFn *AssignFn_, const char *Func, | |||
66 | bool IsReturn) | |||
67 | : IncomingValueAssigner(AssignFn_), Func(Func), IsReturn(IsReturn) {} | |||
68 | ||||
69 | bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, | |||
70 | CCValAssign::LocInfo LocInfo, | |||
71 | const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags, | |||
72 | CCState &State_) override { | |||
73 | MipsCCState &State = static_cast<MipsCCState &>(State_); | |||
74 | ||||
75 | if (IsReturn) | |||
76 | State.PreAnalyzeCallResult(Info.Ty, Func); | |||
77 | else | |||
78 | State.PreAnalyzeFormalArgument(Info.Ty, Flags); | |||
79 | ||||
80 | return CallLowering::IncomingValueAssigner::assignArg( | |||
81 | ValNo, OrigVT, ValVT, LocVT, LocInfo, Info, Flags, State); | |||
82 | } | |||
83 | }; | |||
84 | ||||
85 | class MipsIncomingValueHandler : public CallLowering::IncomingValueHandler { | |||
86 | const MipsSubtarget &STI; | |||
87 | ||||
88 | public: | |||
89 | MipsIncomingValueHandler(MachineIRBuilder &MIRBuilder, | |||
90 | MachineRegisterInfo &MRI) | |||
91 | : IncomingValueHandler(MIRBuilder, MRI), | |||
92 | STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()) {} | |||
93 | ||||
94 | private: | |||
95 | void assignValueToReg(Register ValVReg, Register PhysReg, | |||
96 | CCValAssign VA) override; | |||
97 | ||||
98 | Register getStackAddress(uint64_t Size, int64_t Offset, | |||
99 | MachinePointerInfo &MPO, | |||
100 | ISD::ArgFlagsTy Flags) override; | |||
101 | void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, | |||
102 | MachinePointerInfo &MPO, CCValAssign &VA) override; | |||
103 | ||||
104 | unsigned assignCustomValue(CallLowering::ArgInfo &Arg, | |||
105 | ArrayRef<CCValAssign> VAs, | |||
106 | std::function<void()> *Thunk = nullptr) override; | |||
107 | ||||
108 | virtual void markPhysRegUsed(unsigned PhysReg) { | |||
109 | MIRBuilder.getMRI()->addLiveIn(PhysReg); | |||
110 | MIRBuilder.getMBB().addLiveIn(PhysReg); | |||
111 | } | |||
112 | }; | |||
113 | ||||
114 | class CallReturnHandler : public MipsIncomingValueHandler { | |||
115 | public: | |||
116 | CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, | |||
117 | MachineInstrBuilder &MIB) | |||
118 | : MipsIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} | |||
119 | ||||
120 | private: | |||
121 | void markPhysRegUsed(unsigned PhysReg) override { | |||
122 | MIB.addDef(PhysReg, RegState::Implicit); | |||
123 | } | |||
124 | ||||
125 | MachineInstrBuilder &MIB; | |||
126 | }; | |||
127 | ||||
128 | } // end anonymous namespace | |||
129 | ||||
130 | void MipsIncomingValueHandler::assignValueToReg(Register ValVReg, | |||
131 | Register PhysReg, | |||
132 | CCValAssign VA) { | |||
133 | markPhysRegUsed(PhysReg); | |||
134 | IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); | |||
135 | } | |||
136 | ||||
137 | Register MipsIncomingValueHandler::getStackAddress(uint64_t Size, | |||
138 | int64_t Offset, | |||
139 | MachinePointerInfo &MPO, | |||
140 | ISD::ArgFlagsTy Flags) { | |||
141 | ||||
142 | MachineFunction &MF = MIRBuilder.getMF(); | |||
143 | MachineFrameInfo &MFI = MF.getFrameInfo(); | |||
144 | ||||
145 | // FIXME: This should only be immutable for non-byval memory arguments. | |||
146 | int FI = MFI.CreateFixedObject(Size, Offset, true); | |||
147 | MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); | |||
148 | ||||
149 | return MIRBuilder.buildFrameIndex(LLT::pointer(0, 32), FI).getReg(0); | |||
150 | } | |||
151 | ||||
152 | void MipsIncomingValueHandler::assignValueToAddress(Register ValVReg, | |||
153 | Register Addr, LLT MemTy, | |||
154 | MachinePointerInfo &MPO, | |||
155 | CCValAssign &VA) { | |||
156 | MachineFunction &MF = MIRBuilder.getMF(); | |||
157 | auto MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy, | |||
158 | inferAlignFromPtrInfo(MF, MPO)); | |||
159 | MIRBuilder.buildLoad(ValVReg, Addr, *MMO); | |||
160 | } | |||
161 | ||||
162 | /// Handle cases when f64 is split into 2 32-bit GPRs. This is a custom | |||
163 | /// assignment because generic code assumes getNumRegistersForCallingConv is | |||
164 | /// accurate. In this case it is not because the type/number are context | |||
165 | /// dependent on other arguments. | |||
166 | unsigned | |||
167 | MipsIncomingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg, | |||
168 | ArrayRef<CCValAssign> VAs, | |||
169 | std::function<void()> *Thunk) { | |||
170 | const CCValAssign &VALo = VAs[0]; | |||
171 | const CCValAssign &VAHi = VAs[1]; | |||
172 | ||||
173 | assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&(static_cast <bool> (VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT ::f64 && VAHi.getValVT() == MVT::f64 && "unexpected custom value" ) ? void (0) : __assert_fail ("VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 && \"unexpected custom value\"" , "llvm/lib/Target/Mips/MipsCallLowering.cpp", 175, __extension__ __PRETTY_FUNCTION__)) | |||
174 | VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&(static_cast <bool> (VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT ::f64 && VAHi.getValVT() == MVT::f64 && "unexpected custom value" ) ? void (0) : __assert_fail ("VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 && \"unexpected custom value\"" , "llvm/lib/Target/Mips/MipsCallLowering.cpp", 175, __extension__ __PRETTY_FUNCTION__)) | |||
175 | "unexpected custom value")(static_cast <bool> (VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT ::f64 && VAHi.getValVT() == MVT::f64 && "unexpected custom value" ) ? void (0) : __assert_fail ("VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 && \"unexpected custom value\"" , "llvm/lib/Target/Mips/MipsCallLowering.cpp", 175, __extension__ __PRETTY_FUNCTION__)); | |||
176 | ||||
177 | auto CopyLo = MIRBuilder.buildCopy(LLT::scalar(32), VALo.getLocReg()); | |||
178 | auto CopyHi = MIRBuilder.buildCopy(LLT::scalar(32), VAHi.getLocReg()); | |||
179 | if (!STI.isLittle()) | |||
180 | std::swap(CopyLo, CopyHi); | |||
181 | ||||
182 | Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end()); | |||
183 | Arg.Regs = { CopyLo.getReg(0), CopyHi.getReg(0) }; | |||
184 | MIRBuilder.buildMergeLikeInstr(Arg.OrigRegs[0], {CopyLo, CopyHi}); | |||
185 | ||||
186 | markPhysRegUsed(VALo.getLocReg()); | |||
187 | markPhysRegUsed(VAHi.getLocReg()); | |||
188 | return 2; | |||
189 | } | |||
190 | ||||
191 | namespace { | |||
192 | class MipsOutgoingValueHandler : public CallLowering::OutgoingValueHandler { | |||
193 | const MipsSubtarget &STI; | |||
194 | ||||
195 | public: | |||
196 | MipsOutgoingValueHandler(MachineIRBuilder &MIRBuilder, | |||
197 | MachineRegisterInfo &MRI, MachineInstrBuilder &MIB) | |||
198 | : OutgoingValueHandler(MIRBuilder, MRI), | |||
199 | STI(MIRBuilder.getMF().getSubtarget<MipsSubtarget>()), MIB(MIB) {} | |||
200 | ||||
201 | private: | |||
202 | void assignValueToReg(Register ValVReg, Register PhysReg, | |||
203 | CCValAssign VA) override; | |||
204 | ||||
205 | Register getStackAddress(uint64_t Size, int64_t Offset, | |||
206 | MachinePointerInfo &MPO, | |||
207 | ISD::ArgFlagsTy Flags) override; | |||
208 | ||||
209 | void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, | |||
210 | MachinePointerInfo &MPO, CCValAssign &VA) override; | |||
211 | unsigned assignCustomValue(CallLowering::ArgInfo &Arg, | |||
212 | ArrayRef<CCValAssign> VAs, | |||
213 | std::function<void()> *Thunk) override; | |||
214 | ||||
215 | MachineInstrBuilder &MIB; | |||
216 | }; | |||
217 | } // end anonymous namespace | |||
218 | ||||
219 | void MipsOutgoingValueHandler::assignValueToReg(Register ValVReg, | |||
220 | Register PhysReg, | |||
221 | CCValAssign VA) { | |||
222 | Register ExtReg = extendRegister(ValVReg, VA); | |||
223 | MIRBuilder.buildCopy(PhysReg, ExtReg); | |||
224 | MIB.addUse(PhysReg, RegState::Implicit); | |||
225 | } | |||
226 | ||||
227 | Register MipsOutgoingValueHandler::getStackAddress(uint64_t Size, | |||
228 | int64_t Offset, | |||
229 | MachinePointerInfo &MPO, | |||
230 | ISD::ArgFlagsTy Flags) { | |||
231 | MachineFunction &MF = MIRBuilder.getMF(); | |||
232 | MPO = MachinePointerInfo::getStack(MF, Offset); | |||
233 | ||||
234 | LLT p0 = LLT::pointer(0, 32); | |||
235 | LLT s32 = LLT::scalar(32); | |||
236 | auto SPReg = MIRBuilder.buildCopy(p0, Register(Mips::SP)); | |||
237 | ||||
238 | auto OffsetReg = MIRBuilder.buildConstant(s32, Offset); | |||
239 | auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg); | |||
240 | return AddrReg.getReg(0); | |||
241 | } | |||
242 | ||||
243 | void MipsOutgoingValueHandler::assignValueToAddress(Register ValVReg, | |||
244 | Register Addr, LLT MemTy, | |||
245 | MachinePointerInfo &MPO, | |||
246 | CCValAssign &VA) { | |||
247 | MachineFunction &MF = MIRBuilder.getMF(); | |||
248 | uint64_t LocMemOffset = VA.getLocMemOffset(); | |||
249 | ||||
250 | auto MMO = MF.getMachineMemOperand( | |||
251 | MPO, MachineMemOperand::MOStore, MemTy, | |||
252 | commonAlignment(STI.getStackAlignment(), LocMemOffset)); | |||
253 | ||||
254 | Register ExtReg = extendRegister(ValVReg, VA); | |||
255 | MIRBuilder.buildStore(ExtReg, Addr, *MMO); | |||
256 | } | |||
257 | ||||
258 | unsigned | |||
259 | MipsOutgoingValueHandler::assignCustomValue(CallLowering::ArgInfo &Arg, | |||
260 | ArrayRef<CCValAssign> VAs, | |||
261 | std::function<void()> *Thunk) { | |||
262 | const CCValAssign &VALo = VAs[0]; | |||
263 | const CCValAssign &VAHi = VAs[1]; | |||
264 | ||||
265 | assert(VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 &&(static_cast <bool> (VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT ::f64 && VAHi.getValVT() == MVT::f64 && "unexpected custom value" ) ? void (0) : __assert_fail ("VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 && \"unexpected custom value\"" , "llvm/lib/Target/Mips/MipsCallLowering.cpp", 267, __extension__ __PRETTY_FUNCTION__)) | |||
266 | VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 &&(static_cast <bool> (VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT ::f64 && VAHi.getValVT() == MVT::f64 && "unexpected custom value" ) ? void (0) : __assert_fail ("VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 && \"unexpected custom value\"" , "llvm/lib/Target/Mips/MipsCallLowering.cpp", 267, __extension__ __PRETTY_FUNCTION__)) | |||
267 | "unexpected custom value")(static_cast <bool> (VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT ::f64 && VAHi.getValVT() == MVT::f64 && "unexpected custom value" ) ? void (0) : __assert_fail ("VALo.getLocVT() == MVT::i32 && VAHi.getLocVT() == MVT::i32 && VALo.getValVT() == MVT::f64 && VAHi.getValVT() == MVT::f64 && \"unexpected custom value\"" , "llvm/lib/Target/Mips/MipsCallLowering.cpp", 267, __extension__ __PRETTY_FUNCTION__)); | |||
268 | ||||
269 | auto Unmerge = | |||
270 | MIRBuilder.buildUnmerge({LLT::scalar(32), LLT::scalar(32)}, Arg.Regs[0]); | |||
271 | Register Lo = Unmerge.getReg(0); | |||
272 | Register Hi = Unmerge.getReg(1); | |||
273 | ||||
274 | Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end()); | |||
275 | Arg.Regs = { Lo, Hi }; | |||
276 | if (!STI.isLittle()) | |||
277 | std::swap(Lo, Hi); | |||
278 | ||||
279 | // If we can return a thunk, just include the register copies. The unmerge can | |||
280 | // be emitted earlier. | |||
281 | if (Thunk) { | |||
282 | *Thunk = [=]() { | |||
283 | MIRBuilder.buildCopy(VALo.getLocReg(), Lo); | |||
284 | MIRBuilder.buildCopy(VAHi.getLocReg(), Hi); | |||
285 | }; | |||
286 | return 2; | |||
287 | } | |||
288 | MIRBuilder.buildCopy(VALo.getLocReg(), Lo); | |||
289 | MIRBuilder.buildCopy(VAHi.getLocReg(), Hi); | |||
290 | return 2; | |||
291 | } | |||
292 | ||||
293 | static bool isSupportedArgumentType(Type *T) { | |||
294 | if (T->isIntegerTy()) | |||
295 | return true; | |||
296 | if (T->isPointerTy()) | |||
297 | return true; | |||
298 | if (T->isFloatingPointTy()) | |||
299 | return true; | |||
300 | return false; | |||
301 | } | |||
302 | ||||
303 | static bool isSupportedReturnType(Type *T) { | |||
304 | if (T->isIntegerTy()) | |||
305 | return true; | |||
306 | if (T->isPointerTy()) | |||
307 | return true; | |||
308 | if (T->isFloatingPointTy()) | |||
309 | return true; | |||
310 | if (T->isAggregateType()) | |||
311 | return true; | |||
312 | return false; | |||
313 | } | |||
314 | ||||
315 | bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, | |||
316 | const Value *Val, ArrayRef<Register> VRegs, | |||
317 | FunctionLoweringInfo &FLI) const { | |||
318 | ||||
319 | MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); | |||
320 | ||||
321 | if (Val != nullptr && !isSupportedReturnType(Val->getType())) | |||
| ||||
322 | return false; | |||
323 | ||||
324 | if (!VRegs.empty()) { | |||
325 | MachineFunction &MF = MIRBuilder.getMF(); | |||
326 | const Function &F = MF.getFunction(); | |||
327 | const DataLayout &DL = MF.getDataLayout(); | |||
328 | const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); | |||
329 | ||||
330 | SmallVector<ArgInfo, 8> RetInfos; | |||
331 | ||||
332 | ArgInfo ArgRetInfo(VRegs, *Val, 0); | |||
| ||||
333 | setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F); | |||
334 | splitToValueTypes(ArgRetInfo, RetInfos, DL, F.getCallingConv()); | |||
335 | ||||
336 | SmallVector<CCValAssign, 16> ArgLocs; | |||
337 | SmallVector<ISD::OutputArg, 8> Outs; | |||
338 | ||||
339 | MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, | |||
340 | F.getContext()); | |||
341 | ||||
342 | MipsOutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); | |||
343 | std::string FuncName = F.getName().str(); | |||
344 | MipsOutgoingValueAssigner Assigner(TLI.CCAssignFnForReturn(), | |||
345 | FuncName.c_str(), /*IsReturn*/ true); | |||
346 | ||||
347 | if (!determineAssignments(Assigner, RetInfos, CCInfo)) | |||
348 | return false; | |||
349 | ||||
350 | if (!handleAssignments(RetHandler, RetInfos, CCInfo, ArgLocs, MIRBuilder)) | |||
351 | return false; | |||
352 | } | |||
353 | ||||
354 | MIRBuilder.insertInstr(Ret); | |||
355 | return true; | |||
356 | } | |||
357 | ||||
358 | bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, | |||
359 | const Function &F, | |||
360 | ArrayRef<ArrayRef<Register>> VRegs, | |||
361 | FunctionLoweringInfo &FLI) const { | |||
362 | ||||
363 | // Quick exit if there aren't any args. | |||
364 | if (F.arg_empty()) | |||
365 | return true; | |||
366 | ||||
367 | for (auto &Arg : F.args()) { | |||
368 | if (!isSupportedArgumentType(Arg.getType())) | |||
369 | return false; | |||
370 | } | |||
371 | ||||
372 | MachineFunction &MF = MIRBuilder.getMF(); | |||
373 | const DataLayout &DL = MF.getDataLayout(); | |||
374 | const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); | |||
375 | ||||
376 | SmallVector<ArgInfo, 8> ArgInfos; | |||
377 | unsigned i = 0; | |||
378 | for (auto &Arg : F.args()) { | |||
379 | ArgInfo AInfo(VRegs[i], Arg, i); | |||
380 | setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F); | |||
381 | ||||
382 | splitToValueTypes(AInfo, ArgInfos, DL, F.getCallingConv()); | |||
383 | ++i; | |||
384 | } | |||
385 | ||||
386 | SmallVector<ISD::InputArg, 8> Ins; | |||
387 | ||||
388 | SmallVector<CCValAssign, 16> ArgLocs; | |||
389 | MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, | |||
390 | F.getContext()); | |||
391 | ||||
392 | const MipsTargetMachine &TM = | |||
393 | static_cast<const MipsTargetMachine &>(MF.getTarget()); | |||
394 | const MipsABIInfo &ABI = TM.getABI(); | |||
395 | CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), | |||
396 | Align(1)); | |||
397 | ||||
398 | const std::string FuncName = F.getName().str(); | |||
399 | MipsIncomingValueAssigner Assigner(TLI.CCAssignFnForCall(), FuncName.c_str(), | |||
400 | /*IsReturn*/ false); | |||
401 | if (!determineAssignments(Assigner, ArgInfos, CCInfo)) | |||
402 | return false; | |||
403 | ||||
404 | MipsIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); | |||
405 | if (!handleAssignments(Handler, ArgInfos, CCInfo, ArgLocs, MIRBuilder)) | |||
406 | return false; | |||
407 | ||||
408 | if (F.isVarArg()) { | |||
409 | ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs(); | |||
410 | unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs); | |||
411 | ||||
412 | int VaArgOffset; | |||
413 | unsigned RegSize = 4; | |||
414 | if (ArgRegs.size() == Idx) | |||
415 | VaArgOffset = alignTo(CCInfo.getNextStackOffset(), RegSize); | |||
416 | else { | |||
417 | VaArgOffset = | |||
418 | (int)ABI.GetCalleeAllocdArgSizeInBytes(CCInfo.getCallingConv()) - | |||
419 | (int)(RegSize * (ArgRegs.size() - Idx)); | |||
420 | } | |||
421 | ||||
422 | MachineFrameInfo &MFI = MF.getFrameInfo(); | |||
423 | int FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true); | |||
424 | MF.getInfo<MipsFunctionInfo>()->setVarArgsFrameIndex(FI); | |||
425 | ||||
426 | for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += RegSize) { | |||
427 | MIRBuilder.getMBB().addLiveIn(ArgRegs[I]); | |||
428 | LLT RegTy = LLT::scalar(RegSize * 8); | |||
429 | MachineInstrBuilder Copy = | |||
430 | MIRBuilder.buildCopy(RegTy, Register(ArgRegs[I])); | |||
431 | FI = MFI.CreateFixedObject(RegSize, VaArgOffset, true); | |||
432 | MachinePointerInfo MPO = MachinePointerInfo::getFixedStack(MF, FI); | |||
433 | ||||
434 | const LLT PtrTy = LLT::pointer(MPO.getAddrSpace(), 32); | |||
435 | auto FrameIndex = MIRBuilder.buildFrameIndex(PtrTy, FI); | |||
436 | MachineMemOperand *MMO = MF.getMachineMemOperand( | |||
437 | MPO, MachineMemOperand::MOStore, RegTy, Align(RegSize)); | |||
438 | MIRBuilder.buildStore(Copy, FrameIndex, *MMO); | |||
439 | } | |||
440 | } | |||
441 | ||||
442 | return true; | |||
443 | } | |||
444 | ||||
445 | bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, | |||
446 | CallLoweringInfo &Info) const { | |||
447 | ||||
448 | if (Info.CallConv != CallingConv::C) | |||
449 | return false; | |||
450 | ||||
451 | for (auto &Arg : Info.OrigArgs) { | |||
452 | if (!isSupportedArgumentType(Arg.Ty)) | |||
453 | return false; | |||
454 | if (Arg.Flags[0].isByVal()) | |||
455 | return false; | |||
456 | if (Arg.Flags[0].isSRet() && !Arg.Ty->isPointerTy()) | |||
457 | return false; | |||
458 | } | |||
459 | ||||
460 | if (!Info.OrigRet.Ty->isVoidTy() && !isSupportedReturnType(Info.OrigRet.Ty)) | |||
461 | return false; | |||
462 | ||||
463 | MachineFunction &MF = MIRBuilder.getMF(); | |||
464 | const Function &F = MF.getFunction(); | |||
465 | const DataLayout &DL = MF.getDataLayout(); | |||
466 | const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); | |||
467 | const MipsTargetMachine &TM = | |||
468 | static_cast<const MipsTargetMachine &>(MF.getTarget()); | |||
469 | const MipsABIInfo &ABI = TM.getABI(); | |||
470 | ||||
471 | MachineInstrBuilder CallSeqStart = | |||
472 | MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); | |||
473 | ||||
474 | const bool IsCalleeGlobalPIC = | |||
475 | Info.Callee.isGlobal() && TM.isPositionIndependent(); | |||
476 | ||||
477 | MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert( | |||
478 | Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL); | |||
479 | MIB.addDef(Mips::SP, RegState::Implicit); | |||
480 | if (IsCalleeGlobalPIC) { | |||
481 | Register CalleeReg = | |||
482 | MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32)); | |||
483 | MachineInstr *CalleeGlobalValue = | |||
484 | MIRBuilder.buildGlobalValue(CalleeReg, Info.Callee.getGlobal()); | |||
485 | if (!Info.Callee.getGlobal()->hasLocalLinkage()) | |||
486 | CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL); | |||
487 | MIB.addUse(CalleeReg); | |||
488 | } else | |||
489 | MIB.add(Info.Callee); | |||
490 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); | |||
491 | MIB.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); | |||
492 | ||||
493 | TargetLowering::ArgListTy FuncOrigArgs; | |||
494 | FuncOrigArgs.reserve(Info.OrigArgs.size()); | |||
495 | ||||
496 | SmallVector<ArgInfo, 8> ArgInfos; | |||
497 | for (auto &Arg : Info.OrigArgs) | |||
498 | splitToValueTypes(Arg, ArgInfos, DL, Info.CallConv); | |||
499 | ||||
500 | SmallVector<CCValAssign, 8> ArgLocs; | |||
501 | bool IsCalleeVarArg = false; | |||
502 | if (Info.Callee.isGlobal()) { | |||
503 | const Function *CF = static_cast<const Function *>(Info.Callee.getGlobal()); | |||
504 | IsCalleeVarArg = CF->isVarArg(); | |||
505 | } | |||
506 | ||||
507 | // FIXME: Should use MipsCCState::getSpecialCallingConvForCallee, but it | |||
508 | // depends on looking directly at the call target. | |||
509 | MipsCCState CCInfo(Info.CallConv, IsCalleeVarArg, MF, ArgLocs, | |||
510 | F.getContext()); | |||
511 | ||||
512 | CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(Info.CallConv), | |||
513 | Align(1)); | |||
514 | ||||
515 | const char *Call = | |||
516 | Info.Callee.isSymbol() ? Info.Callee.getSymbolName() : nullptr; | |||
517 | ||||
518 | MipsOutgoingValueAssigner Assigner(TLI.CCAssignFnForCall(), Call, | |||
519 | /*IsReturn*/ false); | |||
520 | if (!determineAssignments(Assigner, ArgInfos, CCInfo)) | |||
521 | return false; | |||
522 | ||||
523 | MipsOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), MIB); | |||
524 | if (!handleAssignments(ArgHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder)) | |||
525 | return false; | |||
526 | ||||
527 | unsigned NextStackOffset = CCInfo.getNextStackOffset(); | |||
528 | unsigned StackAlignment = F.getParent()->getOverrideStackAlignment(); | |||
529 | if (!StackAlignment) { | |||
530 | const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); | |||
531 | StackAlignment = TFL->getStackAlignment(); | |||
532 | } | |||
533 | NextStackOffset = alignTo(NextStackOffset, StackAlignment); | |||
534 | CallSeqStart.addImm(NextStackOffset).addImm(0); | |||
535 | ||||
536 | if (IsCalleeGlobalPIC) { | |||
537 | MIRBuilder.buildCopy( | |||
538 | Register(Mips::GP), | |||
539 | MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel(MF)); | |||
540 | MIB.addDef(Mips::GP, RegState::Implicit); | |||
541 | } | |||
542 | MIRBuilder.insertInstr(MIB); | |||
543 | if (MIB->getOpcode() == Mips::JALRPseudo) { | |||
544 | const MipsSubtarget &STI = MIRBuilder.getMF().getSubtarget<MipsSubtarget>(); | |||
545 | MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), | |||
546 | *STI.getRegBankInfo()); | |||
547 | } | |||
548 | ||||
549 | if (!Info.OrigRet.Ty->isVoidTy()) { | |||
550 | ArgInfos.clear(); | |||
551 | ||||
552 | CallLowering::splitToValueTypes(Info.OrigRet, ArgInfos, DL, | |||
553 | F.getCallingConv()); | |||
554 | ||||
555 | const std::string FuncName = F.getName().str(); | |||
556 | SmallVector<ISD::InputArg, 8> Ins; | |||
557 | SmallVector<CCValAssign, 8> ArgLocs; | |||
558 | MipsIncomingValueAssigner Assigner(TLI.CCAssignFnForReturn(), | |||
559 | FuncName.c_str(), | |||
560 | /*IsReturn*/ true); | |||
561 | CallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); | |||
562 | ||||
563 | MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, | |||
564 | F.getContext()); | |||
565 | ||||
566 | if (!determineAssignments(Assigner, ArgInfos, CCInfo)) | |||
567 | return false; | |||
568 | ||||
569 | if (!handleAssignments(RetHandler, ArgInfos, CCInfo, ArgLocs, MIRBuilder)) | |||
570 | return false; | |||
571 | } | |||
572 | ||||
573 | MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0); | |||
574 | ||||
575 | return true; | |||
576 | } |