//==-- CGFunctionInfo.h - Representation of function argument/return types -==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Defines CGFunctionInfo and associated types used in representing the
// LLVM source types and ABI-coerced types for function arguments and
// return values.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
#define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H

#include "clang/AST/CanonicalType.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>

namespace clang {
namespace CodeGen {

/// ABIArgInfo - Helper class to encapsulate information about how a
/// specific C type should be passed to or returned from a function.
class ABIArgInfo {
public:
  enum Kind : uint8_t {
    /// Direct - Pass the argument directly using the normal converted LLVM
    /// type, or by coercing to another specified type stored in
    /// 'CoerceToType').  If an offset is specified (in UIntData), then the
    /// argument passed is offset by some number of bytes in the memory
    /// representation. A dummy argument is emitted before the real argument
    /// if the specified type stored in "PaddingType" is not zero.
    Direct,

    /// Extend - Valid only for integer argument types. Same as 'direct'
    /// but also emit a zero/sign extension attribute.
    Extend,

    /// Indirect - Pass the argument indirectly via a hidden pointer with the
    /// specified alignment (0 indicates default alignment) and address space.
    Indirect,

    /// IndirectAliased - Similar to Indirect, but the pointer may be to an
    /// object that is otherwise referenced.  The object is known to not be
    /// modified through any other references for the duration of the call, and
    /// the callee must not itself modify the object.  Because C allows
    /// parameter variables to be modified and guarantees that they have unique
    /// addresses, the callee must defensively copy the object into a local
    /// variable if it might be modified or its address might be compared.
    /// Since those are uncommon, in principle this convention allows programs
    /// to avoid copies in more situations.  However, it may introduce *extra*
    /// copies if the callee fails to prove that a copy is unnecessary and the
    /// caller naturally produces an unaliased object for the argument.
    IndirectAliased,

    /// Ignore - Ignore the argument (treat as void). Useful for void and
    /// empty structs.
    Ignore,

    /// Expand - Only valid for aggregate argument types. The structure should
    /// be expanded into consecutive arguments for its constituent fields.
    /// Currently expand is only allowed on structures whose fields
    /// are all scalar types or are themselves expandable types.
    Expand,

    /// CoerceAndExpand - Only valid for aggregate argument types. The
    /// structure should be expanded into consecutive arguments corresponding
    /// to the non-array elements of the type stored in CoerceToType.
    /// Array elements in the type are assumed to be padding and skipped.
    CoerceAndExpand,

    /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
    /// This is similar to indirect with byval, except it only applies to
    /// arguments stored in memory and forbids any implicit copies.  When
    /// applied to a return type, it means the value is returned indirectly via
    /// an implicit sret parameter stored in the argument struct.
    InAlloca,
    KindFirst = Direct,
    KindLast = InAlloca
  };

private:
  llvm::Type *TypeData; // canHaveCoerceToType()
  union {
    llvm::Type *PaddingType; // canHavePaddingType()
    llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand()
  };
  struct DirectAttrInfo {
    unsigned Offset;
    unsigned Align;
  };
  struct IndirectAttrInfo {
    unsigned Align;
    unsigned AddrSpace;
  };
  union {
    DirectAttrInfo DirectAttr;     // isDirect() || isExtend()
    IndirectAttrInfo IndirectAttr; // isIndirect()
    unsigned AllocaFieldIndex; // isInAlloca()
  };
  Kind TheKind;
  bool PaddingInReg : 1;
  bool InAllocaSRet : 1;    // isInAlloca()
  bool InAllocaIndirect : 1;// isInAlloca()
  bool IndirectByVal : 1;   // isIndirect()
  bool IndirectRealign : 1; // isIndirect()
  bool SRetAfterThis : 1;   // isIndirect()
  bool InReg : 1;           // isDirect() || isExtend() || isIndirect()
  bool CanBeFlattened: 1;   // isDirect()
  bool SignExt : 1;         // isExtend()

  bool canHavePaddingType() const {
    return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
           isExpand();
  }
  void setPaddingType(llvm::Type *T) {
    assert(canHavePaddingType());
    PaddingType = T;
  }

