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