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 29namespace clang { 30namespace 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. 34class ABIArgInfo { 35public: 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 79private: 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 99 bool canHavePaddingType() const { 100 return isDirect() || isExtend() || isIndirect() || isExpand(); 101 } 102 void setPaddingType(llvm::Type *T) { 103 assert(canHavePaddingType()); 104 PaddingType = T; 105 } 106 107 void setUnpaddedCoerceToType(llvm::Type *T) { 108 assert(isCoerceAndExpand()); 109 UnpaddedCoerceAndExpandType = T; 110 } 111 112 ABIArgInfo(Kind K) 113 : TheKind(K), PaddingInReg(false), InReg(false) { 114 } 115 116public: 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 } 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 } 168 static ABIArgInfo getInAlloca(unsigned FieldIndex) { 169 auto AI = ABIArgInfo(InAlloca); 170 AI.setInAllocaFieldIndex(FieldIndex); 171 return AI; 172 } 173 static ABIArgInfo getExpand() { 174 auto AI = ABIArgInfo(Expand); 175 AI.setPaddingType(nullptr); 176 return AI; 177 } 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. 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 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 234 Kind getKind() const { return TheKind; } 235 bool isDirect() const { return TheKind == Direct; } 236 bool isInAlloca() const { return TheKind == InAlloca; } 237 bool isExtend() const { return TheKind == Extend; } 238 bool isIgnore() const { return TheKind == Ignore; } 239 bool isIndirect() const { return TheKind == Indirect; } 240 bool isExpand() const { return TheKind == Expand; } 241 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; } 242 243 bool canHaveCoerceToType() const { 244 return isDirect() || isExtend() || isCoerceAndExpand(); 245 } 246 247 // Direct/Extend accessors 248 unsigned getDirectOffset() const { 249 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 250 return DirectOffset; 251 } 252 void setDirectOffset(unsigned Offset) { 253 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 254 DirectOffset = Offset; 255 } 256 257 llvm::Type *getPaddingType() const { 258 return (canHavePaddingType() ? PaddingType : nullptr); 259 } 260 261 bool getPaddingInReg() const { 262 return PaddingInReg; 263 } 264 void setPaddingInReg(bool PIR) { 265 PaddingInReg = PIR; 266 } 267 268 llvm::Type *getCoerceToType() const { 269 assert(canHaveCoerceToType() && "Invalid kind!"); 270 return TypeData; 271 } 272 273 void setCoerceToType(llvm::Type *T) { 274 assert(canHaveCoerceToType() && "Invalid kind!"); 275 TypeData = T; 276 } 277 278 llvm::StructType *getCoerceAndExpandType() const { 279 assert(isCoerceAndExpand()); 280 return cast<llvm::StructType>(TypeData); 281 } 282 283 llvm::Type *getUnpaddedCoerceAndExpandType() const { 284 assert(isCoerceAndExpand()); 285 return UnpaddedCoerceAndExpandType; 286 } 287 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 298 bool getInReg() const { 299 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 300 return InReg; 301 } 302 303 void setInReg(bool IR) { 304 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 305 InReg = IR; 306 } 307 308 // Indirect accessors 309 CharUnits getIndirectAlign() const { 310 assert(isIndirect() && "Invalid kind!"); 311 return CharUnits::fromQuantity(IndirectAlign); 312 } 313 void setIndirectAlign(CharUnits IA) { 314 assert(isIndirect() && "Invalid kind!"); 315 IndirectAlign = IA.getQuantity(); 316 } 317 318 bool getIndirectByVal() const { 319 assert(isIndirect() && "Invalid kind!"); 320 return IndirectByVal; 321 } 322 void setIndirectByVal(bool IBV) { 323 assert(isIndirect() && "Invalid kind!"); 324 IndirectByVal = IBV; 325 } 326 327 bool getIndirectRealign() const { 328 assert(isIndirect() && "Invalid kind!"); 329 return IndirectRealign; 330 } 331 void setIndirectRealign(bool IR) { 332 assert(isIndirect() && "Invalid kind!"); 333 IndirectRealign = IR; 334 } 335 336 bool isSRetAfterThis() const { 337 assert(isIndirect() && "Invalid kind!"); 338 return SRetAfterThis; 339 } 340 void setSRetAfterThis(bool AfterThis) { 341 assert(isIndirect() && "Invalid kind!"); 342 SRetAfterThis = AfterThis; 343 } 344 345 unsigned getInAllocaFieldIndex() const { 346 assert(isInAlloca() && "Invalid kind!"); 347 return AllocaFieldIndex; 348 } 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. 356 bool getInAllocaSRet() const { 357 assert(isInAlloca() && "Invalid kind!"); 358 return InAllocaSRet; 359 } 360 361 void setInAllocaSRet(bool SRet) { 362 assert(isInAlloca() && "Invalid kind!"); 363 InAllocaSRet = SRet; 364 } 365 366 bool getCanBeFlattened() const { 367 assert(isDirect() && "Invalid kind!"); 368 return CanBeFlattened; 369 } 370 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. 381class RequiredArgs { 382 /// The number of required arguments, or ~0 if the signature does 383 /// not permit optional arguments. 384 unsigned NumRequired; 385public: 386 enum All_t { All }; 387 388 RequiredArgs(All_t _) : NumRequired(~0U) {} 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. 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 410 static RequiredArgs forPrototype(const FunctionProtoType *prototype, 411 const FunctionDecl *FD) { 412 return forPrototypePlus(prototype, 0, FD); 413 } 414 415 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype, 416 const FunctionDecl *FD) { 417 return forPrototype(prototype.getTypePtr(), FD); 418 } 419 420 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype, 421 unsigned additional, 422 const FunctionDecl *FD) { 423 return forPrototypePlus(prototype.getTypePtr(), additional, FD); 424 } 425 426 bool allowsOptionalArgs() const { return NumRequired != ~0U; } 427 unsigned getNumRequiredArgs() const { 428 assert(allowsOptionalArgs()); 429 return NumRequired; 430 } 431 432 unsigned getOpaqueData() const { return NumRequired; } 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. 441struct CGFunctionInfoArgInfo { 442 CanQualType type; 443 ABIArgInfo info; 444}; 445 446/// CGFunctionInfo - Class to encapsulate the information about a 447/// function definition. 448class 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 : 7; 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 /// Whether this function saved caller registers. 479 unsigned NoCallerSavedRegs : 1; 480 481 /// How many arguments to pass inreg. 482 unsigned HasRegParm : 1; 483 unsigned RegParm : 3; 484 485 RequiredArgs Required; 486 487 /// The struct representing all arguments passed in memory. Only used when 488 /// passing non-trivial types with inalloca. Not part of the profile. 489 llvm::StructType *ArgStruct; 490 unsigned ArgStructAlign : 31; 491 unsigned HasExtParameterInfos : 1; 492 493 unsigned NumArgs; 494 495 ArgInfo *getArgsBuffer() { 496 return getTrailingObjects<ArgInfo>(); 497 } 498 const ArgInfo *getArgsBuffer() const { 499 return getTrailingObjects<ArgInfo>(); 500 } 501 502 ExtParameterInfo *getExtParameterInfosBuffer() { 503 return getTrailingObjects<ExtParameterInfo>(); 504 } 505 const ExtParameterInfo *getExtParameterInfosBuffer() const{ 506 return getTrailingObjects<ExtParameterInfo>(); 507 } 508 509 CGFunctionInfo() : Required(RequiredArgs::All) {} 510 511public: 512 static CGFunctionInfo *create(unsigned llvmCC, 513 bool instanceMethod, 514 bool chainCall, 515 const FunctionType::ExtInfo &extInfo, 516 ArrayRef<ExtParameterInfo> paramInfos, 517 CanQualType resultType, 518 ArrayRef<CanQualType> argTypes, 519 RequiredArgs required); 520 void operator delete(void *p) { ::operator delete(p); } 521 522 // Friending class TrailingObjects is apparently not good enough for MSVC, 523 // so these have to be public. 524 friend class TrailingObjects; 525 size_t numTrailingObjects(OverloadToken<ArgInfo>) const { 526 return NumArgs + 1; 527 } 528 size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const { 529 return (HasExtParameterInfos ? NumArgs : 0); 530 } 531 532 typedef const ArgInfo *const_arg_iterator; 533 typedef ArgInfo *arg_iterator; 534 535 typedef llvm::iterator_range<arg_iterator> arg_range; 536 typedef llvm::iterator_range<const_arg_iterator> arg_const_range; 537 538 arg_range arguments() { return arg_range(arg_begin(), arg_end()); } 539 arg_const_range arguments() const { 540 return arg_const_range(arg_begin(), arg_end()); 541 } 542 543 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } 544 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } 545 arg_iterator arg_begin() { return getArgsBuffer() + 1; } 546 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; } 547 548 unsigned arg_size() const { return NumArgs; } 549 550 bool isVariadic() const { return Required.allowsOptionalArgs(); } 551 RequiredArgs getRequiredArgs() const { return Required; } 552 unsigned getNumRequiredArgs() const { 553 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size(); 554 } 555 556 bool isInstanceMethod() const { return InstanceMethod; } 557 558 bool isChainCall() const { return ChainCall; } 559 560 bool isNoReturn() const { return NoReturn; } 561 562 /// In ARC, whether this function retains its return value. This 563 /// is not always reliable for call sites. 564 bool isReturnsRetained() const { return ReturnsRetained; } 565 566 /// Whether this function no longer saves caller registers. 567 bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; } 568 569 /// getASTCallingConvention() - Return the AST-specified calling 570 /// convention. 571 CallingConv getASTCallingConvention() const { 572 return CallingConv(ASTCallingConvention); 573 } 574 575 /// getCallingConvention - Return the user specified calling 576 /// convention, which has been translated into an LLVM CC. 577 unsigned getCallingConvention() const { return CallingConvention; } 578 579 /// getEffectiveCallingConvention - Return the actual calling convention to 580 /// use, which may depend on the ABI. 581 unsigned getEffectiveCallingConvention() const { 582 return EffectiveCallingConvention; 583 } 584 void setEffectiveCallingConvention(unsigned Value) { 585 EffectiveCallingConvention = Value; 586 } 587 588 bool getHasRegParm() const { return HasRegParm; } 589 unsigned getRegParm() const { return RegParm; } 590 591 FunctionType::ExtInfo getExtInfo() const { 592 return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(), 593 getASTCallingConvention(), isReturnsRetained(), 594 isNoCallerSavedRegs()); 595 } 596 597 CanQualType getReturnType() const { return getArgsBuffer()[0].type; } 598 599 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } 600 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } 601 602 ArrayRef<ExtParameterInfo> getExtParameterInfos() const { 603 if (!HasExtParameterInfos) return {}; 604 return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs); 605 } 606 ExtParameterInfo getExtParameterInfo(unsigned argIndex) const { 607 assert(argIndex <= NumArgs); 608 if (!HasExtParameterInfos) return ExtParameterInfo(); 609 return getExtParameterInfos()[argIndex]; 610 } 611 612 /// \brief Return true if this function uses inalloca arguments. 613 bool usesInAlloca() const { return ArgStruct; } 614 615 /// \brief Get the struct type used to represent all the arguments in memory. 616 llvm::StructType *getArgStruct() const { return ArgStruct; } 617 CharUnits getArgStructAlignment() const { 618 return CharUnits::fromQuantity(ArgStructAlign); 619 } 620 void setArgStruct(llvm::StructType *Ty, CharUnits Align) { 621 ArgStruct = Ty; 622 ArgStructAlign = Align.getQuantity(); 623 } 624 625 void Profile(llvm::FoldingSetNodeID &ID) { 626 ID.AddInteger(getASTCallingConvention()); 627 ID.AddBoolean(InstanceMethod); 628 ID.AddBoolean(ChainCall); 629 ID.AddBoolean(NoReturn); 630 ID.AddBoolean(ReturnsRetained); 631 ID.AddBoolean(NoCallerSavedRegs); 632 ID.AddBoolean(HasRegParm); 633 ID.AddInteger(RegParm); 634 ID.AddInteger(Required.getOpaqueData()); 635 ID.AddBoolean(HasExtParameterInfos); 636 if (HasExtParameterInfos) { 637 for (auto paramInfo : getExtParameterInfos()) 638 ID.AddInteger(paramInfo.getOpaqueValue()); 639 } 640 getReturnType().Profile(ID); 641 for (const auto &I : arguments()) 642 I.type.Profile(ID); 643 } 644 static void Profile(llvm::FoldingSetNodeID &ID, 645 bool InstanceMethod, 646 bool ChainCall, 647 const FunctionType::ExtInfo &info, 648 ArrayRef<ExtParameterInfo> paramInfos, 649 RequiredArgs required, 650 CanQualType resultType, 651 ArrayRef<CanQualType> argTypes) { 652 ID.AddInteger(info.getCC()); 653 ID.AddBoolean(InstanceMethod); 654 ID.AddBoolean(ChainCall); 655 ID.AddBoolean(info.getNoReturn()); 656 ID.AddBoolean(info.getProducesResult()); 657 ID.AddBoolean(info.getNoCallerSavedRegs()); 658 ID.AddBoolean(info.getHasRegParm()); 659 ID.AddInteger(info.getRegParm()); 660 ID.AddInteger(required.getOpaqueData()); 661 ID.AddBoolean(!paramInfos.empty()); 662 if (!paramInfos.empty()) { 663 for (auto paramInfo : paramInfos) 664 ID.AddInteger(paramInfo.getOpaqueValue()); 665 } 666 resultType.Profile(ID); 667 for (ArrayRef<CanQualType>::iterator 668 i = argTypes.begin(), e = argTypes.end(); i != e; ++i) { 669 i->Profile(ID); 670 } 671 } 672}; 673 674} // end namespace CodeGen 675} // end namespace clang 676 677#endif 678