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