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/LowLevelTypeUtils.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/CodeGenTypes/LowLevelType.h"
37 #include "llvm/CodeGenTypes/MachineValueType.h"
38 #include "llvm/IR/Attributes.h"
39 #include "llvm/IR/DataLayout.h"
40 #include "llvm/IR/DerivedTypes.h"
41 #include "llvm/IR/Function.h"
42 #include "llvm/IR/Type.h"
43 #include "llvm/IR/Value.h"
44 #include "llvm/Support/Casting.h"
53 // Whether Big-endian GISel is enabled, defaults to off, can be enabled for
56 EnableGISelBigEndian("enable-arm-gisel-bigendian", cl::Hidden
,
58 cl::desc("Enable Global-ISel Big Endian Lowering"));
60 ARMCallLowering::ARMCallLowering(const ARMTargetLowering
&TLI
)
61 : CallLowering(&TLI
) {}
63 static bool isSupportedType(const DataLayout
&DL
, const ARMTargetLowering
&TLI
,
66 return isSupportedType(DL
, TLI
, T
->getArrayElementType());
68 if (T
->isStructTy()) {
69 // For now we only allow homogeneous structs that we can manipulate with
70 // G_MERGE_VALUES and G_UNMERGE_VALUES
71 auto StructT
= cast
<StructType
>(T
);
72 for (unsigned i
= 1, e
= StructT
->getNumElements(); i
!= e
; ++i
)
73 if (StructT
->getElementType(i
) != StructT
->getElementType(0))
75 return isSupportedType(DL
, TLI
, StructT
->getElementType(0));
78 EVT VT
= TLI
.getValueType(DL
, T
, true);
79 if (!VT
.isSimple() || VT
.isVector() ||
80 !(VT
.isInteger() || VT
.isFloatingPoint()))
83 unsigned VTSize
= VT
.getSimpleVT().getSizeInBits();
86 // FIXME: Support i64 too
87 return VT
.isFloatingPoint();
89 return VTSize
== 1 || VTSize
== 8 || VTSize
== 16 || VTSize
== 32;
94 /// Helper class for values going out through an ABI boundary (used for handling
95 /// function return values and call parameters).
96 struct ARMOutgoingValueHandler
: public CallLowering::OutgoingValueHandler
{
97 ARMOutgoingValueHandler(MachineIRBuilder
&MIRBuilder
,
98 MachineRegisterInfo
&MRI
, MachineInstrBuilder
&MIB
)
99 : OutgoingValueHandler(MIRBuilder
, MRI
), MIB(MIB
) {}
101 Register
getStackAddress(uint64_t Size
, int64_t Offset
,
102 MachinePointerInfo
&MPO
,
103 ISD::ArgFlagsTy Flags
) override
{
104 assert((Size
== 1 || Size
== 2 || Size
== 4 || Size
== 8) &&
107 LLT p0
= LLT::pointer(0, 32);
108 LLT s32
= LLT::scalar(32);
109 auto SPReg
= MIRBuilder
.buildCopy(p0
, Register(ARM::SP
));
111 auto OffsetReg
= MIRBuilder
.buildConstant(s32
, Offset
);
113 auto AddrReg
= MIRBuilder
.buildPtrAdd(p0
, SPReg
, OffsetReg
);
115 MPO
= MachinePointerInfo::getStack(MIRBuilder
.getMF(), Offset
);
116 return AddrReg
.getReg(0);
119 void assignValueToReg(Register ValVReg
, Register PhysReg
,
120 const CCValAssign
&VA
) override
{
121 assert(VA
.isRegLoc() && "Value shouldn't be assigned to reg");
122 assert(VA
.getLocReg() == PhysReg
&& "Assigning to the wrong reg?");
124 assert(VA
.getValVT().getSizeInBits() <= 64 && "Unsupported value size");
125 assert(VA
.getLocVT().getSizeInBits() <= 64 && "Unsupported location size");
127 Register ExtReg
= extendRegister(ValVReg
, VA
);
128 MIRBuilder
.buildCopy(PhysReg
, ExtReg
);
129 MIB
.addUse(PhysReg
, RegState::Implicit
);
132 void assignValueToAddress(Register ValVReg
, Register Addr
, LLT MemTy
,
133 const MachinePointerInfo
&MPO
,
134 const CCValAssign
&VA
) override
{
135 Register ExtReg
= extendRegister(ValVReg
, VA
);
136 auto MMO
= MIRBuilder
.getMF().getMachineMemOperand(
137 MPO
, MachineMemOperand::MOStore
, MemTy
, Align(1));
138 MIRBuilder
.buildStore(ExtReg
, Addr
, *MMO
);
141 unsigned assignCustomValue(CallLowering::ArgInfo
&Arg
,
142 ArrayRef
<CCValAssign
> VAs
,
143 std::function
<void()> *Thunk
) override
{
144 assert(Arg
.Regs
.size() == 1 && "Can't handle multple regs yet");
146 const CCValAssign
&VA
= VAs
[0];
147 assert(VA
.needsCustom() && "Value doesn't need custom handling");
149 // Custom lowering for other types, such as f16, is currently not supported
150 if (VA
.getValVT() != MVT::f64
)
153 const CCValAssign
&NextVA
= VAs
[1];
154 assert(NextVA
.needsCustom() && "Value doesn't need custom handling");
155 assert(NextVA
.getValVT() == MVT::f64
&& "Unsupported type");
157 assert(VA
.getValNo() == NextVA
.getValNo() &&
158 "Values belong to different arguments");
160 assert(VA
.isRegLoc() && "Value should be in reg");
161 assert(NextVA
.isRegLoc() && "Value should be in reg");
163 Register NewRegs
[] = {MRI
.createGenericVirtualRegister(LLT::scalar(32)),
164 MRI
.createGenericVirtualRegister(LLT::scalar(32))};
165 MIRBuilder
.buildUnmerge(NewRegs
, Arg
.Regs
[0]);
167 bool IsLittle
= MIRBuilder
.getMF().getSubtarget
<ARMSubtarget
>().isLittle();
169 std::swap(NewRegs
[0], NewRegs
[1]);
173 assignValueToReg(NewRegs
[0], VA
.getLocReg(), VA
);
174 assignValueToReg(NewRegs
[1], NextVA
.getLocReg(), NextVA
);
178 assignValueToReg(NewRegs
[0], VA
.getLocReg(), VA
);
179 assignValueToReg(NewRegs
[1], NextVA
.getLocReg(), NextVA
);
183 MachineInstrBuilder MIB
;
186 } // end anonymous namespace
188 /// Lower the return value for the already existing \p Ret. This assumes that
189 /// \p MIRBuilder's insertion point is correct.
190 bool ARMCallLowering::lowerReturnVal(MachineIRBuilder
&MIRBuilder
,
191 const Value
*Val
, ArrayRef
<Register
> VRegs
,
192 MachineInstrBuilder
&Ret
) const {
194 // Nothing to do here.
197 auto &MF
= MIRBuilder
.getMF();
198 const auto &F
= MF
.getFunction();
200 const auto &DL
= MF
.getDataLayout();
201 auto &TLI
= *getTLI
<ARMTargetLowering
>();
202 if (!isSupportedType(DL
, TLI
, Val
->getType()))
205 ArgInfo
OrigRetInfo(VRegs
, Val
->getType(), 0);
206 setArgFlags(OrigRetInfo
, AttributeList::ReturnIndex
, DL
, F
);
208 SmallVector
<ArgInfo
, 4> SplitRetInfos
;
209 splitToValueTypes(OrigRetInfo
, SplitRetInfos
, DL
, F
.getCallingConv());
211 CCAssignFn
*AssignFn
=
212 TLI
.CCAssignFnForReturn(F
.getCallingConv(), F
.isVarArg());
214 OutgoingValueAssigner
RetAssigner(AssignFn
);
215 ARMOutgoingValueHandler
RetHandler(MIRBuilder
, MF
.getRegInfo(), Ret
);
216 return determineAndHandleAssignments(RetHandler
, RetAssigner
, SplitRetInfos
,
217 MIRBuilder
, F
.getCallingConv(),
221 bool ARMCallLowering::lowerReturn(MachineIRBuilder
&MIRBuilder
,
222 const Value
*Val
, ArrayRef
<Register
> VRegs
,
223 FunctionLoweringInfo
&FLI
) const {
224 assert(!Val
== VRegs
.empty() && "Return value without a vreg");
226 auto const &ST
= MIRBuilder
.getMF().getSubtarget
<ARMSubtarget
>();
227 unsigned Opcode
= ST
.getReturnOpcode();
228 auto Ret
= MIRBuilder
.buildInstrNoInsert(Opcode
).add(predOps(ARMCC::AL
));
230 if (!lowerReturnVal(MIRBuilder
, Val
, VRegs
, Ret
))
233 MIRBuilder
.insertInstr(Ret
);
239 /// Helper class for values coming in through an ABI boundary (used for handling
240 /// formal arguments and call return values).
241 struct ARMIncomingValueHandler
: public CallLowering::IncomingValueHandler
{
242 ARMIncomingValueHandler(MachineIRBuilder
&MIRBuilder
,
243 MachineRegisterInfo
&MRI
)
244 : IncomingValueHandler(MIRBuilder
, MRI
) {}
246 Register
getStackAddress(uint64_t Size
, int64_t Offset
,
247 MachinePointerInfo
&MPO
,
248 ISD::ArgFlagsTy Flags
) override
{
249 assert((Size
== 1 || Size
== 2 || Size
== 4 || Size
== 8) &&
252 auto &MFI
= MIRBuilder
.getMF().getFrameInfo();
254 // Byval is assumed to be writable memory, but other stack passed arguments
256 const bool IsImmutable
= !Flags
.isByVal();
258 int FI
= MFI
.CreateFixedObject(Size
, Offset
, IsImmutable
);
259 MPO
= MachinePointerInfo::getFixedStack(MIRBuilder
.getMF(), FI
);
261 return MIRBuilder
.buildFrameIndex(LLT::pointer(MPO
.getAddrSpace(), 32), FI
)
265 void assignValueToAddress(Register ValVReg
, Register Addr
, LLT MemTy
,
266 const MachinePointerInfo
&MPO
,
267 const CCValAssign
&VA
) override
{
268 if (VA
.getLocInfo() == CCValAssign::SExt
||
269 VA
.getLocInfo() == CCValAssign::ZExt
) {
270 // If the value is zero- or sign-extended, its size becomes 4 bytes, so
271 // that's what we should load.
272 MemTy
= LLT::scalar(32);
273 assert(MRI
.getType(ValVReg
).isScalar() && "Only scalars supported atm");
275 auto LoadVReg
= buildLoad(LLT::scalar(32), Addr
, MemTy
, MPO
);
276 MIRBuilder
.buildTrunc(ValVReg
, LoadVReg
);
278 // If the value is not extended, a simple load will suffice.
279 buildLoad(ValVReg
, Addr
, MemTy
, MPO
);
283 MachineInstrBuilder
buildLoad(const DstOp
&Res
, Register Addr
, LLT MemTy
,
284 const MachinePointerInfo
&MPO
) {
285 MachineFunction
&MF
= MIRBuilder
.getMF();
287 auto MMO
= MF
.getMachineMemOperand(MPO
, MachineMemOperand::MOLoad
, MemTy
,
288 inferAlignFromPtrInfo(MF
, MPO
));
289 return MIRBuilder
.buildLoad(Res
, Addr
, *MMO
);
292 void assignValueToReg(Register ValVReg
, Register PhysReg
,
293 const CCValAssign
&VA
) override
{
294 assert(VA
.isRegLoc() && "Value shouldn't be assigned to reg");
295 assert(VA
.getLocReg() == PhysReg
&& "Assigning to the wrong reg?");
297 uint64_t ValSize
= VA
.getValVT().getFixedSizeInBits();
298 uint64_t LocSize
= VA
.getLocVT().getFixedSizeInBits();
300 assert(ValSize
<= 64 && "Unsupported value size");
301 assert(LocSize
<= 64 && "Unsupported location size");
303 markPhysRegUsed(PhysReg
);
304 if (ValSize
== LocSize
) {
305 MIRBuilder
.buildCopy(ValVReg
, PhysReg
);
307 assert(ValSize
< LocSize
&& "Extensions not supported");
309 // We cannot create a truncating copy, nor a trunc of a physical register.
310 // Therefore, we need to copy the content of the physical register into a
311 // virtual one and then truncate that.
312 auto PhysRegToVReg
= MIRBuilder
.buildCopy(LLT::scalar(LocSize
), PhysReg
);
313 MIRBuilder
.buildTrunc(ValVReg
, PhysRegToVReg
);
317 unsigned assignCustomValue(ARMCallLowering::ArgInfo
&Arg
,
318 ArrayRef
<CCValAssign
> VAs
,
319 std::function
<void()> *Thunk
) override
{
320 assert(Arg
.Regs
.size() == 1 && "Can't handle multple regs yet");
322 const CCValAssign
&VA
= VAs
[0];
323 assert(VA
.needsCustom() && "Value doesn't need custom handling");
325 // Custom lowering for other types, such as f16, is currently not supported
326 if (VA
.getValVT() != MVT::f64
)
329 const CCValAssign
&NextVA
= VAs
[1];
330 assert(NextVA
.needsCustom() && "Value doesn't need custom handling");
331 assert(NextVA
.getValVT() == MVT::f64
&& "Unsupported type");
333 assert(VA
.getValNo() == NextVA
.getValNo() &&
334 "Values belong to different arguments");
336 assert(VA
.isRegLoc() && "Value should be in reg");
337 assert(NextVA
.isRegLoc() && "Value should be in reg");
339 Register NewRegs
[] = {MRI
.createGenericVirtualRegister(LLT::scalar(32)),
340 MRI
.createGenericVirtualRegister(LLT::scalar(32))};
342 assignValueToReg(NewRegs
[0], VA
.getLocReg(), VA
);
343 assignValueToReg(NewRegs
[1], NextVA
.getLocReg(), NextVA
);
345 bool IsLittle
= MIRBuilder
.getMF().getSubtarget
<ARMSubtarget
>().isLittle();
347 std::swap(NewRegs
[0], NewRegs
[1]);
349 MIRBuilder
.buildMergeLikeInstr(Arg
.Regs
[0], NewRegs
);
354 /// Marking a physical register as used is different between formal
355 /// parameters, where it's a basic block live-in, and call returns, where it's
356 /// an implicit-def of the call instruction.
357 virtual void markPhysRegUsed(unsigned PhysReg
) = 0;
360 struct FormalArgHandler
: public ARMIncomingValueHandler
{
361 FormalArgHandler(MachineIRBuilder
&MIRBuilder
, MachineRegisterInfo
&MRI
)
362 : ARMIncomingValueHandler(MIRBuilder
, MRI
) {}
364 void markPhysRegUsed(unsigned PhysReg
) override
{
365 MIRBuilder
.getMRI()->addLiveIn(PhysReg
);
366 MIRBuilder
.getMBB().addLiveIn(PhysReg
);
370 } // end anonymous namespace
372 bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder
&MIRBuilder
,
374 ArrayRef
<ArrayRef
<Register
>> VRegs
,
375 FunctionLoweringInfo
&FLI
) const {
376 auto &TLI
= *getTLI
<ARMTargetLowering
>();
377 auto Subtarget
= TLI
.getSubtarget();
379 if (Subtarget
->isThumb1Only())
382 // Quick exit if there aren't any args
389 auto &MF
= MIRBuilder
.getMF();
390 auto &MBB
= MIRBuilder
.getMBB();
391 const auto &DL
= MF
.getDataLayout();
393 for (auto &Arg
: F
.args()) {
394 if (!isSupportedType(DL
, TLI
, Arg
.getType()))
396 if (Arg
.hasPassPointeeByValueCopyAttr())
400 CCAssignFn
*AssignFn
=
401 TLI
.CCAssignFnForCall(F
.getCallingConv(), F
.isVarArg());
403 OutgoingValueAssigner
ArgAssigner(AssignFn
);
404 FormalArgHandler
ArgHandler(MIRBuilder
, MIRBuilder
.getMF().getRegInfo());
406 SmallVector
<ArgInfo
, 8> SplitArgInfos
;
408 for (auto &Arg
: F
.args()) {
409 ArgInfo
OrigArgInfo(VRegs
[Idx
], Arg
.getType(), Idx
);
411 setArgFlags(OrigArgInfo
, Idx
+ AttributeList::FirstArgIndex
, DL
, F
);
412 splitToValueTypes(OrigArgInfo
, SplitArgInfos
, DL
, F
.getCallingConv());
418 MIRBuilder
.setInstr(*MBB
.begin());
420 if (!determineAndHandleAssignments(ArgHandler
, ArgAssigner
, SplitArgInfos
,
421 MIRBuilder
, F
.getCallingConv(),
425 // Move back to the end of the basic block.
426 MIRBuilder
.setMBB(MBB
);
432 struct CallReturnHandler
: public ARMIncomingValueHandler
{
433 CallReturnHandler(MachineIRBuilder
&MIRBuilder
, MachineRegisterInfo
&MRI
,
434 MachineInstrBuilder MIB
)
435 : ARMIncomingValueHandler(MIRBuilder
, MRI
), MIB(MIB
) {}
437 void markPhysRegUsed(unsigned PhysReg
) override
{
438 MIB
.addDef(PhysReg
, RegState::Implicit
);
441 MachineInstrBuilder MIB
;
444 // FIXME: This should move to the ARMSubtarget when it supports all the opcodes.
445 unsigned getCallOpcode(const MachineFunction
&MF
, const ARMSubtarget
&STI
,
448 return STI
.isThumb() ? ARM::tBL
: ARM::BL
;
451 return gettBLXrOpcode(MF
);
454 return getBLXOpcode(MF
);
459 return ARM::BMOVPCRX_CALL
;
461 } // end anonymous namespace
463 bool ARMCallLowering::lowerCall(MachineIRBuilder
&MIRBuilder
, CallLoweringInfo
&Info
) const {
464 MachineFunction
&MF
= MIRBuilder
.getMF();
465 const auto &TLI
= *getTLI
<ARMTargetLowering
>();
466 const auto &DL
= MF
.getDataLayout();
467 const auto &STI
= MF
.getSubtarget
<ARMSubtarget
>();
468 const TargetRegisterInfo
*TRI
= STI
.getRegisterInfo();
469 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
471 if (STI
.genLongCalls())
474 if (STI
.isThumb1Only())
477 auto CallSeqStart
= MIRBuilder
.buildInstr(ARM::ADJCALLSTACKDOWN
);
479 // Create the call instruction so we can add the implicit uses of arg
480 // registers, but don't insert it yet.
481 bool IsDirect
= !Info
.Callee
.isReg();
482 auto CallOpcode
= getCallOpcode(MF
, STI
, IsDirect
);
483 auto MIB
= MIRBuilder
.buildInstrNoInsert(CallOpcode
);
485 bool IsThumb
= STI
.isThumb();
487 MIB
.add(predOps(ARMCC::AL
));
489 MIB
.add(Info
.Callee
);
491 auto CalleeReg
= Info
.Callee
.getReg();
492 if (CalleeReg
&& !CalleeReg
.isPhysical()) {
493 unsigned CalleeIdx
= IsThumb
? 2 : 0;
494 MIB
->getOperand(CalleeIdx
).setReg(constrainOperandRegClass(
495 MF
, *TRI
, MRI
, *STI
.getInstrInfo(), *STI
.getRegBankInfo(),
496 *MIB
.getInstr(), MIB
->getDesc(), Info
.Callee
, CalleeIdx
));
500 MIB
.addRegMask(TRI
->getCallPreservedMask(MF
, Info
.CallConv
));
502 SmallVector
<ArgInfo
, 8> ArgInfos
;
503 for (auto Arg
: Info
.OrigArgs
) {
504 if (!isSupportedType(DL
, TLI
, Arg
.Ty
))
507 if (Arg
.Flags
[0].isByVal())
510 splitToValueTypes(Arg
, ArgInfos
, DL
, Info
.CallConv
);
513 auto ArgAssignFn
= TLI
.CCAssignFnForCall(Info
.CallConv
, Info
.IsVarArg
);
514 OutgoingValueAssigner
ArgAssigner(ArgAssignFn
);
515 ARMOutgoingValueHandler
ArgHandler(MIRBuilder
, MRI
, MIB
);
516 if (!determineAndHandleAssignments(ArgHandler
, ArgAssigner
, ArgInfos
,
517 MIRBuilder
, Info
.CallConv
, Info
.IsVarArg
))
520 // Now we can add the actual call instruction to the correct basic block.
521 MIRBuilder
.insertInstr(MIB
);
523 if (!Info
.OrigRet
.Ty
->isVoidTy()) {
524 if (!isSupportedType(DL
, TLI
, Info
.OrigRet
.Ty
))
528 splitToValueTypes(Info
.OrigRet
, ArgInfos
, DL
, Info
.CallConv
);
529 auto RetAssignFn
= TLI
.CCAssignFnForReturn(Info
.CallConv
, Info
.IsVarArg
);
530 OutgoingValueAssigner
Assigner(RetAssignFn
);
531 CallReturnHandler
RetHandler(MIRBuilder
, MRI
, MIB
);
532 if (!determineAndHandleAssignments(RetHandler
, Assigner
, ArgInfos
,
533 MIRBuilder
, Info
.CallConv
,
538 // We now know the size of the stack - update the ADJCALLSTACKDOWN
540 CallSeqStart
.addImm(ArgAssigner
.StackSize
).addImm(0).add(predOps(ARMCC::AL
));
542 MIRBuilder
.buildInstr(ARM::ADJCALLSTACKUP
)
543 .addImm(ArgAssigner
.StackSize
)
545 .add(predOps(ARMCC::AL
));
550 bool ARMCallLowering::enableBigEndian() const { return EnableGISelBigEndian
; }