1//===-- llvm/CodeGen/TargetCallingConv.h - Calling Convention ---*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines types for working with calling-convention information.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CODEGEN_TARGETCALLINGCONV_H
14#define LLVM_CODEGEN_TARGETCALLINGCONV_H
15
16#include "llvm/CodeGen/ValueTypes.h"
17#include "llvm/Support/Alignment.h"
18#include "llvm/Support/MachineValueType.h"
19#include "llvm/Support/MathExtras.h"
20#include <cassert>
21#include <climits>
22#include <cstdint>
23
24namespace llvm {
25namespace ISD {
26
27 struct ArgFlagsTy {
28 private:
29 unsigned IsZExt : 1; ///< Zero extended
30 unsigned IsSExt : 1; ///< Sign extended
31 unsigned IsInReg : 1; ///< Passed in register
32 unsigned IsSRet : 1; ///< Hidden struct-ret ptr
33 unsigned IsByVal : 1; ///< Struct passed by value
34 unsigned IsByRef : 1; ///< Passed in memory
35 unsigned IsNest : 1; ///< Nested fn static chain
36 unsigned IsReturned : 1; ///< Always returned
37 unsigned IsSplit : 1;
38 unsigned IsInAlloca : 1; ///< Passed with inalloca
39 unsigned IsPreallocated : 1; ///< ByVal without the copy
40 unsigned IsSplitEnd : 1; ///< Last part of a split
41 unsigned IsSwiftSelf : 1; ///< Swift self parameter
42 unsigned IsSwiftError : 1; ///< Swift error parameter
43 unsigned IsCFGuardTarget : 1; ///< Control Flow Guard target
44 unsigned IsHva : 1; ///< HVA field for
45 unsigned IsHvaStart : 1; ///< HVA structure start
46 unsigned IsSecArgPass : 1; ///< Second argument
47 unsigned MemAlign : 4; ///< Log 2 of alignment when arg is passed in memory
48 ///< (including byval/byref)
49 unsigned OrigAlign : 5; ///< Log 2 of original alignment
50 unsigned IsInConsecutiveRegsLast : 1;
51 unsigned IsInConsecutiveRegs : 1;
52 unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate
53 unsigned IsPointer : 1;
54
55 unsigned ByValOrByRefSize; ///< Byval or byref struct size
56
57 unsigned PointerAddrSpace; ///< Address space of pointer argument
58
59 public:
60 ArgFlagsTy()
61 : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
62 IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), IsPreallocated(0),
63 IsSplitEnd(0), IsSwiftSelf(0), IsSwiftError(0), IsCFGuardTarget(0),
64 IsHva(0), IsHvaStart(0), IsSecArgPass(0), MemAlign(0),
65 OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
66 IsCopyElisionCandidate(0), IsPointer(0), ByValOrByRefSize(0),
67 PointerAddrSpace(0) {
68 static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
69 }
70
71 bool isZExt() const { return IsZExt; }
72 void setZExt() { IsZExt = 1; }
73
74 bool isSExt() const { return IsSExt; }
75 void setSExt() { IsSExt = 1; }
76
77 bool isInReg() const { return IsInReg; }
78 void setInReg() { IsInReg = 1; }
79
80 bool isSRet() const { return IsSRet; }
81 void setSRet() { IsSRet = 1; }
82
83 bool isByVal() const { return IsByVal; }
84 void setByVal() { IsByVal = 1; }
85
86 bool isByRef() const { return IsByRef; }
87 void setByRef() { IsByRef = 1; }
88
89 bool isInAlloca() const { return IsInAlloca; }
90 void setInAlloca() { IsInAlloca = 1; }
91
92 bool isPreallocated() const { return IsPreallocated; }
93 void setPreallocated() { IsPreallocated = 1; }
94
95 bool isSwiftSelf() const { return IsSwiftSelf; }
96 void setSwiftSelf() { IsSwiftSelf = 1; }
97
98 bool isSwiftError() const { return IsSwiftError; }
99 void setSwiftError() { IsSwiftError = 1; }
100
101 bool isCFGuardTarget() const { return IsCFGuardTarget; }
102 void setCFGuardTarget() { IsCFGuardTarget = 1; }
103
104 bool isHva() const { return IsHva; }
105 void setHva() { IsHva = 1; }
106
107 bool isHvaStart() const { return IsHvaStart; }
108 void setHvaStart() { IsHvaStart = 1; }
109
110 bool isSecArgPass() const { return IsSecArgPass; }
111 void setSecArgPass() { IsSecArgPass = 1; }
112
113 bool isNest() const { return IsNest; }
114 void setNest() { IsNest = 1; }
115
116 bool isReturned() const { return IsReturned; }
117 void setReturned(bool V = true) { IsReturned = V; }
118
119 bool isInConsecutiveRegs() const { return IsInConsecutiveRegs; }
120 void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; }
121
122 bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; }
123 void setInConsecutiveRegsLast(bool Flag = true) {
124 IsInConsecutiveRegsLast = Flag;
125 }
126
127 bool isSplit() const { return IsSplit; }
128 void setSplit() { IsSplit = 1; }
129
130 bool isSplitEnd() const { return IsSplitEnd; }
131 void setSplitEnd() { IsSplitEnd = 1; }
132
133 bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; }
134 void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; }
135
136 bool isPointer() const { return IsPointer; }
137 void setPointer() { IsPointer = 1; }
138
139 Align getNonZeroMemAlign() const {
140 return decodeMaybeAlign(MemAlign).valueOrOne();
141 }
142
143 void setMemAlign(Align A) {
144 MemAlign = encode(A);
145 assert(getNonZeroMemAlign() == A && "bitfield overflow");
146 }
147
148 Align getNonZeroByValAlign() const {
149 assert(isByVal());
150 MaybeAlign A = decodeMaybeAlign(MemAlign);
151 assert(A && "ByValAlign must be defined");
152 return *A;
153 }
154
155 Align getNonZeroOrigAlign() const {
156 return decodeMaybeAlign(OrigAlign).valueOrOne();
157 }
158
159 void setOrigAlign(Align A) {
160 OrigAlign = encode(A);
161 assert(getNonZeroOrigAlign() == A && "bitfield overflow");
162 }
163
164 unsigned getByValSize() const {
165 assert(isByVal() && !isByRef());
166 return ByValOrByRefSize;
167 }
168 void setByValSize(unsigned S) {
169 assert(isByVal() && !isByRef());
170 ByValOrByRefSize = S;
171 }
172
173 unsigned getByRefSize() const {
174 assert(!isByVal() && isByRef());
175 return ByValOrByRefSize;
176 }
177 void setByRefSize(unsigned S) {
178 assert(!isByVal() && isByRef());
179 ByValOrByRefSize = S;
180 }
181
182 unsigned getPointerAddrSpace() const { return PointerAddrSpace; }
183 void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; }
184};
185
186 /// InputArg - This struct carries flags and type information about a
187 /// single incoming (formal) argument or incoming (from the perspective
188 /// of the caller) return value virtual register.
189 ///
190 struct InputArg {
191 ArgFlagsTy Flags;
192 MVT VT = MVT::Other;
193 EVT ArgVT;
194 bool Used = false;
195
196 /// Index original Function's argument.
197 unsigned OrigArgIndex;
198 /// Sentinel value for implicit machine-level input arguments.
199 static const unsigned NoArgIndex = UINT_MAX;
200
201 /// Offset in bytes of current input value relative to the beginning of
202 /// original argument. E.g. if argument was splitted into four 32 bit
203 /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12.
204 unsigned PartOffset;
205
206 InputArg() = default;
207 InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
208 unsigned origIdx, unsigned partOffs)
209 : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) {
210 VT = vt.getSimpleVT();
211 ArgVT = argvt;
212 }
213
214 bool isOrigArg() const {
215 return OrigArgIndex != NoArgIndex;
216 }
217
218 unsigned getOrigArgIndex() const {
219 assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument");
220 return OrigArgIndex;
221 }
222 };
223
224 /// OutputArg - This struct carries flags and a value for a
225 /// single outgoing (actual) argument or outgoing (from the perspective
226 /// of the caller) return value virtual register.
227 ///
228 struct OutputArg {
229 ArgFlagsTy Flags;
230 MVT VT;
231 EVT ArgVT;
232
233 /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".
234 bool IsFixed = false;
235
236 /// Index original Function's argument.
237 unsigned OrigArgIndex;
238
239 /// Offset in bytes of current output value relative to the beginning of
240 /// original argument. E.g. if argument was splitted into four 32 bit
241 /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12.
242 unsigned PartOffset;
243
244 OutputArg() = default;
245 OutputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool isfixed,
246 unsigned origIdx, unsigned partOffs)
247 : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx),
248 PartOffset(partOffs) {
249 VT = vt.getSimpleVT();
250 ArgVT = argvt;
251 }
252 };
253
254} // end namespace ISD
255} // end namespace llvm
256
257#endif // LLVM_CODEGEN_TARGETCALLINGCONV_H
258