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