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 IsSwiftError : 1; ///< Swift error parameter 43 unsigned IsCFGuardTarget : 1; ///< Control Flow Guard target 44 unsigned IsHva : 1; ///< HVA field for 45 unsigned IsHvaStart : 1; ///< HVA structure start 46 unsigned IsSecArgPass : 1; ///< Second argument 47 unsigned ByValOrByRefAlign : 4; ///< Log 2 of byval/byref alignment 48 unsigned OrigAlign : 5; ///< Log 2 of original alignment 49 unsigned IsInConsecutiveRegsLast : 1; 50 unsigned IsInConsecutiveRegs : 1; 51 unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate 52 unsigned IsPointer : 1; 53 54 unsigned ByValOrByRefSize; ///< Byval or byref struct size 55 56 unsigned PointerAddrSpace; ///< Address space of pointer argument 57 58 /// Set the alignment used by byref or byval parameters. setAlignImplArgFlagsTy59 void setAlignImpl(Align A) { 60 ByValOrByRefAlign = encode(A); 61 assert(getNonZeroByValAlign() == A && "bitfield overflow"); 62 } 63 64 public: ArgFlagsTyArgFlagsTy65 ArgFlagsTy() 66 : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0), 67 IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), IsPreallocated(0), 68 IsSplitEnd(0), IsSwiftSelf(0), IsSwiftError(0), IsCFGuardTarget(0), 69 IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValOrByRefAlign(0), 70 OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), 71 IsCopyElisionCandidate(0), IsPointer(0), ByValOrByRefSize(0), 72 PointerAddrSpace(0) { 73 static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big"); 74 } 75 isZExtArgFlagsTy76 bool isZExt() const { return IsZExt; } setZExtArgFlagsTy77 void setZExt() { IsZExt = 1; } 78 isSExtArgFlagsTy79 bool isSExt() const { return IsSExt; } setSExtArgFlagsTy80 void setSExt() { IsSExt = 1; } 81 isInRegArgFlagsTy82 bool isInReg() const { return IsInReg; } setInRegArgFlagsTy83 void setInReg() { IsInReg = 1; } 84 isSRetArgFlagsTy85 bool isSRet() const { return IsSRet; } setSRetArgFlagsTy86 void setSRet() { IsSRet = 1; } 87 isByValArgFlagsTy88 bool isByVal() const { return IsByVal; } setByValArgFlagsTy89 void setByVal() { IsByVal = 1; } 90 isByRefArgFlagsTy91 bool isByRef() const { return IsByRef; } setByRefArgFlagsTy92 void setByRef() { IsByRef = 1; } 93 isInAllocaArgFlagsTy94 bool isInAlloca() const { return IsInAlloca; } setInAllocaArgFlagsTy95 void setInAlloca() { IsInAlloca = 1; } 96 isPreallocatedArgFlagsTy97 bool isPreallocated() const { return IsPreallocated; } setPreallocatedArgFlagsTy98 void setPreallocated() { IsPreallocated = 1; } 99 isSwiftSelfArgFlagsTy100 bool isSwiftSelf() const { return IsSwiftSelf; } setSwiftSelfArgFlagsTy101 void setSwiftSelf() { IsSwiftSelf = 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; } setReturnedArgFlagsTy122 void setReturned() { IsReturned = 1; } 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 getByValAlignArgFlagsTy144 LLVM_ATTRIBUTE_DEPRECATED(unsigned getByValAlign() const, 145 "Use getNonZeroByValAlign() instead") { 146 MaybeAlign A = decodeMaybeAlign(ByValOrByRefAlign); 147 return A ? A->value() : 0; 148 } getNonZeroByValAlignArgFlagsTy149 Align getNonZeroByValAlign() const { 150 MaybeAlign A = decodeMaybeAlign(ByValOrByRefAlign); 151 assert(A && "ByValAlign must be defined"); 152 return *A; 153 } setByValAlignArgFlagsTy154 void setByValAlign(Align A) { 155 assert(isByVal() && !isByRef()); 156 setAlignImpl(A); 157 } 158 setByRefAlignArgFlagsTy159 void setByRefAlign(Align A) { 160 assert(!isByVal() && isByRef()); 161 setAlignImpl(A); 162 } 163 getOrigAlignArgFlagsTy164 LLVM_ATTRIBUTE_DEPRECATED(unsigned getOrigAlign() const, 165 "Use getNonZeroOrigAlign() instead") { 166 MaybeAlign A = decodeMaybeAlign(OrigAlign); 167 return A ? A->value() : 0; 168 } getNonZeroOrigAlignArgFlagsTy169 Align getNonZeroOrigAlign() const { 170 return decodeMaybeAlign(OrigAlign).valueOrOne(); 171 } setOrigAlignArgFlagsTy172 void setOrigAlign(Align A) { 173 OrigAlign = encode(A); 174 assert(getNonZeroOrigAlign() == A && "bitfield overflow"); 175 } 176 getByValSizeArgFlagsTy177 unsigned getByValSize() const { 178 assert(isByVal() && !isByRef()); 179 return ByValOrByRefSize; 180 } setByValSizeArgFlagsTy181 void setByValSize(unsigned S) { 182 assert(isByVal() && !isByRef()); 183 ByValOrByRefSize = S; 184 } 185 getByRefSizeArgFlagsTy186 unsigned getByRefSize() const { 187 assert(!isByVal() && isByRef()); 188 return ByValOrByRefSize; 189 } setByRefSizeArgFlagsTy190 void setByRefSize(unsigned S) { 191 assert(!isByVal() && isByRef()); 192 ByValOrByRefSize = S; 193 } 194 getPointerAddrSpaceArgFlagsTy195 unsigned getPointerAddrSpace() const { return PointerAddrSpace; } setPointerAddrSpaceArgFlagsTy196 void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; } 197 }; 198 199 /// InputArg - This struct carries flags and type information about a 200 /// single incoming (formal) argument or incoming (from the perspective 201 /// of the caller) return value virtual register. 202 /// 203 struct InputArg { 204 ArgFlagsTy Flags; 205 MVT VT = MVT::Other; 206 EVT ArgVT; 207 bool Used = false; 208 209 /// Index original Function's argument. 210 unsigned OrigArgIndex; 211 /// Sentinel value for implicit machine-level input arguments. 212 static const unsigned NoArgIndex = UINT_MAX; 213 214 /// Offset in bytes of current input value relative to the beginning of 215 /// original argument. E.g. if argument was splitted into four 32 bit 216 /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12. 217 unsigned PartOffset; 218 219 InputArg() = default; InputArgInputArg220 InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used, 221 unsigned origIdx, unsigned partOffs) 222 : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) { 223 VT = vt.getSimpleVT(); 224 ArgVT = argvt; 225 } 226 isOrigArgInputArg227 bool isOrigArg() const { 228 return OrigArgIndex != NoArgIndex; 229 } 230 getOrigArgIndexInputArg231 unsigned getOrigArgIndex() const { 232 assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument"); 233 return OrigArgIndex; 234 } 235 }; 236 237 /// OutputArg - This struct carries flags and a value for a 238 /// single outgoing (actual) argument or outgoing (from the perspective 239 /// of the caller) return value virtual register. 240 /// 241 struct OutputArg { 242 ArgFlagsTy Flags; 243 MVT VT; 244 EVT ArgVT; 245 246 /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...". 247 bool IsFixed = false; 248 249 /// Index original Function's argument. 250 unsigned OrigArgIndex; 251 252 /// Offset in bytes of current output value relative to the beginning of 253 /// original argument. E.g. if argument was splitted into four 32 bit 254 /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12. 255 unsigned PartOffset; 256 257 OutputArg() = default; OutputArgOutputArg258 OutputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool isfixed, 259 unsigned origIdx, unsigned partOffs) 260 : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx), 261 PartOffset(partOffs) { 262 VT = vt.getSimpleVT(); 263 ArgVT = argvt; 264 } 265 }; 266 267 } // end namespace ISD 268 } // end namespace llvm 269 270 #endif // LLVM_CODEGEN_TARGETCALLINGCONV_H 271