1498e5f89SDan Gohman //===-- CallingConvLower.cpp - Calling Conventions ------------------------===//
2498e5f89SDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6498e5f89SDan Gohman //
7498e5f89SDan Gohman //===----------------------------------------------------------------------===//
8498e5f89SDan Gohman //
9498e5f89SDan Gohman // This file implements the CCState class, used for lowering and implementing
10498e5f89SDan Gohman // calling conventions.
11498e5f89SDan Gohman //
12498e5f89SDan Gohman //===----------------------------------------------------------------------===//
13498e5f89SDan Gohman
14498e5f89SDan Gohman #include "llvm/CodeGen/CallingConvLower.h"
150713a9d8SEric Christopher #include "llvm/CodeGen/MachineFrameInfo.h"
167582c5c0SSimon Pilgrim #include "llvm/CodeGen/MachineFunction.h"
17b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetLowering.h"
18b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetRegisterInfo.h"
19b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetSubtargetInfo.h"
20*01be9be2Sserge-sans-paille #include "llvm/MC/MCRegisterInfo.h"
21498e5f89SDan Gohman #include "llvm/Support/Debug.h"
22498e5f89SDan Gohman #include "llvm/Support/ErrorHandling.h"
23ce009334SReid Kleckner #include "llvm/Support/SaveAndRestore.h"
24498e5f89SDan Gohman #include "llvm/Support/raw_ostream.h"
253b951570SOren Ben Simhon
26498e5f89SDan Gohman using namespace llvm;
27498e5f89SDan Gohman
CCState(CallingConv::ID CC,bool isVarArg,MachineFunction & mf,SmallVectorImpl<CCValAssign> & locs,LLVMContext & C)280713a9d8SEric Christopher CCState::CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &mf,
29b5217507SEric Christopher SmallVectorImpl<CCValAssign> &locs, LLVMContext &C)
30b5217507SEric Christopher : CallingConv(CC), IsVarArg(isVarArg), MF(mf),
31c35139ecSReid Kleckner TRI(*MF.getSubtarget().getRegisterInfo()), Locs(locs), Context(C) {
32498e5f89SDan Gohman // No stack is used.
33498e5f89SDan Gohman StackOffset = 0;
34498e5f89SDan Gohman
358c02c982SStepan Dyatkovskiy clearByValRegsInfo();
36498e5f89SDan Gohman UsedRegs.resize((TRI.getNumRegs()+31)/32);
37498e5f89SDan Gohman }
38498e5f89SDan Gohman
398b2150efSSanjay Patel /// Allocate space on the stack large enough to pass an argument by value.
408b2150efSSanjay Patel /// The size and alignment information of the argument is encoded in
418b2150efSSanjay Patel /// its parameter attribute.
HandleByVal(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,int MinSize,Align MinAlign,ISD::ArgFlagsTy ArgFlags)426c5fb61fSGuillaume Chatelet void CCState::HandleByVal(unsigned ValNo, MVT ValVT, MVT LocVT,
436c5fb61fSGuillaume Chatelet CCValAssign::LocInfo LocInfo, int MinSize,
4494b0c32aSGuillaume Chatelet Align MinAlign, ISD::ArgFlagsTy ArgFlags) {
45333f2ad8SGuillaume Chatelet Align Alignment = ArgFlags.getNonZeroByValAlign();
46498e5f89SDan Gohman unsigned Size = ArgFlags.getByValSize();
47498e5f89SDan Gohman if (MinSize > (int)Size)
48498e5f89SDan Gohman Size = MinSize;
4918f805a7SGuillaume Chatelet if (MinAlign > Alignment)
5018f805a7SGuillaume Chatelet Alignment = MinAlign;
5118f805a7SGuillaume Chatelet ensureMaxAlignment(Alignment);
5294b0c32aSGuillaume Chatelet MF.getSubtarget().getTargetLowering()->HandleByVal(this, Size, Alignment);
53da00f2fdSRui Ueyama Size = unsigned(alignTo(Size, MinAlign));
5454076610SGuillaume Chatelet unsigned Offset = AllocateStack(Size, Alignment);
55498e5f89SDan Gohman addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
56498e5f89SDan Gohman }
57498e5f89SDan Gohman
588b2150efSSanjay Patel /// Mark a register and all of its aliases as allocated.
MarkAllocated(MCPhysReg Reg)597a46e36dSMatt Arsenault void CCState::MarkAllocated(MCPhysReg Reg) {
6054038d79SJakob Stoklund Olesen for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI)
6154038d79SJakob Stoklund Olesen UsedRegs[*AI / 32] |= 1 << (*AI & 31);
62498e5f89SDan Gohman }
63498e5f89SDan Gohman
MarkUnallocated(MCPhysReg Reg)643225fcf1SDavid Sherwood void CCState::MarkUnallocated(MCPhysReg Reg) {
653225fcf1SDavid Sherwood for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI)
663225fcf1SDavid Sherwood UsedRegs[*AI / 32] &= ~(1 << (*AI & 31));
673225fcf1SDavid Sherwood }
683225fcf1SDavid Sherwood
IsShadowAllocatedReg(MCRegister Reg) const697a46e36dSMatt Arsenault bool CCState::IsShadowAllocatedReg(MCRegister Reg) const {
703b951570SOren Ben Simhon if (!isAllocated(Reg))
713b951570SOren Ben Simhon return false;
723b951570SOren Ben Simhon
731de11fe3SBenjamin Kramer for (auto const &ValAssign : Locs)
741de11fe3SBenjamin Kramer if (ValAssign.isRegLoc() && TRI.regsOverlap(ValAssign.getLocReg(), Reg))
753b951570SOren Ben Simhon return false;
763b951570SOren Ben Simhon return true;
773b951570SOren Ben Simhon }
783b951570SOren Ben Simhon
798b2150efSSanjay Patel /// Analyze an array of argument values,
80498e5f89SDan Gohman /// incorporating info about the formals into this state.
81498e5f89SDan Gohman void
AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> & Ins,CCAssignFn Fn)82498e5f89SDan Gohman CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
83498e5f89SDan Gohman CCAssignFn Fn) {
84498e5f89SDan Gohman unsigned NumArgs = Ins.size();
85498e5f89SDan Gohman
86498e5f89SDan Gohman for (unsigned i = 0; i != NumArgs; ++i) {
87f5dda01fSDuncan Sands MVT ArgVT = Ins[i].VT;
88498e5f89SDan Gohman ISD::ArgFlagsTy ArgFlags = Ins[i].Flags;
893b1459edSRyan Taylor if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this))
903b1459edSRyan Taylor report_fatal_error("unable to allocate function argument #" + Twine(i));
91498e5f89SDan Gohman }
92498e5f89SDan Gohman }
93498e5f89SDan Gohman
948b2150efSSanjay Patel /// Analyze the return values of a function, returning true if the return can
958b2150efSSanjay Patel /// be performed without sret-demotion and false otherwise.
CheckReturn(const SmallVectorImpl<ISD::OutputArg> & Outs,CCAssignFn Fn)96d7b5ce33SDan Gohman bool CCState::CheckReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
97498e5f89SDan Gohman CCAssignFn Fn) {
98498e5f89SDan Gohman // Determine which register each value should be copied into.
99d7b5ce33SDan Gohman for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
100f5dda01fSDuncan Sands MVT VT = Outs[i].VT;
101d7b5ce33SDan Gohman ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
102498e5f89SDan Gohman if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this))
103498e5f89SDan Gohman return false;
104498e5f89SDan Gohman }
105498e5f89SDan Gohman return true;
106498e5f89SDan Gohman }
107498e5f89SDan Gohman
1088b2150efSSanjay Patel /// Analyze the returned values of a return,
109498e5f89SDan Gohman /// incorporating info about the result values into this state.
AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> & Outs,CCAssignFn Fn)110498e5f89SDan Gohman void CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
111498e5f89SDan Gohman CCAssignFn Fn) {
112498e5f89SDan Gohman // Determine which register each value should be copied into.
113498e5f89SDan Gohman for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
114f5dda01fSDuncan Sands MVT VT = Outs[i].VT;
115498e5f89SDan Gohman ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
1163b1459edSRyan Taylor if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this))
1173b1459edSRyan Taylor report_fatal_error("unable to allocate function return #" + Twine(i));
118498e5f89SDan Gohman }
119498e5f89SDan Gohman }
120498e5f89SDan Gohman
1218b2150efSSanjay Patel /// Analyze the outgoing arguments to a call,
122498e5f89SDan Gohman /// incorporating info about the passed values into this state.
AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> & Outs,CCAssignFn Fn)123498e5f89SDan Gohman void CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
124498e5f89SDan Gohman CCAssignFn Fn) {
125498e5f89SDan Gohman unsigned NumOps = Outs.size();
126498e5f89SDan Gohman for (unsigned i = 0; i != NumOps; ++i) {
127f5dda01fSDuncan Sands MVT ArgVT = Outs[i].VT;
128498e5f89SDan Gohman ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
129498e5f89SDan Gohman if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
130498e5f89SDan Gohman #ifndef NDEBUG
131498e5f89SDan Gohman dbgs() << "Call operand #" << i << " has unhandled type "
13204a5cc39SCraig Topper << EVT(ArgVT).getEVTString() << '\n';
133498e5f89SDan Gohman #endif
134c0196b1bSCraig Topper llvm_unreachable(nullptr);
135498e5f89SDan Gohman }
136498e5f89SDan Gohman }
137498e5f89SDan Gohman }
138498e5f89SDan Gohman
1398b2150efSSanjay Patel /// Same as above except it takes vectors of types and argument flags.
AnalyzeCallOperands(SmallVectorImpl<MVT> & ArgVTs,SmallVectorImpl<ISD::ArgFlagsTy> & Flags,CCAssignFn Fn)140f5dda01fSDuncan Sands void CCState::AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs,
141498e5f89SDan Gohman SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
142498e5f89SDan Gohman CCAssignFn Fn) {
143498e5f89SDan Gohman unsigned NumOps = ArgVTs.size();
144498e5f89SDan Gohman for (unsigned i = 0; i != NumOps; ++i) {
145f5dda01fSDuncan Sands MVT ArgVT = ArgVTs[i];
146498e5f89SDan Gohman ISD::ArgFlagsTy ArgFlags = Flags[i];
147498e5f89SDan Gohman if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
148498e5f89SDan Gohman #ifndef NDEBUG
149498e5f89SDan Gohman dbgs() << "Call operand #" << i << " has unhandled type "
15004a5cc39SCraig Topper << EVT(ArgVT).getEVTString() << '\n';
151498e5f89SDan Gohman #endif
152c0196b1bSCraig Topper llvm_unreachable(nullptr);
153498e5f89SDan Gohman }
154498e5f89SDan Gohman }
155498e5f89SDan Gohman }
156498e5f89SDan Gohman
1578b2150efSSanjay Patel /// Analyze the return values of a call, incorporating info about the passed
1588b2150efSSanjay Patel /// values into this state.
AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> & Ins,CCAssignFn Fn)159498e5f89SDan Gohman void CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
160498e5f89SDan Gohman CCAssignFn Fn) {
161498e5f89SDan Gohman for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
162f5dda01fSDuncan Sands MVT VT = Ins[i].VT;
163498e5f89SDan Gohman ISD::ArgFlagsTy Flags = Ins[i].Flags;
164498e5f89SDan Gohman if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this)) {
165498e5f89SDan Gohman #ifndef NDEBUG
166498e5f89SDan Gohman dbgs() << "Call result #" << i << " has unhandled type "
16704a5cc39SCraig Topper << EVT(VT).getEVTString() << '\n';
168498e5f89SDan Gohman #endif
169c0196b1bSCraig Topper llvm_unreachable(nullptr);
170498e5f89SDan Gohman }
171498e5f89SDan Gohman }
172498e5f89SDan Gohman }
173498e5f89SDan Gohman
1748b2150efSSanjay Patel /// Same as above except it's specialized for calls that produce a single value.
AnalyzeCallResult(MVT VT,CCAssignFn Fn)175f5dda01fSDuncan Sands void CCState::AnalyzeCallResult(MVT VT, CCAssignFn Fn) {
176498e5f89SDan Gohman if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this)) {
177498e5f89SDan Gohman #ifndef NDEBUG
178498e5f89SDan Gohman dbgs() << "Call result has unhandled type "
17904a5cc39SCraig Topper << EVT(VT).getEVTString() << '\n';
180498e5f89SDan Gohman #endif
181c0196b1bSCraig Topper llvm_unreachable(nullptr);
182498e5f89SDan Gohman }
183498e5f89SDan Gohman }
184ce009334SReid Kleckner
ensureMaxAlignment(Align Alignment)1857582c5c0SSimon Pilgrim void CCState::ensureMaxAlignment(Align Alignment) {
1867582c5c0SSimon Pilgrim if (!AnalyzingMustTailForwardedRegs)
1877582c5c0SSimon Pilgrim MF.getFrameInfo().ensureMaxAlignment(Alignment);
1887582c5c0SSimon Pilgrim }
1897582c5c0SSimon Pilgrim
isValueTypeInRegForCC(CallingConv::ID CC,MVT VT)190bba20f06SReid Kleckner static bool isValueTypeInRegForCC(CallingConv::ID CC, MVT VT) {
191bba20f06SReid Kleckner if (VT.isVector())
192bba20f06SReid Kleckner return true; // Assume -msse-regparm might be in effect.
193bba20f06SReid Kleckner if (!VT.isInteger())
194bba20f06SReid Kleckner return false;
19527e1cc6fSFangrui Song return (CC == CallingConv::X86_VectorCall || CC == CallingConv::X86_FastCall);
196bba20f06SReid Kleckner }
197bba20f06SReid Kleckner
getRemainingRegParmsForType(SmallVectorImpl<MCPhysReg> & Regs,MVT VT,CCAssignFn Fn)198ce009334SReid Kleckner void CCState::getRemainingRegParmsForType(SmallVectorImpl<MCPhysReg> &Regs,
199ce009334SReid Kleckner MVT VT, CCAssignFn Fn) {
200ce009334SReid Kleckner unsigned SavedStackOffset = StackOffset;
20118f805a7SGuillaume Chatelet Align SavedMaxStackArgAlign = MaxStackArgAlign;
202ce009334SReid Kleckner unsigned NumLocs = Locs.size();
203ce009334SReid Kleckner
204bba20f06SReid Kleckner // Set the 'inreg' flag if it is used for this calling convention.
205ce009334SReid Kleckner ISD::ArgFlagsTy Flags;
206bba20f06SReid Kleckner if (isValueTypeInRegForCC(CallingConv, VT))
207ce009334SReid Kleckner Flags.setInReg();
208bba20f06SReid Kleckner
209bba20f06SReid Kleckner // Allocate something of this value type repeatedly until we get assigned a
210bba20f06SReid Kleckner // location in memory.
21127e1cc6fSFangrui Song bool HaveRegParm;
21227e1cc6fSFangrui Song do {
213ce009334SReid Kleckner if (Fn(0, VT, VT, CCValAssign::Full, Flags, *this)) {
214ce009334SReid Kleckner #ifndef NDEBUG
215ce009334SReid Kleckner dbgs() << "Call has unhandled type " << EVT(VT).getEVTString()
216ce009334SReid Kleckner << " while computing remaining regparms\n";
217ce009334SReid Kleckner #endif
218ce009334SReid Kleckner llvm_unreachable(nullptr);
219ce009334SReid Kleckner }
220ce009334SReid Kleckner HaveRegParm = Locs.back().isRegLoc();
22127e1cc6fSFangrui Song } while (HaveRegParm);
222ce009334SReid Kleckner
223ce009334SReid Kleckner // Copy all the registers from the value locations we added.
224ce009334SReid Kleckner assert(NumLocs < Locs.size() && "CC assignment failed to add location");
225ce009334SReid Kleckner for (unsigned I = NumLocs, E = Locs.size(); I != E; ++I)
226ce009334SReid Kleckner if (Locs[I].isRegLoc())
227ce009334SReid Kleckner Regs.push_back(MCPhysReg(Locs[I].getLocReg()));
228ce009334SReid Kleckner
229ce009334SReid Kleckner // Clear the assigned values and stack memory. We leave the registers marked
230ce009334SReid Kleckner // as allocated so that future queries don't return the same registers, i.e.
231ce009334SReid Kleckner // when i64 and f64 are both passed in GPRs.
232ce009334SReid Kleckner StackOffset = SavedStackOffset;
233740f9d79SJeroen Ketema MaxStackArgAlign = SavedMaxStackArgAlign;
234ce009334SReid Kleckner Locs.resize(NumLocs);
235ce009334SReid Kleckner }
236ce009334SReid Kleckner
analyzeMustTailForwardedRegisters(SmallVectorImpl<ForwardedRegister> & Forwards,ArrayRef<MVT> RegParmTypes,CCAssignFn Fn)237ce009334SReid Kleckner void CCState::analyzeMustTailForwardedRegisters(
238ce009334SReid Kleckner SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> RegParmTypes,
239ce009334SReid Kleckner CCAssignFn Fn) {
240ce009334SReid Kleckner // Oftentimes calling conventions will not user register parameters for
241ce009334SReid Kleckner // variadic functions, so we need to assume we're not variadic so that we get
242ce009334SReid Kleckner // all the registers that might be used in a non-variadic call.
243ce009334SReid Kleckner SaveAndRestore<bool> SavedVarArg(IsVarArg, false);
24418ec96f0SReid Kleckner SaveAndRestore<bool> SavedMustTail(AnalyzingMustTailForwardedRegs, true);
245ce009334SReid Kleckner
246ce009334SReid Kleckner for (MVT RegVT : RegParmTypes) {
247ce009334SReid Kleckner SmallVector<MCPhysReg, 8> RemainingRegs;
248ce009334SReid Kleckner getRemainingRegParmsForType(RemainingRegs, RegVT, Fn);
249ce009334SReid Kleckner const TargetLowering *TL = MF.getSubtarget().getTargetLowering();
250ce009334SReid Kleckner const TargetRegisterClass *RC = TL->getRegClassFor(RegVT);
251ce009334SReid Kleckner for (MCPhysReg PReg : RemainingRegs) {
25227e1cc6fSFangrui Song Register VReg = MF.addLiveIn(PReg, RC);
253ce009334SReid Kleckner Forwards.push_back(ForwardedRegister(VReg, PReg, RegVT));
254ce009334SReid Kleckner }
255ce009334SReid Kleckner }
256ce009334SReid Kleckner }
2578d414360SMatthias Braun
resultsCompatible(CallingConv::ID CalleeCC,CallingConv::ID CallerCC,MachineFunction & MF,LLVMContext & C,const SmallVectorImpl<ISD::InputArg> & Ins,CCAssignFn CalleeFn,CCAssignFn CallerFn)2588d414360SMatthias Braun bool CCState::resultsCompatible(CallingConv::ID CalleeCC,
2598d414360SMatthias Braun CallingConv::ID CallerCC, MachineFunction &MF,
2608d414360SMatthias Braun LLVMContext &C,
2618d414360SMatthias Braun const SmallVectorImpl<ISD::InputArg> &Ins,
2628d414360SMatthias Braun CCAssignFn CalleeFn, CCAssignFn CallerFn) {
2638d414360SMatthias Braun if (CalleeCC == CallerCC)
2648d414360SMatthias Braun return true;
2658d414360SMatthias Braun SmallVector<CCValAssign, 4> RVLocs1;
2668d414360SMatthias Braun CCState CCInfo1(CalleeCC, false, MF, RVLocs1, C);
2678d414360SMatthias Braun CCInfo1.AnalyzeCallResult(Ins, CalleeFn);
2688d414360SMatthias Braun
2698d414360SMatthias Braun SmallVector<CCValAssign, 4> RVLocs2;
2708d414360SMatthias Braun CCState CCInfo2(CallerCC, false, MF, RVLocs2, C);
2718d414360SMatthias Braun CCInfo2.AnalyzeCallResult(Ins, CallerFn);
2728d414360SMatthias Braun
2738d414360SMatthias Braun if (RVLocs1.size() != RVLocs2.size())
2748d414360SMatthias Braun return false;
2758d414360SMatthias Braun for (unsigned I = 0, E = RVLocs1.size(); I != E; ++I) {
2768d414360SMatthias Braun const CCValAssign &Loc1 = RVLocs1[I];
2778d414360SMatthias Braun const CCValAssign &Loc2 = RVLocs2[I];
278055ea585SDavid Spickett
279055ea585SDavid Spickett if ( // Must both be in registers, or both in memory
280055ea585SDavid Spickett Loc1.isRegLoc() != Loc2.isRegLoc() ||
281055ea585SDavid Spickett // Must fill the same part of their locations
282055ea585SDavid Spickett Loc1.getLocInfo() != Loc2.getLocInfo() ||
283055ea585SDavid Spickett // Memory offset/register number must be the same
284055ea585SDavid Spickett Loc1.getExtraInfo() != Loc2.getExtraInfo())
2858d414360SMatthias Braun return false;
2868d414360SMatthias Braun }
2878d414360SMatthias Braun return true;
2888d414360SMatthias Braun }
289