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 canHavePaddingType()98 bool canHavePaddingType() const { 99 return isDirect() || isExtend() || isIndirect() || isExpand(); 100 } setPaddingType(llvm::Type * T)101 void setPaddingType(llvm::Type *T) { 102 assert(canHavePaddingType()); 103 PaddingType = T; 104 } 105 setUnpaddedCoerceToType(llvm::Type * T)106 void setUnpaddedCoerceToType(llvm::Type *T) { 107 assert(isCoerceAndExpand()); 108 UnpaddedCoerceAndExpandType = T; 109 } 110 111 public: 112 ABIArgInfo(Kind K = Direct) TypeData(nullptr)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 } getIgnore()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 } getInAlloca(unsigned FieldIndex)188 static ABIArgInfo getInAlloca(unsigned FieldIndex) { 189 auto AI = ABIArgInfo(InAlloca); 190 AI.setInAllocaFieldIndex(FieldIndex); 191 return AI; 192 } getExpand()193 static ABIArgInfo getExpand() { 194 auto AI = ABIArgInfo(Expand); 195 AI.setPaddingType(nullptr); 196 return AI; 197 } getExpandWithPadding(bool PaddingInReg,llvm::Type * Padding)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. getCoerceAndExpand(llvm::StructType * coerceToType,llvm::Type * unpaddedCoerceToType)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 isPaddingForCoerceAndExpand(llvm::Type * eltType)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 getKind()254 Kind getKind() const { return TheKind; } isDirect()255 bool isDirect() const { return TheKind == Direct; } isInAlloca()256 bool isInAlloca() const { return TheKind == InAlloca; } isExtend()257 bool isExtend() const { return TheKind == Extend; } isIgnore()258 bool isIgnore() const { return TheKind == Ignore; } isIndirect()259 bool isIndirect() const { return TheKind == Indirect; } isExpand()260 bool isExpand() const { return TheKind == Expand; } isCoerceAndExpand()261 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; } 262 canHaveCoerceToType()263 bool canHaveCoerceToType() const { 264 return isDirect() || isExtend() || isCoerceAndExpand(); 265 } 266 267 // Direct/Extend accessors getDirectOffset()268 unsigned getDirectOffset() const { 269 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 270 return DirectOffset; 271 } setDirectOffset(unsigned Offset)272 void setDirectOffset(unsigned Offset) { 273 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 274 DirectOffset = Offset; 275 } 276 isSignExt()277 bool isSignExt() const { 278 assert(isExtend() && "Invalid kind!"); 279 return SignExt; 280 } setSignExt(bool SExt)281 void setSignExt(bool SExt) { 282 assert(isExtend() && "Invalid kind!"); 283 SignExt = SExt; 284 } 285 getPaddingType()286 llvm::Type *getPaddingType() const { 287 return (canHavePaddingType() ? PaddingType : nullptr); 288 } 289 getPaddingInReg()290 bool getPaddingInReg() const { 291 return PaddingInReg; 292 } setPaddingInReg(bool PIR)293 void setPaddingInReg(bool PIR) { 294 PaddingInReg = PIR; 295 } 296 getCoerceToType()297 llvm::Type *getCoerceToType() const { 298 assert(canHaveCoerceToType() && "Invalid kind!"); 299 return TypeData; 300 } 301 setCoerceToType(llvm::Type * T)302 void setCoerceToType(llvm::Type *T) { 303 assert(canHaveCoerceToType() && "Invalid kind!"); 304 TypeData = T; 305 } 306 getCoerceAndExpandType()307 llvm::StructType *getCoerceAndExpandType() const { 308 assert(isCoerceAndExpand()); 309 return cast<llvm::StructType>(TypeData); 310 } 311 getUnpaddedCoerceAndExpandType()312 llvm::Type *getUnpaddedCoerceAndExpandType() const { 313 assert(isCoerceAndExpand()); 314 return UnpaddedCoerceAndExpandType; 315 } 316 getCoerceAndExpandTypeSequence()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 getInReg()327 bool getInReg() const { 328 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 329 return InReg; 330 } 331 setInReg(bool IR)332 void setInReg(bool IR) { 333 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 334 InReg = IR; 335 } 336 337 // Indirect accessors getIndirectAlign()338 CharUnits getIndirectAlign() const { 339 assert(isIndirect() && "Invalid kind!"); 340 return CharUnits::fromQuantity(IndirectAlign); 341 } setIndirectAlign(CharUnits IA)342 void setIndirectAlign(CharUnits IA) { 343 assert(isIndirect() && "Invalid kind!"); 344 IndirectAlign = IA.getQuantity(); 345 } 346 getIndirectByVal()347 bool getIndirectByVal() const { 348 assert(isIndirect() && "Invalid kind!"); 349 return IndirectByVal; 350 } setIndirectByVal(bool IBV)351 void setIndirectByVal(bool IBV) { 352 assert(isIndirect() && "Invalid kind!"); 353 IndirectByVal = IBV; 354 } 355 getIndirectRealign()356 bool getIndirectRealign() const { 357 assert(isIndirect() && "Invalid kind!"); 358 return IndirectRealign; 359 } setIndirectRealign(bool IR)360 void setIndirectRealign(bool IR) { 361 assert(isIndirect() && "Invalid kind!"); 362 IndirectRealign = IR; 363 } 364 isSRetAfterThis()365 bool isSRetAfterThis() const { 366 assert(isIndirect() && "Invalid kind!"); 367 return SRetAfterThis; 368 } setSRetAfterThis(bool AfterThis)369 void setSRetAfterThis(bool AfterThis) { 370 assert(isIndirect() && "Invalid kind!"); 371 SRetAfterThis = AfterThis; 372 } 373 getInAllocaFieldIndex()374 unsigned getInAllocaFieldIndex() const { 375 assert(isInAlloca() && "Invalid kind!"); 376 return AllocaFieldIndex; 377 } setInAllocaFieldIndex(unsigned FieldIndex)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. getInAllocaSRet()385 bool getInAllocaSRet() const { 386 assert(isInAlloca() && "Invalid kind!"); 387 return InAllocaSRet; 388 } 389 setInAllocaSRet(bool SRet)390 void setInAllocaSRet(bool SRet) { 391 assert(isInAlloca() && "Invalid kind!"); 392 InAllocaSRet = SRet; 393 } 394 getCanBeFlattened()395 bool getCanBeFlattened() const { 396 assert(isDirect() && "Invalid kind!"); 397 return CanBeFlattened; 398 } 399 setCanBeFlattened(bool Flatten)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 RequiredArgs(All_t _)417 RequiredArgs(All_t _) : NumRequired(~0U) {} RequiredArgs(unsigned n)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. forPrototypePlus(const FunctionProtoType * prototype,unsigned additional)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 forPrototypePlus(CanQual<FunctionProtoType> prototype,unsigned additional)441 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype, 442 unsigned additional) { 443 return forPrototypePlus(prototype.getTypePtr(), additional); 444 } 445 forPrototype(const FunctionProtoType * prototype)446 static RequiredArgs forPrototype(const FunctionProtoType *prototype) { 447 return forPrototypePlus(prototype, 0); 448 } 449 forPrototype(CanQual<FunctionProtoType> prototype)450 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) { 451 return forPrototypePlus(prototype.getTypePtr(), 0); 452 } 453 allowsOptionalArgs()454 bool allowsOptionalArgs() const { return NumRequired != ~0U; } getNumRequiredArgs()455 unsigned getNumRequiredArgs() const { 456 assert(allowsOptionalArgs()); 457 return NumRequired; 458 } 459 getOpaqueData()460 unsigned getOpaqueData() const { return NumRequired; } getFromOpaqueData(unsigned value)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 getArgsBuffer()526 ArgInfo *getArgsBuffer() { 527 return getTrailingObjects<ArgInfo>(); 528 } getArgsBuffer()529 const ArgInfo *getArgsBuffer() const { 530 return getTrailingObjects<ArgInfo>(); 531 } 532 getExtParameterInfosBuffer()533 ExtParameterInfo *getExtParameterInfosBuffer() { 534 return getTrailingObjects<ExtParameterInfo>(); 535 } getExtParameterInfosBuffer()536 const ExtParameterInfo *getExtParameterInfosBuffer() const{ 537 return getTrailingObjects<ExtParameterInfo>(); 538 } 539 CGFunctionInfo()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); delete(void * p)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; numTrailingObjects(OverloadToken<ArgInfo>)556 size_t numTrailingObjects(OverloadToken<ArgInfo>) const { 557 return NumArgs + 1; 558 } numTrailingObjects(OverloadToken<ExtParameterInfo>)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 arguments()566 MutableArrayRef<ArgInfo> arguments() { 567 return MutableArrayRef<ArgInfo>(arg_begin(), NumArgs); 568 } arguments()569 ArrayRef<ArgInfo> arguments() const { 570 return ArrayRef<ArgInfo>(arg_begin(), NumArgs); 571 } 572 arg_begin()573 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } arg_end()574 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } arg_begin()575 arg_iterator arg_begin() { return getArgsBuffer() + 1; } arg_end()576 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; } 577 arg_size()578 unsigned arg_size() const { return NumArgs; } 579 isVariadic()580 bool isVariadic() const { return Required.allowsOptionalArgs(); } getRequiredArgs()581 RequiredArgs getRequiredArgs() const { return Required; } getNumRequiredArgs()582 unsigned getNumRequiredArgs() const { 583 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size(); 584 } 585 isInstanceMethod()586 bool isInstanceMethod() const { return InstanceMethod; } 587 isChainCall()588 bool isChainCall() const { return ChainCall; } 589 isNoReturn()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. isReturnsRetained()594 bool isReturnsRetained() const { return ReturnsRetained; } 595 596 /// Whether this function no longer saves caller registers. isNoCallerSavedRegs()597 bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; } 598 599 /// Whether this function has nocf_check attribute. isNoCfCheck()600 bool isNoCfCheck() const { return NoCfCheck; } 601 602 /// getASTCallingConvention() - Return the AST-specified calling 603 /// convention. getASTCallingConvention()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. getCallingConvention()610 unsigned getCallingConvention() const { return CallingConvention; } 611 612 /// getEffectiveCallingConvention - Return the actual calling convention to 613 /// use, which may depend on the ABI. getEffectiveCallingConvention()614 unsigned getEffectiveCallingConvention() const { 615 return EffectiveCallingConvention; 616 } setEffectiveCallingConvention(unsigned Value)617 void setEffectiveCallingConvention(unsigned Value) { 618 EffectiveCallingConvention = Value; 619 } 620 getHasRegParm()621 bool getHasRegParm() const { return HasRegParm; } getRegParm()622 unsigned getRegParm() const { return RegParm; } 623 getExtInfo()624 FunctionType::ExtInfo getExtInfo() const { 625 return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(), 626 getASTCallingConvention(), isReturnsRetained(), 627 isNoCallerSavedRegs(), isNoCfCheck()); 628 } 629 getReturnType()630 CanQualType getReturnType() const { return getArgsBuffer()[0].type; } 631 getReturnInfo()632 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } getReturnInfo()633 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } 634 getExtParameterInfos()635 ArrayRef<ExtParameterInfo> getExtParameterInfos() const { 636 if (!HasExtParameterInfos) return {}; 637 return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs); 638 } getExtParameterInfo(unsigned argIndex)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. usesInAlloca()646 bool usesInAlloca() const { return ArgStruct; } 647 648 /// Get the struct type used to represent all the arguments in memory. getArgStruct()649 llvm::StructType *getArgStruct() const { return ArgStruct; } getArgStructAlignment()650 CharUnits getArgStructAlignment() const { 651 return CharUnits::fromQuantity(ArgStructAlign); 652 } setArgStruct(llvm::StructType * Ty,CharUnits Align)653 void setArgStruct(llvm::StructType *Ty, CharUnits Align) { 654 ArgStruct = Ty; 655 ArgStructAlign = Align.getQuantity(); 656 } 657 Profile(llvm::FoldingSetNodeID & ID)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 } Profile(llvm::FoldingSetNodeID & ID,bool InstanceMethod,bool ChainCall,const FunctionType::ExtInfo & info,ArrayRef<ExtParameterInfo> paramInfos,RequiredArgs required,CanQualType resultType,ArrayRef<CanQualType> argTypes)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