Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 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: | ||
| 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 |