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