Clang Project

clang_source_code/include/clang/CodeGen/CGFunctionInfo.h
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
28namespace clang {
29namespace 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.
33class ABIArgInfo {
34public:
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
78private:
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 CanBeFlattened1;   // 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
117public:
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 = nullptrunsigned 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 Tyllvm::Type *T = nullptr) {
140     (0) . __assert_fail ("Ty->isIntegralOrEnumerationType() && \"Unexpected QualType\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 140, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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 Tyllvm::Type *T = nullptr) {
150     (0) . __assert_fail ("Ty->isIntegralOrEnumerationType() && \"Unexpected QualType\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 150, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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 Tyllvm::Type *T = nullptr) {
162     (0) . __assert_fail ("Ty->isIntegralOrEnumerationType() && \"Unexpected QualType\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 162, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
163    if (Ty->hasSignedIntegerRepresentation())
164      return getSignExtend(TyT);
165    return getZeroExtend(TyT);
166  }
167
168  static ABIArgInfo getExtendInReg(QualType Tyllvm::Type *T = nullptr) {
169    auto AI = getExtend(TyT);
170    AI.setInReg(true);
171    return AI;
172  }
173  static ABIArgInfo getIgnore() {
174    return ABIArgInfo(Ignore);
175  }
176  static ABIArgInfo getIndirect(CharUnits Alignmentbool 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 Alignmentbool ByVal = true,
188                                     bool Realign = false) {
189    auto AI = getIndirect(AlignmentByValRealign);
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    getNumElements() != 1", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 221, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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        getElementType(unpaddedIndex) == eltType", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 229, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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      getNumElements() == unpaddedIndex", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 238, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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      getArrayElementType()->isIntegerTy(8)", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 252, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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     (0) . __assert_fail ("(isDirect() || isExtend()) && \"Not a direct or extend kind\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 274, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((isDirect() || isExtend()) && "Not a direct or extend kind");
275    return DirectOffset;
276  }
277  void setDirectOffset(unsigned Offset) {
278     (0) . __assert_fail ("(isDirect() || isExtend()) && \"Not a direct or extend kind\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 278, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((isDirect() || isExtend()) && "Not a direct or extend kind");
279    DirectOffset = Offset;
280  }
281
282  bool isSignExt() const {
283     (0) . __assert_fail ("isExtend() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 283, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isExtend() && "Invalid kind!");
284    return SignExt;
285  }
286  void setSignExt(bool SExt) {
287     (0) . __assert_fail ("isExtend() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 287, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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     (0) . __assert_fail ("canHaveCoerceToType() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 303, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(canHaveCoerceToType() && "Invalid kind!");
304    return TypeData;
305  }
306
307  void setCoerceToType(llvm::Type *T) {
308     (0) . __assert_fail ("canHaveCoerceToType() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 308, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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     (0) . __assert_fail ("(isDirect() || isExtend() || isIndirect()) && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 333, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
334    return InReg;
335  }
336
337  void setInReg(bool IR) {
338     (0) . __assert_fail ("(isDirect() || isExtend() || isIndirect()) && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 338, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
339    InReg = IR;
340  }
341
342  // Indirect accessors
343  CharUnits getIndirectAlign() const {
344     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 344, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIndirect() && "Invalid kind!");
345    return CharUnits::fromQuantity(IndirectAlign);
346  }
347  void setIndirectAlign(CharUnits IA) {
348     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 348, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIndirect() && "Invalid kind!");
349    IndirectAlign = IA.getQuantity();
350  }
351
352  bool getIndirectByVal() const {
353     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 353, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIndirect() && "Invalid kind!");
354    return IndirectByVal;
355  }
356  void setIndirectByVal(bool IBV) {
357     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 357, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIndirect() && "Invalid kind!");
358    IndirectByVal = IBV;
359  }
360
361  bool getIndirectRealign() const {
362     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 362, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIndirect() && "Invalid kind!");
363    return IndirectRealign;
364  }
365  void setIndirectRealign(bool IR) {
366     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 366, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIndirect() && "Invalid kind!");
367    IndirectRealign = IR;
368  }
369
370  bool isSRetAfterThis() const {
371     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 371, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIndirect() && "Invalid kind!");
372    return SRetAfterThis;
373  }
374  void setSRetAfterThis(bool AfterThis) {
375     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 375, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIndirect() && "Invalid kind!");
376    SRetAfterThis = AfterThis;
377  }
378
379  unsigned getInAllocaFieldIndex() const {
380     (0) . __assert_fail ("isInAlloca() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 380, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isInAlloca() && "Invalid kind!");
381    return AllocaFieldIndex;
382  }
383  void setInAllocaFieldIndex(unsigned FieldIndex) {
384     (0) . __assert_fail ("isInAlloca() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 384, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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     (0) . __assert_fail ("isInAlloca() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 391, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isInAlloca() && "Invalid kind!");
392    return InAllocaSRet;
393  }
394
395  void setInAllocaSRet(bool SRet) {
396     (0) . __assert_fail ("isInAlloca() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 396, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isInAlloca() && "Invalid kind!");
397    InAllocaSRet = SRet;
398  }
399
400  bool getCanBeFlattened() const {
401     (0) . __assert_fail ("isDirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 401, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isDirect() && "Invalid kind!");
402    return CanBeFlattened;
403  }
404
405  void setCanBeFlattened(bool Flatten) {
406     (0) . __assert_fail ("isDirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 406, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isDirect() && "Invalid kind!");
407    CanBeFlattened = Flatten;
408  }
409
410  bool getSuppressSRet() const {
411     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 411, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isIndirect() && "Invalid kind!");
412    return SuppressSRet;
413  }
414
415  void setSuppressSRet(bool Suppress) {
416     (0) . __assert_fail ("isIndirect() && \"Invalid kind!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/CGFunctionInfo.h", 416, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">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.
425class RequiredArgs {
426  /// The number of required arguments, or ~0 if the signature does
427  /// not permit optional arguments.
428  unsigned NumRequired;
429public:
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<FunctionProtoTypeprototype,
457                                       unsigned additional) {
458    return forPrototypePlus(prototype.getTypePtr(), additional);
459  }
460
461  static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
462    return forPrototypePlus(prototype0);
463  }
464
465  static RequiredArgs forPrototype(CanQual<FunctionProtoTypeprototype) {
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 == ~0Ureturn 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.
484struct CGFunctionInfoArgInfo {
485  CanQualType type;
486  ABIArgInfo info;
487};
488
489/// CGFunctionInfo - Class to encapsulate the information about a
490/// function definition.
491class 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
557public:
558  static CGFunctionInfo *create(unsigned llvmCC,
559                                bool instanceMethod,
560                                bool chainCall,
561                                const FunctionType::ExtInfo &extInfo,
562                                ArrayRef<ExtParameterInfoparamInfos,
563                                CanQualType resultType,
564                                ArrayRef<CanQualTypeargTypes,
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<ExtParameterInfogetExtParameterInfos() const {
652    if (!HasExtParameterInfos) return {};
653    return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs);
654  }
655  ExtParameterInfo getExtParameterInfo(unsigned argIndexconst {
656    assert(argIndex <= NumArgs);
657    if (!HasExtParameterInfosreturn 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 *TyCharUnits 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<ExtParameterInfoparamInfos,
699                      RequiredArgs required,
700                      CanQualType resultType,
701                      ArrayRef<CanQualTypeargTypes) {
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
clang::CodeGen::ABIArgInfo::Kind
clang::CodeGen::ABIArgInfo::TypeData
clang::CodeGen::ABIArgInfo::(anonymous union)::PaddingType
clang::CodeGen::ABIArgInfo::(anonymous union)::UnpaddedCoerceAndExpandType
clang::CodeGen::ABIArgInfo::(anonymous union)::DirectOffset
clang::CodeGen::ABIArgInfo::(anonymous union)::IndirectAlign
clang::CodeGen::ABIArgInfo::(anonymous union)::AllocaFieldIndex
clang::CodeGen::ABIArgInfo::TheKind
clang::CodeGen::ABIArgInfo::PaddingInReg
clang::CodeGen::ABIArgInfo::InAllocaSRet
clang::CodeGen::ABIArgInfo::IndirectByVal
clang::CodeGen::ABIArgInfo::IndirectRealign
clang::CodeGen::ABIArgInfo::SRetAfterThis
clang::CodeGen::ABIArgInfo::InReg
clang::CodeGen::ABIArgInfo::CanBeFlattened
clang::CodeGen::ABIArgInfo::SignExt
clang::CodeGen::ABIArgInfo::SuppressSRet
clang::CodeGen::ABIArgInfo::canHavePaddingType
clang::CodeGen::ABIArgInfo::setPaddingType
clang::CodeGen::ABIArgInfo::setUnpaddedCoerceToType
clang::CodeGen::ABIArgInfo::getDirect
clang::CodeGen::ABIArgInfo::getDirectInReg
clang::CodeGen::ABIArgInfo::getSignExtend
clang::CodeGen::ABIArgInfo::getZeroExtend
clang::CodeGen::ABIArgInfo::getExtend
clang::CodeGen::ABIArgInfo::getExtendInReg
clang::CodeGen::ABIArgInfo::getIgnore
clang::CodeGen::ABIArgInfo::getIndirect
clang::CodeGen::ABIArgInfo::getIndirectInReg
clang::CodeGen::ABIArgInfo::getInAlloca
clang::CodeGen::ABIArgInfo::getExpand
clang::CodeGen::ABIArgInfo::getExpandWithPadding
clang::CodeGen::ABIArgInfo::getCoerceAndExpand
clang::CodeGen::ABIArgInfo::isPaddingForCoerceAndExpand
clang::CodeGen::ABIArgInfo::getKind
clang::CodeGen::ABIArgInfo::isDirect
clang::CodeGen::ABIArgInfo::isInAlloca
clang::CodeGen::ABIArgInfo::isExtend
clang::CodeGen::ABIArgInfo::isIgnore
clang::CodeGen::ABIArgInfo::isIndirect
clang::CodeGen::ABIArgInfo::isExpand
clang::CodeGen::ABIArgInfo::isCoerceAndExpand
clang::CodeGen::ABIArgInfo::canHaveCoerceToType
clang::CodeGen::ABIArgInfo::getDirectOffset
clang::CodeGen::ABIArgInfo::setDirectOffset
clang::CodeGen::ABIArgInfo::isSignExt
clang::CodeGen::ABIArgInfo::setSignExt
clang::CodeGen::ABIArgInfo::getPaddingType
clang::CodeGen::ABIArgInfo::getPaddingInReg
clang::CodeGen::ABIArgInfo::setPaddingInReg
clang::CodeGen::ABIArgInfo::getCoerceToType
clang::CodeGen::ABIArgInfo::setCoerceToType
clang::CodeGen::ABIArgInfo::getCoerceAndExpandType
clang::CodeGen::ABIArgInfo::getUnpaddedCoerceAndExpandType
clang::CodeGen::ABIArgInfo::getCoerceAndExpandTypeSequence
clang::CodeGen::ABIArgInfo::getInReg
clang::CodeGen::ABIArgInfo::setInReg
clang::CodeGen::ABIArgInfo::getIndirectAlign
clang::CodeGen::ABIArgInfo::setIndirectAlign
clang::CodeGen::ABIArgInfo::getIndirectByVal
clang::CodeGen::ABIArgInfo::setIndirectByVal
clang::CodeGen::ABIArgInfo::getIndirectRealign
clang::CodeGen::ABIArgInfo::setIndirectRealign
clang::CodeGen::ABIArgInfo::isSRetAfterThis
clang::CodeGen::ABIArgInfo::setSRetAfterThis
clang::CodeGen::ABIArgInfo::getInAllocaFieldIndex
clang::CodeGen::ABIArgInfo::setInAllocaFieldIndex
clang::CodeGen::ABIArgInfo::getInAllocaSRet
clang::CodeGen::ABIArgInfo::setInAllocaSRet
clang::CodeGen::ABIArgInfo::getCanBeFlattened
clang::CodeGen::ABIArgInfo::setCanBeFlattened
clang::CodeGen::ABIArgInfo::getSuppressSRet
clang::CodeGen::ABIArgInfo::setSuppressSRet
clang::CodeGen::ABIArgInfo::dump
clang::CodeGen::RequiredArgs::NumRequired
clang::CodeGen::RequiredArgs::All_t
clang::CodeGen::RequiredArgs::forPrototypePlus
clang::CodeGen::RequiredArgs::forPrototypePlus
clang::CodeGen::RequiredArgs::forPrototype
clang::CodeGen::RequiredArgs::forPrototype
clang::CodeGen::RequiredArgs::allowsOptionalArgs
clang::CodeGen::RequiredArgs::getNumRequiredArgs
clang::CodeGen::RequiredArgs::getOpaqueData
clang::CodeGen::RequiredArgs::getFromOpaqueData
clang::CodeGen::CGFunctionInfoArgInfo::type
clang::CodeGen::CGFunctionInfoArgInfo::info
clang::CodeGen::CGFunctionInfo::CallingConvention
clang::CodeGen::CGFunctionInfo::EffectiveCallingConvention
clang::CodeGen::CGFunctionInfo::ASTCallingConvention
clang::CodeGen::CGFunctionInfo::InstanceMethod
clang::CodeGen::CGFunctionInfo::ChainCall
clang::CodeGen::CGFunctionInfo::NoReturn
clang::CodeGen::CGFunctionInfo::ReturnsRetained
clang::CodeGen::CGFunctionInfo::NoCallerSavedRegs
clang::CodeGen::CGFunctionInfo::HasRegParm
clang::CodeGen::CGFunctionInfo::RegParm
clang::CodeGen::CGFunctionInfo::NoCfCheck
clang::CodeGen::CGFunctionInfo::Required
clang::CodeGen::CGFunctionInfo::ArgStruct
clang::CodeGen::CGFunctionInfo::ArgStructAlign
clang::CodeGen::CGFunctionInfo::HasExtParameterInfos
clang::CodeGen::CGFunctionInfo::NumArgs
clang::CodeGen::CGFunctionInfo::getArgsBuffer
clang::CodeGen::CGFunctionInfo::getArgsBuffer
clang::CodeGen::CGFunctionInfo::getExtParameterInfosBuffer
clang::CodeGen::CGFunctionInfo::getExtParameterInfosBuffer
clang::CodeGen::CGFunctionInfo::create
clang::CodeGen::CGFunctionInfo::numTrailingObjects
clang::CodeGen::CGFunctionInfo::arguments
clang::CodeGen::CGFunctionInfo::arguments
clang::CodeGen::CGFunctionInfo::arg_begin
clang::CodeGen::CGFunctionInfo::arg_end
clang::CodeGen::CGFunctionInfo::arg_begin
clang::CodeGen::CGFunctionInfo::arg_end
clang::CodeGen::CGFunctionInfo::arg_size
clang::CodeGen::CGFunctionInfo::isVariadic
clang::CodeGen::CGFunctionInfo::getRequiredArgs
clang::CodeGen::CGFunctionInfo::getNumRequiredArgs
clang::CodeGen::CGFunctionInfo::isInstanceMethod
clang::CodeGen::CGFunctionInfo::isChainCall
clang::CodeGen::CGFunctionInfo::isNoReturn
clang::CodeGen::CGFunctionInfo::isReturnsRetained
clang::CodeGen::CGFunctionInfo::isNoCallerSavedRegs
clang::CodeGen::CGFunctionInfo::isNoCfCheck
clang::CodeGen::CGFunctionInfo::getASTCallingConvention
clang::CodeGen::CGFunctionInfo::getCallingConvention
clang::CodeGen::CGFunctionInfo::getEffectiveCallingConvention
clang::CodeGen::CGFunctionInfo::setEffectiveCallingConvention
clang::CodeGen::CGFunctionInfo::getHasRegParm
clang::CodeGen::CGFunctionInfo::getRegParm
clang::CodeGen::CGFunctionInfo::getExtInfo
clang::CodeGen::CGFunctionInfo::getReturnType
clang::CodeGen::CGFunctionInfo::getReturnInfo
clang::CodeGen::CGFunctionInfo::getReturnInfo
clang::CodeGen::CGFunctionInfo::getExtParameterInfos
clang::CodeGen::CGFunctionInfo::getExtParameterInfo
clang::CodeGen::CGFunctionInfo::usesInAlloca
clang::CodeGen::CGFunctionInfo::getArgStruct
clang::CodeGen::CGFunctionInfo::getArgStructAlignment
clang::CodeGen::CGFunctionInfo::setArgStruct
clang::CodeGen::CGFunctionInfo::Profile
clang::CodeGen::CGFunctionInfo::Profile
clang::CodeGen::ABIArgInfo::getCoerceAndExpand
clang::CodeGen::CGFunctionInfo::setArgStruct
clang::CodeGen::ABIArgInfo::setPaddingType
clang::CodeGen::ABIArgInfo::setUnpaddedCoerceToType
clang::CodeGen::ABIArgInfo::getDirect
clang::CodeGen::ABIArgInfo::getDirectInReg
clang::CodeGen::ABIArgInfo::getSignExtend
clang::CodeGen::ABIArgInfo::getZeroExtend
clang::CodeGen::ABIArgInfo::getExtend
clang::CodeGen::ABIArgInfo::getExtendInReg
clang::CodeGen::ABIArgInfo::getIndirect
clang::CodeGen::ABIArgInfo::getExpandWithPadding
clang::CodeGen::ABIArgInfo::getCoerceAndExpand
clang::CodeGen::ABIArgInfo::isPaddingForCoerceAndExpand
clang::CodeGen::ABIArgInfo::setCoerceToType