clang API Documentation

CGFunctionInfo.h
Go to the documentation of this file.
00001 //==-- CGFunctionInfo.h - Representation of function argument/return types -==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Defines CGFunctionInfo and associated types used in representing the
00011 // LLVM source types and ABI-coerced types for function arguments and
00012 // return values.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
00017 #define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
00018 
00019 #include "clang/AST/CanonicalType.h"
00020 #include "clang/AST/Type.h"
00021 #include "llvm/ADT/FoldingSet.h"
00022 #include <cassert>
00023 
00024 namespace llvm {
00025   class Type;
00026   class StructType;
00027 }
00028 
00029 namespace clang {
00030 class Decl;
00031 
00032 namespace CodeGen {
00033 
00034 /// ABIArgInfo - Helper class to encapsulate information about how a
00035 /// specific C type should be passed to or returned from a function.
00036 class ABIArgInfo {
00037 public:
00038   enum Kind : uint8_t {
00039     /// Direct - Pass the argument directly using the normal converted LLVM
00040     /// type, or by coercing to another specified type stored in
00041     /// 'CoerceToType').  If an offset is specified (in UIntData), then the
00042     /// argument passed is offset by some number of bytes in the memory
00043     /// representation. A dummy argument is emitted before the real argument
00044     /// if the specified type stored in "PaddingType" is not zero.
00045     Direct,
00046 
00047     /// Extend - Valid only for integer argument types. Same as 'direct'
00048     /// but also emit a zero/sign extension attribute.
00049     Extend,
00050 
00051     /// Indirect - Pass the argument indirectly via a hidden pointer
00052     /// with the specified alignment (0 indicates default alignment).
00053     Indirect,
00054 
00055     /// Ignore - Ignore the argument (treat as void). Useful for void and
00056     /// empty structs.
00057     Ignore,
00058 
00059     /// Expand - Only valid for aggregate argument types. The structure should
00060     /// be expanded into consecutive arguments for its constituent fields.
00061     /// Currently expand is only allowed on structures whose fields
00062     /// are all scalar types or are themselves expandable types.
00063     Expand,
00064 
00065     /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
00066     /// This is similar to 'direct', except it only applies to arguments stored
00067     /// in memory and forbids any implicit copies.  When applied to a return
00068     /// type, it means the value is returned indirectly via an implicit sret
00069     /// parameter stored in the argument struct.
00070     InAlloca,
00071     KindFirst = Direct,
00072     KindLast = InAlloca
00073   };
00074 
00075 private:
00076   llvm::Type *TypeData; // isDirect() || isExtend()
00077   llvm::Type *PaddingType;
00078   union {
00079     unsigned DirectOffset;     // isDirect() || isExtend()
00080     unsigned IndirectAlign;    // isIndirect()
00081     unsigned AllocaFieldIndex; // isInAlloca()
00082   };
00083   Kind TheKind;
00084   bool PaddingInReg : 1;
00085   bool InAllocaSRet : 1;    // isInAlloca()
00086   bool IndirectByVal : 1;   // isIndirect()
00087   bool IndirectRealign : 1; // isIndirect()
00088   bool SRetAfterThis : 1;   // isIndirect()
00089   bool InReg : 1;           // isDirect() || isExtend() || isIndirect()
00090   bool CanBeFlattened: 1;   // isDirect()
00091 
00092   ABIArgInfo(Kind K)
00093       : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {}
00094 
00095 public:
00096   ABIArgInfo()
00097       : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
00098         TheKind(Direct), PaddingInReg(false), InReg(false) {}
00099 
00100   static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
00101                               llvm::Type *Padding = nullptr,
00102                               bool CanBeFlattened = true) {
00103     auto AI = ABIArgInfo(Direct);
00104     AI.setCoerceToType(T);
00105     AI.setDirectOffset(Offset);
00106     AI.setPaddingType(Padding);
00107     AI.setCanBeFlattened(CanBeFlattened);
00108     return AI;
00109   }
00110   static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
00111     auto AI = getDirect(T);
00112     AI.setInReg(true);
00113     return AI;
00114   }
00115   static ABIArgInfo getExtend(llvm::Type *T = nullptr) {
00116     auto AI = ABIArgInfo(Extend);
00117     AI.setCoerceToType(T);
00118     AI.setDirectOffset(0);
00119     return AI;
00120   }
00121   static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) {
00122     auto AI = getExtend(T);
00123     AI.setInReg(true);
00124     return AI;
00125   }
00126   static ABIArgInfo getIgnore() {
00127     return ABIArgInfo(Ignore);
00128   }
00129   static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true,
00130                                 bool Realign = false,
00131                                 llvm::Type *Padding = nullptr) {
00132     auto AI = ABIArgInfo(Indirect);
00133     AI.setIndirectAlign(Alignment);
00134     AI.setIndirectByVal(ByVal);
00135     AI.setIndirectRealign(Realign);
00136     AI.setSRetAfterThis(false);
00137     AI.setPaddingType(Padding);
00138     return AI;
00139   }
00140   static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true,
00141                                      bool Realign = false) {
00142     auto AI = getIndirect(Alignment, ByVal, Realign);
00143     AI.setInReg(true);
00144     return AI;
00145   }
00146   static ABIArgInfo getInAlloca(unsigned FieldIndex) {
00147     auto AI = ABIArgInfo(InAlloca);
00148     AI.setInAllocaFieldIndex(FieldIndex);
00149     return AI;
00150   }
00151   static ABIArgInfo getExpand() {
00152     return ABIArgInfo(Expand);
00153   }
00154   static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
00155                                          llvm::Type *Padding) {
00156     auto AI = getExpand();
00157     AI.setPaddingInReg(PaddingInReg);
00158     AI.setPaddingType(Padding);
00159     return AI;
00160   }
00161 
00162   Kind getKind() const { return TheKind; }
00163   bool isDirect() const { return TheKind == Direct; }
00164   bool isInAlloca() const { return TheKind == InAlloca; }
00165   bool isExtend() const { return TheKind == Extend; }
00166   bool isIgnore() const { return TheKind == Ignore; }
00167   bool isIndirect() const { return TheKind == Indirect; }
00168   bool isExpand() const { return TheKind == Expand; }
00169 
00170   bool canHaveCoerceToType() const { return isDirect() || isExtend(); }
00171 
00172   // Direct/Extend accessors
00173   unsigned getDirectOffset() const {
00174     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
00175     return DirectOffset;
00176   }
00177   void setDirectOffset(unsigned Offset) {
00178     assert((isDirect() || isExtend()) && "Not a direct or extend kind");
00179     DirectOffset = Offset;
00180   }
00181 
00182   llvm::Type *getPaddingType() const { return PaddingType; }
00183 
00184   void setPaddingType(llvm::Type *T) { PaddingType = T; }
00185 
00186   bool getPaddingInReg() const {
00187     return PaddingInReg;
00188   }
00189   void setPaddingInReg(bool PIR) {
00190     PaddingInReg = PIR;
00191   }
00192 
00193   llvm::Type *getCoerceToType() const {
00194     assert(canHaveCoerceToType() && "Invalid kind!");
00195     return TypeData;
00196   }
00197 
00198   void setCoerceToType(llvm::Type *T) {
00199     assert(canHaveCoerceToType() && "Invalid kind!");
00200     TypeData = T;
00201   }
00202 
00203   bool getInReg() const {
00204     assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
00205     return InReg;
00206   }
00207 
00208   void setInReg(bool IR) {
00209     assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
00210     InReg = IR;
00211   }
00212 
00213   // Indirect accessors
00214   unsigned getIndirectAlign() const {
00215     assert(isIndirect() && "Invalid kind!");
00216     return IndirectAlign;
00217   }
00218   void setIndirectAlign(unsigned IA) {
00219     assert(isIndirect() && "Invalid kind!");
00220     IndirectAlign = IA;
00221   }
00222 
00223   bool getIndirectByVal() const {
00224     assert(isIndirect() && "Invalid kind!");
00225     return IndirectByVal;
00226   }
00227   void setIndirectByVal(unsigned IBV) {
00228     assert(isIndirect() && "Invalid kind!");
00229     IndirectByVal = IBV;
00230   }
00231 
00232   bool getIndirectRealign() const {
00233     assert(isIndirect() && "Invalid kind!");
00234     return IndirectRealign;
00235   }
00236   void setIndirectRealign(bool IR) {
00237     assert(isIndirect() && "Invalid kind!");
00238     IndirectRealign = IR;
00239   }
00240 
00241   bool isSRetAfterThis() const {
00242     assert(isIndirect() && "Invalid kind!");
00243     return SRetAfterThis;
00244   }
00245   void setSRetAfterThis(bool AfterThis) {
00246     assert(isIndirect() && "Invalid kind!");
00247     SRetAfterThis = AfterThis;
00248   }
00249 
00250   unsigned getInAllocaFieldIndex() const {
00251     assert(isInAlloca() && "Invalid kind!");
00252     return AllocaFieldIndex;
00253   }
00254   void setInAllocaFieldIndex(unsigned FieldIndex) {
00255     assert(isInAlloca() && "Invalid kind!");
00256     AllocaFieldIndex = FieldIndex;
00257   }
00258 
00259   /// \brief Return true if this field of an inalloca struct should be returned
00260   /// to implement a struct return calling convention.
00261   bool getInAllocaSRet() const {
00262     assert(isInAlloca() && "Invalid kind!");
00263     return InAllocaSRet;
00264   }
00265 
00266   void setInAllocaSRet(bool SRet) {
00267     assert(isInAlloca() && "Invalid kind!");
00268     InAllocaSRet = SRet;
00269   }
00270 
00271   bool getCanBeFlattened() const {
00272     assert(isDirect() && "Invalid kind!");
00273     return CanBeFlattened;
00274   }
00275 
00276   void setCanBeFlattened(bool Flatten) {
00277     assert(isDirect() && "Invalid kind!");
00278     CanBeFlattened = Flatten;
00279   }
00280 
00281   void dump() const;
00282 };
00283 
00284 /// A class for recording the number of arguments that a function
00285 /// signature requires.
00286 class RequiredArgs {
00287   /// The number of required arguments, or ~0 if the signature does
00288   /// not permit optional arguments.
00289   unsigned NumRequired;
00290 public:
00291   enum All_t { All };
00292 
00293   RequiredArgs(All_t _) : NumRequired(~0U) {}
00294   explicit RequiredArgs(unsigned n) : NumRequired(n) {
00295     assert(n != ~0U);
00296   }
00297 
00298   /// Compute the arguments required by the given formal prototype,
00299   /// given that there may be some additional, non-formal arguments
00300   /// in play.
00301   static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
00302                                        unsigned additional) {
00303     if (!prototype->isVariadic()) return All;
00304     return RequiredArgs(prototype->getNumParams() + additional);
00305   }
00306 
00307   static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
00308     return forPrototypePlus(prototype, 0);
00309   }
00310 
00311   static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
00312     return forPrototype(prototype.getTypePtr());
00313   }
00314 
00315   static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
00316                                        unsigned additional) {
00317     return forPrototypePlus(prototype.getTypePtr(), additional);
00318   }
00319 
00320   bool allowsOptionalArgs() const { return NumRequired != ~0U; }
00321   unsigned getNumRequiredArgs() const {
00322     assert(allowsOptionalArgs());
00323     return NumRequired;
00324   }
00325 
00326   unsigned getOpaqueData() const { return NumRequired; }
00327   static RequiredArgs getFromOpaqueData(unsigned value) {
00328     if (value == ~0U) return All;
00329     return RequiredArgs(value);
00330   }
00331 };
00332 
00333 /// CGFunctionInfo - Class to encapsulate the information about a
00334 /// function definition.
00335 class CGFunctionInfo : public llvm::FoldingSetNode {
00336   struct ArgInfo {
00337     CanQualType type;
00338     ABIArgInfo info;
00339   };
00340 
00341   /// The LLVM::CallingConv to use for this function (as specified by the
00342   /// user).
00343   unsigned CallingConvention : 8;
00344 
00345   /// The LLVM::CallingConv to actually use for this function, which may
00346   /// depend on the ABI.
00347   unsigned EffectiveCallingConvention : 8;
00348 
00349   /// The clang::CallingConv that this was originally created with.
00350   unsigned ASTCallingConvention : 8;
00351 
00352   /// Whether this is an instance method.
00353   unsigned InstanceMethod : 1;
00354 
00355   /// Whether this function is noreturn.
00356   unsigned NoReturn : 1;
00357 
00358   /// Whether this function is returns-retained.
00359   unsigned ReturnsRetained : 1;
00360 
00361   /// How many arguments to pass inreg.
00362   unsigned HasRegParm : 1;
00363   unsigned RegParm : 4;
00364 
00365   RequiredArgs Required;
00366 
00367   /// The struct representing all arguments passed in memory.  Only used when
00368   /// passing non-trivial types with inalloca.  Not part of the profile.
00369   llvm::StructType *ArgStruct;
00370 
00371   unsigned NumArgs;
00372   ArgInfo *getArgsBuffer() {
00373     return reinterpret_cast<ArgInfo*>(this+1);
00374   }
00375   const ArgInfo *getArgsBuffer() const {
00376     return reinterpret_cast<const ArgInfo*>(this + 1);
00377   }
00378 
00379   CGFunctionInfo() : Required(RequiredArgs::All) {}
00380 
00381 public:
00382   static CGFunctionInfo *create(unsigned llvmCC,
00383                                 bool InstanceMethod,
00384                                 const FunctionType::ExtInfo &extInfo,
00385                                 CanQualType resultType,
00386                                 ArrayRef<CanQualType> argTypes,
00387                                 RequiredArgs required);
00388 
00389   typedef const ArgInfo *const_arg_iterator;
00390   typedef ArgInfo *arg_iterator;
00391 
00392   typedef llvm::iterator_range<arg_iterator> arg_range;
00393   typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
00394 
00395   arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
00396   arg_const_range arguments() const {
00397     return arg_const_range(arg_begin(), arg_end());
00398   }
00399 
00400   const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
00401   const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
00402   arg_iterator arg_begin() { return getArgsBuffer() + 1; }
00403   arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
00404 
00405   unsigned  arg_size() const { return NumArgs; }
00406 
00407   bool isVariadic() const { return Required.allowsOptionalArgs(); }
00408   RequiredArgs getRequiredArgs() const { return Required; }
00409   unsigned getNumRequiredArgs() const {
00410     return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
00411   }
00412 
00413   bool isInstanceMethod() const { return InstanceMethod; }
00414 
00415   bool isNoReturn() const { return NoReturn; }
00416 
00417   /// In ARC, whether this function retains its return value.  This
00418   /// is not always reliable for call sites.
00419   bool isReturnsRetained() const { return ReturnsRetained; }
00420 
00421   /// getASTCallingConvention() - Return the AST-specified calling
00422   /// convention.
00423   CallingConv getASTCallingConvention() const {
00424     return CallingConv(ASTCallingConvention);
00425   }
00426 
00427   /// getCallingConvention - Return the user specified calling
00428   /// convention, which has been translated into an LLVM CC.
00429   unsigned getCallingConvention() const { return CallingConvention; }
00430 
00431   /// getEffectiveCallingConvention - Return the actual calling convention to
00432   /// use, which may depend on the ABI.
00433   unsigned getEffectiveCallingConvention() const {
00434     return EffectiveCallingConvention;
00435   }
00436   void setEffectiveCallingConvention(unsigned Value) {
00437     EffectiveCallingConvention = Value;
00438   }
00439 
00440   bool getHasRegParm() const { return HasRegParm; }
00441   unsigned getRegParm() const { return RegParm; }
00442 
00443   FunctionType::ExtInfo getExtInfo() const {
00444     return FunctionType::ExtInfo(isNoReturn(),
00445                                  getHasRegParm(), getRegParm(),
00446                                  getASTCallingConvention(),
00447                                  isReturnsRetained());
00448   }
00449 
00450   CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
00451 
00452   ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
00453   const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
00454 
00455   /// \brief Return true if this function uses inalloca arguments.
00456   bool usesInAlloca() const { return ArgStruct; }
00457 
00458   /// \brief Get the struct type used to represent all the arguments in memory.
00459   llvm::StructType *getArgStruct() const { return ArgStruct; }
00460   void setArgStruct(llvm::StructType *Ty) { ArgStruct = Ty; }
00461 
00462   void Profile(llvm::FoldingSetNodeID &ID) {
00463     ID.AddInteger(getASTCallingConvention());
00464     ID.AddBoolean(InstanceMethod);
00465     ID.AddBoolean(NoReturn);
00466     ID.AddBoolean(ReturnsRetained);
00467     ID.AddBoolean(HasRegParm);
00468     ID.AddInteger(RegParm);
00469     ID.AddInteger(Required.getOpaqueData());
00470     getReturnType().Profile(ID);
00471     for (const auto &I : arguments())
00472       I.type.Profile(ID);
00473   }
00474   static void Profile(llvm::FoldingSetNodeID &ID,
00475                       bool InstanceMethod,
00476                       const FunctionType::ExtInfo &info,
00477                       RequiredArgs required,
00478                       CanQualType resultType,
00479                       ArrayRef<CanQualType> argTypes) {
00480     ID.AddInteger(info.getCC());
00481     ID.AddBoolean(InstanceMethod);
00482     ID.AddBoolean(info.getNoReturn());
00483     ID.AddBoolean(info.getProducesResult());
00484     ID.AddBoolean(info.getHasRegParm());
00485     ID.AddInteger(info.getRegParm());
00486     ID.AddInteger(required.getOpaqueData());
00487     resultType.Profile(ID);
00488     for (ArrayRef<CanQualType>::iterator
00489            i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
00490       i->Profile(ID);
00491     }
00492   }
00493 };
00494 
00495 }  // end namespace CodeGen
00496 }  // end namespace clang
00497 
00498 #endif