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). The max alignment is
50                                ///< verified in IR verification.
51     unsigned OrigAlign : 5;    ///< Log 2 of original alignment
52     unsigned IsInConsecutiveRegsLast : 1;
53     unsigned IsInConsecutiveRegs : 1;
54     unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate
55     unsigned IsPointer : 1;
56 
57     unsigned ByValOrByRefSize = 0; ///< Byval or byref struct size
58 
59     unsigned PointerAddrSpace = 0; ///< Address space of pointer argument
60 
61   public:
ArgFlagsTyArgFlagsTy62     ArgFlagsTy()
63         : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
64           IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0),
65           IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftAsync(0),
66           IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), IsHvaStart(0),
67           IsSecArgPass(0), MemAlign(0), OrigAlign(0),
68           IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
69           IsCopyElisionCandidate(0), IsPointer(0) {
70       static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
71     }
72 
isZExtArgFlagsTy73     bool isZExt() const { return IsZExt; }
setZExtArgFlagsTy74     void setZExt() { IsZExt = 1; }
75 
isSExtArgFlagsTy76     bool isSExt() const { return IsSExt; }
setSExtArgFlagsTy77     void setSExt() { IsSExt = 1; }
78 
isInRegArgFlagsTy79     bool isInReg() const { return IsInReg; }
setInRegArgFlagsTy80     void setInReg() { IsInReg = 1; }
81 
isSRetArgFlagsTy82     bool isSRet() const { return IsSRet; }
setSRetArgFlagsTy83     void setSRet() { IsSRet = 1; }
84 
isByValArgFlagsTy85     bool isByVal() const { return IsByVal; }
setByValArgFlagsTy86     void setByVal() { IsByVal = 1; }
87 
isByRefArgFlagsTy88     bool isByRef() const { return IsByRef; }
setByRefArgFlagsTy89     void setByRef() { IsByRef = 1; }
90 
isInAllocaArgFlagsTy91     bool isInAlloca() const { return IsInAlloca; }
setInAllocaArgFlagsTy92     void setInAlloca() { IsInAlloca = 1; }
93 
isPreallocatedArgFlagsTy94     bool isPreallocated() const { return IsPreallocated; }
setPreallocatedArgFlagsTy95     void setPreallocated() { IsPreallocated = 1; }
96 
isSwiftSelfArgFlagsTy97     bool isSwiftSelf() const { return IsSwiftSelf; }
setSwiftSelfArgFlagsTy98     void setSwiftSelf() { IsSwiftSelf = 1; }
99 
isSwiftAsyncArgFlagsTy100     bool isSwiftAsync() const { return IsSwiftAsync; }
setSwiftAsyncArgFlagsTy101     void setSwiftAsync() { IsSwiftAsync = 1; }
102 
isSwiftErrorArgFlagsTy103     bool isSwiftError() const { return IsSwiftError; }
setSwiftErrorArgFlagsTy104     void setSwiftError() { IsSwiftError = 1; }
105 
isCFGuardTargetArgFlagsTy106     bool isCFGuardTarget() const { return IsCFGuardTarget; }
setCFGuardTargetArgFlagsTy107     void setCFGuardTarget() { IsCFGuardTarget = 1; }
108 
isHvaArgFlagsTy109     bool isHva() const { return IsHva; }
setHvaArgFlagsTy110     void setHva() { IsHva = 1; }
111 
isHvaStartArgFlagsTy112     bool isHvaStart() const { return IsHvaStart; }
setHvaStartArgFlagsTy113     void setHvaStart() { IsHvaStart = 1; }
114 
isSecArgPassArgFlagsTy115     bool isSecArgPass() const { return IsSecArgPass; }
setSecArgPassArgFlagsTy116     void setSecArgPass() { IsSecArgPass = 1; }
117 
isNestArgFlagsTy118     bool isNest() const { return IsNest; }
setNestArgFlagsTy119     void setNest() { IsNest = 1; }
120 
isReturnedArgFlagsTy121     bool isReturned() const { return IsReturned; }
122     void setReturned(bool V = true) { IsReturned = V; }
123 
isInConsecutiveRegsArgFlagsTy124     bool isInConsecutiveRegs()  const { return IsInConsecutiveRegs; }
125     void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; }
126 
isInConsecutiveRegsLastArgFlagsTy127     bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; }
128     void setInConsecutiveRegsLast(bool Flag = true) {
129       IsInConsecutiveRegsLast = Flag;
130     }
131 
isSplitArgFlagsTy132     bool isSplit()   const { return IsSplit; }
setSplitArgFlagsTy133     void setSplit()  { IsSplit = 1; }
134 
isSplitEndArgFlagsTy135     bool isSplitEnd()   const { return IsSplitEnd; }
setSplitEndArgFlagsTy136     void setSplitEnd()  { IsSplitEnd = 1; }
137 
isCopyElisionCandidateArgFlagsTy138     bool isCopyElisionCandidate()  const { return IsCopyElisionCandidate; }
setCopyElisionCandidateArgFlagsTy139     void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; }
140 
isPointerArgFlagsTy141     bool isPointer()  const { return IsPointer; }
setPointerArgFlagsTy142     void setPointer() { IsPointer = 1; }
143 
getNonZeroMemAlignArgFlagsTy144     Align getNonZeroMemAlign() const {
145       return decodeMaybeAlign(MemAlign).valueOrOne();
146     }
147 
setMemAlignArgFlagsTy148     void setMemAlign(Align A) {
149       MemAlign = encode(A);
150       assert(getNonZeroMemAlign() == A && "bitfield overflow");
151     }
152 
getNonZeroByValAlignArgFlagsTy153     Align getNonZeroByValAlign() const {
154       assert(isByVal());
155       MaybeAlign A = decodeMaybeAlign(MemAlign);
156       assert(A && "ByValAlign must be defined");
157       return *A;
158     }
159 
getNonZeroOrigAlignArgFlagsTy160     Align getNonZeroOrigAlign() const {
161       return decodeMaybeAlign(OrigAlign).valueOrOne();
162     }
163 
setOrigAlignArgFlagsTy164     void setOrigAlign(Align A) {
165       OrigAlign = encode(A);
166       assert(getNonZeroOrigAlign() == A && "bitfield overflow");
167     }
168 
getByValSizeArgFlagsTy169     unsigned getByValSize() const {
170       assert(isByVal() && !isByRef());
171       return ByValOrByRefSize;
172     }
setByValSizeArgFlagsTy173     void setByValSize(unsigned S) {
174       assert(isByVal() && !isByRef());
175       ByValOrByRefSize = S;
176     }
177 
getByRefSizeArgFlagsTy178     unsigned getByRefSize() const {
179       assert(!isByVal() && isByRef());
180       return ByValOrByRefSize;
181     }
setByRefSizeArgFlagsTy182     void setByRefSize(unsigned S) {
183       assert(!isByVal() && isByRef());
184       ByValOrByRefSize = S;
185     }
186 
getPointerAddrSpaceArgFlagsTy187     unsigned getPointerAddrSpace() const { return PointerAddrSpace; }
setPointerAddrSpaceArgFlagsTy188     void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; }
189 };
190 
191   /// InputArg - This struct carries flags and type information about a
192   /// single incoming (formal) argument or incoming (from the perspective
193   /// of the caller) return value virtual register.
194   ///
195   struct InputArg {
196     ArgFlagsTy Flags;
197     MVT VT = MVT::Other;
198     EVT ArgVT;
199     bool Used = false;
200 
201     /// Index original Function's argument.
202     unsigned OrigArgIndex;
203     /// Sentinel value for implicit machine-level input arguments.
204     static const unsigned NoArgIndex = UINT_MAX;
205 
206     /// Offset in bytes of current input value relative to the beginning of
207     /// original argument. E.g. if argument was splitted into four 32 bit
208     /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12.
209     unsigned PartOffset;
210 
211     InputArg() = default;
InputArgInputArg212     InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
213              unsigned origIdx, unsigned partOffs)
214       : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) {
215       VT = vt.getSimpleVT();
216       ArgVT = argvt;
217     }
218 
isOrigArgInputArg219     bool isOrigArg() const {
220       return OrigArgIndex != NoArgIndex;
221     }
222 
getOrigArgIndexInputArg223     unsigned getOrigArgIndex() const {
224       assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument");
225       return OrigArgIndex;
226     }
227   };
228 
229   /// OutputArg - This struct carries flags and a value for a
230   /// single outgoing (actual) argument or outgoing (from the perspective
231   /// of the caller) return value virtual register.
232   ///
233   struct OutputArg {
234     ArgFlagsTy Flags;
235     MVT VT;
236     EVT ArgVT;
237 
238     /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".
239     bool IsFixed = false;
240 
241     /// Index original Function's argument.
242     unsigned OrigArgIndex;
243 
244     /// Offset in bytes of current output value relative to the beginning of
245     /// original argument. E.g. if argument was splitted into four 32 bit
246     /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12.
247     unsigned PartOffset;
248 
249     OutputArg() = default;
OutputArgOutputArg250     OutputArg(ArgFlagsTy flags, MVT vt, EVT argvt, bool isfixed,
251               unsigned origIdx, unsigned partOffs)
252         : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx),
253           PartOffset(partOffs) {
254       VT = vt;
255       ArgVT = argvt;
256     }
257   };
258 
259 } // end namespace ISD
260 } // end namespace llvm
261 
262 #endif // LLVM_CODEGEN_TARGETCALLINGCONV_H
263