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