Home | History | Annotate | Line # | Download | only in CodeGen
      1 //==-- CGFunctionInfo.h - Representation of function argument/return types -==//
      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 // Defines CGFunctionInfo and associated types used in representing the
     10 // LLVM source types and ABI-coerced types for function arguments and
     11 // return values.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
     16 #define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
     17 
     18 #include "clang/AST/CanonicalType.h"
     19 #include "clang/AST/CharUnits.h"
     20 #include "clang/AST/Decl.h"
     21 #include "clang/AST/Type.h"
     22 #include "llvm/IR/DerivedTypes.h"
     23 #include "llvm/ADT/FoldingSet.h"
     24 #include "llvm/Support/TrailingObjects.h"
     25 #include <cassert>
     26 
     27 namespace clang {
     28 namespace CodeGen {
     29 
     30 /// ABIArgInfo - Helper class to encapsulate information about how a
     31 /// specific C type should be passed to or returned from a function.
     32 class ABIArgInfo {
     33 public:
     34   enum Kind : uint8_t {
     35     /// Direct - Pass the argument directly using the normal converted LLVM
     36     /// type, or by coercing to another specified type stored in
     37     /// 'CoerceToType').  If an offset is specified (in UIntData), then the
     38     /// argument passed is offset by some number of bytes in the memory
     39     /// representation. A dummy argument is emitted before the real argument
     40     /// if the specified type stored in "PaddingType" is not zero.
     41     Direct,
     42 
     43     /// Extend - Valid only for integer argument types. Same as 'direct'
     44     /// but also emit a zero/sign extension attribute.
     45     Extend,
     46 
     47     /// Indirect - Pass the argument indirectly via a hidden pointer with the
     48     /// specified alignment (0 indicates default alignment) and address space.
     49     Indirect,
     50 
     51     /// IndirectAliased - Similar to Indirect, but the pointer may be to an
     52     /// object that is otherwise referenced.  The object is known to not be
     53     /// modified through any other references for the duration of the call, and
     54     /// the callee must not itself modify the object.  Because C allows
     55     /// parameter variables to be modified and guarantees that they have unique
     56     /// addresses, the callee must defensively copy the object into a local
     57     /// variable if it might be modified or its address might be compared.
     58     /// Since those are uncommon, in principle this convention allows programs
     59     /// to avoid copies in more situations.  However, it may introduce *extra*
     60     /// copies if the callee fails to prove that a copy is unnecessary and the
     61     /// caller naturally produces an unaliased object for the argument.
     62     IndirectAliased,
     63 
     64     /// Ignore - Ignore the argument (treat as void). Useful for void and
     65     /// empty structs.
     66     Ignore,
     67 
     68     /// Expand - Only valid for aggregate argument types. The structure should
     69     /// be expanded into consecutive arguments for its constituent fields.
     70     /// Currently expand is only allowed on structures whose fields
     71     /// are all scalar types or are themselves expandable types.
     72     Expand,
     73 
     74     /// CoerceAndExpand - Only valid for aggregate argument types. The
     75     /// structure should be expanded into consecutive arguments corresponding
     76     /// to the non-array elements of the type stored in CoerceToType.
     77     /// Array elements in the type are assumed to be padding and skipped.
     78     CoerceAndExpand,
     79 
     80     /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
     81     /// This is similar to indirect with byval, except it only applies to
     82     /// arguments stored in memory and forbids any implicit copies.  When
     83     /// applied to a return type, it means the value is returned indirectly via
     84     /// an implicit sret parameter stored in the argument struct.
     85     InAlloca,
     86     KindFirst = Direct,
     87     KindLast = InAlloca
     88   };
     89 
     90 private:
     91   llvm::Type *TypeData; // canHaveCoerceToType()
     92   union {
     93     llvm::Type *PaddingType; // canHavePaddingType()
     94     llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand()
     95   };
     96   struct DirectAttrInfo {
     97     unsigned Offset;
     98     unsigned Align;
     99   };
    100   struct IndirectAttrInfo {
    101     unsigned Align;
    102     unsigned AddrSpace;
    103   };
    104   union {
    105     DirectAttrInfo DirectAttr;     // isDirect() || isExtend()
    106     IndirectAttrInfo IndirectAttr; // isIndirect()
    107     unsigned AllocaFieldIndex; // isInAlloca()
    108   };
    109   Kind TheKind;
    110   bool PaddingInReg : 1;
    111   bool InAllocaSRet : 1;    // isInAlloca()
    112   bool InAllocaIndirect : 1;// isInAlloca()
    113   bool IndirectByVal : 1;   // isIndirect()
    114   bool IndirectRealign : 1; // isIndirect()
    115   bool SRetAfterThis : 1;   // isIndirect()
    116   bool InReg : 1;           // isDirect() || isExtend() || isIndirect()
    117   bool CanBeFlattened: 1;   // isDirect()
    118   bool SignExt : 1;         // isExtend()
    119 
    120   bool canHavePaddingType() const {
    121     return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
    122            isExpand();
    123   }
    124   void setPaddingType(llvm::Type *T) {
    125     assert(canHavePaddingType());
    126     PaddingType = T;
    127   }
    128 
    129   void setUnpaddedCoerceToType(llvm::Type *T) {
    130     assert(isCoerceAndExpand());
    131     UnpaddedCoerceAndExpandType = T;
    132   }
    133 
    134 public:
    135   ABIArgInfo(Kind K = Direct)
    136       : TypeData(nullptr), PaddingType(nullptr), DirectAttr{0, 0}, TheKind(K),
    137         PaddingInReg(false), InAllocaSRet(false),
    138         InAllocaIndirect(false), IndirectByVal(false), IndirectRealign(false),
    139         SRetAfterThis(false), InReg(false), CanBeFlattened(false),
    140         SignExt(false) {}
    141 
    142   static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
    143                               llvm::Type *Padding = nullptr,
    144                               bool CanBeFlattened = true, unsigned Align = 0) {
    145     auto AI = ABIArgInfo(Direct);
    146     AI.setCoerceToType(T);
    147     AI.setPaddingType(Padding);
    148     AI.setDirectOffset(Offset);
    149     AI.setDirectAlign(Align);
    150     AI.setCanBeFlattened(CanBeFlattened);
    151     return AI;
    152   }
    153   static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
    154     auto AI = getDirect(T);
    155     AI.setInReg(true);
    156     return AI;
    157   }
    158 
    159   static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) {
    160     assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
    161     auto AI = ABIArgInfo(Extend);
    162     AI.setCoerceToType(T);
    163     AI.setPaddingType(nullptr);
    164     AI.setDirectOffset(0);
    165     AI.setDirectAlign(0);
    166     AI.setSignExt(true);
    167     return AI;
    168   }
    169 
    170   static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) {
    171     assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
    172     auto AI = ABIArgInfo(Extend);
    173     AI.setCoerceToType(T);
    174     AI.setPaddingType(nullptr);
    175     AI.setDirectOffset(0);
    176     AI.setDirectAlign(0);
    177     AI.setSignExt(false);
    178     return AI;
    179   }
    180 
    181   // ABIArgInfo will record the argument as being extended based on the sign
    182   // of its type.
    183   static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
    184     assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
    185     if (Ty->hasSignedIntegerRepresentation())
    186       return getSignExtend(Ty, T);
    187     return getZeroExtend(Ty, T);
    188   }
    189 
    190   static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
    191     auto AI = getExtend(Ty, T);
    192     AI.setInReg(true);
    193     return AI;
    194   }
    195   static ABIArgInfo getIgnore() {
    196     return ABIArgInfo(Ignore);
    197   }
    198   static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
    199                                 bool Realign = false,
    200                                 llvm::Type *Padding = nullptr) {
    201     auto AI = ABIArgInfo(Indirect);
    202     AI.setIndirectAlign(Alignment);
    203     AI.setIndirectByVal(ByVal);
    204     AI.setIndirectRealign(Realign);
    205     AI.setSRetAfterThis(false);
    206     AI.setPaddingType(Padding);
    207     return AI;
    208   }
    209 
    210   /// Pass this in memory using the IR byref attribute.
    211   static ABIArgInfo getIndirectAliased(CharUnits Alignment, unsigned AddrSpace,
    212                                        bool Realign = false,
    213                                        llvm::Type *Padding = nullptr) {
    214     auto AI = ABIArgInfo(IndirectAliased);
    215     AI.setIndirectAlign(Alignment);
    216     AI.setIndirectRealign(Realign);
    217     AI.setPaddingType(Padding);
    218     AI.setIndirectAddrSpace(AddrSpace);
    219     return AI;
    220   }
    221 
    222   static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
    223                                      bool Realign = false) {
    224     auto AI = getIndirect(Alignment, ByVal, Realign);
    225     AI.setInReg(true);
    226     return AI;
    227   }
    228   static ABIArgInfo getInAlloca(unsigned FieldIndex, bool Indirect = false) {
    229     auto AI = ABIArgInfo(InAlloca);
    230     AI.setInAllocaFieldIndex(FieldIndex);
    231     AI.setInAllocaIndirect(Indirect);
    232     return AI;
    233   }
    234   static ABIArgInfo getExpand() {
    235     auto AI = ABIArgInfo(Expand);
    236     AI.setPaddingType(nullptr);
    237     return AI;
    238   }
    239   static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
    240                                          llvm::Type *Padding) {
    241     auto AI = getExpand();
    242     AI.setPaddingInReg(PaddingInReg);
    243     AI.setPaddingType(Padding);
    244     return AI;
    245   }
    246 
    247   /// \param unpaddedCoerceToType The coerce-to type with padding elements
    248   ///   removed, canonicalized to a single element if it would otherwise
    249   ///   have exactly one element.
    250   static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
    251                                        llvm::Type *unpaddedCoerceToType) {
    252 #ifndef NDEBUG
    253     // Sanity checks on unpaddedCoerceToType.
    254 
    255     // Assert that we only have a struct type if there are multiple elements.
    256     auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType);
    257     assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1);
    258 
    259     // Assert that all the non-padding elements have a corresponding element
    260     // in the unpadded type.
    261     unsigned unpaddedIndex = 0;
    262     for (auto eltType : coerceToType->elements()) {
    263       if (isPaddingForCoerceAndExpand(eltType)) continue;
    264       if (unpaddedStruct) {
    265         assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType);
    266       } else {
    267         assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType);
    268       }
    269       unpaddedIndex++;
    270     }
    271 
    272     // Assert that there aren't extra elements in the unpadded type.
    273     if (unpaddedStruct) {
    274       assert(unpaddedStruct->getNumElements() == unpaddedIndex);
    275     } else {
    276       assert(unpaddedIndex == 1);
    277     }
    278 #endif
    279 
    280     auto AI = ABIArgInfo(CoerceAndExpand);
    281     AI.setCoerceToType(coerceToType);
    282     AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
    283     return AI;
    284   }
    285 
    286   static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
    287     if (eltType->isArrayTy()) {
    288       assert(eltType->getArrayElementType()->isIntegerTy(8));
    289       return true;
    290     } else {
    291       return false;
    292     }
    293   }
    294 
    295   Kind getKind() const { return TheKind; }
    296   bool isDirect() const { return TheKind == Direct; }
    297   bool isInAlloca() const { return TheKind == InAlloca; }
    298   bool isExtend() const { return TheKind == Extend; }
    299   bool isIgnore() const { return TheKind == Ignore; }
    300   bool isIndirect() const { return TheKind == Indirect; }
    301   bool isIndirectAliased() const { return TheKind == IndirectAliased; }
    302   bool isExpand() const { return TheKind == Expand; }
    303   bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
    304 
    305   bool canHaveCoerceToType() const {
    306     return isDirect() || isExtend() || isCoerceAndExpand();
    307   }
    308 
    309   // Direct/Extend accessors
    310   unsigned getDirectOffset() const {
    311     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    312     return DirectAttr.Offset;
    313   }
    314   void setDirectOffset(unsigned Offset) {
    315     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    316     DirectAttr.Offset = Offset;
    317   }
    318 
    319   unsigned getDirectAlign() const {
    320     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    321     return DirectAttr.Align;
    322   }
    323   void setDirectAlign(unsigned Align) {
    324     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    325     DirectAttr.Align = Align;
    326   }
    327 
    328   bool isSignExt() const {
    329     assert(isExtend() && "Invalid kind!");
    330     return SignExt;
    331   }
    332   void setSignExt(bool SExt) {
    333     assert(isExtend() && "Invalid kind!");
    334     SignExt = SExt;
    335   }
    336 
    337   llvm::Type *getPaddingType() const {
    338     return (canHavePaddingType() ? PaddingType : nullptr);
    339   }
    340 
    341   bool getPaddingInReg() const {
    342     return PaddingInReg;
    343   }
    344   void setPaddingInReg(bool PIR) {
    345     PaddingInReg = PIR;
    346   }
    347 
    348   llvm::Type *getCoerceToType() const {
    349     assert(canHaveCoerceToType() && "Invalid kind!");
    350     return TypeData;
    351   }
    352 
    353   void setCoerceToType(llvm::Type *T) {
    354     assert(canHaveCoerceToType() && "Invalid kind!");
    355     TypeData = T;
    356   }
    357 
    358   llvm::StructType *getCoerceAndExpandType() const {
    359     assert(isCoerceAndExpand());
    360     return cast<llvm::StructType>(TypeData);
    361   }
    362 
    363   llvm::Type *getUnpaddedCoerceAndExpandType() const {
    364     assert(isCoerceAndExpand());
    365     return UnpaddedCoerceAndExpandType;
    366   }
    367 
    368   ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const {
    369     assert(isCoerceAndExpand());
    370     if (auto structTy =
    371           dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) {
    372       return structTy->elements();
    373     } else {
    374       return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1);
    375     }
    376   }
    377 
    378   bool getInReg() const {
    379     assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
    380     return InReg;
    381   }
    382 
    383   void setInReg(bool IR) {
    384     assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
    385     InReg = IR;
    386   }
    387 
    388   // Indirect accessors
    389   CharUnits getIndirectAlign() const {
    390     assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
    391     return CharUnits::fromQuantity(IndirectAttr.Align);
    392   }
    393   void setIndirectAlign(CharUnits IA) {
    394     assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
    395     IndirectAttr.Align = IA.getQuantity();
    396   }
    397 
    398   bool getIndirectByVal() const {
    399     assert(isIndirect() && "Invalid kind!");
    400     return IndirectByVal;
    401   }
    402   void setIndirectByVal(bool IBV) {
    403     assert(isIndirect() && "Invalid kind!");
    404     IndirectByVal = IBV;
    405   }
    406 
    407   unsigned getIndirectAddrSpace() const {
    408     assert(isIndirectAliased() && "Invalid kind!");
    409     return IndirectAttr.AddrSpace;
    410   }
    411 
    412   void setIndirectAddrSpace(unsigned AddrSpace) {
    413     assert(isIndirectAliased() && "Invalid kind!");
    414     IndirectAttr.AddrSpace = AddrSpace;
    415   }
    416 
    417   bool getIndirectRealign() const {
    418     assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
    419     return IndirectRealign;
    420   }
    421   void setIndirectRealign(bool IR) {
    422     assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
    423     IndirectRealign = IR;
    424   }
    425 
    426   bool isSRetAfterThis() const {
    427     assert(isIndirect() && "Invalid kind!");
    428     return SRetAfterThis;
    429   }
    430   void setSRetAfterThis(bool AfterThis) {
    431     assert(isIndirect() && "Invalid kind!");
    432     SRetAfterThis = AfterThis;
    433   }
    434 
    435   unsigned getInAllocaFieldIndex() const {
    436     assert(isInAlloca() && "Invalid kind!");
    437     return AllocaFieldIndex;
    438   }
    439   void setInAllocaFieldIndex(unsigned FieldIndex) {
    440     assert(isInAlloca() && "Invalid kind!");
    441     AllocaFieldIndex = FieldIndex;
    442   }
    443 
    444   unsigned getInAllocaIndirect() const {
    445     assert(isInAlloca() && "Invalid kind!");
    446     return InAllocaIndirect;
    447   }
    448   void setInAllocaIndirect(bool Indirect) {
    449     assert(isInAlloca() && "Invalid kind!");
    450     InAllocaIndirect = Indirect;
    451   }
    452 
    453   /// Return true if this field of an inalloca struct should be returned
    454   /// to implement a struct return calling convention.
    455   bool getInAllocaSRet() const {
    456     assert(isInAlloca() && "Invalid kind!");
    457     return InAllocaSRet;
    458   }
    459 
    460   void setInAllocaSRet(bool SRet) {
    461     assert(isInAlloca() && "Invalid kind!");
    462     InAllocaSRet = SRet;
    463   }
    464 
    465   bool getCanBeFlattened() const {
    466     assert(isDirect() && "Invalid kind!");
    467     return CanBeFlattened;
    468   }
    469 
    470   void setCanBeFlattened(bool Flatten) {
    471     assert(isDirect() && "Invalid kind!");
    472     CanBeFlattened = Flatten;
    473   }
    474 
    475   void dump() const;
    476 };
    477 
    478 /// A class for recording the number of arguments that a function
    479 /// signature requires.
    480 class RequiredArgs {
    481   /// The number of required arguments, or ~0 if the signature does
    482   /// not permit optional arguments.
    483   unsigned NumRequired;
    484 public:
    485   enum All_t { All };
    486 
    487   RequiredArgs(All_t _) : NumRequired(~0U) {}
    488   explicit RequiredArgs(unsigned n) : NumRequired(n) {
    489     assert(n != ~0U);
    490   }
    491 
    492   /// Compute the arguments required by the given formal prototype,
    493   /// given that there may be some additional, non-formal arguments
    494   /// in play.
    495   ///
    496   /// If FD is not null, this will consider pass_object_size params in FD.
    497   static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
    498                                        unsigned additional) {
    499     if (!prototype->isVariadic()) return All;
    500 
    501     if (prototype->hasExtParameterInfos())
    502       additional += llvm::count_if(
    503           prototype->getExtParameterInfos(),
    504           [](const FunctionProtoType::ExtParameterInfo &ExtInfo) {
    505             return ExtInfo.hasPassObjectSize();
    506           });
    507 
    508     return RequiredArgs(prototype->getNumParams() + additional);
    509   }
    510 
    511   static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
    512                                        unsigned additional) {
    513     return forPrototypePlus(prototype.getTypePtr(), additional);
    514   }
    515 
    516   static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
    517     return forPrototypePlus(prototype, 0);
    518   }
    519 
    520   static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
    521     return forPrototypePlus(prototype.getTypePtr(), 0);
    522   }
    523 
    524   bool allowsOptionalArgs() const { return NumRequired != ~0U; }
    525   unsigned getNumRequiredArgs() const {
    526     assert(allowsOptionalArgs());
    527     return NumRequired;
    528   }
    529 
    530   unsigned getOpaqueData() const { return NumRequired; }
    531   static RequiredArgs getFromOpaqueData(unsigned value) {
    532     if (value == ~0U) return All;
    533     return RequiredArgs(value);
    534   }
    535 };
    536 
    537 // Implementation detail of CGFunctionInfo, factored out so it can be named
    538 // in the TrailingObjects base class of CGFunctionInfo.
    539 struct CGFunctionInfoArgInfo {
    540   CanQualType type;
    541   ABIArgInfo info;
    542 };
    543 
    544 /// CGFunctionInfo - Class to encapsulate the information about a
    545 /// function definition.
    546 class CGFunctionInfo final
    547     : public llvm::FoldingSetNode,
    548       private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo,
    549                                     FunctionProtoType::ExtParameterInfo> {
    550   typedef CGFunctionInfoArgInfo ArgInfo;
    551   typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo;
    552 
    553   /// The LLVM::CallingConv to use for this function (as specified by the
    554   /// user).
    555   unsigned CallingConvention : 8;
    556 
    557   /// The LLVM::CallingConv to actually use for this function, which may
    558   /// depend on the ABI.
    559   unsigned EffectiveCallingConvention : 8;
    560 
    561   /// The clang::CallingConv that this was originally created with.
    562   unsigned ASTCallingConvention : 6;
    563 
    564   /// Whether this is an instance method.
    565   unsigned InstanceMethod : 1;
    566 
    567   /// Whether this is a chain call.
    568   unsigned ChainCall : 1;
    569 
    570   /// Whether this function is a CMSE nonsecure call
    571   unsigned CmseNSCall : 1;
    572 
    573   /// Whether this function is noreturn.
    574   unsigned NoReturn : 1;
    575 
    576   /// Whether this function is returns-retained.
    577   unsigned ReturnsRetained : 1;
    578 
    579   /// Whether this function saved caller registers.
    580   unsigned NoCallerSavedRegs : 1;
    581 
    582   /// How many arguments to pass inreg.
    583   unsigned HasRegParm : 1;
    584   unsigned RegParm : 3;
    585 
    586   /// Whether this function has nocf_check attribute.
    587   unsigned NoCfCheck : 1;
    588 
    589   RequiredArgs Required;
    590 
    591   /// The struct representing all arguments passed in memory.  Only used when
    592   /// passing non-trivial types with inalloca.  Not part of the profile.
    593   llvm::StructType *ArgStruct;
    594   unsigned ArgStructAlign : 31;
    595   unsigned HasExtParameterInfos : 1;
    596 
    597   unsigned NumArgs;
    598 
    599   ArgInfo *getArgsBuffer() {
    600     return getTrailingObjects<ArgInfo>();
    601   }
    602   const ArgInfo *getArgsBuffer() const {
    603     return getTrailingObjects<ArgInfo>();
    604   }
    605 
    606   ExtParameterInfo *getExtParameterInfosBuffer() {
    607     return getTrailingObjects<ExtParameterInfo>();
    608   }
    609   const ExtParameterInfo *getExtParameterInfosBuffer() const{
    610     return getTrailingObjects<ExtParameterInfo>();
    611   }
    612 
    613   CGFunctionInfo() : Required(RequiredArgs::All) {}
    614 
    615 public:
    616   static CGFunctionInfo *create(unsigned llvmCC,
    617                                 bool instanceMethod,
    618                                 bool chainCall,
    619                                 const FunctionType::ExtInfo &extInfo,
    620                                 ArrayRef<ExtParameterInfo> paramInfos,
    621                                 CanQualType resultType,
    622                                 ArrayRef<CanQualType> argTypes,
    623                                 RequiredArgs required);
    624   void operator delete(void *p) { ::operator delete(p); }
    625 
    626   // Friending class TrailingObjects is apparently not good enough for MSVC,
    627   // so these have to be public.
    628   friend class TrailingObjects;
    629   size_t numTrailingObjects(OverloadToken<ArgInfo>) const {
    630     return NumArgs + 1;
    631   }
    632   size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
    633     return (HasExtParameterInfos ? NumArgs : 0);
    634   }
    635 
    636   typedef const ArgInfo *const_arg_iterator;
    637   typedef ArgInfo *arg_iterator;
    638 
    639   MutableArrayRef<ArgInfo> arguments() {
    640     return MutableArrayRef<ArgInfo>(arg_begin(), NumArgs);
    641   }
    642   ArrayRef<ArgInfo> arguments() const {
    643     return ArrayRef<ArgInfo>(arg_begin(), NumArgs);
    644   }
    645 
    646   const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
    647   const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
    648   arg_iterator arg_begin() { return getArgsBuffer() + 1; }
    649   arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
    650 
    651   unsigned  arg_size() const { return NumArgs; }
    652 
    653   bool isVariadic() const { return Required.allowsOptionalArgs(); }
    654   RequiredArgs getRequiredArgs() const { return Required; }
    655   unsigned getNumRequiredArgs() const {
    656     return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
    657   }
    658 
    659   bool isInstanceMethod() const { return InstanceMethod; }
    660 
    661   bool isChainCall() const { return ChainCall; }
    662 
    663   bool isCmseNSCall() const { return CmseNSCall; }
    664 
    665   bool isNoReturn() const { return NoReturn; }
    666 
    667   /// In ARC, whether this function retains its return value.  This
    668   /// is not always reliable for call sites.
    669   bool isReturnsRetained() const { return ReturnsRetained; }
    670 
    671   /// Whether this function no longer saves caller registers.
    672   bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }
    673 
    674   /// Whether this function has nocf_check attribute.
    675   bool isNoCfCheck() const { return NoCfCheck; }
    676 
    677   /// getASTCallingConvention() - Return the AST-specified calling
    678   /// convention.
    679   CallingConv getASTCallingConvention() const {
    680     return CallingConv(ASTCallingConvention);
    681   }
    682 
    683   /// getCallingConvention - Return the user specified calling
    684   /// convention, which has been translated into an LLVM CC.
    685   unsigned getCallingConvention() const { return CallingConvention; }
    686 
    687   /// getEffectiveCallingConvention - Return the actual calling convention to
    688   /// use, which may depend on the ABI.
    689   unsigned getEffectiveCallingConvention() const {
    690     return EffectiveCallingConvention;
    691   }
    692   void setEffectiveCallingConvention(unsigned Value) {
    693     EffectiveCallingConvention = Value;
    694   }
    695 
    696   bool getHasRegParm() const { return HasRegParm; }
    697   unsigned getRegParm() const { return RegParm; }
    698 
    699   FunctionType::ExtInfo getExtInfo() const {
    700     return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
    701                                  getASTCallingConvention(), isReturnsRetained(),
    702                                  isNoCallerSavedRegs(), isNoCfCheck(),
    703                                  isCmseNSCall());
    704   }
    705 
    706   CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
    707 
    708   ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
    709   const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
    710 
    711   ArrayRef<ExtParameterInfo> getExtParameterInfos() const {
    712     if (!HasExtParameterInfos) return {};
    713     return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs);
    714   }
    715   ExtParameterInfo getExtParameterInfo(unsigned argIndex) const {
    716     assert(argIndex <= NumArgs);
    717     if (!HasExtParameterInfos) return ExtParameterInfo();
    718     return getExtParameterInfos()[argIndex];
    719   }
    720 
    721   /// Return true if this function uses inalloca arguments.
    722   bool usesInAlloca() const { return ArgStruct; }
    723 
    724   /// Get the struct type used to represent all the arguments in memory.
    725   llvm::StructType *getArgStruct() const { return ArgStruct; }
    726   CharUnits getArgStructAlignment() const {
    727     return CharUnits::fromQuantity(ArgStructAlign);
    728   }
    729   void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
    730     ArgStruct = Ty;
    731     ArgStructAlign = Align.getQuantity();
    732   }
    733 
    734   void Profile(llvm::FoldingSetNodeID &ID) {
    735     ID.AddInteger(getASTCallingConvention());
    736     ID.AddBoolean(InstanceMethod);
    737     ID.AddBoolean(ChainCall);
    738     ID.AddBoolean(NoReturn);
    739     ID.AddBoolean(ReturnsRetained);
    740     ID.AddBoolean(NoCallerSavedRegs);
    741     ID.AddBoolean(HasRegParm);
    742     ID.AddInteger(RegParm);
    743     ID.AddBoolean(NoCfCheck);
    744     ID.AddBoolean(CmseNSCall);
    745     ID.AddInteger(Required.getOpaqueData());
    746     ID.AddBoolean(HasExtParameterInfos);
    747     if (HasExtParameterInfos) {
    748       for (auto paramInfo : getExtParameterInfos())
    749         ID.AddInteger(paramInfo.getOpaqueValue());
    750     }
    751     getReturnType().Profile(ID);
    752     for (const auto &I : arguments())
    753       I.type.Profile(ID);
    754   }
    755   static void Profile(llvm::FoldingSetNodeID &ID,
    756                       bool InstanceMethod,
    757                       bool ChainCall,
    758                       const FunctionType::ExtInfo &info,
    759                       ArrayRef<ExtParameterInfo> paramInfos,
    760                       RequiredArgs required,
    761                       CanQualType resultType,
    762                       ArrayRef<CanQualType> argTypes) {
    763     ID.AddInteger(info.getCC());
    764     ID.AddBoolean(InstanceMethod);
    765     ID.AddBoolean(ChainCall);
    766     ID.AddBoolean(info.getNoReturn());
    767     ID.AddBoolean(info.getProducesResult());
    768     ID.AddBoolean(info.getNoCallerSavedRegs());
    769     ID.AddBoolean(info.getHasRegParm());
    770     ID.AddInteger(info.getRegParm());
    771     ID.AddBoolean(info.getNoCfCheck());
    772     ID.AddBoolean(info.getCmseNSCall());
    773     ID.AddInteger(required.getOpaqueData());
    774     ID.AddBoolean(!paramInfos.empty());
    775     if (!paramInfos.empty()) {
    776       for (auto paramInfo : paramInfos)
    777         ID.AddInteger(paramInfo.getOpaqueValue());
    778     }
    779     resultType.Profile(ID);
    780     for (ArrayRef<CanQualType>::iterator
    781            i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
    782       i->Profile(ID);
    783     }
    784   }
    785 };
    786 
    787 }  // end namespace CodeGen
    788 }  // end namespace clang
    789 
    790 #endif
    791