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()
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);
136 static ABIArgInfo getExtend(llvm::Type *T = nullptr) {
137 auto AI = ABIArgInfo(Extend);
138 AI.setCoerceToType(T);
139 AI.setPaddingType(nullptr);
140 AI.setDirectOffset(0);
143 static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) {
144 auto AI = getExtend(T);
148 static ABIArgInfo getIgnore() {
149 return ABIArgInfo(Ignore);
151 static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
152 bool Realign = false,
153 llvm::Type *Padding = nullptr) {
154 auto AI = ABIArgInfo(Indirect);
155 AI.setIndirectAlign(Alignment);
156 AI.setIndirectByVal(ByVal);
157 AI.setIndirectRealign(Realign);
158 AI.setSRetAfterThis(false);
159 AI.setPaddingType(Padding);
162 static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
163 bool Realign = false) {
164 auto AI = getIndirect(Alignment, ByVal, Realign);
168 static ABIArgInfo getInAlloca(unsigned FieldIndex) {
169 auto AI = ABIArgInfo(InAlloca);
170 AI.setInAllocaFieldIndex(FieldIndex);
173 static ABIArgInfo getExpand() {
174 auto AI = ABIArgInfo(Expand);
175 AI.setPaddingType(nullptr);
178 static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
179 llvm::Type *Padding) {
180 auto AI = getExpand();
181 AI.setPaddingInReg(PaddingInReg);
182 AI.setPaddingType(Padding);
186 /// \param unpaddedCoerceToType The coerce-to type with padding elements
187 /// removed, canonicalized to a single element if it would otherwise
188 /// have exactly one element.
189 static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
190 llvm::Type *unpaddedCoerceToType) {
192 // Sanity checks on unpaddedCoerceToType.
194 // Assert that we only have a struct type if there are multiple elements.
195 auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType);
196 assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1);
198 // Assert that all the non-padding elements have a corresponding element
199 // in the unpadded type.
200 unsigned unpaddedIndex = 0;
201 for (auto eltType : coerceToType->elements()) {
202 if (isPaddingForCoerceAndExpand(eltType)) continue;
203 if (unpaddedStruct) {
204 assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType);
206 assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType);
211 // Assert that there aren't extra elements in the unpadded type.
212 if (unpaddedStruct) {
213 assert(unpaddedStruct->getNumElements() == unpaddedIndex);
215 assert(unpaddedIndex == 1);
219 auto AI = ABIArgInfo(CoerceAndExpand);
220 AI.setCoerceToType(coerceToType);
221 AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
225 static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
226 if (eltType->isArrayTy()) {
227 assert(eltType->getArrayElementType()->isIntegerTy(8));
234 Kind getKind() const { return TheKind; }
235 bool isDirect() const { return TheKind == Direct; }
236 bool isInAlloca() const { return TheKind == InAlloca; }
237 bool isExtend() const { return TheKind == Extend; }
238 bool isIgnore() const { return TheKind == Ignore; }
239 bool isIndirect() const { return TheKind == Indirect; }
240 bool isExpand() const { return TheKind == Expand; }
241 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
243 bool canHaveCoerceToType() const {
244 return isDirect() || isExtend() || isCoerceAndExpand();
247 // Direct/Extend accessors
248 unsigned getDirectOffset() const {
249 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
252 void setDirectOffset(unsigned Offset) {
253 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
254 DirectOffset = Offset;
257 llvm::Type *getPaddingType() const {
258 return (canHavePaddingType() ? PaddingType : nullptr);
261 bool getPaddingInReg() const {
264 void setPaddingInReg(bool PIR) {
268 llvm::Type *getCoerceToType() const {
269 assert(canHaveCoerceToType() && "Invalid kind!");
273 void setCoerceToType(llvm::Type *T) {
274 assert(canHaveCoerceToType() && "Invalid kind!");
278 llvm::StructType *getCoerceAndExpandType() const {
279 assert(isCoerceAndExpand());
280 return cast<llvm::StructType>(TypeData);
283 llvm::Type *getUnpaddedCoerceAndExpandType() const {
284 assert(isCoerceAndExpand());
285 return UnpaddedCoerceAndExpandType;
288 ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const {
289 assert(isCoerceAndExpand());
291 dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) {
292 return structTy->elements();
294 return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1);
298 bool getInReg() const {
299 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
303 void setInReg(bool IR) {
304 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
308 // Indirect accessors
309 CharUnits getIndirectAlign() const {
310 assert(isIndirect() && "Invalid kind!");
311 return CharUnits::fromQuantity(IndirectAlign);
313 void setIndirectAlign(CharUnits IA) {
314 assert(isIndirect() && "Invalid kind!");
315 IndirectAlign = IA.getQuantity();
318 bool getIndirectByVal() const {
319 assert(isIndirect() && "Invalid kind!");
320 return IndirectByVal;
322 void setIndirectByVal(bool IBV) {
323 assert(isIndirect() && "Invalid kind!");
327 bool getIndirectRealign() const {
328 assert(isIndirect() && "Invalid kind!");
329 return IndirectRealign;
331 void setIndirectRealign(bool IR) {
332 assert(isIndirect() && "Invalid kind!");
333 IndirectRealign = IR;
336 bool isSRetAfterThis() const {
337 assert(isIndirect() && "Invalid kind!");
338 return SRetAfterThis;
340 void setSRetAfterThis(bool AfterThis) {
341 assert(isIndirect() && "Invalid kind!");
342 SRetAfterThis = AfterThis;
345 unsigned getInAllocaFieldIndex() const {
346 assert(isInAlloca() && "Invalid kind!");
347 return AllocaFieldIndex;
349 void setInAllocaFieldIndex(unsigned FieldIndex) {
350 assert(isInAlloca() && "Invalid kind!");
351 AllocaFieldIndex = FieldIndex;
354 /// \brief Return true if this field of an inalloca struct should be returned
355 /// to implement a struct return calling convention.
356 bool getInAllocaSRet() const {
357 assert(isInAlloca() && "Invalid kind!");
361 void setInAllocaSRet(bool SRet) {
362 assert(isInAlloca() && "Invalid kind!");
366 bool getCanBeFlattened() const {
367 assert(isDirect() && "Invalid kind!");
368 return CanBeFlattened;
371 void setCanBeFlattened(bool Flatten) {
372 assert(isDirect() && "Invalid kind!");
373 CanBeFlattened = Flatten;
379 /// A class for recording the number of arguments that a function
380 /// signature requires.
382 /// The number of required arguments, or ~0 if the signature does
383 /// not permit optional arguments.
384 unsigned NumRequired;
388 RequiredArgs(All_t _) : NumRequired(~0U) {}
389 explicit RequiredArgs(unsigned n) : NumRequired(n) {
393 /// Compute the arguments required by the given formal prototype,
394 /// given that there may be some additional, non-formal arguments
397 /// If FD is not null, this will consider pass_object_size params in FD.
398 static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
400 const FunctionDecl *FD) {
401 if (!prototype->isVariadic()) return All;
404 llvm::count_if(FD->parameters(), [](const ParmVarDecl *PVD) {
405 return PVD->hasAttr<PassObjectSizeAttr>();
407 return RequiredArgs(prototype->getNumParams() + additional);
410 static RequiredArgs forPrototype(const FunctionProtoType *prototype,
411 const FunctionDecl *FD) {
412 return forPrototypePlus(prototype, 0, FD);
415 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype,
416 const FunctionDecl *FD) {
417 return forPrototype(prototype.getTypePtr(), FD);
420 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
422 const FunctionDecl *FD) {
423 return forPrototypePlus(prototype.getTypePtr(), additional, FD);
426 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
427 unsigned getNumRequiredArgs() const {
428 assert(allowsOptionalArgs());
432 unsigned getOpaqueData() const { return NumRequired; }
433 static RequiredArgs getFromOpaqueData(unsigned value) {
434 if (value == ~0U) return All;
435 return RequiredArgs(value);
439 // Implementation detail of CGFunctionInfo, factored out so it can be named
440 // in the TrailingObjects base class of CGFunctionInfo.
441 struct CGFunctionInfoArgInfo {
446 /// CGFunctionInfo - Class to encapsulate the information about a
447 /// function definition.
448 class CGFunctionInfo final
449 : public llvm::FoldingSetNode,
450 private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo,
451 FunctionProtoType::ExtParameterInfo> {
452 typedef CGFunctionInfoArgInfo ArgInfo;
453 typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo;
455 /// The LLVM::CallingConv to use for this function (as specified by the
457 unsigned CallingConvention : 8;
459 /// The LLVM::CallingConv to actually use for this function, which may
460 /// depend on the ABI.
461 unsigned EffectiveCallingConvention : 8;
463 /// The clang::CallingConv that this was originally created with.
464 unsigned ASTCallingConvention : 8;
466 /// Whether this is an instance method.
467 unsigned InstanceMethod : 1;
469 /// Whether this is a chain call.
470 unsigned ChainCall : 1;
472 /// Whether this function is noreturn.
473 unsigned NoReturn : 1;
475 /// Whether this function is returns-retained.
476 unsigned ReturnsRetained : 1;
478 /// How many arguments to pass inreg.
479 unsigned HasRegParm : 1;
480 unsigned RegParm : 3;
482 RequiredArgs Required;
484 /// The struct representing all arguments passed in memory. Only used when
485 /// passing non-trivial types with inalloca. Not part of the profile.
486 llvm::StructType *ArgStruct;
487 unsigned ArgStructAlign : 31;
488 unsigned HasExtParameterInfos : 1;
492 ArgInfo *getArgsBuffer() {
493 return getTrailingObjects<ArgInfo>();
495 const ArgInfo *getArgsBuffer() const {
496 return getTrailingObjects<ArgInfo>();
499 ExtParameterInfo *getExtParameterInfosBuffer() {
500 return getTrailingObjects<ExtParameterInfo>();
502 const ExtParameterInfo *getExtParameterInfosBuffer() const{
503 return getTrailingObjects<ExtParameterInfo>();
506 CGFunctionInfo() : Required(RequiredArgs::All) {}
509 static CGFunctionInfo *create(unsigned llvmCC,
512 const FunctionType::ExtInfo &extInfo,
513 ArrayRef<ExtParameterInfo> paramInfos,
514 CanQualType resultType,
515 ArrayRef<CanQualType> argTypes,
516 RequiredArgs required);
517 void operator delete(void *p) { ::operator delete(p); }
519 // Friending class TrailingObjects is apparently not good enough for MSVC,
520 // so these have to be public.
521 friend class TrailingObjects;
522 size_t numTrailingObjects(OverloadToken<ArgInfo>) const {
525 size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
526 return (HasExtParameterInfos ? NumArgs : 0);
529 typedef const ArgInfo *const_arg_iterator;
530 typedef ArgInfo *arg_iterator;
532 typedef llvm::iterator_range<arg_iterator> arg_range;
533 typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
535 arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
536 arg_const_range arguments() const {
537 return arg_const_range(arg_begin(), arg_end());
540 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
541 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
542 arg_iterator arg_begin() { return getArgsBuffer() + 1; }
543 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
545 unsigned arg_size() const { return NumArgs; }
547 bool isVariadic() const { return Required.allowsOptionalArgs(); }
548 RequiredArgs getRequiredArgs() const { return Required; }
549 unsigned getNumRequiredArgs() const {
550 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
553 bool isInstanceMethod() const { return InstanceMethod; }
555 bool isChainCall() const { return ChainCall; }
557 bool isNoReturn() const { return NoReturn; }
559 /// In ARC, whether this function retains its return value. This
560 /// is not always reliable for call sites.
561 bool isReturnsRetained() const { return ReturnsRetained; }
563 /// getASTCallingConvention() - Return the AST-specified calling
565 CallingConv getASTCallingConvention() const {
566 return CallingConv(ASTCallingConvention);
569 /// getCallingConvention - Return the user specified calling
570 /// convention, which has been translated into an LLVM CC.
571 unsigned getCallingConvention() const { return CallingConvention; }
573 /// getEffectiveCallingConvention - Return the actual calling convention to
574 /// use, which may depend on the ABI.
575 unsigned getEffectiveCallingConvention() const {
576 return EffectiveCallingConvention;
578 void setEffectiveCallingConvention(unsigned Value) {
579 EffectiveCallingConvention = Value;
582 bool getHasRegParm() const { return HasRegParm; }
583 unsigned getRegParm() const { return RegParm; }
585 FunctionType::ExtInfo getExtInfo() const {
586 return FunctionType::ExtInfo(isNoReturn(),
587 getHasRegParm(), getRegParm(),
588 getASTCallingConvention(),
589 isReturnsRetained());
592 CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
594 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
595 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
597 ArrayRef<ExtParameterInfo> getExtParameterInfos() const {
598 if (!HasExtParameterInfos) return {};
599 return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs);
601 ExtParameterInfo getExtParameterInfo(unsigned argIndex) const {
602 assert(argIndex <= NumArgs);
603 if (!HasExtParameterInfos) return ExtParameterInfo();
604 return getExtParameterInfos()[argIndex];
607 /// \brief Return true if this function uses inalloca arguments.
608 bool usesInAlloca() const { return ArgStruct; }
610 /// \brief Get the struct type used to represent all the arguments in memory.
611 llvm::StructType *getArgStruct() const { return ArgStruct; }
612 CharUnits getArgStructAlignment() const {
613 return CharUnits::fromQuantity(ArgStructAlign);
615 void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
617 ArgStructAlign = Align.getQuantity();
620 void Profile(llvm::FoldingSetNodeID &ID) {
621 ID.AddInteger(getASTCallingConvention());
622 ID.AddBoolean(InstanceMethod);
623 ID.AddBoolean(ChainCall);
624 ID.AddBoolean(NoReturn);
625 ID.AddBoolean(ReturnsRetained);
626 ID.AddBoolean(HasRegParm);
627 ID.AddInteger(RegParm);
628 ID.AddInteger(Required.getOpaqueData());
629 ID.AddBoolean(HasExtParameterInfos);
630 if (HasExtParameterInfos) {
631 for (auto paramInfo : getExtParameterInfos())
632 ID.AddInteger(paramInfo.getOpaqueValue());
634 getReturnType().Profile(ID);
635 for (const auto &I : arguments())
638 static void Profile(llvm::FoldingSetNodeID &ID,
641 const FunctionType::ExtInfo &info,
642 ArrayRef<ExtParameterInfo> paramInfos,
643 RequiredArgs required,
644 CanQualType resultType,
645 ArrayRef<CanQualType> argTypes) {
646 ID.AddInteger(info.getCC());
647 ID.AddBoolean(InstanceMethod);
648 ID.AddBoolean(ChainCall);
649 ID.AddBoolean(info.getNoReturn());
650 ID.AddBoolean(info.getProducesResult());
651 ID.AddBoolean(info.getHasRegParm());
652 ID.AddInteger(info.getRegParm());
653 ID.AddInteger(required.getOpaqueData());
654 ID.AddBoolean(!paramInfos.empty());
655 if (!paramInfos.empty()) {
656 for (auto paramInfo : paramInfos)
657 ID.AddInteger(paramInfo.getOpaqueValue());
659 resultType.Profile(ID);
660 for (ArrayRef<CanQualType>::iterator
661 i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
667 } // end namespace CodeGen
668 } // end namespace clang