CGFunctionInfo.h revision 651f13cea278ec967336033dd032faef0e9fc2ec
18b54999a831bb195c08541ca995ef0505c96193fMark Lacey//==-- CGFunctionInfo.h - Representation of function argument/return types -==//
28b54999a831bb195c08541ca995ef0505c96193fMark Lacey//
38b54999a831bb195c08541ca995ef0505c96193fMark Lacey//                     The LLVM Compiler Infrastructure
48b54999a831bb195c08541ca995ef0505c96193fMark Lacey//
58b54999a831bb195c08541ca995ef0505c96193fMark Lacey// This file is distributed under the University of Illinois Open Source
68b54999a831bb195c08541ca995ef0505c96193fMark Lacey// License. See LICENSE.TXT for details.
78b54999a831bb195c08541ca995ef0505c96193fMark Lacey//
88b54999a831bb195c08541ca995ef0505c96193fMark Lacey//===----------------------------------------------------------------------===//
98b54999a831bb195c08541ca995ef0505c96193fMark Lacey//
108b54999a831bb195c08541ca995ef0505c96193fMark Lacey// Defines CGFunctionInfo and associated types used in representing the
118b54999a831bb195c08541ca995ef0505c96193fMark Lacey// LLVM source types and ABI-coerced types for function arguments and
128b54999a831bb195c08541ca995ef0505c96193fMark Lacey// return values.
138b54999a831bb195c08541ca995ef0505c96193fMark Lacey//
148b54999a831bb195c08541ca995ef0505c96193fMark Lacey//===----------------------------------------------------------------------===//
158b54999a831bb195c08541ca995ef0505c96193fMark Lacey
168b54999a831bb195c08541ca995ef0505c96193fMark Lacey#ifndef LLVM_CLANG_CODEGEN_FUNCTION_INFO_H
178b54999a831bb195c08541ca995ef0505c96193fMark Lacey#define LLVM_CLANG_CODEGEN_FUNCTION_INFO_H
188b54999a831bb195c08541ca995ef0505c96193fMark Lacey
198b54999a831bb195c08541ca995ef0505c96193fMark Lacey#include "clang/AST/CanonicalType.h"
208b54999a831bb195c08541ca995ef0505c96193fMark Lacey#include "clang/AST/Type.h"
218b54999a831bb195c08541ca995ef0505c96193fMark Lacey#include "llvm/ADT/FoldingSet.h"
228b54999a831bb195c08541ca995ef0505c96193fMark Lacey#include <cassert>
238b54999a831bb195c08541ca995ef0505c96193fMark Lacey
248b54999a831bb195c08541ca995ef0505c96193fMark Laceynamespace llvm {
258b54999a831bb195c08541ca995ef0505c96193fMark Lacey  class Type;
26651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  class StructType;
278b54999a831bb195c08541ca995ef0505c96193fMark Lacey}
288b54999a831bb195c08541ca995ef0505c96193fMark Lacey
298b54999a831bb195c08541ca995ef0505c96193fMark Laceynamespace clang {
30651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass Decl;
31651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
328b54999a831bb195c08541ca995ef0505c96193fMark Laceynamespace CodeGen {
338b54999a831bb195c08541ca995ef0505c96193fMark Lacey
348b54999a831bb195c08541ca995ef0505c96193fMark Lacey/// ABIArgInfo - Helper class to encapsulate information about how a
358b54999a831bb195c08541ca995ef0505c96193fMark Lacey/// specific C type should be passed to or returned from a function.
368b54999a831bb195c08541ca995ef0505c96193fMark Laceyclass ABIArgInfo {
378b54999a831bb195c08541ca995ef0505c96193fMark Laceypublic:
388b54999a831bb195c08541ca995ef0505c96193fMark Lacey  enum Kind {
398b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// Direct - Pass the argument directly using the normal converted LLVM
408b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// type, or by coercing to another specified type stored in
418b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// 'CoerceToType').  If an offset is specified (in UIntData), then the
428b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// argument passed is offset by some number of bytes in the memory
438b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// representation. A dummy argument is emitted before the real argument
448b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// if the specified type stored in "PaddingType" is not zero.
458b54999a831bb195c08541ca995ef0505c96193fMark Lacey    Direct,
468b54999a831bb195c08541ca995ef0505c96193fMark Lacey
478b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// Extend - Valid only for integer argument types. Same as 'direct'
488b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// but also emit a zero/sign extension attribute.
498b54999a831bb195c08541ca995ef0505c96193fMark Lacey    Extend,
508b54999a831bb195c08541ca995ef0505c96193fMark Lacey
518b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// Indirect - Pass the argument indirectly via a hidden pointer
528b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// with the specified alignment (0 indicates default alignment).
538b54999a831bb195c08541ca995ef0505c96193fMark Lacey    Indirect,
548b54999a831bb195c08541ca995ef0505c96193fMark Lacey
558b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// Ignore - Ignore the argument (treat as void). Useful for void and
568b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// empty structs.
578b54999a831bb195c08541ca995ef0505c96193fMark Lacey    Ignore,
588b54999a831bb195c08541ca995ef0505c96193fMark Lacey
598b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// Expand - Only valid for aggregate argument types. The structure should
608b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// be expanded into consecutive arguments for its constituent fields.
618b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// Currently expand is only allowed on structures whose fields
628b54999a831bb195c08541ca995ef0505c96193fMark Lacey    /// are all scalar types or are themselves expandable types.
638b54999a831bb195c08541ca995ef0505c96193fMark Lacey    Expand,
648b54999a831bb195c08541ca995ef0505c96193fMark Lacey
65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    /// This is similar to 'direct', except it only applies to arguments stored
67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    /// in memory and forbids any implicit copies.  When applied to a return
68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    /// type, it means the value is returned indirectly via an implicit sret
69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    /// parameter stored in the argument struct.
70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    InAlloca,
71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    KindFirst = Direct,
73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    KindLast = InAlloca
748b54999a831bb195c08541ca995ef0505c96193fMark Lacey  };
758b54999a831bb195c08541ca995ef0505c96193fMark Lacey
768b54999a831bb195c08541ca995ef0505c96193fMark Laceyprivate:
778b54999a831bb195c08541ca995ef0505c96193fMark Lacey  Kind TheKind;
788b54999a831bb195c08541ca995ef0505c96193fMark Lacey  llvm::Type *TypeData;
798b54999a831bb195c08541ca995ef0505c96193fMark Lacey  llvm::Type *PaddingType;
808b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned UIntData;
818b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool BoolData0;
828b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool BoolData1;
838b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool InReg;
848b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool PaddingInReg;
858b54999a831bb195c08541ca995ef0505c96193fMark Lacey
868b54999a831bb195c08541ca995ef0505c96193fMark Lacey  ABIArgInfo(Kind K, llvm::Type *TD, unsigned UI, bool B0, bool B1, bool IR,
878b54999a831bb195c08541ca995ef0505c96193fMark Lacey             bool PIR, llvm::Type* P)
888b54999a831bb195c08541ca995ef0505c96193fMark Lacey    : TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0),
898b54999a831bb195c08541ca995ef0505c96193fMark Lacey      BoolData1(B1), InReg(IR), PaddingInReg(PIR) {}
908b54999a831bb195c08541ca995ef0505c96193fMark Lacey
918b54999a831bb195c08541ca995ef0505c96193fMark Laceypublic:
928b54999a831bb195c08541ca995ef0505c96193fMark Lacey  ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
938b54999a831bb195c08541ca995ef0505c96193fMark Lacey
948b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0,
958b54999a831bb195c08541ca995ef0505c96193fMark Lacey                              llvm::Type *Padding = 0) {
968b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return ABIArgInfo(Direct, T, Offset, false, false, false, false, Padding);
978b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
988b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static ABIArgInfo getDirectInReg(llvm::Type *T = 0) {
998b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return ABIArgInfo(Direct, T, 0, false, false, true, false, 0);
1008b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1018b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static ABIArgInfo getExtend(llvm::Type *T = 0) {
1028b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return ABIArgInfo(Extend, T, 0, false, false, false, false, 0);
1038b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1048b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static ABIArgInfo getExtendInReg(llvm::Type *T = 0) {
1058b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return ABIArgInfo(Extend, T, 0, false, false, true, false, 0);
1068b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1078b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static ABIArgInfo getIgnore() {
1088b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return ABIArgInfo(Ignore, 0, 0, false, false, false, false, 0);
1098b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1108b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
1118b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                , bool Realign = false
1128b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                , llvm::Type *Padding = 0) {
1138b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, false,
1148b54999a831bb195c08541ca995ef0505c96193fMark Lacey                      Padding);
1158b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  static ABIArgInfo getInAlloca(unsigned FieldIndex) {
117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return ABIArgInfo(InAlloca, 0, FieldIndex, false, false, false, false, 0);
118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
1198b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true
1208b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                , bool Realign = false) {
1218b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, false, 0);
1228b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1238b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static ABIArgInfo getExpand() {
1248b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return ABIArgInfo(Expand, 0, 0, false, false, false, false, 0);
1258b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1268b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
1278b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                         llvm::Type *Padding) {
1288b54999a831bb195c08541ca995ef0505c96193fMark Lacey   return ABIArgInfo(Expand, 0, 0, false, false, false, PaddingInReg,
1298b54999a831bb195c08541ca995ef0505c96193fMark Lacey                     Padding);
1308b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1318b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1328b54999a831bb195c08541ca995ef0505c96193fMark Lacey  Kind getKind() const { return TheKind; }
1338b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool isDirect() const { return TheKind == Direct; }
134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool isInAlloca() const { return TheKind == InAlloca; }
1358b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool isExtend() const { return TheKind == Extend; }
1368b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool isIgnore() const { return TheKind == Ignore; }
1378b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool isIndirect() const { return TheKind == Indirect; }
1388b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool isExpand() const { return TheKind == Expand; }
1398b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1408b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool canHaveCoerceToType() const {
1418b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return TheKind == Direct || TheKind == Extend;
1428b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1438b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1448b54999a831bb195c08541ca995ef0505c96193fMark Lacey  // Direct/Extend accessors
1458b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned getDirectOffset() const {
1468b54999a831bb195c08541ca995ef0505c96193fMark Lacey    assert((isDirect() || isExtend()) && "Not a direct or extend kind");
1478b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return UIntData;
1488b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1498b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1508b54999a831bb195c08541ca995ef0505c96193fMark Lacey  llvm::Type *getPaddingType() const {
1518b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return PaddingType;
1528b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1538b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1548b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool getPaddingInReg() const {
1558b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return PaddingInReg;
1568b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1578b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1588b54999a831bb195c08541ca995ef0505c96193fMark Lacey  llvm::Type *getCoerceToType() const {
1598b54999a831bb195c08541ca995ef0505c96193fMark Lacey    assert(canHaveCoerceToType() && "Invalid kind!");
1608b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return TypeData;
1618b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1628b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1638b54999a831bb195c08541ca995ef0505c96193fMark Lacey  void setCoerceToType(llvm::Type *T) {
1648b54999a831bb195c08541ca995ef0505c96193fMark Lacey    assert(canHaveCoerceToType() && "Invalid kind!");
1658b54999a831bb195c08541ca995ef0505c96193fMark Lacey    TypeData = T;
1668b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1678b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1688b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool getInReg() const {
1698b54999a831bb195c08541ca995ef0505c96193fMark Lacey    assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
1708b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return InReg;
1718b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1728b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1738b54999a831bb195c08541ca995ef0505c96193fMark Lacey  // Indirect accessors
1748b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned getIndirectAlign() const {
1758b54999a831bb195c08541ca995ef0505c96193fMark Lacey    assert(TheKind == Indirect && "Invalid kind!");
1768b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return UIntData;
1778b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1788b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1798b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool getIndirectByVal() const {
1808b54999a831bb195c08541ca995ef0505c96193fMark Lacey    assert(TheKind == Indirect && "Invalid kind!");
1818b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return BoolData0;
1828b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1838b54999a831bb195c08541ca995ef0505c96193fMark Lacey
1848b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool getIndirectRealign() const {
1858b54999a831bb195c08541ca995ef0505c96193fMark Lacey    assert(TheKind == Indirect && "Invalid kind!");
1868b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return BoolData1;
1878b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
1888b54999a831bb195c08541ca995ef0505c96193fMark Lacey
189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned getInAllocaFieldIndex() const {
190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    assert(TheKind == InAlloca && "Invalid kind!");
191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return UIntData;
192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Return true if this field of an inalloca struct should be returned
195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// to implement a struct return calling convention.
196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool getInAllocaSRet() const {
197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    assert(TheKind == InAlloca && "Invalid kind!");
198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return BoolData0;
199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void setInAllocaSRet(bool SRet) {
202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    assert(TheKind == InAlloca && "Invalid kind!");
203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BoolData0 = SRet;
204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2068b54999a831bb195c08541ca995ef0505c96193fMark Lacey  void dump() const;
2078b54999a831bb195c08541ca995ef0505c96193fMark Lacey};
2088b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2098b54999a831bb195c08541ca995ef0505c96193fMark Lacey/// A class for recording the number of arguments that a function
2108b54999a831bb195c08541ca995ef0505c96193fMark Lacey/// signature requires.
2118b54999a831bb195c08541ca995ef0505c96193fMark Laceyclass RequiredArgs {
2128b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// The number of required arguments, or ~0 if the signature does
2138b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// not permit optional arguments.
2148b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned NumRequired;
2158b54999a831bb195c08541ca995ef0505c96193fMark Laceypublic:
2168b54999a831bb195c08541ca995ef0505c96193fMark Lacey  enum All_t { All };
2178b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2188b54999a831bb195c08541ca995ef0505c96193fMark Lacey  RequiredArgs(All_t _) : NumRequired(~0U) {}
2198b54999a831bb195c08541ca995ef0505c96193fMark Lacey  explicit RequiredArgs(unsigned n) : NumRequired(n) {
2208b54999a831bb195c08541ca995ef0505c96193fMark Lacey    assert(n != ~0U);
2218b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
2228b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2238b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// Compute the arguments required by the given formal prototype,
2248b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// given that there may be some additional, non-formal arguments
2258b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// in play.
2268b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
2278b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                       unsigned additional) {
2288b54999a831bb195c08541ca995ef0505c96193fMark Lacey    if (!prototype->isVariadic()) return All;
229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return RequiredArgs(prototype->getNumParams() + additional);
2308b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
2318b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2328b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
2338b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return forPrototypePlus(prototype, 0);
2348b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
2358b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2368b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
2378b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return forPrototype(prototype.getTypePtr());
2388b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
2398b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2408b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
2418b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                       unsigned additional) {
2428b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return forPrototypePlus(prototype.getTypePtr(), additional);
2438b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
2448b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2458b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool allowsOptionalArgs() const { return NumRequired != ~0U; }
2468b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned getNumRequiredArgs() const {
2478b54999a831bb195c08541ca995ef0505c96193fMark Lacey    assert(allowsOptionalArgs());
2488b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return NumRequired;
2498b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
2508b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2518b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned getOpaqueData() const { return NumRequired; }
2528b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static RequiredArgs getFromOpaqueData(unsigned value) {
2538b54999a831bb195c08541ca995ef0505c96193fMark Lacey    if (value == ~0U) return All;
2548b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return RequiredArgs(value);
2558b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
2568b54999a831bb195c08541ca995ef0505c96193fMark Lacey};
2578b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2588b54999a831bb195c08541ca995ef0505c96193fMark Lacey/// CGFunctionInfo - Class to encapsulate the information about a
2598b54999a831bb195c08541ca995ef0505c96193fMark Lacey/// function definition.
2608b54999a831bb195c08541ca995ef0505c96193fMark Laceyclass CGFunctionInfo : public llvm::FoldingSetNode {
2618b54999a831bb195c08541ca995ef0505c96193fMark Lacey  struct ArgInfo {
2628b54999a831bb195c08541ca995ef0505c96193fMark Lacey    CanQualType type;
2638b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ABIArgInfo info;
2648b54999a831bb195c08541ca995ef0505c96193fMark Lacey  };
2658b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2668b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// The LLVM::CallingConv to use for this function (as specified by the
2678b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// user).
2688b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned CallingConvention : 8;
2698b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2708b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// The LLVM::CallingConv to actually use for this function, which may
2718b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// depend on the ABI.
2728b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned EffectiveCallingConvention : 8;
2738b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2748b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// The clang::CallingConv that this was originally created with.
2758b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned ASTCallingConvention : 8;
2768b54999a831bb195c08541ca995ef0505c96193fMark Lacey
277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// Whether this is an instance method.
278651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned InstanceMethod : 1;
279651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2808b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// Whether this function is noreturn.
2818b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned NoReturn : 1;
2828b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2838b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// Whether this function is returns-retained.
2848b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned ReturnsRetained : 1;
2858b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2868b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// How many arguments to pass inreg.
2878b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned HasRegParm : 1;
2888b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned RegParm : 4;
2898b54999a831bb195c08541ca995ef0505c96193fMark Lacey
2908b54999a831bb195c08541ca995ef0505c96193fMark Lacey  RequiredArgs Required;
2918b54999a831bb195c08541ca995ef0505c96193fMark Lacey
292651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// The struct representing all arguments passed in memory.  Only used when
293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// passing non-trivial types with inalloca.  Not part of the profile.
294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::StructType *ArgStruct;
295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
2968b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned NumArgs;
2978b54999a831bb195c08541ca995ef0505c96193fMark Lacey  ArgInfo *getArgsBuffer() {
2988b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return reinterpret_cast<ArgInfo*>(this+1);
2998b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
3008b54999a831bb195c08541ca995ef0505c96193fMark Lacey  const ArgInfo *getArgsBuffer() const {
3018b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return reinterpret_cast<const ArgInfo*>(this + 1);
3028b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
3038b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3048b54999a831bb195c08541ca995ef0505c96193fMark Lacey  CGFunctionInfo() : Required(RequiredArgs::All) {}
3058b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3068b54999a831bb195c08541ca995ef0505c96193fMark Laceypublic:
3078b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static CGFunctionInfo *create(unsigned llvmCC,
308651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                bool InstanceMethod,
3098b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                const FunctionType::ExtInfo &extInfo,
3108b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                CanQualType resultType,
3118b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                ArrayRef<CanQualType> argTypes,
3128b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                RequiredArgs required);
3138b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3148b54999a831bb195c08541ca995ef0505c96193fMark Lacey  typedef const ArgInfo *const_arg_iterator;
3158b54999a831bb195c08541ca995ef0505c96193fMark Lacey  typedef ArgInfo *arg_iterator;
3168b54999a831bb195c08541ca995ef0505c96193fMark Lacey
317651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  typedef llvm::iterator_range<arg_iterator> arg_range;
318651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
319651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
320651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
321651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  arg_const_range arguments() const {
322651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return arg_const_range(arg_begin(), arg_end());
323651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
324651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3258b54999a831bb195c08541ca995ef0505c96193fMark Lacey  const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
3268b54999a831bb195c08541ca995ef0505c96193fMark Lacey  const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
3278b54999a831bb195c08541ca995ef0505c96193fMark Lacey  arg_iterator arg_begin() { return getArgsBuffer() + 1; }
3288b54999a831bb195c08541ca995ef0505c96193fMark Lacey  arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
3298b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3308b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned  arg_size() const { return NumArgs; }
3318b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3328b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool isVariadic() const { return Required.allowsOptionalArgs(); }
3338b54999a831bb195c08541ca995ef0505c96193fMark Lacey  RequiredArgs getRequiredArgs() const { return Required; }
3348b54999a831bb195c08541ca995ef0505c96193fMark Lacey
335651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool isInstanceMethod() const { return InstanceMethod; }
336651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3378b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool isNoReturn() const { return NoReturn; }
3388b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3398b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// In ARC, whether this function retains its return value.  This
3408b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// is not always reliable for call sites.
3418b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool isReturnsRetained() const { return ReturnsRetained; }
3428b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3438b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// getASTCallingConvention() - Return the AST-specified calling
3448b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// convention.
3458b54999a831bb195c08541ca995ef0505c96193fMark Lacey  CallingConv getASTCallingConvention() const {
3468b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return CallingConv(ASTCallingConvention);
3478b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
3488b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3498b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// getCallingConvention - Return the user specified calling
3508b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// convention, which has been translated into an LLVM CC.
3518b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned getCallingConvention() const { return CallingConvention; }
3528b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3538b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// getEffectiveCallingConvention - Return the actual calling convention to
3548b54999a831bb195c08541ca995ef0505c96193fMark Lacey  /// use, which may depend on the ABI.
3558b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned getEffectiveCallingConvention() const {
3568b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return EffectiveCallingConvention;
3578b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
3588b54999a831bb195c08541ca995ef0505c96193fMark Lacey  void setEffectiveCallingConvention(unsigned Value) {
3598b54999a831bb195c08541ca995ef0505c96193fMark Lacey    EffectiveCallingConvention = Value;
3608b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
3618b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3628b54999a831bb195c08541ca995ef0505c96193fMark Lacey  bool getHasRegParm() const { return HasRegParm; }
3638b54999a831bb195c08541ca995ef0505c96193fMark Lacey  unsigned getRegParm() const { return RegParm; }
3648b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3658b54999a831bb195c08541ca995ef0505c96193fMark Lacey  FunctionType::ExtInfo getExtInfo() const {
3668b54999a831bb195c08541ca995ef0505c96193fMark Lacey    return FunctionType::ExtInfo(isNoReturn(),
3678b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                 getHasRegParm(), getRegParm(),
3688b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                 getASTCallingConvention(),
3698b54999a831bb195c08541ca995ef0505c96193fMark Lacey                                 isReturnsRetained());
3708b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
3718b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3728b54999a831bb195c08541ca995ef0505c96193fMark Lacey  CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
3738b54999a831bb195c08541ca995ef0505c96193fMark Lacey
3748b54999a831bb195c08541ca995ef0505c96193fMark Lacey  ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
3758b54999a831bb195c08541ca995ef0505c96193fMark Lacey  const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
3768b54999a831bb195c08541ca995ef0505c96193fMark Lacey
377651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Return true if this function uses inalloca arguments.
378651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool usesInAlloca() const { return ArgStruct; }
379651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
380651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Get the struct type used to represent all the arguments in memory.
381651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::StructType *getArgStruct() const { return ArgStruct; }
382651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void setArgStruct(llvm::StructType *Ty) { ArgStruct = Ty; }
383651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3848b54999a831bb195c08541ca995ef0505c96193fMark Lacey  void Profile(llvm::FoldingSetNodeID &ID) {
3858b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddInteger(getASTCallingConvention());
386651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ID.AddBoolean(InstanceMethod);
3878b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddBoolean(NoReturn);
3888b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddBoolean(ReturnsRetained);
3898b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddBoolean(HasRegParm);
3908b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddInteger(RegParm);
3918b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddInteger(Required.getOpaqueData());
3928b54999a831bb195c08541ca995ef0505c96193fMark Lacey    getReturnType().Profile(ID);
393651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &I : arguments())
394651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      I.type.Profile(ID);
3958b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
3968b54999a831bb195c08541ca995ef0505c96193fMark Lacey  static void Profile(llvm::FoldingSetNodeID &ID,
397651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                      bool InstanceMethod,
3988b54999a831bb195c08541ca995ef0505c96193fMark Lacey                      const FunctionType::ExtInfo &info,
3998b54999a831bb195c08541ca995ef0505c96193fMark Lacey                      RequiredArgs required,
4008b54999a831bb195c08541ca995ef0505c96193fMark Lacey                      CanQualType resultType,
4018b54999a831bb195c08541ca995ef0505c96193fMark Lacey                      ArrayRef<CanQualType> argTypes) {
4028b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddInteger(info.getCC());
403651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ID.AddBoolean(InstanceMethod);
4048b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddBoolean(info.getNoReturn());
4058b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddBoolean(info.getProducesResult());
4068b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddBoolean(info.getHasRegParm());
4078b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddInteger(info.getRegParm());
4088b54999a831bb195c08541ca995ef0505c96193fMark Lacey    ID.AddInteger(required.getOpaqueData());
4098b54999a831bb195c08541ca995ef0505c96193fMark Lacey    resultType.Profile(ID);
4108b54999a831bb195c08541ca995ef0505c96193fMark Lacey    for (ArrayRef<CanQualType>::iterator
4118b54999a831bb195c08541ca995ef0505c96193fMark Lacey           i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
4128b54999a831bb195c08541ca995ef0505c96193fMark Lacey      i->Profile(ID);
4138b54999a831bb195c08541ca995ef0505c96193fMark Lacey    }
4148b54999a831bb195c08541ca995ef0505c96193fMark Lacey  }
4158b54999a831bb195c08541ca995ef0505c96193fMark Lacey};
4168b54999a831bb195c08541ca995ef0505c96193fMark Lacey
4178b54999a831bb195c08541ca995ef0505c96193fMark Lacey}  // end namespace CodeGen
4188b54999a831bb195c08541ca995ef0505c96193fMark Lacey}  // end namespace clang
4198b54999a831bb195c08541ca995ef0505c96193fMark Lacey
4208b54999a831bb195c08541ca995ef0505c96193fMark Lacey#endif
421