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