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 IsNoExt : 1; ///< No extension 32 unsigned IsInReg : 1; ///< Passed in register 33 unsigned IsSRet : 1; ///< Hidden struct-ret ptr 34 unsigned IsByVal : 1; ///< Struct passed by value 35 unsigned IsByRef : 1; ///< Passed in memory 36 unsigned IsNest : 1; ///< Nested fn static chain 37 unsigned IsReturned : 1; ///< Always returned 38 unsigned IsSplit : 1; 39 unsigned IsInAlloca : 1; ///< Passed with inalloca 40 unsigned IsPreallocated : 1; ///< ByVal without the copy 41 unsigned IsSplitEnd : 1; ///< Last part of a split 42 unsigned IsSwiftSelf : 1; ///< Swift self parameter 43 unsigned IsSwiftAsync : 1; ///< Swift async context parameter 44 unsigned IsSwiftError : 1; ///< Swift error parameter 45 unsigned IsCFGuardTarget : 1; ///< Control Flow Guard target 46 unsigned IsHva : 1; ///< HVA field for 47 unsigned IsHvaStart : 1; ///< HVA structure start 48 unsigned IsSecArgPass : 1; ///< Second argument 49 unsigned MemAlign : 6; ///< Log 2 of alignment when arg is passed in memory 50 ///< (including byval/byref). The max alignment is 51 ///< verified in IR verification. 52 unsigned OrigAlign : 5; ///< Log 2 of original alignment 53 unsigned IsInConsecutiveRegsLast : 1; 54 unsigned IsInConsecutiveRegs : 1; 55 unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate 56 unsigned IsPointer : 1; 57 58 unsigned ByValOrByRefSize = 0; ///< Byval or byref struct size 59 60 unsigned PointerAddrSpace = 0; ///< Address space of pointer argument 61 62 public: 63 ArgFlagsTy() 64 : IsZExt(0), IsSExt(0), IsNoExt(0), IsInReg(0), IsSRet(0), IsByVal(0), 65 IsByRef(0), IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), 66 IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftAsync(0), 67 IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), IsHvaStart(0), 68 IsSecArgPass(0), MemAlign(0), OrigAlign(0), 69 IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), 70 IsCopyElisionCandidate(0), IsPointer(0) { 71 static_assert(sizeof(*this) == 4 * sizeof(unsigned), "flags are too big"); 72 } 73 74 bool isZExt() const { return IsZExt; } 75 void setZExt() { IsZExt = 1; } 76 77 bool isSExt() const { return IsSExt; } 78 void setSExt() { IsSExt = 1; } 79 80 bool isNoExt() const { return IsNoExt; } 81 void setNoExt() { IsNoExt = 1; } 82 83 bool isInReg() const { return IsInReg; } 84 void setInReg() { IsInReg = 1; } 85 86 bool isSRet() const { return IsSRet; } 87 void setSRet() { IsSRet = 1; } 88 89 bool isByVal() const { return IsByVal; } 90 void setByVal() { IsByVal = 1; } 91 92 bool isByRef() const { return IsByRef; } 93 void setByRef() { IsByRef = 1; } 94 95 bool isInAlloca() const { return IsInAlloca; } 96 void setInAlloca() { IsInAlloca = 1; } 97 98 bool isPreallocated() const { return IsPreallocated; } 99 void setPreallocated() { IsPreallocated = 1; } 100 101 bool isSwiftSelf() const { return IsSwiftSelf; } 102 void setSwiftSelf() { IsSwiftSelf = 1; } 103 104 bool isSwiftAsync() const { return IsSwiftAsync; } 105 void setSwiftAsync() { IsSwiftAsync = 1; } 106 107 bool isSwiftError() const { return IsSwiftError; } 108 void setSwiftError() { IsSwiftError = 1; } 109 110 bool isCFGuardTarget() const { return IsCFGuardTarget; } 111 void setCFGuardTarget() { IsCFGuardTarget = 1; } 112 113 bool isHva() const { return IsHva; } 114 void setHva() { IsHva = 1; } 115 116 bool isHvaStart() const { return IsHvaStart; } 117 void setHvaStart() { IsHvaStart = 1; } 118 119 bool isSecArgPass() const { return IsSecArgPass; } 120 void setSecArgPass() { IsSecArgPass = 1; } 121 122 bool isNest() const { return IsNest; } 123 void setNest() { IsNest = 1; } 124 125 bool isReturned() const { return IsReturned; } 126 void setReturned(bool V = true) { IsReturned = V; } 127 128 bool isInConsecutiveRegs() const { return IsInConsecutiveRegs; } 129 void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; } 130 131 bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; } 132 void setInConsecutiveRegsLast(bool Flag = true) { 133 IsInConsecutiveRegsLast = Flag; 134 } 135 136 bool isSplit() const { return IsSplit; } 137 void setSplit() { IsSplit = 1; } 138 139 bool isSplitEnd() const { return IsSplitEnd; } 140 void setSplitEnd() { IsSplitEnd = 1; } 141 142 bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; } 143 void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; } 144 145 bool isPointer() const { return IsPointer; } 146 void setPointer() { IsPointer = 1; } 147 148 Align getNonZeroMemAlign() const { 149 return decodeMaybeAlign(MemAlign).valueOrOne(); 150 } 151 152 void setMemAlign(Align A) { 153 MemAlign = encode(A); 154 assert(getNonZeroMemAlign() == A && "bitfield overflow"); 155 } 156 157 Align getNonZeroByValAlign() const { 158 assert(isByVal()); 159 MaybeAlign A = decodeMaybeAlign(MemAlign); 160 assert(A && "ByValAlign must be defined"); 161 return *A; 162 } 163 164 Align getNonZeroOrigAlign() const { 165 return decodeMaybeAlign(OrigAlign).valueOrOne(); 166 } 167 168 void setOrigAlign(Align A) { 169 OrigAlign = encode(A); 170 assert(getNonZeroOrigAlign() == A && "bitfield overflow"); 171 } 172 173 unsigned getByValSize() const { 174 assert(isByVal() && !isByRef()); 175 return ByValOrByRefSize; 176 } 177 void setByValSize(unsigned S) { 178 assert(isByVal() && !isByRef()); 179 ByValOrByRefSize = S; 180 } 181 182 unsigned getByRefSize() const { 183 assert(!isByVal() && isByRef()); 184 return ByValOrByRefSize; 185 } 186 void setByRefSize(unsigned S) { 187 assert(!isByVal() && isByRef()); 188 ByValOrByRefSize = S; 189 } 190 191 unsigned getPointerAddrSpace() const { return PointerAddrSpace; } 192 void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; } 193 }; 194 195 /// InputArg - This struct carries flags and type information about a 196 /// single incoming (formal) argument or incoming (from the perspective 197 /// of the caller) return value virtual register. 198 /// 199 struct InputArg { 200 ArgFlagsTy Flags; 201 MVT VT = MVT::Other; 202 EVT ArgVT; 203 bool Used = false; 204 205 /// Index original Function's argument. 206 unsigned OrigArgIndex; 207 /// Sentinel value for implicit machine-level input arguments. 208 static const unsigned NoArgIndex = UINT_MAX; 209 210 /// Offset in bytes of current input value relative to the beginning of 211 /// original argument. E.g. if argument was splitted into four 32 bit 212 /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12. 213 unsigned PartOffset; 214 215 InputArg() = default; 216 InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used, 217 unsigned origIdx, unsigned partOffs) 218 : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) { 219 VT = vt.getSimpleVT(); 220 ArgVT = argvt; 221 } 222 223 bool isOrigArg() const { 224 return OrigArgIndex != NoArgIndex; 225 } 226 227 unsigned getOrigArgIndex() const { 228 assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument"); 229 return OrigArgIndex; 230 } 231 }; 232 233 /// OutputArg - This struct carries flags and a value for a 234 /// single outgoing (actual) argument or outgoing (from the perspective 235 /// of the caller) return value virtual register. 236 /// 237 struct OutputArg { 238 ArgFlagsTy Flags; 239 MVT VT; 240 EVT ArgVT; 241 242 /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...". 243 bool IsFixed = false; 244 245 /// Index original Function's argument. 246 unsigned OrigArgIndex; 247 248 /// Offset in bytes of current output value relative to the beginning of 249 /// original argument. E.g. if argument was splitted into four 32 bit 250 /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12. 251 unsigned PartOffset; 252 253 OutputArg() = default; 254 OutputArg(ArgFlagsTy flags, MVT vt, EVT argvt, bool isfixed, 255 unsigned origIdx, unsigned partOffs) 256 : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx), 257 PartOffset(partOffs) { 258 VT = vt; 259 ArgVT = argvt; 260 } 261 }; 262 263 } // end namespace ISD 264 } // end namespace llvm 265 266 #endif // LLVM_CODEGEN_TARGETCALLINGCONV_H 267