  void setUnpaddedCoerceToType(llvm::Type *T) {
    assert(isCoerceAndExpand());
    UnpaddedCoerceAndExpandType = T;
  }

public:
  ABIArgInfo(Kind K = Direct)
      : TypeData(nullptr), PaddingType(nullptr), DirectAttr{0, 0}, TheKind(K),
        PaddingInReg(false), InAllocaSRet(false),
        InAllocaIndirect(false), IndirectByVal(false), IndirectRealign(false),
        SRetAfterThis(false), InReg(false), CanBeFlattened(false),
        SignExt(false) {}

  static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
                              llvm::Type *Padding = nullptr,
                              bool CanBeFlattened = true, unsigned Align = 0) {
    auto AI = ABIArgInfo(Direct);
    AI.setCoerceToType(T);
    AI.setPaddingType(Padding);
    AI.setDirectOffset(Offset);
    AI.setDirectAlign(Align);
    AI.setCanBeFlattened(CanBeFlattened);
    return AI;
  }
  static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
    auto AI = getDirect(T);
    AI.setInReg(true);
    return AI;
  }

  static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) {
    assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
    auto AI = ABIArgInfo(Extend);
    AI.setCoerceToType(T);
    AI.setPaddingType(nullptr);
    AI.setDirectOffset(0);
    AI.setDirectAlign(0);
    AI.setSignExt(true);
    return AI;
  }

  static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) {
    assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
    auto AI = ABIArgInfo(Extend);
    AI.setCoerceToType(T);
    AI.setPaddingType(nullptr);
    AI.setDirectOffset(0);
    AI.setDirectAlign(0);
    AI.setSignExt(false);
    return AI;
  }

  // ABIArgInfo will record the argument as being extended based on the sign
  // of its type.
  static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
    assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
    if (Ty->hasSignedIntegerRepresentation())
      return getSignExtend(Ty, T);
    return getZeroExtend(Ty, T);
  }

  static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
    auto AI = getExtend(Ty, T);
    AI.setInReg(true);
    return AI;
  }
  static ABIArgInfo getIgnore() {
    return ABIArgInfo(Ignore);
  }
  static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
                                bool Realign = false,
                                llvm::Type *Padding = nullptr) {
    auto AI = ABIArgInfo(Indirect);
    AI.setIndirectAlign(Alignment);
    AI.setIndirectByVal(ByVal);
    AI.setIndirectRealign(Realign);
    AI.setSRetAfterThis(false);
    AI.setPaddingType(Padding);
    return AI;
  }

  /// Pass this in memory using the IR byref attribute.
  static ABIArgInfo getIndirectAliased(CharUnits Alignment, unsigned AddrSpace,
                                       bool Realign = false,
                                       llvm::Type *Padding = nullptr) {
    auto AI = ABIArgInfo(IndirectAliased);
    AI.setIndirectAlign(Alignment);
    AI.setIndirectRealign(Realign);
    AI.setPaddingType(Padding);
    AI.setIndirectAddrSpace(AddrSpace);
    return AI;
  }

  static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
                                     bool Realign = false) {
    auto AI = getIndirect(Alignment, ByVal, Realign);
    AI.setInReg(true);
    return AI;
  }
  static ABIArgInfo getInAlloca(unsigned FieldIndex, bool Indirect = false) {
    auto AI = ABIArgInfo(InAlloca);
    AI.setInAllocaFieldIndex(FieldIndex);
    AI.setInAllocaIndirect(Indirect);
    return AI;
  }
  static ABIArgInfo getExpand() {
    auto AI = ABIArgInfo(Expand);
    AI.setPaddingType(nullptr);
    return AI;
  }
  static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
                                         llvm::Type *Padding) {
    auto AI = getExpand();
    AI.setPaddingInReg(PaddingInReg);
    AI.setPaddingType(Padding);
    return AI;
  }

  /// \param unpaddedCoerceToType The coerce-to type with padding elements
  ///   removed, canonicalized to a single element if it would otherwise
  ///   have exactly one element.
  static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
                                       llvm::Type *unpaddedCoerceToType) {
#ifndef NDEBUG
    // Sanity checks on unpaddedCoerceToType.

    // Assert that we only have a struct type if there are multiple elements.
    auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType);
    assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1);

    // Assert that all the non-padding elements have a corresponding element
    // in the unpadded type.
    unsigned unpaddedIndex = 0;
    for (auto eltType : coerceToType->elements()) {
      if (isPaddingForCoerceAndExpand(eltType)) continue;
      if (unpaddedStruct) {
        assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType);
      } else {
        assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType);
      }
      unpaddedIndex++;
    }

    // Assert that there aren't extra elements in the unpadded type.
    if (unpaddedStruct) {
      assert(unpaddedStruct->getNumElements() == unpaddedIndex);
    } else {
      assert(unpaddedIndex == 1);
    }
