Home | History | Annotate | Download | only in CodeGen
      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_FUNCTION_INFO_H
     17 #define LLVM_CLANG_CODEGEN_FUNCTION_INFO_H
     18 
     19 #include "clang/AST/CanonicalType.h"
     20 #include "clang/AST/Type.h"
     21 #include "llvm/ADT/FoldingSet.h"
     22 #include <cassert>
     23 
     24 namespace llvm {
     25   class Type;
     26   class StructType;
     27 }
     28 
     29 namespace clang {
     30 class Decl;
     31 
     32 namespace CodeGen {
     33 
     34 /// ABIArgInfo - Helper class to encapsulate information about how a
     35 /// specific C type should be passed to or returned from a function.
     36 class ABIArgInfo {
     37 public:
     38   enum Kind : uint8_t {
     39     /// Direct - Pass the argument directly using the normal converted LLVM
     40     /// type, or by coercing to another specified type stored in
     41     /// 'CoerceToType').  If an offset is specified (in UIntData), then the
     42     /// argument passed is offset by some number of bytes in the memory
     43     /// representation. A dummy argument is emitted before the real argument
     44     /// if the specified type stored in "PaddingType" is not zero.
     45     Direct,
     46 
     47     /// Extend - Valid only for integer argument types. Same as 'direct'
     48     /// but also emit a zero/sign extension attribute.
     49     Extend,
     50 
     51     /// Indirect - Pass the argument indirectly via a hidden pointer
     52     /// with the specified alignment (0 indicates default alignment).
     53     Indirect,
     54 
     55     /// Ignore - Ignore the argument (treat as void). Useful for void and
     56     /// empty structs.
     57     Ignore,
     58 
     59     /// Expand - Only valid for aggregate argument types. The structure should
     60     /// be expanded into consecutive arguments for its constituent fields.
     61     /// Currently expand is only allowed on structures whose fields
     62     /// are all scalar types or are themselves expandable types.
     63     Expand,
     64 
     65     /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
     66     /// This is similar to 'direct', except it only applies to arguments stored
     67     /// in memory and forbids any implicit copies.  When applied to a return
     68     /// type, it means the value is returned indirectly via an implicit sret
     69     /// parameter stored in the argument struct.
     70     InAlloca,
     71     KindFirst = Direct,
     72     KindLast = InAlloca
     73   };
     74 
     75 private:
     76   llvm::Type *TypeData; // isDirect() || isExtend()
     77   llvm::Type *PaddingType;
     78   union {
     79     unsigned DirectOffset;     // isDirect() || isExtend()
     80     unsigned IndirectAlign;    // isIndirect()
     81     unsigned AllocaFieldIndex; // isInAlloca()
     82   };
     83   Kind TheKind;
     84   bool PaddingInReg : 1;
     85   bool InAllocaSRet : 1;    // isInAlloca()
     86   bool IndirectByVal : 1;   // isIndirect()
     87   bool IndirectRealign : 1; // isIndirect()
     88   bool SRetAfterThis : 1;   // isIndirect()
     89   bool InReg : 1;           // isDirect() || isExtend() || isIndirect()
     90 
     91   ABIArgInfo(Kind K)
     92       : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {}
     93 
     94 public:
     95   ABIArgInfo()
     96       : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
     97         TheKind(Direct), PaddingInReg(false), InReg(false) {}
     98 
     99   static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
    100                               llvm::Type *Padding = nullptr) {
    101     auto AI = ABIArgInfo(Direct);
    102     AI.setCoerceToType(T);
    103     AI.setDirectOffset(Offset);
    104     AI.setPaddingType(Padding);
    105     return AI;
    106   }
    107   static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
    108     auto AI = getDirect(T);
    109     AI.setInReg(true);
    110     return AI;
    111   }
    112   static ABIArgInfo getExtend(llvm::Type *T = nullptr) {
    113     auto AI = ABIArgInfo(Extend);
    114     AI.setCoerceToType(T);
    115     AI.setDirectOffset(0);
    116     return AI;
    117   }
    118   static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) {
    119     auto AI = getExtend(T);
    120     AI.setInReg(true);
    121     return AI;
    122   }
    123   static ABIArgInfo getIgnore() {
    124     return ABIArgInfo(Ignore);
    125   }
    126   static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true,
    127                                 bool Realign = false,
    128                                 llvm::Type *Padding = nullptr) {
    129     auto AI = ABIArgInfo(Indirect);
    130     AI.setIndirectAlign(Alignment);
    131     AI.setIndirectByVal(ByVal);
    132     AI.setIndirectRealign(Realign);
    133     AI.setSRetAfterThis(false);
    134     AI.setPaddingType(Padding);
    135     return AI;
    136   }
    137   static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true,
    138                                      bool Realign = false) {
    139     auto AI = getIndirect(Alignment, ByVal, Realign);
    140     AI.setInReg(true);
    141     return AI;
    142   }
    143   static ABIArgInfo getInAlloca(unsigned FieldIndex) {
    144     auto AI = ABIArgInfo(InAlloca);
    145     AI.setInAllocaFieldIndex(FieldIndex);
    146     return AI;
    147   }
    148   static ABIArgInfo getExpand() {
    149     return ABIArgInfo(Expand);
    150   }
    151   static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
    152                                          llvm::Type *Padding) {
    153     auto AI = getExpand();
    154     AI.setPaddingInReg(PaddingInReg);
    155     AI.setPaddingType(Padding);
    156     return AI;
    157   }
    158 
    159   Kind getKind() const { return TheKind; }
    160   bool isDirect() const { return TheKind == Direct; }
    161   bool isInAlloca() const { return TheKind == InAlloca; }
    162   bool isExtend() const { return TheKind == Extend; }
    163   bool isIgnore() const { return TheKind == Ignore; }
    164   bool isIndirect() const { return TheKind == Indirect; }
    165   bool isExpand() const { return TheKind == Expand; }
    166 
    167   bool canHaveCoerceToType() const { return isDirect() || isExtend(); }
    168 
    169   // Direct/Extend accessors
    170   unsigned getDirectOffset() const {
    171     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    172     return DirectOffset;
    173   }
    174   void setDirectOffset(unsigned Offset) {
    175     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
    176     DirectOffset = Offset;
    177   }
    178 
    179   llvm::Type *getPaddingType() const { return PaddingType; }
    180 
    181   void setPaddingType(llvm::Type *T) { PaddingType = T; }
    182 
    183   bool getPaddingInReg() const {
    184     return PaddingInReg;
    185   }
    186   void setPaddingInReg(bool PIR) {
    187     PaddingInReg = PIR;
    188   }
    189 
    190   llvm::Type *getCoerceToType() const {
    191     assert(canHaveCoerceToType() && "Invalid kind!");
    192     return TypeData;
    193   }
    194 
    195   void setCoerceToType(llvm::Type *T) {
    196     assert(canHaveCoerceToType() && "Invalid kind!");
    197     TypeData = T;
    198   }
    199 
    200   bool getInReg() const {
    201     assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
    202     return InReg;
    203   }
    204 
    205   void setInReg(bool IR) {
    206     assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
    207     InReg = IR;
    208   }
    209 
    210   // Indirect accessors
    211   unsigned getIndirectAlign() const {
    212     assert(isIndirect() && "Invalid kind!");
    213     return IndirectAlign;
    214   }
    215   void setIndirectAlign(unsigned IA) {
    216     assert(isIndirect() && "Invalid kind!");
    217     IndirectAlign = IA;
    218   }
    219 
    220   bool getIndirectByVal() const {
    221     assert(isIndirect() && "Invalid kind!");
    222     return IndirectByVal;
    223   }
    224   void setIndirectByVal(unsigned IBV) {
    225     assert(isIndirect() && "Invalid kind!");
    226     IndirectByVal = IBV;
    227   }
    228 
    229   bool getIndirectRealign() const {
    230     assert(isIndirect() && "Invalid kind!");
    231     return IndirectRealign;
    232   }
    233   void setIndirectRealign(bool IR) {
    234     assert(isIndirect() && "Invalid kind!");
    235     IndirectRealign = IR;
    236   }
    237 
    238   bool isSRetAfterThis() const {
    239     assert(isIndirect() && "Invalid kind!");
    240     return SRetAfterThis;
    241   }
    242   void setSRetAfterThis(bool AfterThis) {
    243     assert(isIndirect() && "Invalid kind!");
    244     SRetAfterThis = AfterThis;
    245   }
    246 
    247   unsigned getInAllocaFieldIndex() const {
    248     assert(isInAlloca() && "Invalid kind!");
    249     return AllocaFieldIndex;
    250   }
    251   void setInAllocaFieldIndex(unsigned FieldIndex) {
    252     assert(isInAlloca() && "Invalid kind!");
    253     AllocaFieldIndex = FieldIndex;
    254   }
    255 
    256   /// \brief Return true if this field of an inalloca struct should be returned
    257   /// to implement a struct return calling convention.
    258   bool getInAllocaSRet() const {
    259     assert(isInAlloca() && "Invalid kind!");
    260     return InAllocaSRet;
    261   }
    262 
    263   void setInAllocaSRet(bool SRet) {
    264     assert(isInAlloca() && "Invalid kind!");
    265     InAllocaSRet = SRet;
    266   }
    267 
    268   void dump() const;
    269 };
    270 
    271 /// A class for recording the number of arguments that a function
    272 /// signature requires.
    273 class RequiredArgs {
    274   /// The number of required arguments, or ~0 if the signature does
    275   /// not permit optional arguments.
    276   unsigned NumRequired;
    277 public:
    278   enum All_t { All };
    279 
    280   RequiredArgs(All_t _) : NumRequired(~0U) {}
    281   explicit RequiredArgs(unsigned n) : NumRequired(n) {
    282     assert(n != ~0U);
    283   }
    284 
    285   /// Compute the arguments required by the given formal prototype,
    286   /// given that there may be some additional, non-formal arguments
    287   /// in play.
    288   static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
    289                                        unsigned additional) {
    290     if (!prototype->isVariadic()) return All;
    291     return RequiredArgs(prototype->getNumParams() + additional);
    292   }
    293 
    294   static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
    295     return forPrototypePlus(prototype, 0);
    296   }
    297 
    298   static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
    299     return forPrototype(prototype.getTypePtr());
    300   }
    301 
    302   static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
    303                                        unsigned additional) {
    304     return forPrototypePlus(prototype.getTypePtr(), additional);
    305   }
    306 
    307   bool allowsOptionalArgs() const { return NumRequired != ~0U; }
    308   unsigned getNumRequiredArgs() const {
    309     assert(allowsOptionalArgs());
    310     return NumRequired;
    311   }
    312 
    313   unsigned getOpaqueData() const { return NumRequired; }
    314   static RequiredArgs getFromOpaqueData(unsigned value) {
    315     if (value == ~0U) return All;
    316     return RequiredArgs(value);
    317   }
    318 };
    319 
    320 /// CGFunctionInfo - Class to encapsulate the information about a
    321 /// function definition.
    322 class CGFunctionInfo : public llvm::FoldingSetNode {
    323   struct ArgInfo {
    324     CanQualType type;
    325     ABIArgInfo info;
    326   };
    327 
    328   /// The LLVM::CallingConv to use for this function (as specified by the
    329   /// user).
    330   unsigned CallingConvention : 8;
    331 
    332   /// The LLVM::CallingConv to actually use for this function, which may
    333   /// depend on the ABI.
    334   unsigned EffectiveCallingConvention : 8;
    335 
    336   /// The clang::CallingConv that this was originally created with.
    337   unsigned ASTCallingConvention : 8;
    338 
    339   /// Whether this is an instance method.
    340   unsigned InstanceMethod : 1;
    341 
    342   /// Whether this function is noreturn.
    343   unsigned NoReturn : 1;
    344 
    345   /// Whether this function is returns-retained.
    346   unsigned ReturnsRetained : 1;
    347 
    348   /// How many arguments to pass inreg.
    349   unsigned HasRegParm : 1;
    350   unsigned RegParm : 4;
    351 
    352   RequiredArgs Required;
    353 
    354   /// The struct representing all arguments passed in memory.  Only used when
    355   /// passing non-trivial types with inalloca.  Not part of the profile.
    356   llvm::StructType *ArgStruct;
    357 
    358   unsigned NumArgs;
    359   ArgInfo *getArgsBuffer() {
    360     return reinterpret_cast<ArgInfo*>(this+1);
    361   }
    362   const ArgInfo *getArgsBuffer() const {
    363     return reinterpret_cast<const ArgInfo*>(this + 1);
    364   }
    365 
    366   CGFunctionInfo() : Required(RequiredArgs::All) {}
    367 
    368 public:
    369   static CGFunctionInfo *create(unsigned llvmCC,
    370                                 bool InstanceMethod,
    371                                 const FunctionType::ExtInfo &extInfo,
    372                                 CanQualType resultType,
    373                                 ArrayRef<CanQualType> argTypes,
    374                                 RequiredArgs required);
    375 
    376   typedef const ArgInfo *const_arg_iterator;
    377   typedef ArgInfo *arg_iterator;
    378 
    379   typedef llvm::iterator_range<arg_iterator> arg_range;
    380   typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
    381 
    382   arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
    383   arg_const_range arguments() const {
    384     return arg_const_range(arg_begin(), arg_end());
    385   }
    386 
    387   const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
    388   const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
    389   arg_iterator arg_begin() { return getArgsBuffer() + 1; }
    390   arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
    391 
    392   unsigned  arg_size() const { return NumArgs; }
    393 
    394   bool isVariadic() const { return Required.allowsOptionalArgs(); }
    395   RequiredArgs getRequiredArgs() const { return Required; }
    396 
    397   bool isInstanceMethod() const { return InstanceMethod; }
    398 
    399   bool isNoReturn() const { return NoReturn; }
    400 
    401   /// In ARC, whether this function retains its return value.  This
    402   /// is not always reliable for call sites.
    403   bool isReturnsRetained() const { return ReturnsRetained; }
    404 
    405   /// getASTCallingConvention() - Return the AST-specified calling
    406   /// convention.
    407   CallingConv getASTCallingConvention() const {
    408     return CallingConv(ASTCallingConvention);
    409   }
    410 
    411   /// getCallingConvention - Return the user specified calling
    412   /// convention, which has been translated into an LLVM CC.
    413   unsigned getCallingConvention() const { return CallingConvention; }
    414 
    415   /// getEffectiveCallingConvention - Return the actual calling convention to
    416   /// use, which may depend on the ABI.
    417   unsigned getEffectiveCallingConvention() const {
    418     return EffectiveCallingConvention;
    419   }
    420   void setEffectiveCallingConvention(unsigned Value) {
    421     EffectiveCallingConvention = Value;
    422   }
    423 
    424   bool getHasRegParm() const { return HasRegParm; }
    425   unsigned getRegParm() const { return RegParm; }
    426 
    427   FunctionType::ExtInfo getExtInfo() const {
    428     return FunctionType::ExtInfo(isNoReturn(),
    429                                  getHasRegParm(), getRegParm(),
    430                                  getASTCallingConvention(),
    431                                  isReturnsRetained());
    432   }
    433 
    434   CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
    435 
    436   ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
    437   const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
    438 
    439   /// \brief Return true if this function uses inalloca arguments.
    440   bool usesInAlloca() const { return ArgStruct; }
    441 
    442   /// \brief Get the struct type used to represent all the arguments in memory.
    443   llvm::StructType *getArgStruct() const { return ArgStruct; }
    444   void setArgStruct(llvm::StructType *Ty) { ArgStruct = Ty; }
    445 
    446   void Profile(llvm::FoldingSetNodeID &ID) {
    447     ID.AddInteger(getASTCallingConvention());
    448     ID.AddBoolean(InstanceMethod);
    449     ID.AddBoolean(NoReturn);
    450     ID.AddBoolean(ReturnsRetained);
    451     ID.AddBoolean(HasRegParm);
    452     ID.AddInteger(RegParm);
    453     ID.AddInteger(Required.getOpaqueData());
    454     getReturnType().Profile(ID);
    455     for (const auto &I : arguments())
    456       I.type.Profile(ID);
    457   }
    458   static void Profile(llvm::FoldingSetNodeID &ID,
    459                       bool InstanceMethod,
    460                       const FunctionType::ExtInfo &info,
    461                       RequiredArgs required,
    462                       CanQualType resultType,
    463                       ArrayRef<CanQualType> argTypes) {
    464     ID.AddInteger(info.getCC());
    465     ID.AddBoolean(InstanceMethod);
    466     ID.AddBoolean(info.getNoReturn());
    467     ID.AddBoolean(info.getProducesResult());
    468     ID.AddBoolean(info.getHasRegParm());
    469     ID.AddInteger(info.getRegParm());
    470     ID.AddInteger(required.getOpaqueData());
    471     resultType.Profile(ID);
    472     for (ArrayRef<CanQualType>::iterator
    473            i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
    474       i->Profile(ID);
    475     }
    476   }
    477 };
    478 
    479 }  // end namespace CodeGen
    480 }  // end namespace clang
    481 
    482 #endif
    483