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/CanonicalType.h"
20 #include "clang/AST/Type.h"
21 #include "llvm/ADT/FoldingSet.h"
34 /// ABIArgInfo - Helper class to encapsulate information about how a
35 /// specific C type should be passed to or returned from a function.
39 /// Direct - Pass the argument directly using the normal converted LLVM
40 /// type, or by coercing to another specified type stored in
41 /// 'CoerceToType'). If an offset is specified (in UIntData), then the
42 /// argument passed is offset by some number of bytes in the memory
43 /// representation. A dummy argument is emitted before the real argument
44 /// if the specified type stored in "PaddingType" is not zero.
47 /// Extend - Valid only for integer argument types. Same as 'direct'
48 /// but also emit a zero/sign extension attribute.
51 /// Indirect - Pass the argument indirectly via a hidden pointer
52 /// with the specified alignment (0 indicates default alignment).
55 /// Ignore - Ignore the argument (treat as void). Useful for void and
59 /// Expand - Only valid for aggregate argument types. The structure should
60 /// be expanded into consecutive arguments for its constituent fields.
61 /// Currently expand is only allowed on structures whose fields
62 /// are all scalar types or are themselves expandable types.
65 /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
66 /// This is similar to 'direct', except it only applies to arguments stored
67 /// in memory and forbids any implicit copies. When applied to a return
68 /// type, it means the value is returned indirectly via an implicit sret
69 /// parameter stored in the argument struct.
76 llvm::Type *TypeData; // isDirect() || isExtend()
77 llvm::Type *PaddingType;
79 unsigned DirectOffset; // isDirect() || isExtend()
80 unsigned IndirectAlign; // isIndirect()
81 unsigned AllocaFieldIndex; // isInAlloca()
84 bool PaddingInReg : 1;
85 bool InAllocaSRet : 1; // isInAlloca()
86 bool IndirectByVal : 1; // isIndirect()
87 bool IndirectRealign : 1; // isIndirect()
88 bool SRetAfterThis : 1; // isIndirect()
89 bool InReg : 1; // isDirect() || isExtend() || isIndirect()
90 bool CanBeFlattened: 1; // isDirect()
93 : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {}
97 : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
98 TheKind(Direct), PaddingInReg(false), InReg(false) {}
100 static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
101 llvm::Type *Padding = nullptr,
102 bool CanBeFlattened = true) {
103 auto AI = ABIArgInfo(Direct);
104 AI.setCoerceToType(T);
105 AI.setDirectOffset(Offset);
106 AI.setPaddingType(Padding);
107 AI.setCanBeFlattened(CanBeFlattened);
110 static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
111 auto AI = getDirect(T);
115 static ABIArgInfo getExtend(llvm::Type *T = nullptr) {
116 auto AI = ABIArgInfo(Extend);
117 AI.setCoerceToType(T);
118 AI.setDirectOffset(0);
121 static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) {
122 auto AI = getExtend(T);
126 static ABIArgInfo getIgnore() {
127 return ABIArgInfo(Ignore);
129 static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true,
130 bool Realign = false,
131 llvm::Type *Padding = nullptr) {
132 auto AI = ABIArgInfo(Indirect);
133 AI.setIndirectAlign(Alignment);
134 AI.setIndirectByVal(ByVal);
135 AI.setIndirectRealign(Realign);
136 AI.setSRetAfterThis(false);
137 AI.setPaddingType(Padding);
140 static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true,
141 bool Realign = false) {
142 auto AI = getIndirect(Alignment, ByVal, Realign);
146 static ABIArgInfo getInAlloca(unsigned FieldIndex) {
147 auto AI = ABIArgInfo(InAlloca);
148 AI.setInAllocaFieldIndex(FieldIndex);
151 static ABIArgInfo getExpand() {
152 return ABIArgInfo(Expand);
154 static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
155 llvm::Type *Padding) {
156 auto AI = getExpand();
157 AI.setPaddingInReg(PaddingInReg);
158 AI.setPaddingType(Padding);
162 Kind getKind() const { return TheKind; }
163 bool isDirect() const { return TheKind == Direct; }
164 bool isInAlloca() const { return TheKind == InAlloca; }
165 bool isExtend() const { return TheKind == Extend; }
166 bool isIgnore() const { return TheKind == Ignore; }
167 bool isIndirect() const { return TheKind == Indirect; }
168 bool isExpand() const { return TheKind == Expand; }
170 bool canHaveCoerceToType() const { return isDirect() || isExtend(); }
172 // Direct/Extend accessors
173 unsigned getDirectOffset() const {
174 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
177 void setDirectOffset(unsigned Offset) {
178 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
179 DirectOffset = Offset;
182 llvm::Type *getPaddingType() const { return PaddingType; }
184 void setPaddingType(llvm::Type *T) { PaddingType = T; }
186 bool getPaddingInReg() const {
189 void setPaddingInReg(bool PIR) {
193 llvm::Type *getCoerceToType() const {
194 assert(canHaveCoerceToType() && "Invalid kind!");
198 void setCoerceToType(llvm::Type *T) {
199 assert(canHaveCoerceToType() && "Invalid kind!");
203 bool getInReg() const {
204 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
208 void setInReg(bool IR) {
209 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
213 // Indirect accessors
214 unsigned getIndirectAlign() const {
215 assert(isIndirect() && "Invalid kind!");
216 return IndirectAlign;
218 void setIndirectAlign(unsigned IA) {
219 assert(isIndirect() && "Invalid kind!");
223 bool getIndirectByVal() const {
224 assert(isIndirect() && "Invalid kind!");
225 return IndirectByVal;
227 void setIndirectByVal(unsigned IBV) {
228 assert(isIndirect() && "Invalid kind!");
232 bool getIndirectRealign() const {
233 assert(isIndirect() && "Invalid kind!");
234 return IndirectRealign;
236 void setIndirectRealign(bool IR) {
237 assert(isIndirect() && "Invalid kind!");
238 IndirectRealign = IR;
241 bool isSRetAfterThis() const {
242 assert(isIndirect() && "Invalid kind!");
243 return SRetAfterThis;
245 void setSRetAfterThis(bool AfterThis) {
246 assert(isIndirect() && "Invalid kind!");
247 SRetAfterThis = AfterThis;
250 unsigned getInAllocaFieldIndex() const {
251 assert(isInAlloca() && "Invalid kind!");
252 return AllocaFieldIndex;
254 void setInAllocaFieldIndex(unsigned FieldIndex) {
255 assert(isInAlloca() && "Invalid kind!");
256 AllocaFieldIndex = FieldIndex;
259 /// \brief Return true if this field of an inalloca struct should be returned
260 /// to implement a struct return calling convention.
261 bool getInAllocaSRet() const {
262 assert(isInAlloca() && "Invalid kind!");
266 void setInAllocaSRet(bool SRet) {
267 assert(isInAlloca() && "Invalid kind!");
271 bool getCanBeFlattened() const {
272 assert(isDirect() && "Invalid kind!");
273 return CanBeFlattened;
276 void setCanBeFlattened(bool Flatten) {
277 assert(isDirect() && "Invalid kind!");
278 CanBeFlattened = Flatten;
284 /// A class for recording the number of arguments that a function
285 /// signature requires.
287 /// The number of required arguments, or ~0 if the signature does
288 /// not permit optional arguments.
289 unsigned NumRequired;
293 RequiredArgs(All_t _) : NumRequired(~0U) {}
294 explicit RequiredArgs(unsigned n) : NumRequired(n) {
298 /// Compute the arguments required by the given formal prototype,
299 /// given that there may be some additional, non-formal arguments
301 static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
302 unsigned additional) {
303 if (!prototype->isVariadic()) return All;
304 return RequiredArgs(prototype->getNumParams() + additional);
307 static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
308 return forPrototypePlus(prototype, 0);
311 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
312 return forPrototype(prototype.getTypePtr());
315 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
316 unsigned additional) {
317 return forPrototypePlus(prototype.getTypePtr(), additional);
320 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
321 unsigned getNumRequiredArgs() const {
322 assert(allowsOptionalArgs());
326 unsigned getOpaqueData() const { return NumRequired; }
327 static RequiredArgs getFromOpaqueData(unsigned value) {
328 if (value == ~0U) return All;
329 return RequiredArgs(value);
333 /// CGFunctionInfo - Class to encapsulate the information about a
334 /// function definition.
335 class CGFunctionInfo : public llvm::FoldingSetNode {
341 /// The LLVM::CallingConv to use for this function (as specified by the
343 unsigned CallingConvention : 8;
345 /// The LLVM::CallingConv to actually use for this function, which may
346 /// depend on the ABI.
347 unsigned EffectiveCallingConvention : 8;
349 /// The clang::CallingConv that this was originally created with.
350 unsigned ASTCallingConvention : 8;
352 /// Whether this is an instance method.
353 unsigned InstanceMethod : 1;
355 /// Whether this is a chain call.
356 unsigned ChainCall : 1;
358 /// Whether this function is noreturn.
359 unsigned NoReturn : 1;
361 /// Whether this function is returns-retained.
362 unsigned ReturnsRetained : 1;
364 /// How many arguments to pass inreg.
365 unsigned HasRegParm : 1;
366 unsigned RegParm : 3;
368 RequiredArgs Required;
370 /// The struct representing all arguments passed in memory. Only used when
371 /// passing non-trivial types with inalloca. Not part of the profile.
372 llvm::StructType *ArgStruct;
375 ArgInfo *getArgsBuffer() {
376 return reinterpret_cast<ArgInfo*>(this+1);
378 const ArgInfo *getArgsBuffer() const {
379 return reinterpret_cast<const ArgInfo*>(this + 1);
382 CGFunctionInfo() : Required(RequiredArgs::All) {}
385 static CGFunctionInfo *create(unsigned llvmCC,
388 const FunctionType::ExtInfo &extInfo,
389 CanQualType resultType,
390 ArrayRef<CanQualType> argTypes,
391 RequiredArgs required);
393 typedef const ArgInfo *const_arg_iterator;
394 typedef ArgInfo *arg_iterator;
396 typedef llvm::iterator_range<arg_iterator> arg_range;
397 typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
399 arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
400 arg_const_range arguments() const {
401 return arg_const_range(arg_begin(), arg_end());
404 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
405 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
406 arg_iterator arg_begin() { return getArgsBuffer() + 1; }
407 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
409 unsigned arg_size() const { return NumArgs; }
411 bool isVariadic() const { return Required.allowsOptionalArgs(); }
412 RequiredArgs getRequiredArgs() const { return Required; }
413 unsigned getNumRequiredArgs() const {
414 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
417 bool isInstanceMethod() const { return InstanceMethod; }
419 bool isChainCall() const { return ChainCall; }
421 bool isNoReturn() const { return NoReturn; }
423 /// In ARC, whether this function retains its return value. This
424 /// is not always reliable for call sites.
425 bool isReturnsRetained() const { return ReturnsRetained; }
427 /// getASTCallingConvention() - Return the AST-specified calling
429 CallingConv getASTCallingConvention() const {
430 return CallingConv(ASTCallingConvention);
433 /// getCallingConvention - Return the user specified calling
434 /// convention, which has been translated into an LLVM CC.
435 unsigned getCallingConvention() const { return CallingConvention; }
437 /// getEffectiveCallingConvention - Return the actual calling convention to
438 /// use, which may depend on the ABI.
439 unsigned getEffectiveCallingConvention() const {
440 return EffectiveCallingConvention;
442 void setEffectiveCallingConvention(unsigned Value) {
443 EffectiveCallingConvention = Value;
446 bool getHasRegParm() const { return HasRegParm; }
447 unsigned getRegParm() const { return RegParm; }
449 FunctionType::ExtInfo getExtInfo() const {
450 return FunctionType::ExtInfo(isNoReturn(),
451 getHasRegParm(), getRegParm(),
452 getASTCallingConvention(),
453 isReturnsRetained());
456 CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
458 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
459 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
461 /// \brief Return true if this function uses inalloca arguments.
462 bool usesInAlloca() const { return ArgStruct; }
464 /// \brief Get the struct type used to represent all the arguments in memory.
465 llvm::StructType *getArgStruct() const { return ArgStruct; }
466 void setArgStruct(llvm::StructType *Ty) { ArgStruct = Ty; }
468 void Profile(llvm::FoldingSetNodeID &ID) {
469 ID.AddInteger(getASTCallingConvention());
470 ID.AddBoolean(InstanceMethod);
471 ID.AddBoolean(ChainCall);
472 ID.AddBoolean(NoReturn);
473 ID.AddBoolean(ReturnsRetained);
474 ID.AddBoolean(HasRegParm);
475 ID.AddInteger(RegParm);
476 ID.AddInteger(Required.getOpaqueData());
477 getReturnType().Profile(ID);
478 for (const auto &I : arguments())
481 static void Profile(llvm::FoldingSetNodeID &ID,
484 const FunctionType::ExtInfo &info,
485 RequiredArgs required,
486 CanQualType resultType,
487 ArrayRef<CanQualType> argTypes) {
488 ID.AddInteger(info.getCC());
489 ID.AddBoolean(InstanceMethod);
490 ID.AddBoolean(ChainCall);
491 ID.AddBoolean(info.getNoReturn());
492 ID.AddBoolean(info.getProducesResult());
493 ID.AddBoolean(info.getHasRegParm());
494 ID.AddInteger(info.getRegParm());
495 ID.AddInteger(required.getOpaqueData());
496 resultType.Profile(ID);
497 for (ArrayRef<CanQualType>::iterator
498 i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
504 } // end namespace CodeGen
505 } // end namespace clang