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