Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:52

0001 //==-- CGFunctionInfo.h - Representation of function argument/return types -==//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Defines CGFunctionInfo and associated types used in representing the
0010 // LLVM source types and ABI-coerced types for function arguments and
0011 // return values.
0012 //
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
0016 #define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
0017 
0018 #include "clang/AST/CanonicalType.h"
0019 #include "clang/AST/CharUnits.h"
0020 #include "clang/AST/Decl.h"
0021 #include "clang/AST/Type.h"
0022 #include "llvm/IR/DerivedTypes.h"
0023 #include "llvm/ADT/FoldingSet.h"
0024 #include "llvm/Support/TrailingObjects.h"
0025 #include <cassert>
0026 
0027 namespace clang {
0028 namespace CodeGen {
0029 
0030 /// ABIArgInfo - Helper class to encapsulate information about how a
0031 /// specific C type should be passed to or returned from a function.
0032 class ABIArgInfo {
0033 public:
0034   enum Kind : uint8_t {
0035     /// Direct - Pass the argument directly using the normal converted LLVM
0036     /// type, or by coercing to another specified type stored in
0037     /// 'CoerceToType').  If an offset is specified (in UIntData), then the
0038     /// argument passed is offset by some number of bytes in the memory
0039     /// representation. A dummy argument is emitted before the real argument
0040     /// if the specified type stored in "PaddingType" is not zero.
0041     Direct,
0042 
0043     /// Extend - Valid only for integer argument types. Same as 'direct'
0044     /// but also emit a zero/sign extension attribute.
0045     Extend,
0046 
0047     /// Indirect - Pass the argument indirectly via a hidden pointer with the
0048     /// specified alignment (0 indicates default alignment) and address space.
0049     Indirect,
0050 
0051     /// IndirectAliased - Similar to Indirect, but the pointer may be to an
0052     /// object that is otherwise referenced.  The object is known to not be
0053     /// modified through any other references for the duration of the call, and
0054     /// the callee must not itself modify the object.  Because C allows
0055     /// parameter variables to be modified and guarantees that they have unique
0056     /// addresses, the callee must defensively copy the object into a local
0057     /// variable if it might be modified or its address might be compared.
0058     /// Since those are uncommon, in principle this convention allows programs
0059     /// to avoid copies in more situations.  However, it may introduce *extra*
0060     /// copies if the callee fails to prove that a copy is unnecessary and the
0061     /// caller naturally produces an unaliased object for the argument.
0062     IndirectAliased,
0063 
0064     /// Ignore - Ignore the argument (treat as void). Useful for void and
0065     /// empty structs.
0066     Ignore,
0067 
0068     /// Expand - Only valid for aggregate argument types. The structure should
0069     /// be expanded into consecutive arguments for its constituent fields.
0070     /// Currently expand is only allowed on structures whose fields
0071     /// are all scalar types or are themselves expandable types.
0072     Expand,
0073 
0074     /// CoerceAndExpand - Only valid for aggregate argument types. The
0075     /// structure should be expanded into consecutive arguments corresponding
0076     /// to the non-array elements of the type stored in CoerceToType.
0077     /// Array elements in the type are assumed to be padding and skipped.
0078     CoerceAndExpand,
0079 
0080     /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
0081     /// This is similar to indirect with byval, except it only applies to
0082     /// arguments stored in memory and forbids any implicit copies.  When
0083     /// applied to a return type, it means the value is returned indirectly via
0084     /// an implicit sret parameter stored in the argument struct.
0085     InAlloca,
0086     KindFirst = Direct,
0087     KindLast = InAlloca
0088   };
0089 
0090 private:
0091   llvm::Type *TypeData; // canHaveCoerceToType()
0092   union {
0093     llvm::Type *PaddingType; // canHavePaddingType()
0094     llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand()
0095   };
0096   struct DirectAttrInfo {
0097     unsigned Offset;
0098     unsigned Align;
0099   };
0100   struct IndirectAttrInfo {
0101     unsigned Align;
0102     unsigned AddrSpace;
0103   };
0104   union {
0105     DirectAttrInfo DirectAttr;     // isDirect() || isExtend()
0106     IndirectAttrInfo IndirectAttr; // isIndirect()
0107     unsigned AllocaFieldIndex; // isInAlloca()
0108   };
0109   Kind TheKind;
0110   bool PaddingInReg : 1;
0111   bool InAllocaSRet : 1;    // isInAlloca()
0112   bool InAllocaIndirect : 1;// isInAlloca()
0113   bool IndirectByVal : 1;   // isIndirect()
0114   bool IndirectRealign : 1; // isIndirect()
0115   bool SRetAfterThis : 1;   // isIndirect()
0116   bool InReg : 1;           // isDirect() || isExtend() || isIndirect()
0117   bool CanBeFlattened: 1;   // isDirect()
0118   bool SignExt : 1;         // isExtend()
0119   bool ZeroExt : 1;         // isExtend()
0120 
0121   bool canHavePaddingType() const {
0122     return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
0123            isExpand();
0124   }
0125   void setPaddingType(llvm::Type *T) {
0126     assert(canHavePaddingType());
0127     PaddingType = T;
0128   }
0129 
0130   void setUnpaddedCoerceToType(llvm::Type *T) {
0131     assert(isCoerceAndExpand());
0132     UnpaddedCoerceAndExpandType = T;
0133   }
0134 
0135 public:
0136   ABIArgInfo(Kind K = Direct)
0137       : TypeData(nullptr), PaddingType(nullptr), DirectAttr{0, 0}, TheKind(K),
0138         PaddingInReg(false), InAllocaSRet(false),
0139         InAllocaIndirect(false), IndirectByVal(false), IndirectRealign(false),
0140         SRetAfterThis(false), InReg(false), CanBeFlattened(false),
0141         SignExt(false), ZeroExt(false) {}
0142 
0143   static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
0144                               llvm::Type *Padding = nullptr,
0145                               bool CanBeFlattened = true, unsigned Align = 0) {
0146     auto AI = ABIArgInfo(Direct);
0147     AI.setCoerceToType(T);
0148     AI.setPaddingType(Padding);
0149     AI.setDirectOffset(Offset);
0150     AI.setDirectAlign(Align);
0151     AI.setCanBeFlattened(CanBeFlattened);
0152     return AI;
0153   }
0154   static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
0155     auto AI = getDirect(T);
0156     AI.setInReg(true);
0157     return AI;
0158   }
0159 
0160   static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) {
0161     assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
0162     auto AI = ABIArgInfo(Extend);
0163     AI.setCoerceToType(T);
0164     AI.setPaddingType(nullptr);
0165     AI.setDirectOffset(0);
0166     AI.setDirectAlign(0);
0167     AI.setSignExt(true);
0168     return AI;
0169   }
0170 
0171   static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) {
0172     assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
0173     auto AI = ABIArgInfo(Extend);
0174     AI.setCoerceToType(T);
0175     AI.setPaddingType(nullptr);
0176     AI.setDirectOffset(0);
0177     AI.setDirectAlign(0);
0178     AI.setZeroExt(true);
0179     return AI;
0180   }
0181 
0182   // ABIArgInfo will record the argument as being extended based on the sign
0183   // of its type. Produces a sign or zero extension.
0184   static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
0185     assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
0186     if (Ty->hasSignedIntegerRepresentation())
0187       return getSignExtend(Ty, T);
0188     return getZeroExtend(Ty, T);
0189   }
0190 
0191   // Struct in register marked explicitly as not needing extension.
0192   static ABIArgInfo getNoExtend(llvm::IntegerType *T) {
0193     auto AI = ABIArgInfo(Extend);
0194     AI.setCoerceToType(T);
0195     AI.setPaddingType(nullptr);
0196     AI.setDirectOffset(0);
0197     AI.setDirectAlign(0);
0198     return AI;
0199   }
0200 
0201   static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
0202     auto AI = getExtend(Ty, T);
0203     AI.setInReg(true);
0204     return AI;
0205   }
0206   static ABIArgInfo getIgnore() {
0207     return ABIArgInfo(Ignore);
0208   }
0209   static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
0210                                 bool Realign = false,
0211                                 llvm::Type *Padding = nullptr) {
0212     auto AI = ABIArgInfo(Indirect);
0213     AI.setIndirectAlign(Alignment);
0214     AI.setIndirectByVal(ByVal);
0215     AI.setIndirectRealign(Realign);
0216     AI.setSRetAfterThis(false);
0217     AI.setPaddingType(Padding);
0218     return AI;
0219   }
0220 
0221   /// Pass this in memory using the IR byref attribute.
0222   static ABIArgInfo getIndirectAliased(CharUnits Alignment, unsigned AddrSpace,
0223                                        bool Realign = false,
0224                                        llvm::Type *Padding = nullptr) {
0225     auto AI = ABIArgInfo(IndirectAliased);
0226     AI.setIndirectAlign(Alignment);
0227     AI.setIndirectRealign(Realign);
0228     AI.setPaddingType(Padding);
0229     AI.setIndirectAddrSpace(AddrSpace);
0230     return AI;
0231   }
0232 
0233   static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
0234                                      bool Realign = false) {
0235     auto AI = getIndirect(Alignment, ByVal, Realign);
0236     AI.setInReg(true);
0237     return AI;
0238   }
0239   static ABIArgInfo getInAlloca(unsigned FieldIndex, bool Indirect = false) {
0240     auto AI = ABIArgInfo(InAlloca);
0241     AI.setInAllocaFieldIndex(FieldIndex);
0242     AI.setInAllocaIndirect(Indirect);
0243     return AI;
0244   }
0245   static ABIArgInfo getExpand() {
0246     auto AI = ABIArgInfo(Expand);
0247     AI.setPaddingType(nullptr);
0248     return AI;
0249   }
0250   static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
0251                                          llvm::Type *Padding) {
0252     auto AI = getExpand();
0253     AI.setPaddingInReg(PaddingInReg);
0254     AI.setPaddingType(Padding);
0255     return AI;
0256   }
0257 
0258   /// \param unpaddedCoerceToType The coerce-to type with padding elements
0259   ///   removed, canonicalized to a single element if it would otherwise
0260   ///   have exactly one element.
0261   static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
0262                                        llvm::Type *unpaddedCoerceToType) {
0263 #ifndef NDEBUG
0264     // Check that unpaddedCoerceToType has roughly the right shape.
0265 
0266     // Assert that we only have a struct type if there are multiple elements.
0267     auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType);
0268     assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1);
0269 
0270     // Assert that all the non-padding elements have a corresponding element
0271     // in the unpadded type.
0272     unsigned unpaddedIndex = 0;
0273     for (auto eltType : coerceToType->elements()) {
0274       if (isPaddingForCoerceAndExpand(eltType))
0275         continue;
0276       unpaddedIndex++;
0277     }
0278 
0279     // Assert that there aren't extra elements in the unpadded type.
0280     if (unpaddedStruct) {
0281       assert(unpaddedStruct->getNumElements() == unpaddedIndex);
0282     } else {
0283       assert(unpaddedIndex == 1);
0284     }
0285 #endif
0286 
0287     auto AI = ABIArgInfo(CoerceAndExpand);
0288     AI.setCoerceToType(coerceToType);
0289     AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
0290     return AI;
0291   }
0292 
0293   static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
0294     return eltType->isArrayTy() &&
0295            eltType->getArrayElementType()->isIntegerTy(8);
0296   }
0297 
0298   Kind getKind() const { return TheKind; }
0299   bool isDirect() const { return TheKind == Direct; }
0300   bool isInAlloca() const { return TheKind == InAlloca; }
0301   bool isExtend() const { return TheKind == Extend; }
0302   bool isIgnore() const { return TheKind == Ignore; }
0303   bool isIndirect() const { return TheKind == Indirect; }
0304   bool isIndirectAliased() const { return TheKind == IndirectAliased; }
0305   bool isExpand() const { return TheKind == Expand; }
0306   bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
0307 
0308   bool canHaveCoerceToType() const {
0309     return isDirect() || isExtend() || isCoerceAndExpand();
0310   }
0311 
0312   // Direct/Extend accessors
0313   unsigned getDirectOffset() const {
0314     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
0315     return DirectAttr.Offset;
0316   }
0317   void setDirectOffset(unsigned Offset) {
0318     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
0319     DirectAttr.Offset = Offset;
0320   }
0321 
0322   unsigned getDirectAlign() const {
0323     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
0324     return DirectAttr.Align;
0325   }
0326   void setDirectAlign(unsigned Align) {
0327     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
0328     DirectAttr.Align = Align;
0329   }
0330 
0331   bool isSignExt() const {
0332     assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
0333     return SignExt;
0334   }
0335   void setSignExt(bool SExt) {
0336     assert(isExtend() && "Invalid kind!");
0337     SignExt = SExt;
0338   }
0339 
0340   bool isZeroExt() const {
0341     assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
0342     return ZeroExt;
0343   }
0344   void setZeroExt(bool ZExt) {
0345     assert(isExtend() && "Invalid kind!");
0346     ZeroExt = ZExt;
0347   }
0348 
0349   bool isNoExt() const {
0350     assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
0351     return !SignExt && !ZeroExt;
0352   }
0353 
0354   llvm::Type *getPaddingType() const {
0355     return (canHavePaddingType() ? PaddingType : nullptr);
0356   }
0357 
0358   bool getPaddingInReg() const {
0359     return PaddingInReg;
0360   }
0361   void setPaddingInReg(bool PIR) {
0362     PaddingInReg = PIR;
0363   }
0364 
0365   llvm::Type *getCoerceToType() const {
0366     assert(canHaveCoerceToType() && "Invalid kind!");
0367     return TypeData;
0368   }
0369 
0370   void setCoerceToType(llvm::Type *T) {
0371     assert(canHaveCoerceToType() && "Invalid kind!");
0372     TypeData = T;
0373   }
0374 
0375   llvm::StructType *getCoerceAndExpandType() const {
0376     assert(isCoerceAndExpand());
0377     return cast<llvm::StructType>(TypeData);
0378   }
0379 
0380   llvm::Type *getUnpaddedCoerceAndExpandType() const {
0381     assert(isCoerceAndExpand());
0382     return UnpaddedCoerceAndExpandType;
0383   }
0384 
0385   ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const {
0386     assert(isCoerceAndExpand());
0387     if (auto structTy =
0388           dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) {
0389       return structTy->elements();
0390     } else {
0391       return llvm::ArrayRef(&UnpaddedCoerceAndExpandType, 1);
0392     }
0393   }
0394 
0395   bool getInReg() const {
0396     assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
0397     return InReg;
0398   }
0399 
0400   void setInReg(bool IR) {
0401     assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
0402     InReg = IR;
0403   }
0404 
0405   // Indirect accessors
0406   CharUnits getIndirectAlign() const {
0407     assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
0408     return CharUnits::fromQuantity(IndirectAttr.Align);
0409   }
0410   void setIndirectAlign(CharUnits IA) {
0411     assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
0412     IndirectAttr.Align = IA.getQuantity();
0413   }
0414 
0415   bool getIndirectByVal() const {
0416     assert(isIndirect() && "Invalid kind!");
0417     return IndirectByVal;
0418   }
0419   void setIndirectByVal(bool IBV) {
0420     assert(isIndirect() && "Invalid kind!");
0421     IndirectByVal = IBV;
0422   }
0423 
0424   unsigned getIndirectAddrSpace() const {
0425     assert(isIndirectAliased() && "Invalid kind!");
0426     return IndirectAttr.AddrSpace;
0427   }
0428 
0429   void setIndirectAddrSpace(unsigned AddrSpace) {
0430     assert(isIndirectAliased() && "Invalid kind!");
0431     IndirectAttr.AddrSpace = AddrSpace;
0432   }
0433 
0434   bool getIndirectRealign() const {
0435     assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
0436     return IndirectRealign;
0437   }
0438   void setIndirectRealign(bool IR) {
0439     assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
0440     IndirectRealign = IR;
0441   }
0442 
0443   bool isSRetAfterThis() const {
0444     assert(isIndirect() && "Invalid kind!");
0445     return SRetAfterThis;
0446   }
0447   void setSRetAfterThis(bool AfterThis) {
0448     assert(isIndirect() && "Invalid kind!");
0449     SRetAfterThis = AfterThis;
0450   }
0451 
0452   unsigned getInAllocaFieldIndex() const {
0453     assert(isInAlloca() && "Invalid kind!");
0454     return AllocaFieldIndex;
0455   }
0456   void setInAllocaFieldIndex(unsigned FieldIndex) {
0457     assert(isInAlloca() && "Invalid kind!");
0458     AllocaFieldIndex = FieldIndex;
0459   }
0460 
0461   unsigned getInAllocaIndirect() const {
0462     assert(isInAlloca() && "Invalid kind!");
0463     return InAllocaIndirect;
0464   }
0465   void setInAllocaIndirect(bool Indirect) {
0466     assert(isInAlloca() && "Invalid kind!");
0467     InAllocaIndirect = Indirect;
0468   }
0469 
0470   /// Return true if this field of an inalloca struct should be returned
0471   /// to implement a struct return calling convention.
0472   bool getInAllocaSRet() const {
0473     assert(isInAlloca() && "Invalid kind!");
0474     return InAllocaSRet;
0475   }
0476 
0477   void setInAllocaSRet(bool SRet) {
0478     assert(isInAlloca() && "Invalid kind!");
0479     InAllocaSRet = SRet;
0480   }
0481 
0482   bool getCanBeFlattened() const {
0483     assert(isDirect() && "Invalid kind!");
0484     return CanBeFlattened;
0485   }
0486 
0487   void setCanBeFlattened(bool Flatten) {
0488     assert(isDirect() && "Invalid kind!");
0489     CanBeFlattened = Flatten;
0490   }
0491 
0492   void dump() const;
0493 };
0494 
0495 /// A class for recording the number of arguments that a function
0496 /// signature requires.
0497 class RequiredArgs {
0498   /// The number of required arguments, or ~0 if the signature does
0499   /// not permit optional arguments.
0500   unsigned NumRequired;
0501 public:
0502   enum All_t { All };
0503 
0504   RequiredArgs(All_t _) : NumRequired(~0U) {}
0505   explicit RequiredArgs(unsigned n) : NumRequired(n) {
0506     assert(n != ~0U);
0507   }
0508 
0509   /// Compute the arguments required by the given formal prototype,
0510   /// given that there may be some additional, non-formal arguments
0511   /// in play.
0512   ///
0513   /// If FD is not null, this will consider pass_object_size params in FD.
0514   static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
0515                                        unsigned additional) {
0516     if (!prototype->isVariadic()) return All;
0517 
0518     if (prototype->hasExtParameterInfos())
0519       additional += llvm::count_if(
0520           prototype->getExtParameterInfos(),
0521           [](const FunctionProtoType::ExtParameterInfo &ExtInfo) {
0522             return ExtInfo.hasPassObjectSize();
0523           });
0524 
0525     return RequiredArgs(prototype->getNumParams() + additional);
0526   }
0527 
0528   static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
0529                                        unsigned additional) {
0530     return forPrototypePlus(prototype.getTypePtr(), additional);
0531   }
0532 
0533   static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
0534     return forPrototypePlus(prototype, 0);
0535   }
0536 
0537   static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
0538     return forPrototypePlus(prototype.getTypePtr(), 0);
0539   }
0540 
0541   bool allowsOptionalArgs() const { return NumRequired != ~0U; }
0542   unsigned getNumRequiredArgs() const {
0543     assert(allowsOptionalArgs());
0544     return NumRequired;
0545   }
0546 
0547   /// Return true if the argument at a given index is required.
0548   bool isRequiredArg(unsigned argIdx) const {
0549     return argIdx == ~0U || argIdx < NumRequired;
0550   }
0551 
0552   unsigned getOpaqueData() const { return NumRequired; }
0553   static RequiredArgs getFromOpaqueData(unsigned value) {
0554     if (value == ~0U) return All;
0555     return RequiredArgs(value);
0556   }
0557 };
0558 
0559 // Implementation detail of CGFunctionInfo, factored out so it can be named
0560 // in the TrailingObjects base class of CGFunctionInfo.
0561 struct CGFunctionInfoArgInfo {
0562   CanQualType type;
0563   ABIArgInfo info;
0564 };
0565 
0566 /// CGFunctionInfo - Class to encapsulate the information about a
0567 /// function definition.
0568 class CGFunctionInfo final
0569     : public llvm::FoldingSetNode,
0570       private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo,
0571                                     FunctionProtoType::ExtParameterInfo> {
0572   typedef CGFunctionInfoArgInfo ArgInfo;
0573   typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo;
0574 
0575   /// The LLVM::CallingConv to use for this function (as specified by the
0576   /// user).
0577   unsigned CallingConvention : 8;
0578 
0579   /// The LLVM::CallingConv to actually use for this function, which may
0580   /// depend on the ABI.
0581   unsigned EffectiveCallingConvention : 8;
0582 
0583   /// The clang::CallingConv that this was originally created with.
0584   LLVM_PREFERRED_TYPE(CallingConv)
0585   unsigned ASTCallingConvention : 6;
0586 
0587   /// Whether this is an instance method.
0588   LLVM_PREFERRED_TYPE(bool)
0589   unsigned InstanceMethod : 1;
0590 
0591   /// Whether this is a chain call.
0592   LLVM_PREFERRED_TYPE(bool)
0593   unsigned ChainCall : 1;
0594 
0595   /// Whether this function is called by forwarding arguments.
0596   /// This doesn't support inalloca or varargs.
0597   LLVM_PREFERRED_TYPE(bool)
0598   unsigned DelegateCall : 1;
0599 
0600   /// Whether this function is a CMSE nonsecure call
0601   LLVM_PREFERRED_TYPE(bool)
0602   unsigned CmseNSCall : 1;
0603 
0604   /// Whether this function is noreturn.
0605   LLVM_PREFERRED_TYPE(bool)
0606   unsigned NoReturn : 1;
0607 
0608   /// Whether this function is returns-retained.
0609   LLVM_PREFERRED_TYPE(bool)
0610   unsigned ReturnsRetained : 1;
0611 
0612   /// Whether this function saved caller registers.
0613   LLVM_PREFERRED_TYPE(bool)
0614   unsigned NoCallerSavedRegs : 1;
0615 
0616   /// How many arguments to pass inreg.
0617   LLVM_PREFERRED_TYPE(bool)
0618   unsigned HasRegParm : 1;
0619   unsigned RegParm : 3;
0620 
0621   /// Whether this function has nocf_check attribute.
0622   LLVM_PREFERRED_TYPE(bool)
0623   unsigned NoCfCheck : 1;
0624 
0625   /// Log 2 of the maximum vector width.
0626   unsigned MaxVectorWidth : 4;
0627 
0628   RequiredArgs Required;
0629 
0630   /// The struct representing all arguments passed in memory.  Only used when
0631   /// passing non-trivial types with inalloca.  Not part of the profile.
0632   llvm::StructType *ArgStruct;
0633   unsigned ArgStructAlign : 31;
0634   LLVM_PREFERRED_TYPE(bool)
0635   unsigned HasExtParameterInfos : 1;
0636 
0637   unsigned NumArgs;
0638 
0639   ArgInfo *getArgsBuffer() {
0640     return getTrailingObjects<ArgInfo>();
0641   }
0642   const ArgInfo *getArgsBuffer() const {
0643     return getTrailingObjects<ArgInfo>();
0644   }
0645 
0646   ExtParameterInfo *getExtParameterInfosBuffer() {
0647     return getTrailingObjects<ExtParameterInfo>();
0648   }
0649   const ExtParameterInfo *getExtParameterInfosBuffer() const{
0650     return getTrailingObjects<ExtParameterInfo>();
0651   }
0652 
0653   CGFunctionInfo() : Required(RequiredArgs::All) {}
0654 
0655 public:
0656   static CGFunctionInfo *
0657   create(unsigned llvmCC, bool instanceMethod, bool chainCall,
0658          bool delegateCall, const FunctionType::ExtInfo &extInfo,
0659          ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
0660          ArrayRef<CanQualType> argTypes, RequiredArgs required);
0661   void operator delete(void *p) { ::operator delete(p); }
0662 
0663   // Friending class TrailingObjects is apparently not good enough for MSVC,
0664   // so these have to be public.
0665   friend class TrailingObjects;
0666   size_t numTrailingObjects(OverloadToken<ArgInfo>) const {
0667     return NumArgs + 1;
0668   }
0669   size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
0670     return (HasExtParameterInfos ? NumArgs : 0);
0671   }
0672 
0673   typedef const ArgInfo *const_arg_iterator;
0674   typedef ArgInfo *arg_iterator;
0675 
0676   MutableArrayRef<ArgInfo> arguments() {
0677     return MutableArrayRef<ArgInfo>(arg_begin(), NumArgs);
0678   }
0679   ArrayRef<ArgInfo> arguments() const {
0680     return ArrayRef<ArgInfo>(arg_begin(), NumArgs);
0681   }
0682 
0683   const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
0684   const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
0685   arg_iterator arg_begin() { return getArgsBuffer() + 1; }
0686   arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
0687 
0688   unsigned  arg_size() const { return NumArgs; }
0689 
0690   bool isVariadic() const { return Required.allowsOptionalArgs(); }
0691   RequiredArgs getRequiredArgs() const { return Required; }
0692   unsigned getNumRequiredArgs() const {
0693     return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
0694   }
0695 
0696   bool isInstanceMethod() const { return InstanceMethod; }
0697 
0698   bool isChainCall() const { return ChainCall; }
0699 
0700   bool isDelegateCall() const { return DelegateCall; }
0701 
0702   bool isCmseNSCall() const { return CmseNSCall; }
0703 
0704   bool isNoReturn() const { return NoReturn; }
0705 
0706   /// In ARC, whether this function retains its return value.  This
0707   /// is not always reliable for call sites.
0708   bool isReturnsRetained() const { return ReturnsRetained; }
0709 
0710   /// Whether this function no longer saves caller registers.
0711   bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }
0712 
0713   /// Whether this function has nocf_check attribute.
0714   bool isNoCfCheck() const { return NoCfCheck; }
0715 
0716   /// getASTCallingConvention() - Return the AST-specified calling
0717   /// convention.
0718   CallingConv getASTCallingConvention() const {
0719     return CallingConv(ASTCallingConvention);
0720   }
0721 
0722   /// getCallingConvention - Return the user specified calling
0723   /// convention, which has been translated into an LLVM CC.
0724   unsigned getCallingConvention() const { return CallingConvention; }
0725 
0726   /// getEffectiveCallingConvention - Return the actual calling convention to
0727   /// use, which may depend on the ABI.
0728   unsigned getEffectiveCallingConvention() const {
0729     return EffectiveCallingConvention;
0730   }
0731   void setEffectiveCallingConvention(unsigned Value) {
0732     EffectiveCallingConvention = Value;
0733   }
0734 
0735   bool getHasRegParm() const { return HasRegParm; }
0736   unsigned getRegParm() const { return RegParm; }
0737 
0738   FunctionType::ExtInfo getExtInfo() const {
0739     return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
0740                                  getASTCallingConvention(), isReturnsRetained(),
0741                                  isNoCallerSavedRegs(), isNoCfCheck(),
0742                                  isCmseNSCall());
0743   }
0744 
0745   CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
0746 
0747   ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
0748   const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
0749 
0750   ArrayRef<ExtParameterInfo> getExtParameterInfos() const {
0751     if (!HasExtParameterInfos) return {};
0752     return llvm::ArrayRef(getExtParameterInfosBuffer(), NumArgs);
0753   }
0754   ExtParameterInfo getExtParameterInfo(unsigned argIndex) const {
0755     assert(argIndex <= NumArgs);
0756     if (!HasExtParameterInfos) return ExtParameterInfo();
0757     return getExtParameterInfos()[argIndex];
0758   }
0759 
0760   /// Return true if this function uses inalloca arguments.
0761   bool usesInAlloca() const { return ArgStruct; }
0762 
0763   /// Get the struct type used to represent all the arguments in memory.
0764   llvm::StructType *getArgStruct() const { return ArgStruct; }
0765   CharUnits getArgStructAlignment() const {
0766     return CharUnits::fromQuantity(ArgStructAlign);
0767   }
0768   void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
0769     ArgStruct = Ty;
0770     ArgStructAlign = Align.getQuantity();
0771   }
0772 
0773   /// Return the maximum vector width in the arguments.
0774   unsigned getMaxVectorWidth() const {
0775     return MaxVectorWidth ? 1U << (MaxVectorWidth - 1) : 0;
0776   }
0777 
0778   /// Set the maximum vector width in the arguments.
0779   void setMaxVectorWidth(unsigned Width) {
0780     assert(llvm::isPowerOf2_32(Width) && "Expected power of 2 vector");
0781     MaxVectorWidth = llvm::countr_zero(Width) + 1;
0782   }
0783 
0784   void Profile(llvm::FoldingSetNodeID &ID) {
0785     ID.AddInteger(getASTCallingConvention());
0786     ID.AddBoolean(InstanceMethod);
0787     ID.AddBoolean(ChainCall);
0788     ID.AddBoolean(DelegateCall);
0789     ID.AddBoolean(NoReturn);
0790     ID.AddBoolean(ReturnsRetained);
0791     ID.AddBoolean(NoCallerSavedRegs);
0792     ID.AddBoolean(HasRegParm);
0793     ID.AddInteger(RegParm);
0794     ID.AddBoolean(NoCfCheck);
0795     ID.AddBoolean(CmseNSCall);
0796     ID.AddInteger(Required.getOpaqueData());
0797     ID.AddBoolean(HasExtParameterInfos);
0798     if (HasExtParameterInfos) {
0799       for (auto paramInfo : getExtParameterInfos())
0800         ID.AddInteger(paramInfo.getOpaqueValue());
0801     }
0802     getReturnType().Profile(ID);
0803     for (const auto &I : arguments())
0804       I.type.Profile(ID);
0805   }
0806   static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod,
0807                       bool ChainCall, bool IsDelegateCall,
0808                       const FunctionType::ExtInfo &info,
0809                       ArrayRef<ExtParameterInfo> paramInfos,
0810                       RequiredArgs required, CanQualType resultType,
0811                       ArrayRef<CanQualType> argTypes) {
0812     ID.AddInteger(info.getCC());
0813     ID.AddBoolean(InstanceMethod);
0814     ID.AddBoolean(ChainCall);
0815     ID.AddBoolean(IsDelegateCall);
0816     ID.AddBoolean(info.getNoReturn());
0817     ID.AddBoolean(info.getProducesResult());
0818     ID.AddBoolean(info.getNoCallerSavedRegs());
0819     ID.AddBoolean(info.getHasRegParm());
0820     ID.AddInteger(info.getRegParm());
0821     ID.AddBoolean(info.getNoCfCheck());
0822     ID.AddBoolean(info.getCmseNSCall());
0823     ID.AddInteger(required.getOpaqueData());
0824     ID.AddBoolean(!paramInfos.empty());
0825     if (!paramInfos.empty()) {
0826       for (auto paramInfo : paramInfos)
0827         ID.AddInteger(paramInfo.getOpaqueValue());
0828     }
0829     resultType.Profile(ID);
0830     for (ArrayRef<CanQualType>::iterator
0831            i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
0832       i->Profile(ID);
0833     }
0834   }
0835 };
0836 
0837 }  // end namespace CodeGen
0838 }  // end namespace clang
0839 
0840 #endif