#endif

    auto AI = ABIArgInfo(CoerceAndExpand);
    AI.setCoerceToType(coerceToType);
    AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
    return AI;
  }

  static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
    if (eltType->isArrayTy()) {
      assert(eltType->getArrayElementType()->isIntegerTy(8));
      return true;
    } else {
      return false;
    }
  }

  Kind getKind() const { return TheKind; }
  bool isDirect() const { return TheKind == Direct; }
  bool isInAlloca() const { return TheKind == InAlloca; }
  bool isExtend() const { return TheKind == Extend; }
  bool isIgnore() const { return TheKind == Ignore; }
  bool isIndirect() const { return TheKind == Indirect; }
  bool isIndirectAliased() const { return TheKind == IndirectAliased; }
  bool isExpand() const { return TheKind == Expand; }
  bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }

  bool canHaveCoerceToType() const {
    return isDirect() || isExtend() || isCoerceAndExpand();
  }

  // Direct/Extend accessors
  unsigned getDirectOffset() const {
    assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    return DirectAttr.Offset;
  }
  void setDirectOffset(unsigned Offset) {
    assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    DirectAttr.Offset = Offset;
  }

  unsigned getDirectAlign() const {
    assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    return DirectAttr.Align;
  }
  void setDirectAlign(unsigned Align) {
    assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    DirectAttr.Align = Align;
  }

  bool isSignExt() const {
    assert(isExtend() && "Invalid kind!");
    return SignExt;
  }
  void setSignExt(bool SExt) {
    assert(isExtend() && "Invalid kind!");
    SignExt = SExt;
  }

  llvm::Type *getPaddingType() const {
    return (canHavePaddingType() ? PaddingType : nullptr);
  }

  bool getPaddingInReg() const {
    return PaddingInReg;
  }
  void setPaddingInReg(bool PIR) {
    PaddingInReg = PIR;
  }

  llvm::Type *getCoerceToType() const {
    assert(canHaveCoerceToType() && "Invalid kind!");
    return TypeData;
  }

  void setCoerceToType(llvm::Type *T) {
    assert(canHaveCoerceToType() && "Invalid kind!");
    TypeData = T;
  }

  llvm::StructType *getCoerceAndExpandType() const {
    assert(isCoerceAndExpand());
    return cast<llvm::StructType>(TypeData);
  }

  llvm::Type *getUnpaddedCoerceAndExpandType() const {
    assert(isCoerceAndExpand());
    return UnpaddedCoerceAndExpandType;
  }

  ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const {
    assert(isCoerceAndExpand());
    if (auto structTy =
          dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) {
      return structTy->elements();
    } else {
      return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1);
    }
  }

  bool getInReg() const {
    assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
    return InReg;
  }

  void setInReg(bool IR) {
    assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
    InReg = IR;
  }

  // Indirect accessors
  CharUnits getIndirectAlign() const {
    assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
    return CharUnits::fromQuantity(IndirectAttr.Align);
  }
  void setIndirectAlign(CharUnits IA) {
    assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
    IndirectAttr.Align = IA.getQuantity();
  }

  bool getIndirectByVal() const {
    assert(isIndirect() && "Invalid kind!");
    return IndirectByVal;
  }
  void setIndirectByVal(bool IBV) {
    assert(isIndirect() && "Invalid kind!");
    IndirectByVal = IBV;
  }

  unsigned getIndirectAddrSpace() const {
    assert(isIndirectAliased() && "Invalid kind!");
    return IndirectAttr.AddrSpace;
  }

  void setIndirectAddrSpace(unsigned AddrSpace) {
    assert(isIndirectAliased() && "Invalid kind!");
    IndirectAttr.AddrSpace = AddrSpace;
  }

  bool getIndirectRealign() const {
    assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
    return IndirectRealign;
  }
  void setIndirectRealign(bool IR) {
    assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
    IndirectRealign = IR;
  }

  bool isSRetAfterThis() const {
    assert(isIndirect() && "Invalid kind!");
    return SRetAfterThis;
  }
  void setSRetAfterThis(bool AfterThis) {
    assert(isIndirect() && "Invalid kind!");
    SRetAfterThis = AfterThis;
  }

  unsigned getInAllocaFieldIndex() const {
    assert(isInAlloca() && "Invalid kind!");
    return AllocaFieldIndex;
  }
  void setInAllocaFieldIndex(unsigned FieldIndex) {
    assert(isInAlloca() && "Invalid kind!");
    AllocaFieldIndex = FieldIndex;
  }

  unsigned getInAllocaIndirect() const {
    assert(isInAlloca() && "Invalid kind!");
    return InAllocaIndirect;
  }
  void setInAllocaIndirect(bool Indirect) {
    assert(isInAlloca() && "Invalid kind!");
    InAllocaIndirect = Indirect;
  }

  /// Return true if this field of an inalloca struct should be returned
  /// to implement a struct return calling convention.
  bool getInAllocaSRet() const {
    assert(isInAlloca() && "Invalid kind!");
    return InAllocaSRet;
  }

  void setInAllocaSRet(bool SRet) {
    assert(isInAlloca() && "Invalid kind!");
    InAllocaSRet = SRet;
  }

  bool getCanBeFlattened() const {
    assert(isDirect() && "Invalid kind!");
    return CanBeFlattened;
  }

  void setCanBeFlattened(bool Flatten) {
    assert(isDirect() && "Invalid kind!");
    CanBeFlattened = Flatten;
  }

  void dump() const;
};

