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