• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 ByValOrByRefAlign : 4; ///< Log 2 of byval/byref alignment
48     unsigned OrigAlign : 5;    ///< Log 2 of original alignment
49     unsigned IsInConsecutiveRegsLast : 1;
50     unsigned IsInConsecutiveRegs : 1;
51     unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate
52     unsigned IsPointer : 1;
53 
54     unsigned ByValOrByRefSize; ///< Byval or byref struct size
55 
56     unsigned PointerAddrSpace; ///< Address space of pointer argument
57 
58     /// Set the alignment used by byref or byval parameters.
setAlignImplArgFlagsTy59     void setAlignImpl(Align A) {
60       ByValOrByRefAlign = encode(A);
61       assert(getNonZeroByValAlign() == A && "bitfield overflow");
62     }
63 
64   public:
ArgFlagsTyArgFlagsTy65     ArgFlagsTy()
66       : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
67           IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), IsPreallocated(0),
68           IsSplitEnd(0), IsSwiftSelf(0), IsSwiftError(0), IsCFGuardTarget(0),
69           IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValOrByRefAlign(0),
70           OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
71           IsCopyElisionCandidate(0), IsPointer(0), ByValOrByRefSize(0),
72           PointerAddrSpace(0) {
73       static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
74     }
75 
isZExtArgFlagsTy76     bool isZExt() const { return IsZExt; }
setZExtArgFlagsTy77     void setZExt() { IsZExt = 1; }
78 
isSExtArgFlagsTy79     bool isSExt() const { return IsSExt; }
setSExtArgFlagsTy80     void setSExt() { IsSExt = 1; }
81 
isInRegArgFlagsTy82     bool isInReg() const { return IsInReg; }
setInRegArgFlagsTy83     void setInReg() { IsInReg = 1; }
84 
isSRetArgFlagsTy85     bool isSRet() const { return IsSRet; }
setSRetArgFlagsTy86     void setSRet() { IsSRet = 1; }
87 
isByValArgFlagsTy88     bool isByVal() const { return IsByVal; }
setByValArgFlagsTy89     void setByVal() { IsByVal = 1; }
90 
isByRefArgFlagsTy91     bool isByRef() const { return IsByRef; }
setByRefArgFlagsTy92     void setByRef() { IsByRef = 1; }
93 
isInAllocaArgFlagsTy94     bool isInAlloca() const { return IsInAlloca; }
setInAllocaArgFlagsTy95     void setInAlloca() { IsInAlloca = 1; }
96 
isPreallocatedArgFlagsTy97     bool isPreallocated() const { return IsPreallocated; }
setPreallocatedArgFlagsTy98     void setPreallocated() { IsPreallocated = 1; }
99 
isSwiftSelfArgFlagsTy100     bool isSwiftSelf() const { return IsSwiftSelf; }
setSwiftSelfArgFlagsTy101     void setSwiftSelf() { IsSwiftSelf = 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; }
setReturnedArgFlagsTy122     void setReturned() { IsReturned = 1; }
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 
getByValAlignArgFlagsTy144     LLVM_ATTRIBUTE_DEPRECATED(unsigned getByValAlign() const,
145                               "Use getNonZeroByValAlign() instead") {
146       MaybeAlign A = decodeMaybeAlign(ByValOrByRefAlign);
147       return A ? A->value() : 0;
148     }
getNonZeroByValAlignArgFlagsTy149     Align getNonZeroByValAlign() const {
150       MaybeAlign A = decodeMaybeAlign(ByValOrByRefAlign);
151       assert(A && "ByValAlign must be defined");
152       return *A;
153     }
setByValAlignArgFlagsTy154     void setByValAlign(Align A) {
155       assert(isByVal() && !isByRef());
156       setAlignImpl(A);
157     }
158 
setByRefAlignArgFlagsTy159     void setByRefAlign(Align A) {
160       assert(!isByVal() && isByRef());
161       setAlignImpl(A);
162     }
163 
getOrigAlignArgFlagsTy164     LLVM_ATTRIBUTE_DEPRECATED(unsigned getOrigAlign() const,
165                               "Use getNonZeroOrigAlign() instead") {
166       MaybeAlign A = decodeMaybeAlign(OrigAlign);
167       return A ? A->value() : 0;
168     }
getNonZeroOrigAlignArgFlagsTy169     Align getNonZeroOrigAlign() const {
170       return decodeMaybeAlign(OrigAlign).valueOrOne();
171     }
setOrigAlignArgFlagsTy172     void setOrigAlign(Align A) {
173       OrigAlign = encode(A);
174       assert(getNonZeroOrigAlign() == A && "bitfield overflow");
175     }
176 
getByValSizeArgFlagsTy177     unsigned getByValSize() const {
178       assert(isByVal() && !isByRef());
179       return ByValOrByRefSize;
180     }
setByValSizeArgFlagsTy181     void setByValSize(unsigned S) {
182       assert(isByVal() && !isByRef());
183       ByValOrByRefSize = S;
184     }
185 
getByRefSizeArgFlagsTy186     unsigned getByRefSize() const {
187       assert(!isByVal() && isByRef());
188       return ByValOrByRefSize;
189     }
setByRefSizeArgFlagsTy190     void setByRefSize(unsigned S) {
191       assert(!isByVal() && isByRef());
192       ByValOrByRefSize = S;
193     }
194 
getPointerAddrSpaceArgFlagsTy195     unsigned getPointerAddrSpace() const { return PointerAddrSpace; }
setPointerAddrSpaceArgFlagsTy196     void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; }
197 };
198 
199   /// InputArg - This struct carries flags and type information about a
200   /// single incoming (formal) argument or incoming (from the perspective
201   /// of the caller) return value virtual register.
202   ///
203   struct InputArg {
204     ArgFlagsTy Flags;
205     MVT VT = MVT::Other;
206     EVT ArgVT;
207     bool Used = false;
208 
209     /// Index original Function's argument.
210     unsigned OrigArgIndex;
211     /// Sentinel value for implicit machine-level input arguments.
212     static const unsigned NoArgIndex = UINT_MAX;
213 
214     /// Offset in bytes of current input value relative to the beginning of
215     /// original argument. E.g. if argument was splitted into four 32 bit
216     /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12.
217     unsigned PartOffset;
218 
219     InputArg() = default;
InputArgInputArg220     InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
221              unsigned origIdx, unsigned partOffs)
222       : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) {
223       VT = vt.getSimpleVT();
224       ArgVT = argvt;
225     }
226 
isOrigArgInputArg227     bool isOrigArg() const {
228       return OrigArgIndex != NoArgIndex;
229     }
230 
getOrigArgIndexInputArg231     unsigned getOrigArgIndex() const {
232       assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument");
233       return OrigArgIndex;
234     }
235   };
236 
237   /// OutputArg - This struct carries flags and a value for a
238   /// single outgoing (actual) argument or outgoing (from the perspective
239   /// of the caller) return value virtual register.
240   ///
241   struct OutputArg {
242     ArgFlagsTy Flags;
243     MVT VT;
244     EVT ArgVT;
245 
246     /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".
247     bool IsFixed = false;
248 
249     /// Index original Function's argument.
250     unsigned OrigArgIndex;
251 
252     /// Offset in bytes of current output value relative to the beginning of
253     /// original argument. E.g. if argument was splitted into four 32 bit
254     /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12.
255     unsigned PartOffset;
256 
257     OutputArg() = default;
OutputArgOutputArg258     OutputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool isfixed,
259               unsigned origIdx, unsigned partOffs)
260       : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx),
261         PartOffset(partOffs) {
262       VT = vt.getSimpleVT();
263       ArgVT = argvt;
264     }
265   };
266 
267 } // end namespace ISD
268 } // end namespace llvm
269 
270 #endif // LLVM_CODEGEN_TARGETCALLINGCONV_H
271