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