clang API Documentation
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