/// A class for recording the number of arguments that a function
/// signature requires.
class RequiredArgs {
  /// The number of required arguments, or ~0 if the signature does
  /// not permit optional arguments.
  unsigned NumRequired;
public:
  enum All_t { All };

  RequiredArgs(All_t _) : NumRequired(~0U) {}
  explicit RequiredArgs(unsigned n) : NumRequired(n) {
    assert(n != ~0U);
  }

  /// Compute the arguments required by the given formal prototype,
  /// given that there may be some additional, non-formal arguments
  /// in play.
  ///
  /// If FD is not null, this will consider pass_object_size params in FD.
  static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
                                       unsigned additional) {
    if (!prototype->isVariadic()) return All;

    if (prototype->hasExtParameterInfos())
      additional += llvm::count_if(
          prototype->getExtParameterInfos(),
          [](const FunctionProtoType::ExtParameterInfo &ExtInfo) {
            return ExtInfo.hasPassObjectSize();
          });

    return RequiredArgs(prototype->getNumParams() + additional);
  }

  static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
                                       unsigned additional) {
    return forPrototypePlus(prototype.getTypePtr(), additional);
  }

  static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
    return forPrototypePlus(prototype, 0);
  }

  static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
    return forPrototypePlus(prototype.getTypePtr(), 0);
  }

  bool allowsOptionalArgs() const { return NumRequired != ~0U; }
  unsigned getNumRequiredArgs() const {
    assert(allowsOptionalArgs());
    return NumRequired;
  }

  unsigned getOpaqueData() const { return NumRequired; }
  static RequiredArgs getFromOpaqueData(unsigned value) {
    if (value == ~0U) return All;
    return RequiredArgs(value);
  }
};

// Implementation detail of CGFunctionInfo, factored out so it can be named
// in the TrailingObjects base class of CGFunctionInfo.
struct CGFunctionInfoArgInfo {
  CanQualType type;
  ABIArgInfo info;
};

