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