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: 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) == 3 * 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