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