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/MachineValueType.h"
17#include "llvm/CodeGen/ValueTypes.h"
18#include "llvm/Support/Alignment.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 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:
62    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
73    bool isZExt() const { return IsZExt; }
74    void setZExt() { IsZExt = 1; }
75
76    bool isSExt() const { return IsSExt; }
77    void setSExt() { IsSExt = 1; }
78
79    bool isInReg() const { return IsInReg; }
80    void setInReg() { IsInReg = 1; }
81
82    bool isSRet() const { return IsSRet; }
83    void setSRet() { IsSRet = 1; }
84
85    bool isByVal() const { return IsByVal; }
86    void setByVal() { IsByVal = 1; }
87
88    bool isByRef() const { return IsByRef; }
89    void setByRef() { IsByRef = 1; }
90
91    bool isInAlloca() const { return IsInAlloca; }
92    void setInAlloca() { IsInAlloca = 1; }
93
94    bool isPreallocated() const { return IsPreallocated; }
95    void setPreallocated() { IsPreallocated = 1; }
96
97    bool isSwiftSelf() const { return IsSwiftSelf; }
98    void setSwiftSelf() { IsSwiftSelf = 1; }
99
100    bool isSwiftAsync() const { return IsSwiftAsync; }
101    void setSwiftAsync() { IsSwiftAsync = 1; }
102
103    bool isSwiftError() const { return IsSwiftError; }
104    void setSwiftError() { IsSwiftError = 1; }
105
106    bool isCFGuardTarget() const { return IsCFGuardTarget; }
107    void setCFGuardTarget() { IsCFGuardTarget = 1; }
108
109    bool isHva() const { return IsHva; }
110    void setHva() { IsHva = 1; }
111
112    bool isHvaStart() const { return IsHvaStart; }
113    void setHvaStart() { IsHvaStart = 1; }
114
115    bool isSecArgPass() const { return IsSecArgPass; }
116    void setSecArgPass() { IsSecArgPass = 1; }
117
118    bool isNest() const { return IsNest; }
119    void setNest() { IsNest = 1; }
120
121    bool isReturned() const { return IsReturned; }
122    void setReturned(bool V = true) { IsReturned = V; }
123
124    bool isInConsecutiveRegs()  const { return IsInConsecutiveRegs; }
125    void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; }
126
127    bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; }
128    void setInConsecutiveRegsLast(bool Flag = true) {
129      IsInConsecutiveRegsLast = Flag;
130    }
131
132    bool isSplit()   const { return IsSplit; }
133    void setSplit()  { IsSplit = 1; }
134
135    bool isSplitEnd()   const { return IsSplitEnd; }
136    void setSplitEnd()  { IsSplitEnd = 1; }
137
138    bool isCopyElisionCandidate()  const { return IsCopyElisionCandidate; }
139    void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; }
140
141    bool isPointer()  const { return IsPointer; }
142    void setPointer() { IsPointer = 1; }
143
144    Align getNonZeroMemAlign() const {
145      return decodeMaybeAlign(MemAlign).valueOrOne();
146    }
147
148    void setMemAlign(Align A) {
149      MemAlign = encode(A);
150      assert(getNonZeroMemAlign() == A && "bitfield overflow");
151    }
152
153    Align getNonZeroByValAlign() const {
154      assert(isByVal());
155      MaybeAlign A = decodeMaybeAlign(MemAlign);
156      assert(A && "ByValAlign must be defined");
157      return *A;
158    }
159
160    Align getNonZeroOrigAlign() const {
161      return decodeMaybeAlign(OrigAlign).valueOrOne();
162    }
163
164    void setOrigAlign(Align A) {
165      OrigAlign = encode(A);
166      assert(getNonZeroOrigAlign() == A && "bitfield overflow");
167    }
168
169    unsigned getByValSize() const {
170      assert(isByVal() && !isByRef());
171      return ByValOrByRefSize;
172    }
173    void setByValSize(unsigned S) {
174      assert(isByVal() && !isByRef());
175      ByValOrByRefSize = S;
176    }
177
178    unsigned getByRefSize() const {
179      assert(!isByVal() && isByRef());
180      return ByValOrByRefSize;
181    }
182    void setByRefSize(unsigned S) {
183      assert(!isByVal() && isByRef());
184      ByValOrByRefSize = S;
185    }
186
187    unsigned getPointerAddrSpace() const { return PointerAddrSpace; }
188    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;
212    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
219    bool isOrigArg() const {
220      return OrigArgIndex != NoArgIndex;
221    }
222
223    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;
250    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