1 //==-- CGFunctionInfo.h - Representation of function argument/return types -==//
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
7 //===----------------------------------------------------------------------===//
9 // Defines CGFunctionInfo and associated types used in representing the
10 // LLVM source types and ABI-coerced types for function arguments and
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
16 #define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
18 #include "clang/AST/Attr.h"
19 #include "clang/AST/CanonicalType.h"
20 #include "clang/AST/CharUnits.h"
21 #include "clang/AST/Decl.h"
22 #include "clang/AST/Type.h"
23 #include "llvm/IR/DerivedTypes.h"
24 #include "llvm/ADT/FoldingSet.h"
25 #include "llvm/Support/TrailingObjects.h"
31 /// ABIArgInfo - Helper class to encapsulate information about how a
32 /// specific C type should be passed to or returned from a function.
36 /// Direct - Pass the argument directly using the normal converted LLVM
37 /// type, or by coercing to another specified type stored in
38 /// 'CoerceToType'). If an offset is specified (in UIntData), then the
39 /// argument passed is offset by some number of bytes in the memory
40 /// representation. A dummy argument is emitted before the real argument
41 /// if the specified type stored in "PaddingType" is not zero.
44 /// Extend - Valid only for integer argument types. Same as 'direct'
45 /// but also emit a zero/sign extension attribute.
48 /// Indirect - Pass the argument indirectly via a hidden pointer
49 /// with the specified alignment (0 indicates default alignment).
52 /// Ignore - Ignore the argument (treat as void). Useful for void and
56 /// Expand - Only valid for aggregate argument types. The structure should
57 /// be expanded into consecutive arguments for its constituent fields.
58 /// Currently expand is only allowed on structures whose fields
59 /// are all scalar types or are themselves expandable types.
62 /// CoerceAndExpand - Only valid for aggregate argument types. The
63 /// structure should be expanded into consecutive arguments corresponding
64 /// to the non-array elements of the type stored in CoerceToType.
65 /// Array elements in the type are assumed to be padding and skipped.
68 /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
69 /// This is similar to indirect with byval, except it only applies to
70 /// arguments stored in memory and forbids any implicit copies. When
71 /// applied to a return type, it means the value is returned indirectly via
72 /// an implicit sret parameter stored in the argument struct.
79 llvm::Type *TypeData; // canHaveCoerceToType()
81 llvm::Type *PaddingType; // canHavePaddingType()
82 llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand()
85 unsigned DirectOffset; // isDirect() || isExtend()
86 unsigned IndirectAlign; // isIndirect()
87 unsigned AllocaFieldIndex; // isInAlloca()
90 bool PaddingInReg : 1;
91 bool InAllocaSRet : 1; // isInAlloca()
92 bool IndirectByVal : 1; // isIndirect()
93 bool IndirectRealign : 1; // isIndirect()
94 bool SRetAfterThis : 1; // isIndirect()
95 bool InReg : 1; // isDirect() || isExtend() || isIndirect()
96 bool CanBeFlattened: 1; // isDirect()
97 bool SignExt : 1; // isExtend()
99 bool canHavePaddingType() const {
100 return isDirect() || isExtend() || isIndirect() || isExpand();
102 void setPaddingType(llvm::Type *T) {
103 assert(canHavePaddingType());
107 void setUnpaddedCoerceToType(llvm::Type *T) {
108 assert(isCoerceAndExpand());
109 UnpaddedCoerceAndExpandType = T;
113 : TheKind(K), PaddingInReg(false), InReg(false) {
118 : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
119 TheKind(Direct), PaddingInReg(false), InReg(false) {}
121 static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
122 llvm::Type *Padding = nullptr,
123 bool CanBeFlattened = true) {
124 auto AI = ABIArgInfo(Direct);
125 AI.setCoerceToType(T);
126 AI.setPaddingType(Padding);
127 AI.setDirectOffset(Offset);
128 AI.setCanBeFlattened(CanBeFlattened);
131 static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
132 auto AI = getDirect(T);
137 static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) {
138 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
139 auto AI = ABIArgInfo(Extend);
140 AI.setCoerceToType(T);
141 AI.setPaddingType(nullptr);
142 AI.setDirectOffset(0);
147 static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) {
148 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
149 auto AI = ABIArgInfo(Extend);
150 AI.setCoerceToType(T);
151 AI.setPaddingType(nullptr);
152 AI.setDirectOffset(0);
153 AI.setSignExt(false);
157 // ABIArgInfo will record the argument as being extended based on the sign
159 static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
160 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
161 if (Ty->hasSignedIntegerRepresentation())
162 return getSignExtend(Ty, T);
163 return getZeroExtend(Ty, T);
166 static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
167 auto AI = getExtend(Ty, T);
171 static ABIArgInfo getIgnore() {
172 return ABIArgInfo(Ignore);
174 static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
175 bool Realign = false,
176 llvm::Type *Padding = nullptr) {
177 auto AI = ABIArgInfo(Indirect);
178 AI.setIndirectAlign(Alignment);
179 AI.setIndirectByVal(ByVal);
180 AI.setIndirectRealign(Realign);
181 AI.setSRetAfterThis(false);
182 AI.setPaddingType(Padding);
185 static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
186 bool Realign = false) {
187 auto AI = getIndirect(Alignment, ByVal, Realign);
191 static ABIArgInfo getInAlloca(unsigned FieldIndex) {
192 auto AI = ABIArgInfo(InAlloca);
193 AI.setInAllocaFieldIndex(FieldIndex);
196 static ABIArgInfo getExpand() {
197 auto AI = ABIArgInfo(Expand);
198 AI.setPaddingType(nullptr);
201 static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
202 llvm::Type *Padding) {
203 auto AI = getExpand();
204 AI.setPaddingInReg(PaddingInReg);
205 AI.setPaddingType(Padding);
209 /// \param unpaddedCoerceToType The coerce-to type with padding elements
210 /// removed, canonicalized to a single element if it would otherwise
211 /// have exactly one element.
212 static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
213 llvm::Type *unpaddedCoerceToType) {
215 // Sanity checks on unpaddedCoerceToType.
217 // Assert that we only have a struct type if there are multiple elements.
218 auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType);
219 assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1);
221 // Assert that all the non-padding elements have a corresponding element
222 // in the unpadded type.
223 unsigned unpaddedIndex = 0;
224 for (auto eltType : coerceToType->elements()) {
225 if (isPaddingForCoerceAndExpand(eltType)) continue;
226 if (unpaddedStruct) {
227 assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType);
229 assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType);
234 // Assert that there aren't extra elements in the unpadded type.
235 if (unpaddedStruct) {
236 assert(unpaddedStruct->getNumElements() == unpaddedIndex);
238 assert(unpaddedIndex == 1);
242 auto AI = ABIArgInfo(CoerceAndExpand);
243 AI.setCoerceToType(coerceToType);
244 AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
248 static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
249 if (eltType->isArrayTy()) {
250 assert(eltType->getArrayElementType()->isIntegerTy(8));
257 Kind getKind() const { return TheKind; }
258 bool isDirect() const { return TheKind == Direct; }
259 bool isInAlloca() const { return TheKind == InAlloca; }
260 bool isExtend() const { return TheKind == Extend; }
261 bool isIgnore() const { return TheKind == Ignore; }
262 bool isIndirect() const { return TheKind == Indirect; }
263 bool isExpand() const { return TheKind == Expand; }
264 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
266 bool canHaveCoerceToType() const {
267 return isDirect() || isExtend() || isCoerceAndExpand();
270 // Direct/Extend accessors
271 unsigned getDirectOffset() const {
272 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
275 void setDirectOffset(unsigned Offset) {
276 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
277 DirectOffset = Offset;
280 bool isSignExt() const {
281 assert(isExtend() && "Invalid kind!");
284 void setSignExt(bool SExt) {
285 assert(isExtend() && "Invalid kind!");
289 llvm::Type *getPaddingType() const {
290 return (canHavePaddingType() ? PaddingType : nullptr);
293 bool getPaddingInReg() const {
296 void setPaddingInReg(bool PIR) {
300 llvm::Type *getCoerceToType() const {
301 assert(canHaveCoerceToType() && "Invalid kind!");
305 void setCoerceToType(llvm::Type *T) {
306 assert(canHaveCoerceToType() && "Invalid kind!");
310 llvm::StructType *getCoerceAndExpandType() const {
311 assert(isCoerceAndExpand());
312 return cast<llvm::StructType>(TypeData);
315 llvm::Type *getUnpaddedCoerceAndExpandType() const {
316 assert(isCoerceAndExpand());
317 return UnpaddedCoerceAndExpandType;
320 ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const {
321 assert(isCoerceAndExpand());
323 dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) {
324 return structTy->elements();
326 return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1);
330 bool getInReg() const {
331 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
335 void setInReg(bool IR) {
336 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
340 // Indirect accessors
341 CharUnits getIndirectAlign() const {
342 assert(isIndirect() && "Invalid kind!");
343 return CharUnits::fromQuantity(IndirectAlign);
345 void setIndirectAlign(CharUnits IA) {
346 assert(isIndirect() && "Invalid kind!");
347 IndirectAlign = IA.getQuantity();
350 bool getIndirectByVal() const {
351 assert(isIndirect() && "Invalid kind!");
352 return IndirectByVal;
354 void setIndirectByVal(bool IBV) {
355 assert(isIndirect() && "Invalid kind!");
359 bool getIndirectRealign() const {
360 assert(isIndirect() && "Invalid kind!");
361 return IndirectRealign;
363 void setIndirectRealign(bool IR) {
364 assert(isIndirect() && "Invalid kind!");
365 IndirectRealign = IR;
368 bool isSRetAfterThis() const {
369 assert(isIndirect() && "Invalid kind!");
370 return SRetAfterThis;
372 void setSRetAfterThis(bool AfterThis) {
373 assert(isIndirect() && "Invalid kind!");
374 SRetAfterThis = AfterThis;
377 unsigned getInAllocaFieldIndex() const {
378 assert(isInAlloca() && "Invalid kind!");
379 return AllocaFieldIndex;
381 void setInAllocaFieldIndex(unsigned FieldIndex) {
382 assert(isInAlloca() && "Invalid kind!");
383 AllocaFieldIndex = FieldIndex;
386 /// Return true if this field of an inalloca struct should be returned
387 /// to implement a struct return calling convention.
388 bool getInAllocaSRet() const {
389 assert(isInAlloca() && "Invalid kind!");
393 void setInAllocaSRet(bool SRet) {
394 assert(isInAlloca() && "Invalid kind!");
398 bool getCanBeFlattened() const {
399 assert(isDirect() && "Invalid kind!");
400 return CanBeFlattened;
403 void setCanBeFlattened(bool Flatten) {
404 assert(isDirect() && "Invalid kind!");
405 CanBeFlattened = Flatten;
411 /// A class for recording the number of arguments that a function
412 /// signature requires.
414 /// The number of required arguments, or ~0 if the signature does
415 /// not permit optional arguments.
416 unsigned NumRequired;
420 RequiredArgs(All_t _) : NumRequired(~0U) {}
421 explicit RequiredArgs(unsigned n) : NumRequired(n) {
425 /// Compute the arguments required by the given formal prototype,
426 /// given that there may be some additional, non-formal arguments
429 /// If FD is not null, this will consider pass_object_size params in FD.
430 static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
431 unsigned additional) {
432 if (!prototype->isVariadic()) return All;
434 if (prototype->hasExtParameterInfos())
435 additional += llvm::count_if(
436 prototype->getExtParameterInfos(),
437 [](const FunctionProtoType::ExtParameterInfo &ExtInfo) {
438 return ExtInfo.hasPassObjectSize();
441 return RequiredArgs(prototype->getNumParams() + additional);
444 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
445 unsigned additional) {
446 return forPrototypePlus(prototype.getTypePtr(), additional);
449 static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
450 return forPrototypePlus(prototype, 0);
453 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
454 return forPrototypePlus(prototype.getTypePtr(), 0);
457 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
458 unsigned getNumRequiredArgs() const {
459 assert(allowsOptionalArgs());
463 unsigned getOpaqueData() const { return NumRequired; }
464 static RequiredArgs getFromOpaqueData(unsigned value) {
465 if (value == ~0U) return All;
466 return RequiredArgs(value);
470 // Implementation detail of CGFunctionInfo, factored out so it can be named
471 // in the TrailingObjects base class of CGFunctionInfo.
472 struct CGFunctionInfoArgInfo {
477 /// CGFunctionInfo - Class to encapsulate the information about a
478 /// function definition.
479 class CGFunctionInfo final
480 : public llvm::FoldingSetNode,
481 private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo,
482 FunctionProtoType::ExtParameterInfo> {
483 typedef CGFunctionInfoArgInfo ArgInfo;
484 typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo;
486 /// The LLVM::CallingConv to use for this function (as specified by the
488 unsigned CallingConvention : 8;
490 /// The LLVM::CallingConv to actually use for this function, which may
491 /// depend on the ABI.
492 unsigned EffectiveCallingConvention : 8;
494 /// The clang::CallingConv that this was originally created with.
495 unsigned ASTCallingConvention : 6;
497 /// Whether this is an instance method.
498 unsigned InstanceMethod : 1;
500 /// Whether this is a chain call.
501 unsigned ChainCall : 1;
503 /// Whether this function is noreturn.
504 unsigned NoReturn : 1;
506 /// Whether this function is returns-retained.
507 unsigned ReturnsRetained : 1;
509 /// Whether this function saved caller registers.
510 unsigned NoCallerSavedRegs : 1;
512 /// How many arguments to pass inreg.
513 unsigned HasRegParm : 1;
514 unsigned RegParm : 3;
516 /// Whether this function has nocf_check attribute.
517 unsigned NoCfCheck : 1;
519 RequiredArgs Required;
521 /// The struct representing all arguments passed in memory. Only used when
522 /// passing non-trivial types with inalloca. Not part of the profile.
523 llvm::StructType *ArgStruct;
524 unsigned ArgStructAlign : 31;
525 unsigned HasExtParameterInfos : 1;
529 ArgInfo *getArgsBuffer() {
530 return getTrailingObjects<ArgInfo>();
532 const ArgInfo *getArgsBuffer() const {
533 return getTrailingObjects<ArgInfo>();
536 ExtParameterInfo *getExtParameterInfosBuffer() {
537 return getTrailingObjects<ExtParameterInfo>();
539 const ExtParameterInfo *getExtParameterInfosBuffer() const{
540 return getTrailingObjects<ExtParameterInfo>();
543 CGFunctionInfo() : Required(RequiredArgs::All) {}
546 static CGFunctionInfo *create(unsigned llvmCC,
549 const FunctionType::ExtInfo &extInfo,
550 ArrayRef<ExtParameterInfo> paramInfos,
551 CanQualType resultType,
552 ArrayRef<CanQualType> argTypes,
553 RequiredArgs required);
554 void operator delete(void *p) { ::operator delete(p); }
556 // Friending class TrailingObjects is apparently not good enough for MSVC,
557 // so these have to be public.
558 friend class TrailingObjects;
559 size_t numTrailingObjects(OverloadToken<ArgInfo>) const {
562 size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
563 return (HasExtParameterInfos ? NumArgs : 0);
566 typedef const ArgInfo *const_arg_iterator;
567 typedef ArgInfo *arg_iterator;
569 typedef llvm::iterator_range<arg_iterator> arg_range;
570 typedef llvm::iterator_range<const_arg_iterator> const_arg_range;
572 arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
573 const_arg_range arguments() const {
574 return const_arg_range(arg_begin(), arg_end());
577 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
578 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
579 arg_iterator arg_begin() { return getArgsBuffer() + 1; }
580 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
582 unsigned arg_size() const { return NumArgs; }
584 bool isVariadic() const { return Required.allowsOptionalArgs(); }
585 RequiredArgs getRequiredArgs() const { return Required; }
586 unsigned getNumRequiredArgs() const {
587 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
590 bool isInstanceMethod() const { return InstanceMethod; }
592 bool isChainCall() const { return ChainCall; }
594 bool isNoReturn() const { return NoReturn; }
596 /// In ARC, whether this function retains its return value. This
597 /// is not always reliable for call sites.
598 bool isReturnsRetained() const { return ReturnsRetained; }
600 /// Whether this function no longer saves caller registers.
601 bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }
603 /// Whether this function has nocf_check attribute.
604 bool isNoCfCheck() const { return NoCfCheck; }
606 /// getASTCallingConvention() - Return the AST-specified calling
608 CallingConv getASTCallingConvention() const {
609 return CallingConv(ASTCallingConvention);
612 /// getCallingConvention - Return the user specified calling
613 /// convention, which has been translated into an LLVM CC.
614 unsigned getCallingConvention() const { return CallingConvention; }
616 /// getEffectiveCallingConvention - Return the actual calling convention to
617 /// use, which may depend on the ABI.
618 unsigned getEffectiveCallingConvention() const {
619 return EffectiveCallingConvention;
621 void setEffectiveCallingConvention(unsigned Value) {
622 EffectiveCallingConvention = Value;
625 bool getHasRegParm() const { return HasRegParm; }
626 unsigned getRegParm() const { return RegParm; }
628 FunctionType::ExtInfo getExtInfo() const {
629 return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
630 getASTCallingConvention(), isReturnsRetained(),
631 isNoCallerSavedRegs(), isNoCfCheck());
634 CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
636 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
637 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
639 ArrayRef<ExtParameterInfo> getExtParameterInfos() const {
640 if (!HasExtParameterInfos) return {};
641 return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs);
643 ExtParameterInfo getExtParameterInfo(unsigned argIndex) const {
644 assert(argIndex <= NumArgs);
645 if (!HasExtParameterInfos) return ExtParameterInfo();
646 return getExtParameterInfos()[argIndex];
649 /// Return true if this function uses inalloca arguments.
650 bool usesInAlloca() const { return ArgStruct; }
652 /// Get the struct type used to represent all the arguments in memory.
653 llvm::StructType *getArgStruct() const { return ArgStruct; }
654 CharUnits getArgStructAlignment() const {
655 return CharUnits::fromQuantity(ArgStructAlign);
657 void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
659 ArgStructAlign = Align.getQuantity();
662 void Profile(llvm::FoldingSetNodeID &ID) {
663 ID.AddInteger(getASTCallingConvention());
664 ID.AddBoolean(InstanceMethod);
665 ID.AddBoolean(ChainCall);
666 ID.AddBoolean(NoReturn);
667 ID.AddBoolean(ReturnsRetained);
668 ID.AddBoolean(NoCallerSavedRegs);
669 ID.AddBoolean(HasRegParm);
670 ID.AddInteger(RegParm);
671 ID.AddBoolean(NoCfCheck);
672 ID.AddInteger(Required.getOpaqueData());
673 ID.AddBoolean(HasExtParameterInfos);
674 if (HasExtParameterInfos) {
675 for (auto paramInfo : getExtParameterInfos())
676 ID.AddInteger(paramInfo.getOpaqueValue());
678 getReturnType().Profile(ID);
679 for (const auto &I : arguments())
682 static void Profile(llvm::FoldingSetNodeID &ID,
685 const FunctionType::ExtInfo &info,
686 ArrayRef<ExtParameterInfo> paramInfos,
687 RequiredArgs required,
688 CanQualType resultType,
689 ArrayRef<CanQualType> argTypes) {
690 ID.AddInteger(info.getCC());
691 ID.AddBoolean(InstanceMethod);
692 ID.AddBoolean(ChainCall);
693 ID.AddBoolean(info.getNoReturn());
694 ID.AddBoolean(info.getProducesResult());
695 ID.AddBoolean(info.getNoCallerSavedRegs());
696 ID.AddBoolean(info.getHasRegParm());
697 ID.AddInteger(info.getRegParm());
698 ID.AddBoolean(info.getNoCfCheck());
699 ID.AddInteger(required.getOpaqueData());
700 ID.AddBoolean(!paramInfos.empty());
701 if (!paramInfos.empty()) {
702 for (auto paramInfo : paramInfos)
703 ID.AddInteger(paramInfo.getOpaqueValue());
705 resultType.Profile(ID);
706 for (ArrayRef<CanQualType>::iterator
707 i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
713 } // end namespace CodeGen
714 } // end namespace clang