1 //===- llvm/lib/Target/ARM/ARMCallLowering.cpp - Call lowering ------------===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements the lowering of LLVM calls to machine code calls for
13 //===----------------------------------------------------------------------===//
15 #include "ARMCallLowering.h"
16 #include "ARMBaseInstrInfo.h"
17 #include "ARMISelLowering.h"
18 #include "ARMSubtarget.h"
19 #include "Utils/ARMBaseInfo.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/Attributes.h"
37 #include "llvm/IR/DataLayout.h"
38 #include "llvm/IR/DerivedTypes.h"
39 #include "llvm/IR/Function.h"
40 #include "llvm/IR/Type.h"
41 #include "llvm/IR/Value.h"
42 #include "llvm/Support/Casting.h"
43 #include "llvm/Support/LowLevelTypeImpl.h"
44 #include "llvm/Support/MachineValueType.h"
52 ARMCallLowering::ARMCallLowering(const ARMTargetLowering
&TLI
)
53 : CallLowering(&TLI
) {}
55 static bool isSupportedType(const DataLayout
&DL
, const ARMTargetLowering
&TLI
,
58 return isSupportedType(DL
, TLI
, T
->getArrayElementType());
60 if (T
->isStructTy()) {
61 // For now we only allow homogeneous structs that we can manipulate with
62 // G_MERGE_VALUES and G_UNMERGE_VALUES
63 auto StructT
= cast
<StructType
>(T
);
64 for (unsigned i
= 1, e
= StructT
->getNumElements(); i
!= e
; ++i
)
65 if (StructT
->getElementType(i
) != StructT
->getElementType(0))
67 return isSupportedType(DL
, TLI
, StructT
->getElementType(0));
70 EVT VT
= TLI
.getValueType(DL
, T
, true);
71 if (!VT
.isSimple() || VT
.isVector() ||
72 !(VT
.isInteger() || VT
.isFloatingPoint()))
75 unsigned VTSize
= VT
.getSimpleVT().getSizeInBits();
78 // FIXME: Support i64 too
79 return VT
.isFloatingPoint();
81 return VTSize
== 1 || VTSize
== 8 || VTSize
== 16 || VTSize
== 32;
86 /// Helper class for values going out through an ABI boundary (used for handling
87 /// function return values and call parameters).
88 struct ARMOutgoingValueHandler
: public CallLowering::OutgoingValueHandler
{
89 ARMOutgoingValueHandler(MachineIRBuilder
&MIRBuilder
,
90 MachineRegisterInfo
&MRI
, MachineInstrBuilder
&MIB
)
91 : OutgoingValueHandler(MIRBuilder
, MRI
), MIB(MIB
) {}
93 Register
getStackAddress(uint64_t Size
, int64_t Offset
,
94 MachinePointerInfo
&MPO
,
95 ISD::ArgFlagsTy Flags
) override
{
96 assert((Size
== 1 || Size
== 2 || Size
== 4 || Size
== 8) &&
99 LLT p0
= LLT::pointer(0, 32);
100 LLT s32
= LLT::scalar(32);
101 auto SPReg
= MIRBuilder
.buildCopy(p0
, Register(ARM::SP
));
103 auto OffsetReg
= MIRBuilder
.buildConstant(s32
, Offset
);
105 auto AddrReg
= MIRBuilder
.buildPtrAdd(p0
, SPReg
, OffsetReg
);
107 MPO
= MachinePointerInfo::getStack(MIRBuilder
.getMF(), Offset
);
108 return AddrReg
.getReg(0);
111 void assignValueToReg(Register ValVReg
, Register PhysReg
,
112 CCValAssign
&VA
) override
{
113 assert(VA
.isRegLoc() && "Value shouldn't be assigned to reg");
114 assert(VA
.getLocReg() == PhysReg
&& "Assigning to the wrong reg?");
116 assert(VA
.getValVT().getSizeInBits() <= 64 && "Unsupported value size");
117 assert(VA
.getLocVT().getSizeInBits() <= 64 && "Unsupported location size");
119 Register ExtReg
= extendRegister(ValVReg
, VA
);
120 MIRBuilder
.buildCopy(PhysReg
, ExtReg
);
121 MIB
.addUse(PhysReg
, RegState::Implicit
);
124 void assignValueToAddress(Register ValVReg
, Register Addr
, LLT MemTy
,
125 MachinePointerInfo
&MPO
, CCValAssign
&VA
) override
{
126 Register ExtReg
= extendRegister(ValVReg
, VA
);
127 auto MMO
= MIRBuilder
.getMF().getMachineMemOperand(
128 MPO
, MachineMemOperand::MOStore
, MemTy
, Align(1));
129 MIRBuilder
.buildStore(ExtReg
, Addr
, *MMO
);
132 unsigned assignCustomValue(CallLowering::ArgInfo
&Arg
,
133 ArrayRef
<CCValAssign
> VAs
) override
{
134 assert(Arg
.Regs
.size() == 1 && "Can't handle multple regs yet");
136 CCValAssign VA
= VAs
[0];
137 assert(VA
.needsCustom() && "Value doesn't need custom handling");
139 // Custom lowering for other types, such as f16, is currently not supported
140 if (VA
.getValVT() != MVT::f64
)
143 CCValAssign NextVA
= VAs
[1];
144 assert(NextVA
.needsCustom() && "Value doesn't need custom handling");
145 assert(NextVA
.getValVT() == MVT::f64
&& "Unsupported type");
147 assert(VA
.getValNo() == NextVA
.getValNo() &&
148 "Values belong to different arguments");
150 assert(VA
.isRegLoc() && "Value should be in reg");
151 assert(NextVA
.isRegLoc() && "Value should be in reg");
153 Register NewRegs
[] = {MRI
.createGenericVirtualRegister(LLT::scalar(32)),
154 MRI
.createGenericVirtualRegister(LLT::scalar(32))};
155 MIRBuilder
.buildUnmerge(NewRegs
, Arg
.Regs
[0]);
157 bool IsLittle
= MIRBuilder
.getMF().getSubtarget
<ARMSubtarget
>().isLittle();
159 std::swap(NewRegs
[0], NewRegs
[1]);
161 assignValueToReg(NewRegs
[0], VA
.getLocReg(), VA
);
162 assignValueToReg(NewRegs
[1], NextVA
.getLocReg(), NextVA
);
167 MachineInstrBuilder MIB
;
170 } // end anonymous namespace
172 /// Lower the return value for the already existing \p Ret. This assumes that
173 /// \p MIRBuilder's insertion point is correct.
174 bool ARMCallLowering::lowerReturnVal(MachineIRBuilder
&MIRBuilder
,
175 const Value
*Val
, ArrayRef
<Register
> VRegs
,
176 MachineInstrBuilder
&Ret
) const {
178 // Nothing to do here.
181 auto &MF
= MIRBuilder
.getMF();
182 const auto &F
= MF
.getFunction();
184 const auto &DL
= MF
.getDataLayout();
185 auto &TLI
= *getTLI
<ARMTargetLowering
>();
186 if (!isSupportedType(DL
, TLI
, Val
->getType()))
189 ArgInfo
OrigRetInfo(VRegs
, Val
->getType(), 0);
190 setArgFlags(OrigRetInfo
, AttributeList::ReturnIndex
, DL
, F
);
192 SmallVector
<ArgInfo
, 4> SplitRetInfos
;
193 splitToValueTypes(OrigRetInfo
, SplitRetInfos
, DL
, F
.getCallingConv());
195 CCAssignFn
*AssignFn
=
196 TLI
.CCAssignFnForReturn(F
.getCallingConv(), F
.isVarArg());
198 OutgoingValueAssigner
RetAssigner(AssignFn
);
199 ARMOutgoingValueHandler
RetHandler(MIRBuilder
, MF
.getRegInfo(), Ret
);
200 return determineAndHandleAssignments(RetHandler
, RetAssigner
, SplitRetInfos
,
201 MIRBuilder
, F
.getCallingConv(),
205 bool ARMCallLowering::lowerReturn(MachineIRBuilder
&MIRBuilder
,
206 const Value
*Val
, ArrayRef
<Register
> VRegs
,
207 FunctionLoweringInfo
&FLI
) const {
208 assert(!Val
== VRegs
.empty() && "Return value without a vreg");
210 auto const &ST
= MIRBuilder
.getMF().getSubtarget
<ARMSubtarget
>();
211 unsigned Opcode
= ST
.getReturnOpcode();
212 auto Ret
= MIRBuilder
.buildInstrNoInsert(Opcode
).add(predOps(ARMCC::AL
));
214 if (!lowerReturnVal(MIRBuilder
, Val
, VRegs
, Ret
))
217 MIRBuilder
.insertInstr(Ret
);
223 /// Helper class for values coming in through an ABI boundary (used for handling
224 /// formal arguments and call return values).
225 struct ARMIncomingValueHandler
: public CallLowering::IncomingValueHandler
{
226 ARMIncomingValueHandler(MachineIRBuilder
&MIRBuilder
,
227 MachineRegisterInfo
&MRI
)
228 : IncomingValueHandler(MIRBuilder
, MRI
) {}
230 Register
getStackAddress(uint64_t Size
, int64_t Offset
,
231 MachinePointerInfo
&MPO
,
232 ISD::ArgFlagsTy Flags
) override
{
233 assert((Size
== 1 || Size
== 2 || Size
== 4 || Size
== 8) &&
236 auto &MFI
= MIRBuilder
.getMF().getFrameInfo();
238 // Byval is assumed to be writable memory, but other stack passed arguments
240 const bool IsImmutable
= !Flags
.isByVal();
242 int FI
= MFI
.CreateFixedObject(Size
, Offset
, IsImmutable
);
243 MPO
= MachinePointerInfo::getFixedStack(MIRBuilder
.getMF(), FI
);
245 return MIRBuilder
.buildFrameIndex(LLT::pointer(MPO
.getAddrSpace(), 32), FI
)
249 void assignValueToAddress(Register ValVReg
, Register Addr
, LLT MemTy
,
250 MachinePointerInfo
&MPO
, CCValAssign
&VA
) override
{
251 if (VA
.getLocInfo() == CCValAssign::SExt
||
252 VA
.getLocInfo() == CCValAssign::ZExt
) {
253 // If the value is zero- or sign-extended, its size becomes 4 bytes, so
254 // that's what we should load.
255 MemTy
= LLT::scalar(32);
256 assert(MRI
.getType(ValVReg
).isScalar() && "Only scalars supported atm");
258 auto LoadVReg
= buildLoad(LLT::scalar(32), Addr
, MemTy
, MPO
);
259 MIRBuilder
.buildTrunc(ValVReg
, LoadVReg
);
261 // If the value is not extended, a simple load will suffice.
262 buildLoad(ValVReg
, Addr
, MemTy
, MPO
);
266 MachineInstrBuilder
buildLoad(const DstOp
&Res
, Register Addr
, LLT MemTy
,
267 MachinePointerInfo
&MPO
) {
268 MachineFunction
&MF
= MIRBuilder
.getMF();
270 auto MMO
= MF
.getMachineMemOperand(MPO
, MachineMemOperand::MOLoad
, MemTy
,
271 inferAlignFromPtrInfo(MF
, MPO
));
272 return MIRBuilder
.buildLoad(Res
, Addr
, *MMO
);
275 void assignValueToReg(Register ValVReg
, Register PhysReg
,
276 CCValAssign
&VA
) override
{
277 assert(VA
.isRegLoc() && "Value shouldn't be assigned to reg");
278 assert(VA
.getLocReg() == PhysReg
&& "Assigning to the wrong reg?");
280 uint64_t ValSize
= VA
.getValVT().getFixedSizeInBits();
281 uint64_t LocSize
= VA
.getLocVT().getFixedSizeInBits();
283 assert(ValSize
<= 64 && "Unsupported value size");
284 assert(LocSize
<= 64 && "Unsupported location size");
286 markPhysRegUsed(PhysReg
);
287 if (ValSize
== LocSize
) {
288 MIRBuilder
.buildCopy(ValVReg
, PhysReg
);
290 assert(ValSize
< LocSize
&& "Extensions not supported");
292 // We cannot create a truncating copy, nor a trunc of a physical register.
293 // Therefore, we need to copy the content of the physical register into a
294 // virtual one and then truncate that.
295 auto PhysRegToVReg
= MIRBuilder
.buildCopy(LLT::scalar(LocSize
), PhysReg
);
296 MIRBuilder
.buildTrunc(ValVReg
, PhysRegToVReg
);
300 unsigned assignCustomValue(ARMCallLowering::ArgInfo
&Arg
,
301 ArrayRef
<CCValAssign
> VAs
) override
{
302 assert(Arg
.Regs
.size() == 1 && "Can't handle multple regs yet");
304 CCValAssign VA
= VAs
[0];
305 assert(VA
.needsCustom() && "Value doesn't need custom handling");
307 // Custom lowering for other types, such as f16, is currently not supported
308 if (VA
.getValVT() != MVT::f64
)
311 CCValAssign NextVA
= VAs
[1];
312 assert(NextVA
.needsCustom() && "Value doesn't need custom handling");
313 assert(NextVA
.getValVT() == MVT::f64
&& "Unsupported type");
315 assert(VA
.getValNo() == NextVA
.getValNo() &&
316 "Values belong to different arguments");
318 assert(VA
.isRegLoc() && "Value should be in reg");
319 assert(NextVA
.isRegLoc() && "Value should be in reg");
321 Register NewRegs
[] = {MRI
.createGenericVirtualRegister(LLT::scalar(32)),
322 MRI
.createGenericVirtualRegister(LLT::scalar(32))};
324 assignValueToReg(NewRegs
[0], VA
.getLocReg(), VA
);
325 assignValueToReg(NewRegs
[1], NextVA
.getLocReg(), NextVA
);
327 bool IsLittle
= MIRBuilder
.getMF().getSubtarget
<ARMSubtarget
>().isLittle();
329 std::swap(NewRegs
[0], NewRegs
[1]);
331 MIRBuilder
.buildMerge(Arg
.Regs
[0], NewRegs
);
336 /// Marking a physical register as used is different between formal
337 /// parameters, where it's a basic block live-in, and call returns, where it's
338 /// an implicit-def of the call instruction.
339 virtual void markPhysRegUsed(unsigned PhysReg
) = 0;
342 struct FormalArgHandler
: public ARMIncomingValueHandler
{
343 FormalArgHandler(MachineIRBuilder
&MIRBuilder
, MachineRegisterInfo
&MRI
)
344 : ARMIncomingValueHandler(MIRBuilder
, MRI
) {}
346 void markPhysRegUsed(unsigned PhysReg
) override
{
347 MIRBuilder
.getMRI()->addLiveIn(PhysReg
);
348 MIRBuilder
.getMBB().addLiveIn(PhysReg
);
352 } // end anonymous namespace
354 bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder
&MIRBuilder
,
356 ArrayRef
<ArrayRef
<Register
>> VRegs
,
357 FunctionLoweringInfo
&FLI
) const {
358 auto &TLI
= *getTLI
<ARMTargetLowering
>();
359 auto Subtarget
= TLI
.getSubtarget();
361 if (Subtarget
->isThumb1Only())
364 // Quick exit if there aren't any args
371 auto &MF
= MIRBuilder
.getMF();
372 auto &MBB
= MIRBuilder
.getMBB();
373 const auto &DL
= MF
.getDataLayout();
375 for (auto &Arg
: F
.args()) {
376 if (!isSupportedType(DL
, TLI
, Arg
.getType()))
378 if (Arg
.hasPassPointeeByValueCopyAttr())
382 CCAssignFn
*AssignFn
=
383 TLI
.CCAssignFnForCall(F
.getCallingConv(), F
.isVarArg());
385 OutgoingValueAssigner
ArgAssigner(AssignFn
);
386 FormalArgHandler
ArgHandler(MIRBuilder
, MIRBuilder
.getMF().getRegInfo());
388 SmallVector
<ArgInfo
, 8> SplitArgInfos
;
390 for (auto &Arg
: F
.args()) {
391 ArgInfo
OrigArgInfo(VRegs
[Idx
], Arg
.getType(), Idx
);
393 setArgFlags(OrigArgInfo
, Idx
+ AttributeList::FirstArgIndex
, DL
, F
);
394 splitToValueTypes(OrigArgInfo
, SplitArgInfos
, DL
, F
.getCallingConv());
400 MIRBuilder
.setInstr(*MBB
.begin());
402 if (!determineAndHandleAssignments(ArgHandler
, ArgAssigner
, SplitArgInfos
,
403 MIRBuilder
, F
.getCallingConv(),
407 // Move back to the end of the basic block.
408 MIRBuilder
.setMBB(MBB
);
414 struct CallReturnHandler
: public ARMIncomingValueHandler
{
415 CallReturnHandler(MachineIRBuilder
&MIRBuilder
, MachineRegisterInfo
&MRI
,
416 MachineInstrBuilder MIB
)
417 : ARMIncomingValueHandler(MIRBuilder
, MRI
), MIB(MIB
) {}
419 void markPhysRegUsed(unsigned PhysReg
) override
{
420 MIB
.addDef(PhysReg
, RegState::Implicit
);
423 MachineInstrBuilder MIB
;
426 // FIXME: This should move to the ARMSubtarget when it supports all the opcodes.
427 unsigned getCallOpcode(const MachineFunction
&MF
, const ARMSubtarget
&STI
,
430 return STI
.isThumb() ? ARM::tBL
: ARM::BL
;
433 return gettBLXrOpcode(MF
);
436 return getBLXOpcode(MF
);
441 return ARM::BMOVPCRX_CALL
;
443 } // end anonymous namespace
445 bool ARMCallLowering::lowerCall(MachineIRBuilder
&MIRBuilder
, CallLoweringInfo
&Info
) const {
446 MachineFunction
&MF
= MIRBuilder
.getMF();
447 const auto &TLI
= *getTLI
<ARMTargetLowering
>();
448 const auto &DL
= MF
.getDataLayout();
449 const auto &STI
= MF
.getSubtarget
<ARMSubtarget
>();
450 const TargetRegisterInfo
*TRI
= STI
.getRegisterInfo();
451 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
453 if (STI
.genLongCalls())
456 if (STI
.isThumb1Only())
459 auto CallSeqStart
= MIRBuilder
.buildInstr(ARM::ADJCALLSTACKDOWN
);
461 // Create the call instruction so we can add the implicit uses of arg
462 // registers, but don't insert it yet.
463 bool IsDirect
= !Info
.Callee
.isReg();
464 auto CallOpcode
= getCallOpcode(MF
, STI
, IsDirect
);
465 auto MIB
= MIRBuilder
.buildInstrNoInsert(CallOpcode
);
467 bool IsThumb
= STI
.isThumb();
469 MIB
.add(predOps(ARMCC::AL
));
471 MIB
.add(Info
.Callee
);
473 auto CalleeReg
= Info
.Callee
.getReg();
474 if (CalleeReg
&& !Register::isPhysicalRegister(CalleeReg
)) {
475 unsigned CalleeIdx
= IsThumb
? 2 : 0;
476 MIB
->getOperand(CalleeIdx
).setReg(constrainOperandRegClass(
477 MF
, *TRI
, MRI
, *STI
.getInstrInfo(), *STI
.getRegBankInfo(),
478 *MIB
.getInstr(), MIB
->getDesc(), Info
.Callee
, CalleeIdx
));
482 MIB
.addRegMask(TRI
->getCallPreservedMask(MF
, Info
.CallConv
));
484 SmallVector
<ArgInfo
, 8> ArgInfos
;
485 for (auto Arg
: Info
.OrigArgs
) {
486 if (!isSupportedType(DL
, TLI
, Arg
.Ty
))
489 if (Arg
.Flags
[0].isByVal())
492 splitToValueTypes(Arg
, ArgInfos
, DL
, Info
.CallConv
);
495 auto ArgAssignFn
= TLI
.CCAssignFnForCall(Info
.CallConv
, Info
.IsVarArg
);
496 OutgoingValueAssigner
ArgAssigner(ArgAssignFn
);
497 ARMOutgoingValueHandler
ArgHandler(MIRBuilder
, MRI
, MIB
);
498 if (!determineAndHandleAssignments(ArgHandler
, ArgAssigner
, ArgInfos
,
499 MIRBuilder
, Info
.CallConv
, Info
.IsVarArg
))
502 // Now we can add the actual call instruction to the correct basic block.
503 MIRBuilder
.insertInstr(MIB
);
505 if (!Info
.OrigRet
.Ty
->isVoidTy()) {
506 if (!isSupportedType(DL
, TLI
, Info
.OrigRet
.Ty
))
510 splitToValueTypes(Info
.OrigRet
, ArgInfos
, DL
, Info
.CallConv
);
511 auto RetAssignFn
= TLI
.CCAssignFnForReturn(Info
.CallConv
, Info
.IsVarArg
);
512 OutgoingValueAssigner
Assigner(RetAssignFn
);
513 CallReturnHandler
RetHandler(MIRBuilder
, MRI
, MIB
);
514 if (!determineAndHandleAssignments(RetHandler
, Assigner
, ArgInfos
,
515 MIRBuilder
, Info
.CallConv
,
520 // We now know the size of the stack - update the ADJCALLSTACKDOWN
522 CallSeqStart
.addImm(ArgAssigner
.StackOffset
)
524 .add(predOps(ARMCC::AL
));
526 MIRBuilder
.buildInstr(ARM::ADJCALLSTACKUP
)
527 .addImm(ArgAssigner
.StackOffset
)
529 .add(predOps(ARMCC::AL
));