1 //===-- lib/CodeGen/GlobalISel/CallLowering.cpp - Call lowering -----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// This file implements some simple delegations needed for call lowering.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
16 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
17 #include "llvm/CodeGen/MachineOperand.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/CodeGen/TargetLowering.h"
20 #include "llvm/IR/DataLayout.h"
21 #include "llvm/IR/Instructions.h"
22 #include "llvm/IR/Module.h"
26 bool CallLowering::lowerCall(
27 MachineIRBuilder
&MIRBuilder
, ImmutableCallSite CS
, unsigned ResReg
,
28 ArrayRef
<unsigned> ArgRegs
, std::function
<unsigned()> GetCalleeReg
) const {
29 auto &DL
= CS
.getParent()->getParent()->getParent()->getDataLayout();
31 // First step is to marshall all the function's parameters into the correct
32 // physregs and memory locations. Gather the sequence of argument types that
33 // we'll pass to the assigner function.
34 SmallVector
<ArgInfo
, 8> OrigArgs
;
36 unsigned NumFixedArgs
= CS
.getFunctionType()->getNumParams();
37 for (auto &Arg
: CS
.args()) {
38 ArgInfo OrigArg
{ArgRegs
[i
], Arg
->getType(), ISD::ArgFlagsTy
{},
40 setArgFlags(OrigArg
, i
+ AttributeList::FirstArgIndex
, DL
, CS
);
41 // We don't currently support swifterror or swiftself args.
42 if (OrigArg
.Flags
.isSwiftError() || OrigArg
.Flags
.isSwiftSelf())
44 OrigArgs
.push_back(OrigArg
);
48 MachineOperand Callee
= MachineOperand::CreateImm(0);
49 if (const Function
*F
= CS
.getCalledFunction())
50 Callee
= MachineOperand::CreateGA(F
, 0);
52 Callee
= MachineOperand::CreateReg(GetCalleeReg(), false);
54 ArgInfo OrigRet
{ResReg
, CS
.getType(), ISD::ArgFlagsTy
{}};
55 if (!OrigRet
.Ty
->isVoidTy())
56 setArgFlags(OrigRet
, AttributeList::ReturnIndex
, DL
, CS
);
58 return lowerCall(MIRBuilder
, CS
.getCallingConv(), Callee
, OrigRet
, OrigArgs
);
61 template <typename FuncInfoTy
>
62 void CallLowering::setArgFlags(CallLowering::ArgInfo
&Arg
, unsigned OpIdx
,
64 const FuncInfoTy
&FuncInfo
) const {
65 const AttributeList
&Attrs
= FuncInfo
.getAttributes();
66 if (Attrs
.hasAttribute(OpIdx
, Attribute::ZExt
))
68 if (Attrs
.hasAttribute(OpIdx
, Attribute::SExt
))
70 if (Attrs
.hasAttribute(OpIdx
, Attribute::InReg
))
72 if (Attrs
.hasAttribute(OpIdx
, Attribute::StructRet
))
74 if (Attrs
.hasAttribute(OpIdx
, Attribute::SwiftSelf
))
75 Arg
.Flags
.setSwiftSelf();
76 if (Attrs
.hasAttribute(OpIdx
, Attribute::SwiftError
))
77 Arg
.Flags
.setSwiftError();
78 if (Attrs
.hasAttribute(OpIdx
, Attribute::ByVal
))
80 if (Attrs
.hasAttribute(OpIdx
, Attribute::InAlloca
))
81 Arg
.Flags
.setInAlloca();
83 if (Arg
.Flags
.isByVal() || Arg
.Flags
.isInAlloca()) {
84 Type
*ElementTy
= cast
<PointerType
>(Arg
.Ty
)->getElementType();
85 Arg
.Flags
.setByValSize(DL
.getTypeAllocSize(ElementTy
));
86 // For ByVal, alignment should be passed from FE. BE will guess if
87 // this info is not there but there are cases it cannot get right.
89 if (FuncInfo
.getParamAlignment(OpIdx
- 2))
90 FrameAlign
= FuncInfo
.getParamAlignment(OpIdx
- 2);
92 FrameAlign
= getTLI()->getByValTypeAlignment(ElementTy
, DL
);
93 Arg
.Flags
.setByValAlign(FrameAlign
);
95 if (Attrs
.hasAttribute(OpIdx
, Attribute::Nest
))
97 Arg
.Flags
.setOrigAlign(DL
.getABITypeAlignment(Arg
.Ty
));
101 CallLowering::setArgFlags
<Function
>(CallLowering::ArgInfo
&Arg
, unsigned OpIdx
,
102 const DataLayout
&DL
,
103 const Function
&FuncInfo
) const;
106 CallLowering::setArgFlags
<CallInst
>(CallLowering::ArgInfo
&Arg
, unsigned OpIdx
,
107 const DataLayout
&DL
,
108 const CallInst
&FuncInfo
) const;
110 bool CallLowering::handleAssignments(MachineIRBuilder
&MIRBuilder
,
111 ArrayRef
<ArgInfo
> Args
,
112 ValueHandler
&Handler
) const {
113 MachineFunction
&MF
= MIRBuilder
.getMF();
114 const Function
&F
= MF
.getFunction();
115 const DataLayout
&DL
= F
.getParent()->getDataLayout();
117 SmallVector
<CCValAssign
, 16> ArgLocs
;
118 CCState
CCInfo(F
.getCallingConv(), F
.isVarArg(), MF
, ArgLocs
, F
.getContext());
120 unsigned NumArgs
= Args
.size();
121 for (unsigned i
= 0; i
!= NumArgs
; ++i
) {
122 MVT CurVT
= MVT::getVT(Args
[i
].Ty
);
123 if (Handler
.assignArg(i
, CurVT
, CurVT
, CCValAssign::Full
, Args
[i
], CCInfo
))
127 for (unsigned i
= 0, e
= Args
.size(), j
= 0; i
!= e
; ++i
, ++j
) {
128 assert(j
< ArgLocs
.size() && "Skipped too many arg locs");
130 CCValAssign
&VA
= ArgLocs
[j
];
131 assert(VA
.getValNo() == i
&& "Location doesn't correspond to current arg");
133 if (VA
.needsCustom()) {
134 j
+= Handler
.assignCustomValue(Args
[i
], makeArrayRef(ArgLocs
).slice(j
));
139 Handler
.assignValueToReg(Args
[i
].Reg
, VA
.getLocReg(), VA
);
140 else if (VA
.isMemLoc()) {
141 unsigned Size
= VA
.getValVT() == MVT::iPTR
142 ? DL
.getPointerSize()
143 : alignTo(VA
.getValVT().getSizeInBits(), 8) / 8;
144 unsigned Offset
= VA
.getLocMemOffset();
145 MachinePointerInfo MPO
;
146 unsigned StackAddr
= Handler
.getStackAddress(Size
, Offset
, MPO
);
147 Handler
.assignValueToAddress(Args
[i
].Reg
, StackAddr
, Size
, MPO
, VA
);
149 // FIXME: Support byvals and other weirdness
156 unsigned CallLowering::ValueHandler::extendRegister(unsigned ValReg
,
158 LLT LocTy
{VA
.getLocVT()};
159 switch (VA
.getLocInfo()) {
161 case CCValAssign::Full
:
162 case CCValAssign::BCvt
:
163 // FIXME: bitconverting between vector types may or may not be a
164 // nop in big-endian situations.
166 case CCValAssign::AExt
: {
167 auto MIB
= MIRBuilder
.buildAnyExt(LocTy
, ValReg
);
168 return MIB
->getOperand(0).getReg();
170 case CCValAssign::SExt
: {
171 unsigned NewReg
= MRI
.createGenericVirtualRegister(LocTy
);
172 MIRBuilder
.buildSExt(NewReg
, ValReg
);
175 case CCValAssign::ZExt
: {
176 unsigned NewReg
= MRI
.createGenericVirtualRegister(LocTy
);
177 MIRBuilder
.buildZExt(NewReg
, ValReg
);
181 llvm_unreachable("unable to extend register");