xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/TargetCallingConv.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/CodeGenTypes/MachineValueType.h"
18  #include "llvm/Support/Alignment.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 : 6; ///< 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) == 4 * 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