1 //===-- SystemZCallingConv.h - Calling conventions for SystemZ --*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZCALLINGCONV_H
10 #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZCALLINGCONV_H
12 #include "SystemZSubtarget.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/CodeGen/CallingConvLower.h"
15 #include "llvm/MC/MCRegisterInfo.h"
19 const unsigned ELFNumArgGPRs
= 5;
20 extern const MCPhysReg ELFArgGPRs
[ELFNumArgGPRs
];
22 const unsigned ELFNumArgFPRs
= 4;
23 extern const MCPhysReg ELFArgFPRs
[ELFNumArgFPRs
];
25 const unsigned XPLINK64NumArgGPRs
= 3;
26 extern const MCPhysReg XPLINK64ArgGPRs
[XPLINK64NumArgGPRs
];
28 const unsigned XPLINK64NumArgFPRs
= 4;
29 extern const MCPhysReg XPLINK64ArgFPRs
[XPLINK64NumArgFPRs
];
30 } // end namespace SystemZ
32 class SystemZCCState
: public CCState
{
34 /// Records whether the value was a fixed argument.
35 /// See ISD::OutputArg::IsFixed.
36 SmallVector
<bool, 4> ArgIsFixed
;
38 /// Records whether the value was widened from a short vector type.
39 SmallVector
<bool, 4> ArgIsShortVector
;
41 // Check whether ArgVT is a short vector type.
42 bool IsShortVectorType(EVT ArgVT
) {
43 return ArgVT
.isVector() && ArgVT
.getStoreSize() <= 8;
47 SystemZCCState(CallingConv::ID CC
, bool isVarArg
, MachineFunction
&MF
,
48 SmallVectorImpl
<CCValAssign
> &locs
, LLVMContext
&C
)
49 : CCState(CC
, isVarArg
, MF
, locs
, C
) {}
51 void AnalyzeFormalArguments(const SmallVectorImpl
<ISD::InputArg
> &Ins
,
53 // Formal arguments are always fixed.
55 for (unsigned i
= 0; i
< Ins
.size(); ++i
)
56 ArgIsFixed
.push_back(true);
57 // Record whether the call operand was a short vector.
58 ArgIsShortVector
.clear();
59 for (unsigned i
= 0; i
< Ins
.size(); ++i
)
60 ArgIsShortVector
.push_back(IsShortVectorType(Ins
[i
].ArgVT
));
62 CCState::AnalyzeFormalArguments(Ins
, Fn
);
65 void AnalyzeCallOperands(const SmallVectorImpl
<ISD::OutputArg
> &Outs
,
67 // Record whether the call operand was a fixed argument.
69 for (unsigned i
= 0; i
< Outs
.size(); ++i
)
70 ArgIsFixed
.push_back(Outs
[i
].IsFixed
);
71 // Record whether the call operand was a short vector.
72 ArgIsShortVector
.clear();
73 for (unsigned i
= 0; i
< Outs
.size(); ++i
)
74 ArgIsShortVector
.push_back(IsShortVectorType(Outs
[i
].ArgVT
));
76 CCState::AnalyzeCallOperands(Outs
, Fn
);
79 // This version of AnalyzeCallOperands in the base class is not usable
80 // since we must provide a means of accessing ISD::OutputArg::IsFixed.
81 void AnalyzeCallOperands(const SmallVectorImpl
<MVT
> &Outs
,
82 SmallVectorImpl
<ISD::ArgFlagsTy
> &Flags
,
83 CCAssignFn Fn
) = delete;
85 bool IsFixed(unsigned ValNo
) { return ArgIsFixed
[ValNo
]; }
86 bool IsShortVector(unsigned ValNo
) { return ArgIsShortVector
[ValNo
]; }
89 // Handle i128 argument types. These need to be passed by implicit
90 // reference. This could be as simple as the following .td line:
91 // CCIfType<[i128], CCPassIndirect<i64>>,
92 // except that i128 is not a legal type, and therefore gets split by
93 // common code into a pair of i64 arguments.
94 inline bool CC_SystemZ_I128Indirect(unsigned &ValNo
, MVT
&ValVT
,
96 CCValAssign::LocInfo
&LocInfo
,
97 ISD::ArgFlagsTy
&ArgFlags
,
99 SmallVectorImpl
<CCValAssign
> &PendingMembers
= State
.getPendingLocs();
101 // ArgFlags.isSplit() is true on the first part of a i128 argument;
102 // PendingMembers.empty() is false on all subsequent parts.
103 if (!ArgFlags
.isSplit() && PendingMembers
.empty())
106 // Push a pending Indirect value location for each part.
108 LocInfo
= CCValAssign::Indirect
;
109 PendingMembers
.push_back(CCValAssign::getPending(ValNo
, ValVT
,
111 if (!ArgFlags
.isSplitEnd())
114 // OK, we've collected all parts in the pending list. Allocate
115 // the location (register or stack slot) for the indirect pointer.
116 // (This duplicates the usual i64 calling convention rules.)
118 const SystemZSubtarget
&Subtarget
=
119 State
.getMachineFunction().getSubtarget
<SystemZSubtarget
>();
120 if (Subtarget
.isTargetELF())
121 Reg
= State
.AllocateReg(SystemZ::ELFArgGPRs
);
122 else if (Subtarget
.isTargetXPLINK64())
123 Reg
= State
.AllocateReg(SystemZ::XPLINK64ArgGPRs
);
125 llvm_unreachable("Unknown Calling Convention!");
127 unsigned Offset
= Reg
&& !Subtarget
.isTargetXPLINK64()
129 : State
.AllocateStack(8, Align(8));
131 // Use that same location for all the pending parts.
132 for (auto &It
: PendingMembers
) {
134 It
.convertToReg(Reg
);
136 It
.convertToMem(Offset
);
140 PendingMembers
.clear();
145 // A pointer in 64bit mode is always passed as 64bit.
146 inline bool CC_XPLINK64_Pointer(unsigned &ValNo
, MVT
&ValVT
, MVT
&LocVT
,
147 CCValAssign::LocInfo
&LocInfo
,
148 ISD::ArgFlagsTy
&ArgFlags
, CCState
&State
) {
149 if (LocVT
!= MVT::i64
) {
151 LocInfo
= CCValAssign::ZExt
;
156 inline bool CC_XPLINK64_Shadow_Reg(unsigned &ValNo
, MVT
&ValVT
, MVT
&LocVT
,
157 CCValAssign::LocInfo
&LocInfo
,
158 ISD::ArgFlagsTy
&ArgFlags
, CCState
&State
) {
159 if (LocVT
== MVT::f32
|| LocVT
== MVT::f64
) {
160 State
.AllocateReg(SystemZ::XPLINK64ArgGPRs
);
162 if (LocVT
== MVT::f128
|| LocVT
.is128BitVector()) {
163 // Shadow next two GPRs, if available.
164 State
.AllocateReg(SystemZ::XPLINK64ArgGPRs
);
165 State
.AllocateReg(SystemZ::XPLINK64ArgGPRs
);
167 // Quad precision floating point needs to
168 // go inside pre-defined FPR pair.
169 if (LocVT
== MVT::f128
) {
170 for (unsigned I
= 0; I
< SystemZ::XPLINK64NumArgFPRs
; I
+= 2)
171 if (State
.isAllocated(SystemZ::XPLINK64ArgFPRs
[I
]))
172 State
.AllocateReg(SystemZ::XPLINK64ArgFPRs
[I
+ 1]);
178 inline bool CC_XPLINK64_Allocate128BitVararg(unsigned &ValNo
, MVT
&ValVT
,
180 CCValAssign::LocInfo
&LocInfo
,
181 ISD::ArgFlagsTy
&ArgFlags
,
183 // For any C or C++ program, this should always be
184 // false, since it is illegal to have a function
185 // where the first argument is variadic. Therefore
186 // the first fixed argument should already have
187 // allocated GPR1 either through shadowing it or
188 // using it for parameter passing.
189 State
.AllocateReg(SystemZ::R1D
);
191 bool AllocGPR2
= State
.AllocateReg(SystemZ::R2D
);
192 bool AllocGPR3
= State
.AllocateReg(SystemZ::R3D
);
194 // If GPR2 and GPR3 are available, then we may pass vararg in R2Q.
195 // If only GPR3 is available, we need to set custom handling to copy
196 // hi bits into GPR3.
197 // Either way, we allocate on the stack.
199 // For f128 and vector var arg case, set the bitcast flag to bitcast to
202 LocInfo
= CCValAssign::BCvt
;
203 auto Offset
= State
.AllocateStack(16, Align(8));
206 CCValAssign::getReg(ValNo
, ValVT
, SystemZ::R2Q
, LocVT
, LocInfo
));
209 CCValAssign::getCustomMem(ValNo
, ValVT
, Offset
, LocVT
, LocInfo
));
216 inline bool RetCC_SystemZ_Error(unsigned &, MVT
&, MVT
&,
217 CCValAssign::LocInfo
&, ISD::ArgFlagsTy
&,
219 llvm_unreachable("Return value calling convention currently unsupported.");
222 inline bool CC_SystemZ_Error(unsigned &, MVT
&, MVT
&, CCValAssign::LocInfo
&,
223 ISD::ArgFlagsTy
&, CCState
&) {
224 llvm_unreachable("Argument calling convention currently unsupported.");
227 inline bool CC_SystemZ_GHC_Error(unsigned &, MVT
&, MVT
&,
228 CCValAssign::LocInfo
&, ISD::ArgFlagsTy
&,
230 report_fatal_error("No registers left in GHC calling convention");
234 } // end namespace llvm