1 //==-- CGFunctionInfo.h - Representation of function argument/return types -==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Defines CGFunctionInfo and associated types used in representing the
11 // LLVM source types and ABI-coerced types for function arguments and
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
17 #define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
19 #include "clang/AST/Attr.h"
20 #include "clang/AST/CanonicalType.h"
21 #include "clang/AST/CharUnits.h"
22 #include "clang/AST/Decl.h"
23 #include "clang/AST/Type.h"
24 #include "llvm/IR/DerivedTypes.h"
25 #include "llvm/ADT/FoldingSet.h"
26 #include "llvm/Support/TrailingObjects.h"
32 /// ABIArgInfo - Helper class to encapsulate information about how a
33 /// specific C type should be passed to or returned from a function.
37 /// Direct - Pass the argument directly using the normal converted LLVM
38 /// type, or by coercing to another specified type stored in
39 /// 'CoerceToType'). If an offset is specified (in UIntData), then the
40 /// argument passed is offset by some number of bytes in the memory
41 /// representation. A dummy argument is emitted before the real argument
42 /// if the specified type stored in "PaddingType" is not zero.
45 /// Extend - Valid only for integer argument types. Same as 'direct'
46 /// but also emit a zero/sign extension attribute.
49 /// Indirect - Pass the argument indirectly via a hidden pointer
50 /// with the specified alignment (0 indicates default alignment).
53 /// Ignore - Ignore the argument (treat as void). Useful for void and
57 /// Expand - Only valid for aggregate argument types. The structure should
58 /// be expanded into consecutive arguments for its constituent fields.
59 /// Currently expand is only allowed on structures whose fields
60 /// are all scalar types or are themselves expandable types.
63 /// CoerceAndExpand - Only valid for aggregate argument types. The
64 /// structure should be expanded into consecutive arguments corresponding
65 /// to the non-array elements of the type stored in CoerceToType.
66 /// Array elements in the type are assumed to be padding and skipped.
69 /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
70 /// This is similar to indirect with byval, except it only applies to
71 /// arguments stored in memory and forbids any implicit copies. When
72 /// applied to a return type, it means the value is returned indirectly via
73 /// an implicit sret parameter stored in the argument struct.
80 llvm::Type *TypeData; // canHaveCoerceToType()
82 llvm::Type *PaddingType; // canHavePaddingType()
83 llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand()
86 unsigned DirectOffset; // isDirect() || isExtend()
87 unsigned IndirectAlign; // isIndirect()
88 unsigned AllocaFieldIndex; // isInAlloca()
91 bool PaddingInReg : 1;
92 bool InAllocaSRet : 1; // isInAlloca()
93 bool IndirectByVal : 1; // isIndirect()
94 bool IndirectRealign : 1; // isIndirect()
95 bool SRetAfterThis : 1; // isIndirect()
96 bool InReg : 1; // isDirect() || isExtend() || isIndirect()
97 bool CanBeFlattened: 1; // isDirect()
98 bool SignExt : 1; // isExtend()
99 bool SuppressSRet : 1; // isIndirect()
101 bool canHavePaddingType() const {
102 return isDirect() || isExtend() || isIndirect() || isExpand();
104 void setPaddingType(llvm::Type *T) {
105 assert(canHavePaddingType());
109 void setUnpaddedCoerceToType(llvm::Type *T) {
110 assert(isCoerceAndExpand());
111 UnpaddedCoerceAndExpandType = T;
115 : TheKind(K), PaddingInReg(false), InReg(false), SuppressSRet(false) {
120 : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
121 TheKind(Direct), PaddingInReg(false), InReg(false),
122 SuppressSRet(false) {}
124 static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
125 llvm::Type *Padding = nullptr,
126 bool CanBeFlattened = true) {
127 auto AI = ABIArgInfo(Direct);
128 AI.setCoerceToType(T);
129 AI.setPaddingType(Padding);
130 AI.setDirectOffset(Offset);
131 AI.setCanBeFlattened(CanBeFlattened);
134 static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
135 auto AI = getDirect(T);
140 static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) {
141 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
142 auto AI = ABIArgInfo(Extend);
143 AI.setCoerceToType(T);
144 AI.setPaddingType(nullptr);
145 AI.setDirectOffset(0);
150 static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) {
151 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
152 auto AI = ABIArgInfo(Extend);
153 AI.setCoerceToType(T);
154 AI.setPaddingType(nullptr);
155 AI.setDirectOffset(0);
156 AI.setSignExt(false);
160 // ABIArgInfo will record the argument as being extended based on the sign
162 static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
163 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
164 if (Ty->hasSignedIntegerRepresentation())
165 return getSignExtend(Ty, T);
166 return getZeroExtend(Ty, T);
169 static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
170 auto AI = getExtend(Ty, T);
174 static ABIArgInfo getIgnore() {
175 return ABIArgInfo(Ignore);
177 static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
178 bool Realign = false,
179 llvm::Type *Padding = nullptr) {
180 auto AI = ABIArgInfo(Indirect);
181 AI.setIndirectAlign(Alignment);
182 AI.setIndirectByVal(ByVal);
183 AI.setIndirectRealign(Realign);
184 AI.setSRetAfterThis(false);
185 AI.setPaddingType(Padding);
188 static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
189 bool Realign = false) {
190 auto AI = getIndirect(Alignment, ByVal, Realign);
194 static ABIArgInfo getInAlloca(unsigned FieldIndex) {
195 auto AI = ABIArgInfo(InAlloca);
196 AI.setInAllocaFieldIndex(FieldIndex);
199 static ABIArgInfo getExpand() {
200 auto AI = ABIArgInfo(Expand);
201 AI.setPaddingType(nullptr);
204 static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
205 llvm::Type *Padding) {
206 auto AI = getExpand();
207 AI.setPaddingInReg(PaddingInReg);
208 AI.setPaddingType(Padding);
212 /// \param unpaddedCoerceToType The coerce-to type with padding elements
213 /// removed, canonicalized to a single element if it would otherwise
214 /// have exactly one element.
215 static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
216 llvm::Type *unpaddedCoerceToType) {
218 // Sanity checks on unpaddedCoerceToType.
220 // Assert that we only have a struct type if there are multiple elements.
221 auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType);
222 assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1);
224 // Assert that all the non-padding elements have a corresponding element
225 // in the unpadded type.
226 unsigned unpaddedIndex = 0;
227 for (auto eltType : coerceToType->elements()) {
228 if (isPaddingForCoerceAndExpand(eltType)) continue;
229 if (unpaddedStruct) {
230 assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType);
232 assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType);
237 // Assert that there aren't extra elements in the unpadded type.
238 if (unpaddedStruct) {
239 assert(unpaddedStruct->getNumElements() == unpaddedIndex);
241 assert(unpaddedIndex == 1);
245 auto AI = ABIArgInfo(CoerceAndExpand);
246 AI.setCoerceToType(coerceToType);
247 AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
251 static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
252 if (eltType->isArrayTy()) {
253 assert(eltType->getArrayElementType()->isIntegerTy(8));
260 Kind getKind() const { return TheKind; }
261 bool isDirect() const { return TheKind == Direct; }
262 bool isInAlloca() const { return TheKind == InAlloca; }
263 bool isExtend() const { return TheKind == Extend; }
264 bool isIgnore() const { return TheKind == Ignore; }
265 bool isIndirect() const { return TheKind == Indirect; }
266 bool isExpand() const { return TheKind == Expand; }
267 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
269 bool canHaveCoerceToType() const {
270 return isDirect() || isExtend() || isCoerceAndExpand();
273 // Direct/Extend accessors
274 unsigned getDirectOffset() const {
275 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
278 void setDirectOffset(unsigned Offset) {
279 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
280 DirectOffset = Offset;
283 bool isSignExt() const {
284 assert(isExtend() && "Invalid kind!");
287 void setSignExt(bool SExt) {
288 assert(isExtend() && "Invalid kind!");
292 llvm::Type *getPaddingType() const {
293 return (canHavePaddingType() ? PaddingType : nullptr);
296 bool getPaddingInReg() const {
299 void setPaddingInReg(bool PIR) {
303 llvm::Type *getCoerceToType() const {
304 assert(canHaveCoerceToType() && "Invalid kind!");
308 void setCoerceToType(llvm::Type *T) {
309 assert(canHaveCoerceToType() && "Invalid kind!");
313 llvm::StructType *getCoerceAndExpandType() const {
314 assert(isCoerceAndExpand());
315 return cast<llvm::StructType>(TypeData);
318 llvm::Type *getUnpaddedCoerceAndExpandType() const {
319 assert(isCoerceAndExpand());
320 return UnpaddedCoerceAndExpandType;
323 ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const {
324 assert(isCoerceAndExpand());
326 dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) {
327 return structTy->elements();
329 return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1);
333 bool getInReg() const {
334 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
338 void setInReg(bool IR) {
339 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
343 // Indirect accessors
344 CharUnits getIndirectAlign() const {
345 assert(isIndirect() && "Invalid kind!");
346 return CharUnits::fromQuantity(IndirectAlign);
348 void setIndirectAlign(CharUnits IA) {
349 assert(isIndirect() && "Invalid kind!");
350 IndirectAlign = IA.getQuantity();
353 bool getIndirectByVal() const {
354 assert(isIndirect() && "Invalid kind!");
355 return IndirectByVal;
357 void setIndirectByVal(bool IBV) {
358 assert(isIndirect() && "Invalid kind!");
362 bool getIndirectRealign() const {
363 assert(isIndirect() && "Invalid kind!");
364 return IndirectRealign;
366 void setIndirectRealign(bool IR) {
367 assert(isIndirect() && "Invalid kind!");
368 IndirectRealign = IR;
371 bool isSRetAfterThis() const {
372 assert(isIndirect() && "Invalid kind!");
373 return SRetAfterThis;
375 void setSRetAfterThis(bool AfterThis) {
376 assert(isIndirect() && "Invalid kind!");
377 SRetAfterThis = AfterThis;
380 unsigned getInAllocaFieldIndex() const {
381 assert(isInAlloca() && "Invalid kind!");
382 return AllocaFieldIndex;
384 void setInAllocaFieldIndex(unsigned FieldIndex) {
385 assert(isInAlloca() && "Invalid kind!");
386 AllocaFieldIndex = FieldIndex;
389 /// Return true if this field of an inalloca struct should be returned
390 /// to implement a struct return calling convention.
391 bool getInAllocaSRet() const {
392 assert(isInAlloca() && "Invalid kind!");
396 void setInAllocaSRet(bool SRet) {
397 assert(isInAlloca() && "Invalid kind!");
401 bool getCanBeFlattened() const {
402 assert(isDirect() && "Invalid kind!");
403 return CanBeFlattened;
406 void setCanBeFlattened(bool Flatten) {
407 assert(isDirect() && "Invalid kind!");
408 CanBeFlattened = Flatten;
411 bool getSuppressSRet() const {
412 assert(isIndirect() && "Invalid kind!");
416 void setSuppressSRet(bool Suppress) {
417 assert(isIndirect() && "Invalid kind!");
418 SuppressSRet = Suppress;
424 /// A class for recording the number of arguments that a function
425 /// signature requires.
427 /// The number of required arguments, or ~0 if the signature does
428 /// not permit optional arguments.
429 unsigned NumRequired;
433 RequiredArgs(All_t _) : NumRequired(~0U) {}
434 explicit RequiredArgs(unsigned n) : NumRequired(n) {
438 /// Compute the arguments required by the given formal prototype,
439 /// given that there may be some additional, non-formal arguments
442 /// If FD is not null, this will consider pass_object_size params in FD.
443 static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
445 const FunctionDecl *FD) {
446 if (!prototype->isVariadic()) return All;
449 llvm::count_if(FD->parameters(), [](const ParmVarDecl *PVD) {
450 return PVD->hasAttr<PassObjectSizeAttr>();
452 return RequiredArgs(prototype->getNumParams() + additional);
455 static RequiredArgs forPrototype(const FunctionProtoType *prototype,
456 const FunctionDecl *FD) {
457 return forPrototypePlus(prototype, 0, FD);
460 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype,
461 const FunctionDecl *FD) {
462 return forPrototype(prototype.getTypePtr(), FD);
465 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
467 const FunctionDecl *FD) {
468 return forPrototypePlus(prototype.getTypePtr(), additional, FD);
471 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
472 unsigned getNumRequiredArgs() const {
473 assert(allowsOptionalArgs());
477 unsigned getOpaqueData() const { return NumRequired; }
478 static RequiredArgs getFromOpaqueData(unsigned value) {
479 if (value == ~0U) return All;
480 return RequiredArgs(value);
484 // Implementation detail of CGFunctionInfo, factored out so it can be named
485 // in the TrailingObjects base class of CGFunctionInfo.
486 struct CGFunctionInfoArgInfo {
491 /// CGFunctionInfo - Class to encapsulate the information about a
492 /// function definition.
493 class CGFunctionInfo final
494 : public llvm::FoldingSetNode,
495 private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo,
496 FunctionProtoType::ExtParameterInfo> {
497 typedef CGFunctionInfoArgInfo ArgInfo;
498 typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo;
500 /// The LLVM::CallingConv to use for this function (as specified by the
502 unsigned CallingConvention : 8;
504 /// The LLVM::CallingConv to actually use for this function, which may
505 /// depend on the ABI.
506 unsigned EffectiveCallingConvention : 8;
508 /// The clang::CallingConv that this was originally created with.
509 unsigned ASTCallingConvention : 6;
511 /// Whether this is an instance method.
512 unsigned InstanceMethod : 1;
514 /// Whether this is a chain call.
515 unsigned ChainCall : 1;
517 /// Whether this function is noreturn.
518 unsigned NoReturn : 1;
520 /// Whether this function is returns-retained.
521 unsigned ReturnsRetained : 1;
523 /// Whether this function saved caller registers.
524 unsigned NoCallerSavedRegs : 1;
526 /// How many arguments to pass inreg.
527 unsigned HasRegParm : 1;
528 unsigned RegParm : 3;
530 /// Whether this function has nocf_check attribute.
531 unsigned NoCfCheck : 1;
533 RequiredArgs Required;
535 /// The struct representing all arguments passed in memory. Only used when
536 /// passing non-trivial types with inalloca. Not part of the profile.
537 llvm::StructType *ArgStruct;
538 unsigned ArgStructAlign : 31;
539 unsigned HasExtParameterInfos : 1;
543 ArgInfo *getArgsBuffer() {
544 return getTrailingObjects<ArgInfo>();
546 const ArgInfo *getArgsBuffer() const {
547 return getTrailingObjects<ArgInfo>();
550 ExtParameterInfo *getExtParameterInfosBuffer() {
551 return getTrailingObjects<ExtParameterInfo>();
553 const ExtParameterInfo *getExtParameterInfosBuffer() const{
554 return getTrailingObjects<ExtParameterInfo>();
557 CGFunctionInfo() : Required(RequiredArgs::All) {}
560 static CGFunctionInfo *create(unsigned llvmCC,
563 const FunctionType::ExtInfo &extInfo,
564 ArrayRef<ExtParameterInfo> paramInfos,
565 CanQualType resultType,
566 ArrayRef<CanQualType> argTypes,
567 RequiredArgs required);
568 void operator delete(void *p) { ::operator delete(p); }
570 // Friending class TrailingObjects is apparently not good enough for MSVC,
571 // so these have to be public.
572 friend class TrailingObjects;
573 size_t numTrailingObjects(OverloadToken<ArgInfo>) const {
576 size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
577 return (HasExtParameterInfos ? NumArgs : 0);
580 typedef const ArgInfo *const_arg_iterator;
581 typedef ArgInfo *arg_iterator;
583 typedef llvm::iterator_range<arg_iterator> arg_range;
584 typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
586 arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
587 arg_const_range arguments() const {
588 return arg_const_range(arg_begin(), arg_end());
591 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
592 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
593 arg_iterator arg_begin() { return getArgsBuffer() + 1; }
594 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
596 unsigned arg_size() const { return NumArgs; }
598 bool isVariadic() const { return Required.allowsOptionalArgs(); }
599 RequiredArgs getRequiredArgs() const { return Required; }
600 unsigned getNumRequiredArgs() const {
601 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
604 bool isInstanceMethod() const { return InstanceMethod; }
606 bool isChainCall() const { return ChainCall; }
608 bool isNoReturn() const { return NoReturn; }
610 /// In ARC, whether this function retains its return value. This
611 /// is not always reliable for call sites.
612 bool isReturnsRetained() const { return ReturnsRetained; }
614 /// Whether this function no longer saves caller registers.
615 bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }
617 /// Whether this function has nocf_check attribute.
618 bool isNoCfCheck() const { return NoCfCheck; }
620 /// getASTCallingConvention() - Return the AST-specified calling
622 CallingConv getASTCallingConvention() const {
623 return CallingConv(ASTCallingConvention);
626 /// getCallingConvention - Return the user specified calling
627 /// convention, which has been translated into an LLVM CC.
628 unsigned getCallingConvention() const { return CallingConvention; }
630 /// getEffectiveCallingConvention - Return the actual calling convention to
631 /// use, which may depend on the ABI.
632 unsigned getEffectiveCallingConvention() const {
633 return EffectiveCallingConvention;
635 void setEffectiveCallingConvention(unsigned Value) {
636 EffectiveCallingConvention = Value;
639 bool getHasRegParm() const { return HasRegParm; }
640 unsigned getRegParm() const { return RegParm; }
642 FunctionType::ExtInfo getExtInfo() const {
643 return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
644 getASTCallingConvention(), isReturnsRetained(),
645 isNoCallerSavedRegs(), isNoCfCheck());
648 CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
650 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
651 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
653 ArrayRef<ExtParameterInfo> getExtParameterInfos() const {
654 if (!HasExtParameterInfos) return {};
655 return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs);
657 ExtParameterInfo getExtParameterInfo(unsigned argIndex) const {
658 assert(argIndex <= NumArgs);
659 if (!HasExtParameterInfos) return ExtParameterInfo();
660 return getExtParameterInfos()[argIndex];
663 /// Return true if this function uses inalloca arguments.
664 bool usesInAlloca() const { return ArgStruct; }
666 /// Get the struct type used to represent all the arguments in memory.
667 llvm::StructType *getArgStruct() const { return ArgStruct; }
668 CharUnits getArgStructAlignment() const {
669 return CharUnits::fromQuantity(ArgStructAlign);
671 void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
673 ArgStructAlign = Align.getQuantity();
676 void Profile(llvm::FoldingSetNodeID &ID) {
677 ID.AddInteger(getASTCallingConvention());
678 ID.AddBoolean(InstanceMethod);
679 ID.AddBoolean(ChainCall);
680 ID.AddBoolean(NoReturn);
681 ID.AddBoolean(ReturnsRetained);
682 ID.AddBoolean(NoCallerSavedRegs);
683 ID.AddBoolean(HasRegParm);
684 ID.AddInteger(RegParm);
685 ID.AddBoolean(NoCfCheck);
686 ID.AddInteger(Required.getOpaqueData());
687 ID.AddBoolean(HasExtParameterInfos);
688 if (HasExtParameterInfos) {
689 for (auto paramInfo : getExtParameterInfos())
690 ID.AddInteger(paramInfo.getOpaqueValue());
692 getReturnType().Profile(ID);
693 for (const auto &I : arguments())
696 static void Profile(llvm::FoldingSetNodeID &ID,
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.AddInteger(required.getOpaqueData());
714 ID.AddBoolean(!paramInfos.empty());
715 if (!paramInfos.empty()) {
716 for (auto paramInfo : paramInfos)
717 ID.AddInteger(paramInfo.getOpaqueValue());
719 resultType.Profile(ID);
720 for (ArrayRef<CanQualType>::iterator
721 i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
727 } // end namespace CodeGen
728 } // end namespace clang