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