/// CGFunctionInfo - Class to encapsulate the information about a
/// function definition.
class CGFunctionInfo final
    : public llvm::FoldingSetNode,
      private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo,
                                    FunctionProtoType::ExtParameterInfo> {
  typedef CGFunctionInfoArgInfo ArgInfo;
  typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo;

  /// The LLVM::CallingConv to use for this function (as specified by the
  /// user).
  unsigned CallingConvention : 8;

  /// The LLVM::CallingConv to actually use for this function, which may
  /// depend on the ABI.
  unsigned EffectiveCallingConvention : 8;

  /// The clang::CallingConv that this was originally created with.
  unsigned ASTCallingConvention : 6;

  /// Whether this is an instance method.
  unsigned InstanceMethod : 1;

  /// Whether this is a chain call.
  unsigned ChainCall : 1;

  /// Whether this function is a CMSE nonsecure call
  unsigned CmseNSCall : 1;

  /// Whether this function is noreturn.
  unsigned NoReturn : 1;

  /// Whether this function is returns-retained.
  unsigned ReturnsRetained : 1;

  /// Whether this function saved caller registers.
  unsigned NoCallerSavedRegs : 1;

  /// How many arguments to pass inreg.
  unsigned HasRegParm : 1;
  unsigned RegParm : 3;

  /// Whether this function has nocf_check attribute.
  unsigned NoCfCheck : 1;

  RequiredArgs Required;

  /// The struct representing all arguments passed in memory.  Only used when
  /// passing non-trivial types with inalloca.  Not part of the profile.
  llvm::StructType *ArgStruct;
  unsigned ArgStructAlign : 31;
  unsigned HasExtParameterInfos : 1;

  unsigned NumArgs;

  ArgInfo *getArgsBuffer() {
    return getTrailingObjects<ArgInfo>();
  }
  const ArgInfo *getArgsBuffer() const {
    return getTrailingObjects<ArgInfo>();
  }

  ExtParameterInfo *getExtParameterInfosBuffer() {
    return getTrailingObjects<ExtParameterInfo>();
  }
  const ExtParameterInfo *getExtParameterInfosBuffer() const{
    return getTrailingObjects<ExtParameterInfo>();
  }

  CGFunctionInfo() : Required(RequiredArgs::All) {}

public:
  static CGFunctionInfo *create(unsigned llvmCC,
                                bool instanceMethod,
                                bool chainCall,
                                const FunctionType::ExtInfo &extInfo,
                                ArrayRef<ExtParameterInfo> paramInfos,
                                CanQualType resultType,
                                ArrayRef<CanQualType> argTypes,
                                RequiredArgs required);
  void operator delete(void *p) { ::operator delete(p); }

  // Friending class TrailingObjects is apparently not good enough for MSVC,
  // so these have to be public.
  friend class TrailingObjects;
  size_t numTrailingObjects(OverloadToken<ArgInfo>) const {
    return NumArgs + 1;
  }
  size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
    return (HasExtParameterInfos ? NumArgs : 0);
  }

  typedef const ArgInfo *const_arg_iterator;
  typedef ArgInfo *arg_iterator;

  MutableArrayRef<ArgInfo> arguments() {
    return MutableArrayRef<ArgInfo>(arg_begin(), NumArgs);
  }
  ArrayRef<ArgInfo> arguments() const {
    return ArrayRef<ArgInfo>(arg_begin(), NumArgs);
  }

  const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
  const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
  arg_iterator arg_begin() { return getArgsBuffer() + 1; }
  arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }

  unsigned  arg_size() const { return NumArgs; }

  bool isVariadic() const { return Required.allowsOptionalArgs(); }
  RequiredArgs getRequiredArgs() const { return Required; }
  unsigned getNumRequiredArgs() const {
    return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
  }

  bool isInstanceMethod() const { return InstanceMethod; }

  bool isChainCall() const { return ChainCall; }

  bool isCmseNSCall() const { return CmseNSCall; }

  bool isNoReturn() const { return NoReturn; }

  /// In ARC, whether this function retains its return value.  This
  /// is not always reliable for call sites.
  bool isReturnsRetained() const { return ReturnsRetained; }

  /// Whether this function no longer saves caller registers.
  bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }

  /// Whether this function has nocf_check attribute.
  bool isNoCfCheck() const { return NoCfCheck; }

  /// getASTCallingConvention() - Return the AST-specified calling
  /// convention.
  CallingConv getASTCallingConvention() const {
    return CallingConv(ASTCallingConvention);
  }

  /// getCallingConvention - Return the user specified calling
  /// convention, which has been translated into an LLVM CC.
  unsigned getCallingConvention() const { return CallingConvention; }

  /// getEffectiveCallingConvention - Return the actual calling convention to
  /// use, which may depend on the ABI.
  unsigned getEffectiveCallingConvention() const {
    return EffectiveCallingConvention;
  }
  void setEffectiveCallingConvention(unsigned Value) {
    EffectiveCallingConvention = Value;
  }

  bool getHasRegParm() const { return HasRegParm; }
  unsigned getRegParm() const { return RegParm; }

  FunctionType::ExtInfo getExtInfo() const {
    return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
                                 getASTCallingConvention(), isReturnsRetained(),
                                 isNoCallerSavedRegs(), isNoCfCheck(),
                                 isCmseNSCall());
  }

  CanQualType getReturnType() const { return getArgsBuffer()[0].type; }

  ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
  const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }

  ArrayRef<ExtParameterInfo> getExtParameterInfos() const {
    if (!HasExtParameterInfos) return {};
    return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs);
  }
  ExtParameterInfo getExtParameterInfo(unsigned argIndex) const {
    assert(argIndex <= NumArgs);
    if (!HasExtParameterInfos) return ExtParameterInfo();
    return getExtParameterInfos()[argIndex];
  }

  /// Return true if this function uses inalloca arguments.
  bool usesInAlloca() const { return ArgStruct; }

  /// Get the struct type used to represent all the arguments in memory.
  llvm::StructType *getArgStruct() const { return ArgStruct; }
  CharUnits getArgStructAlignment() const {
    return CharUnits::fromQuantity(ArgStructAlign);
  }
  void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
    ArgStruct = Ty;
    ArgStructAlign = Align.getQuantity();
  }

  void Profile(llvm::FoldingSetNodeID &ID) {
    ID.AddInteger(getASTCallingConvention());
    ID.AddBoolean(InstanceMethod);
    ID.AddBoolean(ChainCall);
    ID.AddBoolean(NoReturn);
    ID.AddBoolean(ReturnsRetained);
    ID.AddBoolean(NoCallerSavedRegs);
    ID.AddBoolean(HasRegParm);
    ID.AddInteger(RegParm);
    ID.AddBoolean(NoCfCheck);
    ID.AddBoolean(CmseNSCall);
    ID.AddInteger(Required.getOpaqueData());
    ID.AddBoolean(HasExtParameterInfos);
    if (HasExtParameterInfos) {
      for (auto paramInfo : getExtParameterInfos())
        ID.AddInteger(paramInfo.getOpaqueValue());
    }
    getReturnType().Profile(ID);
    for (const auto &I : arguments())
      I.type.Profile(ID);
  }
  static void Profile(llvm::FoldingSetNodeID &ID,
                      bool InstanceMethod,
                      bool ChainCall,
                      const FunctionType::ExtInfo &info,
                      ArrayRef<ExtParameterInfo> paramInfos,
                      RequiredArgs required,
                      CanQualType resultType,
                      ArrayRef<CanQualType> argTypes) {
    ID.AddInteger(info.getCC());
    ID.AddBoolean(InstanceMethod);
    ID.AddBoolean(ChainCall);
    ID.AddBoolean(info.getNoReturn());
    ID.AddBoolean(info.getProducesResult());
    ID.AddBoolean(info.getNoCallerSavedRegs());
    ID.AddBoolean(info.getHasRegParm());
    ID.AddInteger(info.getRegParm());
    ID.AddBoolean(info.getNoCfCheck());
    ID.AddBoolean(info.getCmseNSCall());
    ID.AddInteger(required.getOpaqueData());
    ID.AddBoolean(!paramInfos.empty());
    if (!paramInfos.empty()) {
      for (auto paramInfo : paramInfos)
        ID.AddInteger(paramInfo.getOpaqueValue());
    }
    resultType.Profile(ID);
    for (ArrayRef<CanQualType>::iterator
           i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
      i->Profile(ID);
    }
  }
};

}  // end namespace CodeGen
}  // end namespace clang

#endif
