/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AArch64/AArch64CallLowering.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- AArch64CallLowering.cpp - Call lowering --------------------------===// |
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 "AArch64CallLowering.h" |
16 | | #include "AArch64ISelLowering.h" |
17 | | #include "AArch64MachineFunctionInfo.h" |
18 | | #include "AArch64Subtarget.h" |
19 | | #include "llvm/ADT/ArrayRef.h" |
20 | | #include "llvm/ADT/SmallVector.h" |
21 | | #include "llvm/CodeGen/Analysis.h" |
22 | | #include "llvm/CodeGen/CallingConvLower.h" |
23 | | #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" |
24 | | #include "llvm/CodeGen/GlobalISel/Utils.h" |
25 | | #include "llvm/CodeGen/LowLevelType.h" |
26 | | #include "llvm/CodeGen/MachineBasicBlock.h" |
27 | | #include "llvm/CodeGen/MachineFrameInfo.h" |
28 | | #include "llvm/CodeGen/MachineFunction.h" |
29 | | #include "llvm/CodeGen/MachineInstrBuilder.h" |
30 | | #include "llvm/CodeGen/MachineMemOperand.h" |
31 | | #include "llvm/CodeGen/MachineOperand.h" |
32 | | #include "llvm/CodeGen/MachineRegisterInfo.h" |
33 | | #include "llvm/CodeGen/TargetRegisterInfo.h" |
34 | | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
35 | | #include "llvm/CodeGen/ValueTypes.h" |
36 | | #include "llvm/IR/Argument.h" |
37 | | #include "llvm/IR/Attributes.h" |
38 | | #include "llvm/IR/Function.h" |
39 | | #include "llvm/IR/Type.h" |
40 | | #include "llvm/IR/Value.h" |
41 | | #include "llvm/Support/MachineValueType.h" |
42 | | #include <algorithm> |
43 | | #include <cassert> |
44 | | #include <cstdint> |
45 | | #include <iterator> |
46 | | |
47 | | #define DEBUG_TYPE "aarch64-call-lowering" |
48 | | |
49 | | using namespace llvm; |
50 | | |
51 | | AArch64CallLowering::AArch64CallLowering(const AArch64TargetLowering &TLI) |
52 | 9.10k | : CallLowering(&TLI) {} |
53 | | |
54 | | namespace { |
55 | | struct IncomingArgHandler : public CallLowering::ValueHandler { |
56 | | IncomingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, |
57 | | CCAssignFn *AssignFn) |
58 | 1.08M | : ValueHandler(MIRBuilder, MRI, AssignFn), StackUsed(0) {} |
59 | | |
60 | | Register getStackAddress(uint64_t Size, int64_t Offset, |
61 | 17.8k | MachinePointerInfo &MPO) override { |
62 | 17.8k | auto &MFI = MIRBuilder.getMF().getFrameInfo(); |
63 | 17.8k | int FI = MFI.CreateFixedObject(Size, Offset, true); |
64 | 17.8k | MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); |
65 | 17.8k | Register AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 64)); |
66 | 17.8k | MIRBuilder.buildFrameIndex(AddrReg, FI); |
67 | 17.8k | StackUsed = std::max(StackUsed, Size + Offset); |
68 | 17.8k | return AddrReg; |
69 | 17.8k | } |
70 | | |
71 | | void assignValueToReg(Register ValVReg, Register PhysReg, |
72 | 1.39M | CCValAssign &VA) override { |
73 | 1.39M | markPhysRegUsed(PhysReg); |
74 | 1.39M | switch (VA.getLocInfo()) { |
75 | 1.39M | default: |
76 | 1.36M | MIRBuilder.buildCopy(ValVReg, PhysReg); |
77 | 1.36M | break; |
78 | 1.39M | case CCValAssign::LocInfo::SExt: |
79 | 23.9k | case CCValAssign::LocInfo::ZExt: |
80 | 23.9k | case CCValAssign::LocInfo::AExt: { |
81 | 23.9k | auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); |
82 | 23.9k | MIRBuilder.buildTrunc(ValVReg, Copy); |
83 | 23.9k | break; |
84 | 23.9k | } |
85 | 1.39M | } |
86 | 1.39M | } |
87 | | |
88 | | void assignValueToAddress(Register ValVReg, Register Addr, uint64_t Size, |
89 | 17.8k | MachinePointerInfo &MPO, CCValAssign &VA) override { |
90 | 17.8k | // FIXME: Get alignment |
91 | 17.8k | auto MMO = MIRBuilder.getMF().getMachineMemOperand( |
92 | 17.8k | MPO, MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant, Size, |
93 | 17.8k | 1); |
94 | 17.8k | MIRBuilder.buildLoad(ValVReg, Addr, *MMO); |
95 | 17.8k | } |
96 | | |
97 | | /// How the physical register gets marked varies between formal |
98 | | /// parameters (it's a basic-block live-in), and a call instruction |
99 | | /// (it's an implicit-def of the BL). |
100 | | virtual void markPhysRegUsed(unsigned PhysReg) = 0; |
101 | | |
102 | 1.39M | bool isArgumentHandler() const override { return true; } |
103 | | |
104 | | uint64_t StackUsed; |
105 | | }; |
106 | | |
107 | | struct FormalArgHandler : public IncomingArgHandler { |
108 | | FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, |
109 | | CCAssignFn *AssignFn) |
110 | 235k | : IncomingArgHandler(MIRBuilder, MRI, AssignFn) {} |
111 | | |
112 | 541k | void markPhysRegUsed(unsigned PhysReg) override { |
113 | 541k | MIRBuilder.getMBB().addLiveIn(PhysReg); |
114 | 541k | } |
115 | | }; |
116 | | |
117 | | struct CallReturnHandler : public IncomingArgHandler { |
118 | | CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, |
119 | | MachineInstrBuilder MIB, CCAssignFn *AssignFn) |
120 | 847k | : IncomingArgHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {} |
121 | | |
122 | 848k | void markPhysRegUsed(unsigned PhysReg) override { |
123 | 848k | MIB.addDef(PhysReg, RegState::Implicit); |
124 | 848k | } |
125 | | |
126 | | MachineInstrBuilder MIB; |
127 | | }; |
128 | | |
129 | | struct OutgoingArgHandler : public CallLowering::ValueHandler { |
130 | | OutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, |
131 | | MachineInstrBuilder MIB, CCAssignFn *AssignFn, |
132 | | CCAssignFn *AssignFnVarArg) |
133 | | : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB), |
134 | 1.51M | AssignFnVarArg(AssignFnVarArg), StackSize(0) {} |
135 | | |
136 | | Register getStackAddress(uint64_t Size, int64_t Offset, |
137 | 61.3k | MachinePointerInfo &MPO) override { |
138 | 61.3k | LLT p0 = LLT::pointer(0, 64); |
139 | 61.3k | LLT s64 = LLT::scalar(64); |
140 | 61.3k | Register SPReg = MRI.createGenericVirtualRegister(p0); |
141 | 61.3k | MIRBuilder.buildCopy(SPReg, Register(AArch64::SP)); |
142 | 61.3k | |
143 | 61.3k | Register OffsetReg = MRI.createGenericVirtualRegister(s64); |
144 | 61.3k | MIRBuilder.buildConstant(OffsetReg, Offset); |
145 | 61.3k | |
146 | 61.3k | Register AddrReg = MRI.createGenericVirtualRegister(p0); |
147 | 61.3k | MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); |
148 | 61.3k | |
149 | 61.3k | MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); |
150 | 61.3k | return AddrReg; |
151 | 61.3k | } |
152 | | |
153 | | void assignValueToReg(Register ValVReg, Register PhysReg, |
154 | 3.02M | CCValAssign &VA) override { |
155 | 3.02M | MIB.addUse(PhysReg, RegState::Implicit); |
156 | 3.02M | Register ExtReg = extendRegister(ValVReg, VA); |
157 | 3.02M | MIRBuilder.buildCopy(PhysReg, ExtReg); |
158 | 3.02M | } |
159 | | |
160 | | void assignValueToAddress(Register ValVReg, Register Addr, uint64_t Size, |
161 | 61.3k | MachinePointerInfo &MPO, CCValAssign &VA) override { |
162 | 61.3k | if (VA.getLocInfo() == CCValAssign::LocInfo::AExt) { |
163 | 15.5k | Size = VA.getLocVT().getSizeInBits() / 8; |
164 | 15.5k | ValVReg = MIRBuilder.buildAnyExt(LLT::scalar(Size * 8), ValVReg) |
165 | 15.5k | ->getOperand(0) |
166 | 15.5k | .getReg(); |
167 | 15.5k | } |
168 | 61.3k | auto MMO = MIRBuilder.getMF().getMachineMemOperand( |
169 | 61.3k | MPO, MachineMemOperand::MOStore, Size, 1); |
170 | 61.3k | MIRBuilder.buildStore(ValVReg, Addr, *MMO); |
171 | 61.3k | } |
172 | | |
173 | | bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT, |
174 | | CCValAssign::LocInfo LocInfo, |
175 | | const CallLowering::ArgInfo &Info, |
176 | 3.08M | CCState &State) override { |
177 | 3.08M | bool Res; |
178 | 3.08M | if (Info.IsFixed) |
179 | 3.04M | Res = AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State); |
180 | 42.1k | else |
181 | 42.1k | Res = AssignFnVarArg(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State); |
182 | 3.08M | |
183 | 3.08M | StackSize = State.getNextStackOffset(); |
184 | 3.08M | return Res; |
185 | 3.08M | } |
186 | | |
187 | | MachineInstrBuilder MIB; |
188 | | CCAssignFn *AssignFnVarArg; |
189 | | uint64_t StackSize; |
190 | | }; |
191 | | } // namespace |
192 | | |
193 | | void AArch64CallLowering::splitToValueTypes( |
194 | | const ArgInfo &OrigArg, SmallVectorImpl<ArgInfo> &SplitArgs, |
195 | 4.49M | const DataLayout &DL, MachineRegisterInfo &MRI, CallingConv::ID CallConv) const { |
196 | 4.49M | const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>(); |
197 | 4.49M | LLVMContext &Ctx = OrigArg.Ty->getContext(); |
198 | 4.49M | |
199 | 4.49M | if (OrigArg.Ty->isVoidTy()) |
200 | 0 | return; |
201 | 4.49M | |
202 | 4.49M | SmallVector<EVT, 4> SplitVTs; |
203 | 4.49M | SmallVector<uint64_t, 4> Offsets; |
204 | 4.49M | ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0); |
205 | 4.49M | |
206 | 4.49M | if (SplitVTs.size() == 1) { |
207 | 4.49M | // No splitting to do, but we want to replace the original type (e.g. [1 x |
208 | 4.49M | // double] -> double). |
209 | 4.49M | SplitArgs.emplace_back(OrigArg.Regs[0], SplitVTs[0].getTypeForEVT(Ctx), |
210 | 4.49M | OrigArg.Flags, OrigArg.IsFixed); |
211 | 4.49M | return; |
212 | 4.49M | } |
213 | 1.04k | |
214 | 1.04k | // Create one ArgInfo for each virtual register in the original ArgInfo. |
215 | 1.04k | assert(OrigArg.Regs.size() == SplitVTs.size() && "Regs / types mismatch"); |
216 | 1.04k | |
217 | 1.04k | bool NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters( |
218 | 1.04k | OrigArg.Ty, CallConv, false); |
219 | 3.50k | for (unsigned i = 0, e = SplitVTs.size(); i < e; ++i2.46k ) { |
220 | 2.46k | Type *SplitTy = SplitVTs[i].getTypeForEVT(Ctx); |
221 | 2.46k | SplitArgs.emplace_back(OrigArg.Regs[i], SplitTy, OrigArg.Flags, |
222 | 2.46k | OrigArg.IsFixed); |
223 | 2.46k | if (NeedsRegBlock) |
224 | 1.75k | SplitArgs.back().Flags.setInConsecutiveRegs(); |
225 | 2.46k | } |
226 | 1.04k | |
227 | 1.04k | SplitArgs.back().Flags.setInConsecutiveRegsLast(); |
228 | 1.04k | } |
229 | | |
230 | | bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, |
231 | | const Value *Val, |
232 | | ArrayRef<Register> VRegs, |
233 | 342k | Register SwiftErrorVReg) const { |
234 | 342k | auto MIB = MIRBuilder.buildInstrNoInsert(AArch64::RET_ReallyLR); |
235 | 342k | assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) && |
236 | 342k | "Return value without a vreg"); |
237 | 342k | |
238 | 342k | bool Success = true; |
239 | 342k | if (!VRegs.empty()) { |
240 | 255k | MachineFunction &MF = MIRBuilder.getMF(); |
241 | 255k | const Function &F = MF.getFunction(); |
242 | 255k | |
243 | 255k | MachineRegisterInfo &MRI = MF.getRegInfo(); |
244 | 255k | const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>(); |
245 | 255k | CCAssignFn *AssignFn = TLI.CCAssignFnForReturn(F.getCallingConv()); |
246 | 255k | auto &DL = F.getParent()->getDataLayout(); |
247 | 255k | LLVMContext &Ctx = Val->getType()->getContext(); |
248 | 255k | |
249 | 255k | SmallVector<EVT, 4> SplitEVTs; |
250 | 255k | ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs); |
251 | 255k | assert(VRegs.size() == SplitEVTs.size() && |
252 | 255k | "For each split Type there should be exactly one VReg."); |
253 | 255k | |
254 | 255k | SmallVector<ArgInfo, 8> SplitArgs; |
255 | 255k | CallingConv::ID CC = F.getCallingConv(); |
256 | 255k | |
257 | 511k | for (unsigned i = 0; i < SplitEVTs.size(); ++i255k ) { |
258 | 255k | if (TLI.getNumRegistersForCallingConv(Ctx, CC, SplitEVTs[i]) > 1) { |
259 | 14 | LLVM_DEBUG(dbgs() << "Can't handle extended arg types which need split"); |
260 | 14 | return false; |
261 | 14 | } |
262 | 255k | |
263 | 255k | Register CurVReg = VRegs[i]; |
264 | 255k | ArgInfo CurArgInfo = ArgInfo{CurVReg, SplitEVTs[i].getTypeForEVT(Ctx)}; |
265 | 255k | setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F); |
266 | 255k | |
267 | 255k | // i1 is a special case because SDAG i1 true is naturally zero extended |
268 | 255k | // when widened using ANYEXT. We need to do it explicitly here. |
269 | 255k | if (MRI.getType(CurVReg).getSizeInBits() == 1) { |
270 | 7.60k | CurVReg = MIRBuilder.buildZExt(LLT::scalar(8), CurVReg).getReg(0); |
271 | 248k | } else { |
272 | 248k | // Some types will need extending as specified by the CC. |
273 | 248k | MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CC, SplitEVTs[i]); |
274 | 248k | if (EVT(NewVT) != SplitEVTs[i]) { |
275 | 123 | unsigned ExtendOp = TargetOpcode::G_ANYEXT; |
276 | 123 | if (F.getAttributes().hasAttribute(AttributeList::ReturnIndex, |
277 | 123 | Attribute::SExt)) |
278 | 62 | ExtendOp = TargetOpcode::G_SEXT; |
279 | 61 | else if (F.getAttributes().hasAttribute(AttributeList::ReturnIndex, |
280 | 61 | Attribute::ZExt)) |
281 | 50 | ExtendOp = TargetOpcode::G_ZEXT; |
282 | 123 | |
283 | 123 | LLT NewLLT(NewVT); |
284 | 123 | LLT OldLLT(MVT::getVT(CurArgInfo.Ty)); |
285 | 123 | CurArgInfo.Ty = EVT(NewVT).getTypeForEVT(Ctx); |
286 | 123 | // Instead of an extend, we might have a vector type which needs |
287 | 123 | // padding with more elements, e.g. <2 x half> -> <4 x half>. |
288 | 123 | if (NewVT.isVector()) { |
289 | 4 | if (OldLLT.isVector()) { |
290 | 3 | if (NewLLT.getNumElements() > OldLLT.getNumElements()) { |
291 | 1 | // We don't handle VA types which are not exactly twice the |
292 | 1 | // size, but can easily be done in future. |
293 | 1 | if (NewLLT.getNumElements() != OldLLT.getNumElements() * 2) { |
294 | 0 | LLVM_DEBUG(dbgs() << "Outgoing vector ret has too many elts"); |
295 | 0 | return false; |
296 | 0 | } |
297 | 1 | auto Undef = MIRBuilder.buildUndef({OldLLT}); |
298 | 1 | CurVReg = |
299 | 1 | MIRBuilder.buildMerge({NewLLT}, {CurVReg, Undef.getReg(0)}) |
300 | 1 | .getReg(0); |
301 | 2 | } else { |
302 | 2 | // Just do a vector extend. |
303 | 2 | CurVReg = MIRBuilder.buildInstr(ExtendOp, {NewLLT}, {CurVReg}) |
304 | 2 | .getReg(0); |
305 | 2 | } |
306 | 3 | } else if (1 NewLLT.getNumElements() == 21 ) { |
307 | 1 | // We need to pad a <1 x S> type to <2 x S>. Since we don't have |
308 | 1 | // <1 x S> vector types in GISel we use a build_vector instead |
309 | 1 | // of a vector merge/concat. |
310 | 1 | auto Undef = MIRBuilder.buildUndef({OldLLT}); |
311 | 1 | CurVReg = |
312 | 1 | MIRBuilder |
313 | 1 | .buildBuildVector({NewLLT}, {CurVReg, Undef.getReg(0)}) |
314 | 1 | .getReg(0); |
315 | 1 | } else { |
316 | 0 | LLVM_DEBUG(dbgs() << "Could not handle ret ty"); |
317 | 0 | return false; |
318 | 0 | } |
319 | 119 | } else { |
320 | 119 | // A scalar extend. |
321 | 119 | CurVReg = |
322 | 119 | MIRBuilder.buildInstr(ExtendOp, {NewLLT}, {CurVReg}).getReg(0); |
323 | 119 | } |
324 | 123 | } |
325 | 248k | } |
326 | 255k | if (CurVReg != CurArgInfo.Regs[0]) { |
327 | 7.73k | CurArgInfo.Regs[0] = CurVReg; |
328 | 7.73k | // Reset the arg flags after modifying CurVReg. |
329 | 7.73k | setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F); |
330 | 7.73k | } |
331 | 255k | splitToValueTypes(CurArgInfo, SplitArgs, DL, MRI, CC); |
332 | 255k | } |
333 | 255k | |
334 | 255k | OutgoingArgHandler Handler(MIRBuilder, MRI, MIB, AssignFn, AssignFn); |
335 | 255k | Success = handleAssignments(MIRBuilder, SplitArgs, Handler); |
336 | 255k | } |
337 | 342k | |
338 | 342k | if (342k SwiftErrorVReg342k ) { |
339 | 11 | MIB.addUse(AArch64::X21, RegState::Implicit); |
340 | 11 | MIRBuilder.buildCopy(AArch64::X21, SwiftErrorVReg); |
341 | 11 | } |
342 | 342k | |
343 | 342k | MIRBuilder.insertInstr(MIB); |
344 | 342k | return Success; |
345 | 342k | } |
346 | | |
347 | | bool AArch64CallLowering::lowerFormalArguments( |
348 | | MachineIRBuilder &MIRBuilder, const Function &F, |
349 | 235k | ArrayRef<ArrayRef<Register>> VRegs) const { |
350 | 235k | MachineFunction &MF = MIRBuilder.getMF(); |
351 | 235k | MachineBasicBlock &MBB = MIRBuilder.getMBB(); |
352 | 235k | MachineRegisterInfo &MRI = MF.getRegInfo(); |
353 | 235k | auto &DL = F.getParent()->getDataLayout(); |
354 | 235k | |
355 | 235k | SmallVector<ArgInfo, 8> SplitArgs; |
356 | 235k | unsigned i = 0; |
357 | 559k | for (auto &Arg : F.args()) { |
358 | 559k | if (DL.getTypeStoreSize(Arg.getType()) == 0) |
359 | 2 | continue; |
360 | 559k | |
361 | 559k | ArgInfo OrigArg{VRegs[i], Arg.getType()}; |
362 | 559k | setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F); |
363 | 559k | |
364 | 559k | splitToValueTypes(OrigArg, SplitArgs, DL, MRI, F.getCallingConv()); |
365 | 559k | ++i; |
366 | 559k | } |
367 | 235k | |
368 | 235k | if (!MBB.empty()) |
369 | 7 | MIRBuilder.setInstr(*MBB.begin()); |
370 | 235k | |
371 | 235k | const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>(); |
372 | 235k | CCAssignFn *AssignFn = |
373 | 235k | TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false); |
374 | 235k | |
375 | 235k | FormalArgHandler Handler(MIRBuilder, MRI, AssignFn); |
376 | 235k | if (!handleAssignments(MIRBuilder, SplitArgs, Handler)) |
377 | 7 | return false; |
378 | 235k | |
379 | 235k | if (F.isVarArg()) { |
380 | 62 | if (!MF.getSubtarget<AArch64Subtarget>().isTargetDarwin()) { |
381 | 0 | // FIXME: we need to reimplement saveVarArgsRegisters from |
382 | 0 | // AArch64ISelLowering. |
383 | 0 | return false; |
384 | 0 | } |
385 | 62 | |
386 | 62 | // We currently pass all varargs at 8-byte alignment. |
387 | 62 | uint64_t StackOffset = alignTo(Handler.StackUsed, 8); |
388 | 62 | |
389 | 62 | auto &MFI = MIRBuilder.getMF().getFrameInfo(); |
390 | 62 | AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>(); |
391 | 62 | FuncInfo->setVarArgsStackIndex(MFI.CreateFixedObject(4, StackOffset, true)); |
392 | 62 | } |
393 | 235k | |
394 | 235k | auto &Subtarget = MF.getSubtarget<AArch64Subtarget>(); |
395 | 235k | if (Subtarget.hasCustomCallingConv()) |
396 | 10 | Subtarget.getRegisterInfo()->UpdateCustomCalleeSavedRegs(MF); |
397 | 235k | |
398 | 235k | // Move back to the end of the basic block. |
399 | 235k | MIRBuilder.setMBB(MBB); |
400 | 235k | |
401 | 235k | return true; |
402 | 235k | } |
403 | | |
404 | | bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, |
405 | | CallingConv::ID CallConv, |
406 | | const MachineOperand &Callee, |
407 | | const ArgInfo &OrigRet, |
408 | | ArrayRef<ArgInfo> OrigArgs, |
409 | 1.25M | Register SwiftErrorVReg) const { |
410 | 1.25M | MachineFunction &MF = MIRBuilder.getMF(); |
411 | 1.25M | const Function &F = MF.getFunction(); |
412 | 1.25M | MachineRegisterInfo &MRI = MF.getRegInfo(); |
413 | 1.25M | auto &DL = F.getParent()->getDataLayout(); |
414 | 1.25M | |
415 | 1.25M | SmallVector<ArgInfo, 8> SplitArgs; |
416 | 2.83M | for (auto &OrigArg : OrigArgs) { |
417 | 2.83M | splitToValueTypes(OrigArg, SplitArgs, DL, MRI, CallConv); |
418 | 2.83M | // AAPCS requires that we zero-extend i1 to 8 bits by the caller. |
419 | 2.83M | if (OrigArg.Ty->isIntegerTy(1)) |
420 | 1.02k | SplitArgs.back().Flags.setZExt(); |
421 | 2.83M | } |
422 | 1.25M | |
423 | 1.25M | // Find out which ABI gets to decide where things go. |
424 | 1.25M | const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>(); |
425 | 1.25M | CCAssignFn *AssignFnFixed = |
426 | 1.25M | TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/false); |
427 | 1.25M | CCAssignFn *AssignFnVarArg = |
428 | 1.25M | TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/true); |
429 | 1.25M | |
430 | 1.25M | auto CallSeqStart = MIRBuilder.buildInstr(AArch64::ADJCALLSTACKDOWN); |
431 | 1.25M | |
432 | 1.25M | // Create a temporarily-floating call instruction so we can add the implicit |
433 | 1.25M | // uses of arg registers. |
434 | 1.25M | auto MIB = MIRBuilder.buildInstrNoInsert(Callee.isReg() ? AArch64::BLR67.3k |
435 | 1.25M | : AArch64::BL1.18M ); |
436 | 1.25M | MIB.add(Callee); |
437 | 1.25M | |
438 | 1.25M | // Tell the call which registers are clobbered. |
439 | 1.25M | auto TRI = MF.getSubtarget<AArch64Subtarget>().getRegisterInfo(); |
440 | 1.25M | const uint32_t *Mask = TRI->getCallPreservedMask(MF, F.getCallingConv()); |
441 | 1.25M | if (MF.getSubtarget<AArch64Subtarget>().hasCustomCallingConv()) |
442 | 1 | TRI->UpdateCustomCallPreservedMask(MF, &Mask); |
443 | 1.25M | MIB.addRegMask(Mask); |
444 | 1.25M | |
445 | 1.25M | if (TRI->isAnyArgRegReserved(MF)) |
446 | 2 | TRI->emitReservedArgRegCallError(MF); |
447 | 1.25M | |
448 | 1.25M | // Do the actual argument marshalling. |
449 | 1.25M | SmallVector<unsigned, 8> PhysRegs; |
450 | 1.25M | OutgoingArgHandler Handler(MIRBuilder, MRI, MIB, AssignFnFixed, |
451 | 1.25M | AssignFnVarArg); |
452 | 1.25M | if (!handleAssignments(MIRBuilder, SplitArgs, Handler)) |
453 | 2 | return false; |
454 | 1.25M | |
455 | 1.25M | // Now we can add the actual call instruction to the correct basic block. |
456 | 1.25M | MIRBuilder.insertInstr(MIB); |
457 | 1.25M | |
458 | 1.25M | // If Callee is a reg, since it is used by a target specific |
459 | 1.25M | // instruction, it must have a register class matching the |
460 | 1.25M | // constraint of that instruction. |
461 | 1.25M | if (Callee.isReg()) |
462 | 67.3k | MIB->getOperand(0).setReg(constrainOperandRegClass( |
463 | 67.3k | MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(), |
464 | 67.3k | *MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), Callee, 0)); |
465 | 1.25M | |
466 | 1.25M | // Finally we can copy the returned value back into its virtual-register. In |
467 | 1.25M | // symmetry with the arugments, the physical register must be an |
468 | 1.25M | // implicit-define of the call instruction. |
469 | 1.25M | CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn(F.getCallingConv()); |
470 | 1.25M | if (!OrigRet.Ty->isVoidTy()) { |
471 | 847k | SplitArgs.clear(); |
472 | 847k | |
473 | 847k | splitToValueTypes(OrigRet, SplitArgs, DL, MRI, F.getCallingConv()); |
474 | 847k | |
475 | 847k | CallReturnHandler Handler(MIRBuilder, MRI, MIB, RetAssignFn); |
476 | 847k | if (!handleAssignments(MIRBuilder, SplitArgs, Handler)) |
477 | 0 | return false; |
478 | 1.25M | } |
479 | 1.25M | |
480 | 1.25M | if (SwiftErrorVReg) { |
481 | 12 | MIB.addDef(AArch64::X21, RegState::Implicit); |
482 | 12 | MIRBuilder.buildCopy(SwiftErrorVReg, Register(AArch64::X21)); |
483 | 12 | } |
484 | 1.25M | |
485 | 1.25M | CallSeqStart.addImm(Handler.StackSize).addImm(0); |
486 | 1.25M | MIRBuilder.buildInstr(AArch64::ADJCALLSTACKUP) |
487 | 1.25M | .addImm(Handler.StackSize) |
488 | 1.25M | .addImm(0); |
489 | 1.25M | |
490 | 1.25M | return true; |
491 | 1.25M | } |