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_CGFUNCTIONINFO_H 17 #define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_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 indirect with byval, except it only applies to 67 /// arguments stored in memory and forbids any implicit copies. When 68 /// applied to a return type, it means the value is returned indirectly via 69 /// an implicit sret 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 bool CanBeFlattened: 1; // isDirect() 91 ABIArgInfo(Kind K)92 ABIArgInfo(Kind K) 93 : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {} 94 95 public: ABIArgInfo()96 ABIArgInfo() 97 : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0), 98 TheKind(Direct), PaddingInReg(false), InReg(false) {} 99 100 static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, 101 llvm::Type *Padding = nullptr, 102 bool CanBeFlattened = true) { 103 auto AI = ABIArgInfo(Direct); 104 AI.setCoerceToType(T); 105 AI.setDirectOffset(Offset); 106 AI.setPaddingType(Padding); 107 AI.setCanBeFlattened(CanBeFlattened); 108 return AI; 109 } 110 static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) { 111 auto AI = getDirect(T); 112 AI.setInReg(true); 113 return AI; 114 } 115 static ABIArgInfo getExtend(llvm::Type *T = nullptr) { 116 auto AI = ABIArgInfo(Extend); 117 AI.setCoerceToType(T); 118 AI.setDirectOffset(0); 119 return AI; 120 } 121 static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) { 122 auto AI = getExtend(T); 123 AI.setInReg(true); 124 return AI; 125 } getIgnore()126 static ABIArgInfo getIgnore() { 127 return ABIArgInfo(Ignore); 128 } 129 static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true, 130 bool Realign = false, 131 llvm::Type *Padding = nullptr) { 132 auto AI = ABIArgInfo(Indirect); 133 AI.setIndirectAlign(Alignment); 134 AI.setIndirectByVal(ByVal); 135 AI.setIndirectRealign(Realign); 136 AI.setSRetAfterThis(false); 137 AI.setPaddingType(Padding); 138 return AI; 139 } 140 static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true, 141 bool Realign = false) { 142 auto AI = getIndirect(Alignment, ByVal, Realign); 143 AI.setInReg(true); 144 return AI; 145 } getInAlloca(unsigned FieldIndex)146 static ABIArgInfo getInAlloca(unsigned FieldIndex) { 147 auto AI = ABIArgInfo(InAlloca); 148 AI.setInAllocaFieldIndex(FieldIndex); 149 return AI; 150 } getExpand()151 static ABIArgInfo getExpand() { 152 return ABIArgInfo(Expand); 153 } getExpandWithPadding(bool PaddingInReg,llvm::Type * Padding)154 static ABIArgInfo getExpandWithPadding(bool PaddingInReg, 155 llvm::Type *Padding) { 156 auto AI = getExpand(); 157 AI.setPaddingInReg(PaddingInReg); 158 AI.setPaddingType(Padding); 159 return AI; 160 } 161 getKind()162 Kind getKind() const { return TheKind; } isDirect()163 bool isDirect() const { return TheKind == Direct; } isInAlloca()164 bool isInAlloca() const { return TheKind == InAlloca; } isExtend()165 bool isExtend() const { return TheKind == Extend; } isIgnore()166 bool isIgnore() const { return TheKind == Ignore; } isIndirect()167 bool isIndirect() const { return TheKind == Indirect; } isExpand()168 bool isExpand() const { return TheKind == Expand; } 169 canHaveCoerceToType()170 bool canHaveCoerceToType() const { return isDirect() || isExtend(); } 171 172 // Direct/Extend accessors getDirectOffset()173 unsigned getDirectOffset() const { 174 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 175 return DirectOffset; 176 } setDirectOffset(unsigned Offset)177 void setDirectOffset(unsigned Offset) { 178 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 179 DirectOffset = Offset; 180 } 181 getPaddingType()182 llvm::Type *getPaddingType() const { return PaddingType; } 183 setPaddingType(llvm::Type * T)184 void setPaddingType(llvm::Type *T) { PaddingType = T; } 185 getPaddingInReg()186 bool getPaddingInReg() const { 187 return PaddingInReg; 188 } setPaddingInReg(bool PIR)189 void setPaddingInReg(bool PIR) { 190 PaddingInReg = PIR; 191 } 192 getCoerceToType()193 llvm::Type *getCoerceToType() const { 194 assert(canHaveCoerceToType() && "Invalid kind!"); 195 return TypeData; 196 } 197 setCoerceToType(llvm::Type * T)198 void setCoerceToType(llvm::Type *T) { 199 assert(canHaveCoerceToType() && "Invalid kind!"); 200 TypeData = T; 201 } 202 getInReg()203 bool getInReg() const { 204 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 205 return InReg; 206 } 207 setInReg(bool IR)208 void setInReg(bool IR) { 209 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 210 InReg = IR; 211 } 212 213 // Indirect accessors getIndirectAlign()214 unsigned getIndirectAlign() const { 215 assert(isIndirect() && "Invalid kind!"); 216 return IndirectAlign; 217 } setIndirectAlign(unsigned IA)218 void setIndirectAlign(unsigned IA) { 219 assert(isIndirect() && "Invalid kind!"); 220 IndirectAlign = IA; 221 } 222 getIndirectByVal()223 bool getIndirectByVal() const { 224 assert(isIndirect() && "Invalid kind!"); 225 return IndirectByVal; 226 } setIndirectByVal(unsigned IBV)227 void setIndirectByVal(unsigned IBV) { 228 assert(isIndirect() && "Invalid kind!"); 229 IndirectByVal = IBV; 230 } 231 getIndirectRealign()232 bool getIndirectRealign() const { 233 assert(isIndirect() && "Invalid kind!"); 234 return IndirectRealign; 235 } setIndirectRealign(bool IR)236 void setIndirectRealign(bool IR) { 237 assert(isIndirect() && "Invalid kind!"); 238 IndirectRealign = IR; 239 } 240 isSRetAfterThis()241 bool isSRetAfterThis() const { 242 assert(isIndirect() && "Invalid kind!"); 243 return SRetAfterThis; 244 } setSRetAfterThis(bool AfterThis)245 void setSRetAfterThis(bool AfterThis) { 246 assert(isIndirect() && "Invalid kind!"); 247 SRetAfterThis = AfterThis; 248 } 249 getInAllocaFieldIndex()250 unsigned getInAllocaFieldIndex() const { 251 assert(isInAlloca() && "Invalid kind!"); 252 return AllocaFieldIndex; 253 } setInAllocaFieldIndex(unsigned FieldIndex)254 void setInAllocaFieldIndex(unsigned FieldIndex) { 255 assert(isInAlloca() && "Invalid kind!"); 256 AllocaFieldIndex = FieldIndex; 257 } 258 259 /// \brief Return true if this field of an inalloca struct should be returned 260 /// to implement a struct return calling convention. getInAllocaSRet()261 bool getInAllocaSRet() const { 262 assert(isInAlloca() && "Invalid kind!"); 263 return InAllocaSRet; 264 } 265 setInAllocaSRet(bool SRet)266 void setInAllocaSRet(bool SRet) { 267 assert(isInAlloca() && "Invalid kind!"); 268 InAllocaSRet = SRet; 269 } 270 getCanBeFlattened()271 bool getCanBeFlattened() const { 272 assert(isDirect() && "Invalid kind!"); 273 return CanBeFlattened; 274 } 275 setCanBeFlattened(bool Flatten)276 void setCanBeFlattened(bool Flatten) { 277 assert(isDirect() && "Invalid kind!"); 278 CanBeFlattened = Flatten; 279 } 280 281 void dump() const; 282 }; 283 284 /// A class for recording the number of arguments that a function 285 /// signature requires. 286 class RequiredArgs { 287 /// The number of required arguments, or ~0 if the signature does 288 /// not permit optional arguments. 289 unsigned NumRequired; 290 public: 291 enum All_t { All }; 292 RequiredArgs(All_t _)293 RequiredArgs(All_t _) : NumRequired(~0U) {} RequiredArgs(unsigned n)294 explicit RequiredArgs(unsigned n) : NumRequired(n) { 295 assert(n != ~0U); 296 } 297 298 /// Compute the arguments required by the given formal prototype, 299 /// given that there may be some additional, non-formal arguments 300 /// in play. forPrototypePlus(const FunctionProtoType * prototype,unsigned additional)301 static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, 302 unsigned additional) { 303 if (!prototype->isVariadic()) return All; 304 return RequiredArgs(prototype->getNumParams() + additional); 305 } 306 forPrototype(const FunctionProtoType * prototype)307 static RequiredArgs forPrototype(const FunctionProtoType *prototype) { 308 return forPrototypePlus(prototype, 0); 309 } 310 forPrototype(CanQual<FunctionProtoType> prototype)311 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) { 312 return forPrototype(prototype.getTypePtr()); 313 } 314 forPrototypePlus(CanQual<FunctionProtoType> prototype,unsigned additional)315 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype, 316 unsigned additional) { 317 return forPrototypePlus(prototype.getTypePtr(), additional); 318 } 319 allowsOptionalArgs()320 bool allowsOptionalArgs() const { return NumRequired != ~0U; } getNumRequiredArgs()321 unsigned getNumRequiredArgs() const { 322 assert(allowsOptionalArgs()); 323 return NumRequired; 324 } 325 getOpaqueData()326 unsigned getOpaqueData() const { return NumRequired; } getFromOpaqueData(unsigned value)327 static RequiredArgs getFromOpaqueData(unsigned value) { 328 if (value == ~0U) return All; 329 return RequiredArgs(value); 330 } 331 }; 332 333 /// CGFunctionInfo - Class to encapsulate the information about a 334 /// function definition. 335 class CGFunctionInfo : public llvm::FoldingSetNode { 336 struct ArgInfo { 337 CanQualType type; 338 ABIArgInfo info; 339 }; 340 341 /// The LLVM::CallingConv to use for this function (as specified by the 342 /// user). 343 unsigned CallingConvention : 8; 344 345 /// The LLVM::CallingConv to actually use for this function, which may 346 /// depend on the ABI. 347 unsigned EffectiveCallingConvention : 8; 348 349 /// The clang::CallingConv that this was originally created with. 350 unsigned ASTCallingConvention : 8; 351 352 /// Whether this is an instance method. 353 unsigned InstanceMethod : 1; 354 355 /// Whether this is a chain call. 356 unsigned ChainCall : 1; 357 358 /// Whether this function is noreturn. 359 unsigned NoReturn : 1; 360 361 /// Whether this function is returns-retained. 362 unsigned ReturnsRetained : 1; 363 364 /// How many arguments to pass inreg. 365 unsigned HasRegParm : 1; 366 unsigned RegParm : 3; 367 368 RequiredArgs Required; 369 370 /// The struct representing all arguments passed in memory. Only used when 371 /// passing non-trivial types with inalloca. Not part of the profile. 372 llvm::StructType *ArgStruct; 373 374 unsigned NumArgs; getArgsBuffer()375 ArgInfo *getArgsBuffer() { 376 return reinterpret_cast<ArgInfo*>(this+1); 377 } getArgsBuffer()378 const ArgInfo *getArgsBuffer() const { 379 return reinterpret_cast<const ArgInfo*>(this + 1); 380 } 381 CGFunctionInfo()382 CGFunctionInfo() : Required(RequiredArgs::All) {} 383 384 public: 385 static CGFunctionInfo *create(unsigned llvmCC, 386 bool instanceMethod, 387 bool chainCall, 388 const FunctionType::ExtInfo &extInfo, 389 CanQualType resultType, 390 ArrayRef<CanQualType> argTypes, 391 RequiredArgs required); 392 393 typedef const ArgInfo *const_arg_iterator; 394 typedef ArgInfo *arg_iterator; 395 396 typedef llvm::iterator_range<arg_iterator> arg_range; 397 typedef llvm::iterator_range<const_arg_iterator> arg_const_range; 398 arguments()399 arg_range arguments() { return arg_range(arg_begin(), arg_end()); } arguments()400 arg_const_range arguments() const { 401 return arg_const_range(arg_begin(), arg_end()); 402 } 403 arg_begin()404 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } arg_end()405 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } arg_begin()406 arg_iterator arg_begin() { return getArgsBuffer() + 1; } arg_end()407 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; } 408 arg_size()409 unsigned arg_size() const { return NumArgs; } 410 isVariadic()411 bool isVariadic() const { return Required.allowsOptionalArgs(); } getRequiredArgs()412 RequiredArgs getRequiredArgs() const { return Required; } getNumRequiredArgs()413 unsigned getNumRequiredArgs() const { 414 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size(); 415 } 416 isInstanceMethod()417 bool isInstanceMethod() const { return InstanceMethod; } 418 isChainCall()419 bool isChainCall() const { return ChainCall; } 420 isNoReturn()421 bool isNoReturn() const { return NoReturn; } 422 423 /// In ARC, whether this function retains its return value. This 424 /// is not always reliable for call sites. isReturnsRetained()425 bool isReturnsRetained() const { return ReturnsRetained; } 426 427 /// getASTCallingConvention() - Return the AST-specified calling 428 /// convention. getASTCallingConvention()429 CallingConv getASTCallingConvention() const { 430 return CallingConv(ASTCallingConvention); 431 } 432 433 /// getCallingConvention - Return the user specified calling 434 /// convention, which has been translated into an LLVM CC. getCallingConvention()435 unsigned getCallingConvention() const { return CallingConvention; } 436 437 /// getEffectiveCallingConvention - Return the actual calling convention to 438 /// use, which may depend on the ABI. getEffectiveCallingConvention()439 unsigned getEffectiveCallingConvention() const { 440 return EffectiveCallingConvention; 441 } setEffectiveCallingConvention(unsigned Value)442 void setEffectiveCallingConvention(unsigned Value) { 443 EffectiveCallingConvention = Value; 444 } 445 getHasRegParm()446 bool getHasRegParm() const { return HasRegParm; } getRegParm()447 unsigned getRegParm() const { return RegParm; } 448 getExtInfo()449 FunctionType::ExtInfo getExtInfo() const { 450 return FunctionType::ExtInfo(isNoReturn(), 451 getHasRegParm(), getRegParm(), 452 getASTCallingConvention(), 453 isReturnsRetained()); 454 } 455 getReturnType()456 CanQualType getReturnType() const { return getArgsBuffer()[0].type; } 457 getReturnInfo()458 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } getReturnInfo()459 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } 460 461 /// \brief Return true if this function uses inalloca arguments. usesInAlloca()462 bool usesInAlloca() const { return ArgStruct; } 463 464 /// \brief Get the struct type used to represent all the arguments in memory. getArgStruct()465 llvm::StructType *getArgStruct() const { return ArgStruct; } setArgStruct(llvm::StructType * Ty)466 void setArgStruct(llvm::StructType *Ty) { ArgStruct = Ty; } 467 Profile(llvm::FoldingSetNodeID & ID)468 void Profile(llvm::FoldingSetNodeID &ID) { 469 ID.AddInteger(getASTCallingConvention()); 470 ID.AddBoolean(InstanceMethod); 471 ID.AddBoolean(ChainCall); 472 ID.AddBoolean(NoReturn); 473 ID.AddBoolean(ReturnsRetained); 474 ID.AddBoolean(HasRegParm); 475 ID.AddInteger(RegParm); 476 ID.AddInteger(Required.getOpaqueData()); 477 getReturnType().Profile(ID); 478 for (const auto &I : arguments()) 479 I.type.Profile(ID); 480 } Profile(llvm::FoldingSetNodeID & ID,bool InstanceMethod,bool ChainCall,const FunctionType::ExtInfo & info,RequiredArgs required,CanQualType resultType,ArrayRef<CanQualType> argTypes)481 static void Profile(llvm::FoldingSetNodeID &ID, 482 bool InstanceMethod, 483 bool ChainCall, 484 const FunctionType::ExtInfo &info, 485 RequiredArgs required, 486 CanQualType resultType, 487 ArrayRef<CanQualType> argTypes) { 488 ID.AddInteger(info.getCC()); 489 ID.AddBoolean(InstanceMethod); 490 ID.AddBoolean(ChainCall); 491 ID.AddBoolean(info.getNoReturn()); 492 ID.AddBoolean(info.getProducesResult()); 493 ID.AddBoolean(info.getHasRegParm()); 494 ID.AddInteger(info.getRegParm()); 495 ID.AddInteger(required.getOpaqueData()); 496 resultType.Profile(ID); 497 for (ArrayRef<CanQualType>::iterator 498 i = argTypes.begin(), e = argTypes.end(); i != e; ++i) { 499 i->Profile(ID); 500 } 501 } 502 }; 503 504 } // end namespace CodeGen 505 } // end namespace clang 506 507 #endif 508