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/Attr.h" 20 #include "clang/AST/CanonicalType.h" 21 #include "clang/AST/CharUnits.h" 22 #include "clang/AST/Decl.h" 23 #include "clang/AST/Type.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/ADT/FoldingSet.h" 26 #include "llvm/Support/TrailingObjects.h" 27 #include <cassert> 28 29 namespace clang { 30 namespace CodeGen { 31 32 /// ABIArgInfo - Helper class to encapsulate information about how a 33 /// specific C type should be passed to or returned from a function. 34 class ABIArgInfo { 35 public: 36 enum Kind : uint8_t { 37 /// Direct - Pass the argument directly using the normal converted LLVM 38 /// type, or by coercing to another specified type stored in 39 /// 'CoerceToType'). If an offset is specified (in UIntData), then the 40 /// argument passed is offset by some number of bytes in the memory 41 /// representation. A dummy argument is emitted before the real argument 42 /// if the specified type stored in "PaddingType" is not zero. 43 Direct, 44 45 /// Extend - Valid only for integer argument types. Same as 'direct' 46 /// but also emit a zero/sign extension attribute. 47 Extend, 48 49 /// Indirect - Pass the argument indirectly via a hidden pointer 50 /// with the specified alignment (0 indicates default alignment). 51 Indirect, 52 53 /// Ignore - Ignore the argument (treat as void). Useful for void and 54 /// empty structs. 55 Ignore, 56 57 /// Expand - Only valid for aggregate argument types. The structure should 58 /// be expanded into consecutive arguments for its constituent fields. 59 /// Currently expand is only allowed on structures whose fields 60 /// are all scalar types or are themselves expandable types. 61 Expand, 62 63 /// CoerceAndExpand - Only valid for aggregate argument types. The 64 /// structure should be expanded into consecutive arguments corresponding 65 /// to the non-array elements of the type stored in CoerceToType. 66 /// Array elements in the type are assumed to be padding and skipped. 67 CoerceAndExpand, 68 69 /// InAlloca - Pass the argument directly using the LLVM inalloca attribute. 70 /// This is similar to indirect with byval, except it only applies to 71 /// arguments stored in memory and forbids any implicit copies. When 72 /// applied to a return type, it means the value is returned indirectly via 73 /// an implicit sret parameter stored in the argument struct. 74 InAlloca, 75 KindFirst = Direct, 76 KindLast = InAlloca 77 }; 78 79 private: 80 llvm::Type *TypeData; // canHaveCoerceToType() 81 union { 82 llvm::Type *PaddingType; // canHavePaddingType() 83 llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand() 84 }; 85 union { 86 unsigned DirectOffset; // isDirect() || isExtend() 87 unsigned IndirectAlign; // isIndirect() 88 unsigned AllocaFieldIndex; // isInAlloca() 89 }; 90 Kind TheKind; 91 bool PaddingInReg : 1; 92 bool InAllocaSRet : 1; // isInAlloca() 93 bool IndirectByVal : 1; // isIndirect() 94 bool IndirectRealign : 1; // isIndirect() 95 bool SRetAfterThis : 1; // isIndirect() 96 bool InReg : 1; // isDirect() || isExtend() || isIndirect() 97 bool CanBeFlattened: 1; // isDirect() 98 canHavePaddingType()99 bool canHavePaddingType() const { 100 return isDirect() || isExtend() || isIndirect() || isExpand(); 101 } setPaddingType(llvm::Type * T)102 void setPaddingType(llvm::Type *T) { 103 assert(canHavePaddingType()); 104 PaddingType = T; 105 } 106 setUnpaddedCoerceToType(llvm::Type * T)107 void setUnpaddedCoerceToType(llvm::Type *T) { 108 assert(isCoerceAndExpand()); 109 UnpaddedCoerceAndExpandType = T; 110 } 111 ABIArgInfo(Kind K)112 ABIArgInfo(Kind K) 113 : TheKind(K), PaddingInReg(false), InReg(false) { 114 } 115 116 public: ABIArgInfo()117 ABIArgInfo() 118 : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0), 119 TheKind(Direct), PaddingInReg(false), InReg(false) {} 120 121 static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, 122 llvm::Type *Padding = nullptr, 123 bool CanBeFlattened = true) { 124 auto AI = ABIArgInfo(Direct); 125 AI.setCoerceToType(T); 126 AI.setPaddingType(Padding); 127 AI.setDirectOffset(Offset); 128 AI.setCanBeFlattened(CanBeFlattened); 129 return AI; 130 } 131 static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) { 132 auto AI = getDirect(T); 133 AI.setInReg(true); 134 return AI; 135 } 136 static ABIArgInfo getExtend(llvm::Type *T = nullptr) { 137 auto AI = ABIArgInfo(Extend); 138 AI.setCoerceToType(T); 139 AI.setPaddingType(nullptr); 140 AI.setDirectOffset(0); 141 return AI; 142 } 143 static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) { 144 auto AI = getExtend(T); 145 AI.setInReg(true); 146 return AI; 147 } getIgnore()148 static ABIArgInfo getIgnore() { 149 return ABIArgInfo(Ignore); 150 } 151 static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true, 152 bool Realign = false, 153 llvm::Type *Padding = nullptr) { 154 auto AI = ABIArgInfo(Indirect); 155 AI.setIndirectAlign(Alignment); 156 AI.setIndirectByVal(ByVal); 157 AI.setIndirectRealign(Realign); 158 AI.setSRetAfterThis(false); 159 AI.setPaddingType(Padding); 160 return AI; 161 } 162 static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true, 163 bool Realign = false) { 164 auto AI = getIndirect(Alignment, ByVal, Realign); 165 AI.setInReg(true); 166 return AI; 167 } getInAlloca(unsigned FieldIndex)168 static ABIArgInfo getInAlloca(unsigned FieldIndex) { 169 auto AI = ABIArgInfo(InAlloca); 170 AI.setInAllocaFieldIndex(FieldIndex); 171 return AI; 172 } getExpand()173 static ABIArgInfo getExpand() { 174 auto AI = ABIArgInfo(Expand); 175 AI.setPaddingType(nullptr); 176 return AI; 177 } getExpandWithPadding(bool PaddingInReg,llvm::Type * Padding)178 static ABIArgInfo getExpandWithPadding(bool PaddingInReg, 179 llvm::Type *Padding) { 180 auto AI = getExpand(); 181 AI.setPaddingInReg(PaddingInReg); 182 AI.setPaddingType(Padding); 183 return AI; 184 } 185 186 /// \param unpaddedCoerceToType The coerce-to type with padding elements 187 /// removed, canonicalized to a single element if it would otherwise 188 /// have exactly one element. getCoerceAndExpand(llvm::StructType * coerceToType,llvm::Type * unpaddedCoerceToType)189 static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, 190 llvm::Type *unpaddedCoerceToType) { 191 #ifndef NDEBUG 192 // Sanity checks on unpaddedCoerceToType. 193 194 // Assert that we only have a struct type if there are multiple elements. 195 auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType); 196 assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1); 197 198 // Assert that all the non-padding elements have a corresponding element 199 // in the unpadded type. 200 unsigned unpaddedIndex = 0; 201 for (auto eltType : coerceToType->elements()) { 202 if (isPaddingForCoerceAndExpand(eltType)) continue; 203 if (unpaddedStruct) { 204 assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType); 205 } else { 206 assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType); 207 } 208 unpaddedIndex++; 209 } 210 211 // Assert that there aren't extra elements in the unpadded type. 212 if (unpaddedStruct) { 213 assert(unpaddedStruct->getNumElements() == unpaddedIndex); 214 } else { 215 assert(unpaddedIndex == 1); 216 } 217 #endif 218 219 auto AI = ABIArgInfo(CoerceAndExpand); 220 AI.setCoerceToType(coerceToType); 221 AI.setUnpaddedCoerceToType(unpaddedCoerceToType); 222 return AI; 223 } 224 isPaddingForCoerceAndExpand(llvm::Type * eltType)225 static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) { 226 if (eltType->isArrayTy()) { 227 assert(eltType->getArrayElementType()->isIntegerTy(8)); 228 return true; 229 } else { 230 return false; 231 } 232 } 233 getKind()234 Kind getKind() const { return TheKind; } isDirect()235 bool isDirect() const { return TheKind == Direct; } isInAlloca()236 bool isInAlloca() const { return TheKind == InAlloca; } isExtend()237 bool isExtend() const { return TheKind == Extend; } isIgnore()238 bool isIgnore() const { return TheKind == Ignore; } isIndirect()239 bool isIndirect() const { return TheKind == Indirect; } isExpand()240 bool isExpand() const { return TheKind == Expand; } isCoerceAndExpand()241 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; } 242 canHaveCoerceToType()243 bool canHaveCoerceToType() const { 244 return isDirect() || isExtend() || isCoerceAndExpand(); 245 } 246 247 // Direct/Extend accessors getDirectOffset()248 unsigned getDirectOffset() const { 249 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 250 return DirectOffset; 251 } setDirectOffset(unsigned Offset)252 void setDirectOffset(unsigned Offset) { 253 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 254 DirectOffset = Offset; 255 } 256 getPaddingType()257 llvm::Type *getPaddingType() const { 258 return (canHavePaddingType() ? PaddingType : nullptr); 259 } 260 getPaddingInReg()261 bool getPaddingInReg() const { 262 return PaddingInReg; 263 } setPaddingInReg(bool PIR)264 void setPaddingInReg(bool PIR) { 265 PaddingInReg = PIR; 266 } 267 getCoerceToType()268 llvm::Type *getCoerceToType() const { 269 assert(canHaveCoerceToType() && "Invalid kind!"); 270 return TypeData; 271 } 272 setCoerceToType(llvm::Type * T)273 void setCoerceToType(llvm::Type *T) { 274 assert(canHaveCoerceToType() && "Invalid kind!"); 275 TypeData = T; 276 } 277 getCoerceAndExpandType()278 llvm::StructType *getCoerceAndExpandType() const { 279 assert(isCoerceAndExpand()); 280 return cast<llvm::StructType>(TypeData); 281 } 282 getUnpaddedCoerceAndExpandType()283 llvm::Type *getUnpaddedCoerceAndExpandType() const { 284 assert(isCoerceAndExpand()); 285 return UnpaddedCoerceAndExpandType; 286 } 287 getCoerceAndExpandTypeSequence()288 ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const { 289 assert(isCoerceAndExpand()); 290 if (auto structTy = 291 dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) { 292 return structTy->elements(); 293 } else { 294 return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1); 295 } 296 } 297 getInReg()298 bool getInReg() const { 299 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 300 return InReg; 301 } 302 setInReg(bool IR)303 void setInReg(bool IR) { 304 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 305 InReg = IR; 306 } 307 308 // Indirect accessors getIndirectAlign()309 CharUnits getIndirectAlign() const { 310 assert(isIndirect() && "Invalid kind!"); 311 return CharUnits::fromQuantity(IndirectAlign); 312 } setIndirectAlign(CharUnits IA)313 void setIndirectAlign(CharUnits IA) { 314 assert(isIndirect() && "Invalid kind!"); 315 IndirectAlign = IA.getQuantity(); 316 } 317 getIndirectByVal()318 bool getIndirectByVal() const { 319 assert(isIndirect() && "Invalid kind!"); 320 return IndirectByVal; 321 } setIndirectByVal(bool IBV)322 void setIndirectByVal(bool IBV) { 323 assert(isIndirect() && "Invalid kind!"); 324 IndirectByVal = IBV; 325 } 326 getIndirectRealign()327 bool getIndirectRealign() const { 328 assert(isIndirect() && "Invalid kind!"); 329 return IndirectRealign; 330 } setIndirectRealign(bool IR)331 void setIndirectRealign(bool IR) { 332 assert(isIndirect() && "Invalid kind!"); 333 IndirectRealign = IR; 334 } 335 isSRetAfterThis()336 bool isSRetAfterThis() const { 337 assert(isIndirect() && "Invalid kind!"); 338 return SRetAfterThis; 339 } setSRetAfterThis(bool AfterThis)340 void setSRetAfterThis(bool AfterThis) { 341 assert(isIndirect() && "Invalid kind!"); 342 SRetAfterThis = AfterThis; 343 } 344 getInAllocaFieldIndex()345 unsigned getInAllocaFieldIndex() const { 346 assert(isInAlloca() && "Invalid kind!"); 347 return AllocaFieldIndex; 348 } setInAllocaFieldIndex(unsigned FieldIndex)349 void setInAllocaFieldIndex(unsigned FieldIndex) { 350 assert(isInAlloca() && "Invalid kind!"); 351 AllocaFieldIndex = FieldIndex; 352 } 353 354 /// \brief Return true if this field of an inalloca struct should be returned 355 /// to implement a struct return calling convention. getInAllocaSRet()356 bool getInAllocaSRet() const { 357 assert(isInAlloca() && "Invalid kind!"); 358 return InAllocaSRet; 359 } 360 setInAllocaSRet(bool SRet)361 void setInAllocaSRet(bool SRet) { 362 assert(isInAlloca() && "Invalid kind!"); 363 InAllocaSRet = SRet; 364 } 365 getCanBeFlattened()366 bool getCanBeFlattened() const { 367 assert(isDirect() && "Invalid kind!"); 368 return CanBeFlattened; 369 } 370 setCanBeFlattened(bool Flatten)371 void setCanBeFlattened(bool Flatten) { 372 assert(isDirect() && "Invalid kind!"); 373 CanBeFlattened = Flatten; 374 } 375 376 void dump() const; 377 }; 378 379 /// A class for recording the number of arguments that a function 380 /// signature requires. 381 class RequiredArgs { 382 /// The number of required arguments, or ~0 if the signature does 383 /// not permit optional arguments. 384 unsigned NumRequired; 385 public: 386 enum All_t { All }; 387 RequiredArgs(All_t _)388 RequiredArgs(All_t _) : NumRequired(~0U) {} RequiredArgs(unsigned n)389 explicit RequiredArgs(unsigned n) : NumRequired(n) { 390 assert(n != ~0U); 391 } 392 393 /// Compute the arguments required by the given formal prototype, 394 /// given that there may be some additional, non-formal arguments 395 /// in play. 396 /// 397 /// If FD is not null, this will consider pass_object_size params in FD. forPrototypePlus(const FunctionProtoType * prototype,unsigned additional,const FunctionDecl * FD)398 static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, 399 unsigned additional, 400 const FunctionDecl *FD) { 401 if (!prototype->isVariadic()) return All; 402 if (FD) 403 additional += 404 llvm::count_if(FD->parameters(), [](const ParmVarDecl *PVD) { 405 return PVD->hasAttr<PassObjectSizeAttr>(); 406 }); 407 return RequiredArgs(prototype->getNumParams() + additional); 408 } 409 forPrototype(const FunctionProtoType * prototype,const FunctionDecl * FD)410 static RequiredArgs forPrototype(const FunctionProtoType *prototype, 411 const FunctionDecl *FD) { 412 return forPrototypePlus(prototype, 0, FD); 413 } 414 forPrototype(CanQual<FunctionProtoType> prototype,const FunctionDecl * FD)415 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype, 416 const FunctionDecl *FD) { 417 return forPrototype(prototype.getTypePtr(), FD); 418 } 419 forPrototypePlus(CanQual<FunctionProtoType> prototype,unsigned additional,const FunctionDecl * FD)420 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype, 421 unsigned additional, 422 const FunctionDecl *FD) { 423 return forPrototypePlus(prototype.getTypePtr(), additional, FD); 424 } 425 allowsOptionalArgs()426 bool allowsOptionalArgs() const { return NumRequired != ~0U; } getNumRequiredArgs()427 unsigned getNumRequiredArgs() const { 428 assert(allowsOptionalArgs()); 429 return NumRequired; 430 } 431 getOpaqueData()432 unsigned getOpaqueData() const { return NumRequired; } getFromOpaqueData(unsigned value)433 static RequiredArgs getFromOpaqueData(unsigned value) { 434 if (value == ~0U) return All; 435 return RequiredArgs(value); 436 } 437 }; 438 439 // Implementation detail of CGFunctionInfo, factored out so it can be named 440 // in the TrailingObjects base class of CGFunctionInfo. 441 struct CGFunctionInfoArgInfo { 442 CanQualType type; 443 ABIArgInfo info; 444 }; 445 446 /// CGFunctionInfo - Class to encapsulate the information about a 447 /// function definition. 448 class CGFunctionInfo final 449 : public llvm::FoldingSetNode, 450 private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo, 451 FunctionProtoType::ExtParameterInfo> { 452 typedef CGFunctionInfoArgInfo ArgInfo; 453 typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo; 454 455 /// The LLVM::CallingConv to use for this function (as specified by the 456 /// user). 457 unsigned CallingConvention : 8; 458 459 /// The LLVM::CallingConv to actually use for this function, which may 460 /// depend on the ABI. 461 unsigned EffectiveCallingConvention : 8; 462 463 /// The clang::CallingConv that this was originally created with. 464 unsigned ASTCallingConvention : 8; 465 466 /// Whether this is an instance method. 467 unsigned InstanceMethod : 1; 468 469 /// Whether this is a chain call. 470 unsigned ChainCall : 1; 471 472 /// Whether this function is noreturn. 473 unsigned NoReturn : 1; 474 475 /// Whether this function is returns-retained. 476 unsigned ReturnsRetained : 1; 477 478 /// How many arguments to pass inreg. 479 unsigned HasRegParm : 1; 480 unsigned RegParm : 3; 481 482 RequiredArgs Required; 483 484 /// The struct representing all arguments passed in memory. Only used when 485 /// passing non-trivial types with inalloca. Not part of the profile. 486 llvm::StructType *ArgStruct; 487 unsigned ArgStructAlign : 31; 488 unsigned HasExtParameterInfos : 1; 489 490 unsigned NumArgs; 491 getArgsBuffer()492 ArgInfo *getArgsBuffer() { 493 return getTrailingObjects<ArgInfo>(); 494 } getArgsBuffer()495 const ArgInfo *getArgsBuffer() const { 496 return getTrailingObjects<ArgInfo>(); 497 } 498 getExtParameterInfosBuffer()499 ExtParameterInfo *getExtParameterInfosBuffer() { 500 return getTrailingObjects<ExtParameterInfo>(); 501 } getExtParameterInfosBuffer()502 const ExtParameterInfo *getExtParameterInfosBuffer() const{ 503 return getTrailingObjects<ExtParameterInfo>(); 504 } 505 CGFunctionInfo()506 CGFunctionInfo() : Required(RequiredArgs::All) {} 507 508 public: 509 static CGFunctionInfo *create(unsigned llvmCC, 510 bool instanceMethod, 511 bool chainCall, 512 const FunctionType::ExtInfo &extInfo, 513 ArrayRef<ExtParameterInfo> paramInfos, 514 CanQualType resultType, 515 ArrayRef<CanQualType> argTypes, 516 RequiredArgs required); delete(void * p)517 void operator delete(void *p) { ::operator delete(p); } 518 519 // Friending class TrailingObjects is apparently not good enough for MSVC, 520 // so these have to be public. 521 friend class TrailingObjects; numTrailingObjects(OverloadToken<ArgInfo>)522 size_t numTrailingObjects(OverloadToken<ArgInfo>) const { 523 return NumArgs + 1; 524 } numTrailingObjects(OverloadToken<ExtParameterInfo>)525 size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const { 526 return (HasExtParameterInfos ? NumArgs : 0); 527 } 528 529 typedef const ArgInfo *const_arg_iterator; 530 typedef ArgInfo *arg_iterator; 531 532 typedef llvm::iterator_range<arg_iterator> arg_range; 533 typedef llvm::iterator_range<const_arg_iterator> arg_const_range; 534 arguments()535 arg_range arguments() { return arg_range(arg_begin(), arg_end()); } arguments()536 arg_const_range arguments() const { 537 return arg_const_range(arg_begin(), arg_end()); 538 } 539 arg_begin()540 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } arg_end()541 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } arg_begin()542 arg_iterator arg_begin() { return getArgsBuffer() + 1; } arg_end()543 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; } 544 arg_size()545 unsigned arg_size() const { return NumArgs; } 546 isVariadic()547 bool isVariadic() const { return Required.allowsOptionalArgs(); } getRequiredArgs()548 RequiredArgs getRequiredArgs() const { return Required; } getNumRequiredArgs()549 unsigned getNumRequiredArgs() const { 550 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size(); 551 } 552 isInstanceMethod()553 bool isInstanceMethod() const { return InstanceMethod; } 554 isChainCall()555 bool isChainCall() const { return ChainCall; } 556 isNoReturn()557 bool isNoReturn() const { return NoReturn; } 558 559 /// In ARC, whether this function retains its return value. This 560 /// is not always reliable for call sites. isReturnsRetained()561 bool isReturnsRetained() const { return ReturnsRetained; } 562 563 /// getASTCallingConvention() - Return the AST-specified calling 564 /// convention. getASTCallingConvention()565 CallingConv getASTCallingConvention() const { 566 return CallingConv(ASTCallingConvention); 567 } 568 569 /// getCallingConvention - Return the user specified calling 570 /// convention, which has been translated into an LLVM CC. getCallingConvention()571 unsigned getCallingConvention() const { return CallingConvention; } 572 573 /// getEffectiveCallingConvention - Return the actual calling convention to 574 /// use, which may depend on the ABI. getEffectiveCallingConvention()575 unsigned getEffectiveCallingConvention() const { 576 return EffectiveCallingConvention; 577 } setEffectiveCallingConvention(unsigned Value)578 void setEffectiveCallingConvention(unsigned Value) { 579 EffectiveCallingConvention = Value; 580 } 581 getHasRegParm()582 bool getHasRegParm() const { return HasRegParm; } getRegParm()583 unsigned getRegParm() const { return RegParm; } 584 getExtInfo()585 FunctionType::ExtInfo getExtInfo() const { 586 return FunctionType::ExtInfo(isNoReturn(), 587 getHasRegParm(), getRegParm(), 588 getASTCallingConvention(), 589 isReturnsRetained()); 590 } 591 getReturnType()592 CanQualType getReturnType() const { return getArgsBuffer()[0].type; } 593 getReturnInfo()594 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } getReturnInfo()595 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } 596 getExtParameterInfos()597 ArrayRef<ExtParameterInfo> getExtParameterInfos() const { 598 if (!HasExtParameterInfos) return {}; 599 return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs); 600 } getExtParameterInfo(unsigned argIndex)601 ExtParameterInfo getExtParameterInfo(unsigned argIndex) const { 602 assert(argIndex <= NumArgs); 603 if (!HasExtParameterInfos) return ExtParameterInfo(); 604 return getExtParameterInfos()[argIndex]; 605 } 606 607 /// \brief Return true if this function uses inalloca arguments. usesInAlloca()608 bool usesInAlloca() const { return ArgStruct; } 609 610 /// \brief Get the struct type used to represent all the arguments in memory. getArgStruct()611 llvm::StructType *getArgStruct() const { return ArgStruct; } getArgStructAlignment()612 CharUnits getArgStructAlignment() const { 613 return CharUnits::fromQuantity(ArgStructAlign); 614 } setArgStruct(llvm::StructType * Ty,CharUnits Align)615 void setArgStruct(llvm::StructType *Ty, CharUnits Align) { 616 ArgStruct = Ty; 617 ArgStructAlign = Align.getQuantity(); 618 } 619 Profile(llvm::FoldingSetNodeID & ID)620 void Profile(llvm::FoldingSetNodeID &ID) { 621 ID.AddInteger(getASTCallingConvention()); 622 ID.AddBoolean(InstanceMethod); 623 ID.AddBoolean(ChainCall); 624 ID.AddBoolean(NoReturn); 625 ID.AddBoolean(ReturnsRetained); 626 ID.AddBoolean(HasRegParm); 627 ID.AddInteger(RegParm); 628 ID.AddInteger(Required.getOpaqueData()); 629 ID.AddBoolean(HasExtParameterInfos); 630 if (HasExtParameterInfos) { 631 for (auto paramInfo : getExtParameterInfos()) 632 ID.AddInteger(paramInfo.getOpaqueValue()); 633 } 634 getReturnType().Profile(ID); 635 for (const auto &I : arguments()) 636 I.type.Profile(ID); 637 } Profile(llvm::FoldingSetNodeID & ID,bool InstanceMethod,bool ChainCall,const FunctionType::ExtInfo & info,ArrayRef<ExtParameterInfo> paramInfos,RequiredArgs required,CanQualType resultType,ArrayRef<CanQualType> argTypes)638 static void Profile(llvm::FoldingSetNodeID &ID, 639 bool InstanceMethod, 640 bool ChainCall, 641 const FunctionType::ExtInfo &info, 642 ArrayRef<ExtParameterInfo> paramInfos, 643 RequiredArgs required, 644 CanQualType resultType, 645 ArrayRef<CanQualType> argTypes) { 646 ID.AddInteger(info.getCC()); 647 ID.AddBoolean(InstanceMethod); 648 ID.AddBoolean(ChainCall); 649 ID.AddBoolean(info.getNoReturn()); 650 ID.AddBoolean(info.getProducesResult()); 651 ID.AddBoolean(info.getHasRegParm()); 652 ID.AddInteger(info.getRegParm()); 653 ID.AddInteger(required.getOpaqueData()); 654 ID.AddBoolean(!paramInfos.empty()); 655 if (!paramInfos.empty()) { 656 for (auto paramInfo : paramInfos) 657 ID.AddInteger(paramInfo.getOpaqueValue()); 658 } 659 resultType.Profile(ID); 660 for (ArrayRef<CanQualType>::iterator 661 i = argTypes.begin(), e = argTypes.end(); i != e; ++i) { 662 i->Profile(ID); 663 } 664 } 665 }; 666 667 /// CGCalleeInfo - Class to encapsulate the information about a callee to be 668 /// used during the generation of call/invoke instructions. 669 class CGCalleeInfo { 670 /// \brief The function proto type of the callee. 671 const FunctionProtoType *CalleeProtoTy; 672 /// \brief The function declaration of the callee. 673 const Decl *CalleeDecl; 674 675 public: CGCalleeInfo()676 explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {} CGCalleeInfo(const FunctionProtoType * calleeProtoTy,const Decl * calleeDecl)677 CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl) 678 : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {} CGCalleeInfo(const FunctionProtoType * calleeProtoTy)679 CGCalleeInfo(const FunctionProtoType *calleeProtoTy) 680 : CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {} CGCalleeInfo(const Decl * calleeDecl)681 CGCalleeInfo(const Decl *calleeDecl) 682 : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {} 683 getCalleeFunctionProtoType()684 const FunctionProtoType *getCalleeFunctionProtoType() { 685 return CalleeProtoTy; 686 } getCalleeDecl()687 const Decl *getCalleeDecl() { return CalleeDecl; } 688 }; 689 690 } // end namespace CodeGen 691 } // end namespace clang 692 693 #endif 694