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