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/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"
26#include <cassert>
27
28namespace clang {
29namespace CodeGen {
30
31/// ABIArgInfo - Helper class to encapsulate information about how a
32/// specific C type should be passed to or returned from a function.
33class ABIArgInfo {
34public:
35 enum Kind : uint8_t {
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.
42 Direct,
43
44 /// Extend - Valid only for integer argument types. Same as 'direct'
45 /// but also emit a zero/sign extension attribute.
46 Extend,
47
48 /// Indirect - Pass the argument indirectly via a hidden pointer
49 /// with the specified alignment (0 indicates default alignment).
50 Indirect,
51
52 /// Ignore - Ignore the argument (treat as void). Useful for void and
53 /// empty structs.
54 Ignore,
55
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.
60 Expand,
61
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.
66 CoerceAndExpand,
67
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.
73 InAlloca,
74 KindFirst = Direct,
75 KindLast = InAlloca
76 };
77
78private:
79 llvm::Type *TypeData; // canHaveCoerceToType()
80 union {
81 llvm::Type *PaddingType; // canHavePaddingType()
82 llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand()
83 };
84 union {
85 unsigned DirectOffset; // isDirect() || isExtend()
86 unsigned IndirectAlign; // isIndirect()
87 unsigned AllocaFieldIndex; // isInAlloca()
88 };
89 Kind TheKind;
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()
98 bool SuppressSRet : 1; // isIndirect()
99
100 bool canHavePaddingType() const {
101 return isDirect() || isExtend() || isIndirect() || isExpand();
102 }
103 void setPaddingType(llvm::Type *T) {
104 assert(canHavePaddingType());
105 PaddingType = T;
106 }
107
108 void setUnpaddedCoerceToType(llvm::Type *T) {
109 assert(isCoerceAndExpand());
110 UnpaddedCoerceAndExpandType = T;
111 }
112
113 ABIArgInfo(Kind K)
114 : TheKind(K), PaddingInReg(false), InReg(false), SuppressSRet(false) {
115 }
116
117public:
118 ABIArgInfo()
119 : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
120 TheKind(Direct), PaddingInReg(false), InReg(false),
121 SuppressSRet(false) {}
122
123 static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
124 llvm::Type *Padding = nullptr,
125 bool CanBeFlattened = true) {
126 auto AI = ABIArgInfo(Direct);
127 AI.setCoerceToType(T);
128 AI.setPaddingType(Padding);
129 AI.setDirectOffset(Offset);
130 AI.setCanBeFlattened(CanBeFlattened);
131 return AI;
132 }
133 static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
134 auto AI = getDirect(T);
135 AI.setInReg(true);
136 return AI;
137 }
138
139 static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) {
140 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
141 auto AI = ABIArgInfo(Extend);
142 AI.setCoerceToType(T);
143 AI.setPaddingType(nullptr);
144 AI.setDirectOffset(0);
145 AI.setSignExt(true);
146 return AI;
147 }
148
149 static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) {
150 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
151 auto AI = ABIArgInfo(Extend);
152 AI.setCoerceToType(T);
153 AI.setPaddingType(nullptr);
154 AI.setDirectOffset(0);
155 AI.setSignExt(false);
156 return AI;
157 }
158
159 // ABIArgInfo will record the argument as being extended based on the sign
160 // of its type.
161 static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
162 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
163 if (Ty->hasSignedIntegerRepresentation())
164 return getSignExtend(Ty, T);
165 return getZeroExtend(Ty, T);
166 }
167
168 static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
169 auto AI = getExtend(Ty, T);
170 AI.setInReg(true);
171 return AI;
172 }
173 static ABIArgInfo getIgnore() {
174 return ABIArgInfo(Ignore);
175 }
176 static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
177 bool Realign = false,
178 llvm::Type *Padding = nullptr) {
179 auto AI = ABIArgInfo(Indirect);
180 AI.setIndirectAlign(Alignment);
181 AI.setIndirectByVal(ByVal);
182 AI.setIndirectRealign(Realign);
183 AI.setSRetAfterThis(false);
184 AI.setPaddingType(Padding);
185 return AI;
186 }
187 static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
188 bool Realign = false) {
189 auto AI = getIndirect(Alignment, ByVal, Realign);
190 AI.setInReg(true);
191 return AI;
192 }
193 static ABIArgInfo getInAlloca(unsigned FieldIndex) {
194 auto AI = ABIArgInfo(InAlloca);
195 AI.setInAllocaFieldIndex(FieldIndex);
196 return AI;
197 }
198 static ABIArgInfo getExpand() {
199 auto AI = ABIArgInfo(Expand);
200 AI.setPaddingType(nullptr);
201 return AI;
202 }
203 static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
204 llvm::Type *Padding) {
205 auto AI = getExpand();
206 AI.setPaddingInReg(PaddingInReg);
207 AI.setPaddingType(Padding);
208 return AI;
209 }
210
211 /// \param unpaddedCoerceToType The coerce-to type with padding elements
212 /// removed, canonicalized to a single element if it would otherwise
213 /// have exactly one element.
214 static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
215 llvm::Type *unpaddedCoerceToType) {
216#ifndef NDEBUG
217 // Sanity checks on unpaddedCoerceToType.
218
219 // Assert that we only have a struct type if there are multiple elements.
220 auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType);
221 assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1);
222
223 // Assert that all the non-padding elements have a corresponding element
224 // in the unpadded type.
225 unsigned unpaddedIndex = 0;
226 for (auto eltType : coerceToType->elements()) {
227 if (isPaddingForCoerceAndExpand(eltType)) continue;
228 if (unpaddedStruct) {
229 assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType);
230 } else {
231 assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType);
232 }
233 unpaddedIndex++;
234 }
235
236 // Assert that there aren't extra elements in the unpadded type.
237 if (unpaddedStruct) {
238 assert(unpaddedStruct->getNumElements() == unpaddedIndex);
239 } else {
240 assert(unpaddedIndex == 1);
241 }
242#endif
243
244 auto AI = ABIArgInfo(CoerceAndExpand);
245 AI.setCoerceToType(coerceToType);
246 AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
247 return AI;
248 }
249
250 static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
251 if (eltType->isArrayTy()) {
252 assert(eltType->getArrayElementType()->isIntegerTy(8));
253 return true;
254 } else {
255 return false;
256 }
257 }
258
259 Kind getKind() const { return TheKind; }
260 bool isDirect() const { return TheKind == Direct; }
261 bool isInAlloca() const { return TheKind == InAlloca; }
262 bool isExtend() const { return TheKind == Extend; }
263 bool isIgnore() const { return TheKind == Ignore; }
264 bool isIndirect() const { return TheKind == Indirect; }
265 bool isExpand() const { return TheKind == Expand; }
266 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
267
268 bool canHaveCoerceToType() const {
269 return isDirect() || isExtend() || isCoerceAndExpand();
270 }
271
272 // Direct/Extend accessors
273 unsigned getDirectOffset() const {
274 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
275 return DirectOffset;
276 }
277 void setDirectOffset(unsigned Offset) {
278 assert((isDirect() || isExtend()) && "Not a direct or extend kind");
279 DirectOffset = Offset;
280 }
281
282 bool isSignExt() const {
283 assert(isExtend() && "Invalid kind!");
284 return SignExt;
285 }
286 void setSignExt(bool SExt) {
287 assert(isExtend() && "Invalid kind!");
288 SignExt = SExt;
289 }
290
291 llvm::Type *getPaddingType() const {
292 return (canHavePaddingType() ? PaddingType : nullptr);
293 }
294
295 bool getPaddingInReg() const {
296 return PaddingInReg;
297 }
298 void setPaddingInReg(bool PIR) {
299 PaddingInReg = PIR;
300 }
301
302 llvm::Type *getCoerceToType() const {
303 assert(canHaveCoerceToType() && "Invalid kind!");
304 return TypeData;
305 }
306
307 void setCoerceToType(llvm::Type *T) {
308 assert(canHaveCoerceToType() && "Invalid kind!");
309 TypeData = T;
310 }
311
312 llvm::StructType *getCoerceAndExpandType() const {
313 assert(isCoerceAndExpand());
314 return cast<llvm::StructType>(TypeData);
315 }
316
317 llvm::Type *getUnpaddedCoerceAndExpandType() const {
318 assert(isCoerceAndExpand());
319 return UnpaddedCoerceAndExpandType;
320 }
321
322 ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const {
323 assert(isCoerceAndExpand());
324 if (auto structTy =
325 dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) {
326 return structTy->elements();
327 } else {
328 return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1);
329 }
330 }
331
332 bool getInReg() const {
333 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
334 return InReg;
335 }
336
337 void setInReg(bool IR) {
338 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
339 InReg = IR;
340 }
341
342 // Indirect accessors
343 CharUnits getIndirectAlign() const {
344 assert(isIndirect() && "Invalid kind!");
345 return CharUnits::fromQuantity(IndirectAlign);
346 }
347 void setIndirectAlign(CharUnits IA) {
348 assert(isIndirect() && "Invalid kind!");
349 IndirectAlign = IA.getQuantity();
350 }
351
352 bool getIndirectByVal() const {
353 assert(isIndirect() && "Invalid kind!");
354 return IndirectByVal;
355 }
356 void setIndirectByVal(bool IBV) {
357 assert(isIndirect() && "Invalid kind!");
358 IndirectByVal = IBV;
359 }
360
361 bool getIndirectRealign() const {
362 assert(isIndirect() && "Invalid kind!");
363 return IndirectRealign;
364 }
365 void setIndirectRealign(bool IR) {
366 assert(isIndirect() && "Invalid kind!");
367 IndirectRealign = IR;
368 }
369
370 bool isSRetAfterThis() const {
371 assert(isIndirect() && "Invalid kind!");
372 return SRetAfterThis;
373 }
374 void setSRetAfterThis(bool AfterThis) {
375 assert(isIndirect() && "Invalid kind!");
376 SRetAfterThis = AfterThis;
377 }
378
379 unsigned getInAllocaFieldIndex() const {
380 assert(isInAlloca() && "Invalid kind!");
381 return AllocaFieldIndex;
382 }
383 void setInAllocaFieldIndex(unsigned FieldIndex) {
384 assert(isInAlloca() && "Invalid kind!");
385 AllocaFieldIndex = FieldIndex;
386 }
387
388 /// Return true if this field of an inalloca struct should be returned
389 /// to implement a struct return calling convention.
390 bool getInAllocaSRet() const {
391 assert(isInAlloca() && "Invalid kind!");
392 return InAllocaSRet;
393 }
394
395 void setInAllocaSRet(bool SRet) {
396 assert(isInAlloca() && "Invalid kind!");
397 InAllocaSRet = SRet;
398 }
399
400 bool getCanBeFlattened() const {
401 assert(isDirect() && "Invalid kind!");
402 return CanBeFlattened;
403 }
404
405 void setCanBeFlattened(bool Flatten) {
406 assert(isDirect() && "Invalid kind!");
407 CanBeFlattened = Flatten;
408 }
409
410 bool getSuppressSRet() const {
411 assert(isIndirect() && "Invalid kind!");
412 return SuppressSRet;
413 }
414
415 void setSuppressSRet(bool Suppress) {
416 assert(isIndirect() && "Invalid kind!");
417 SuppressSRet = Suppress;
418 }
419
420 void dump() const;
421};
422
423/// A class for recording the number of arguments that a function
424/// signature requires.
425class RequiredArgs {
426 /// The number of required arguments, or ~0 if the signature does
427 /// not permit optional arguments.
428 unsigned NumRequired;
429public:
430 enum All_t { All };
431
432 RequiredArgs(All_t _) : NumRequired(~0U) {}
433 explicit RequiredArgs(unsigned n) : NumRequired(n) {
434 assert(n != ~0U);
435 }
436
437 /// Compute the arguments required by the given formal prototype,
438 /// given that there may be some additional, non-formal arguments
439 /// in play.
440 ///
441 /// If FD is not null, this will consider pass_object_size params in FD.
442 static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
443 unsigned additional) {
444 if (!prototype->isVariadic()) return All;
445
446 if (prototype->hasExtParameterInfos())
447 additional += llvm::count_if(
448 prototype->getExtParameterInfos(),
449 [](const FunctionProtoType::ExtParameterInfo &ExtInfo) {
450 return ExtInfo.hasPassObjectSize();
451 });
452
453 return RequiredArgs(prototype->getNumParams() + additional);
454 }
455
456 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
457 unsigned additional) {
458 return forPrototypePlus(prototype.getTypePtr(), additional);
459 }
460
461 static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
462 return forPrototypePlus(prototype, 0);
463 }
464
465 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
466 return forPrototypePlus(prototype.getTypePtr(), 0);
467 }
468
469 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
470 unsigned getNumRequiredArgs() const {
471 assert(allowsOptionalArgs());
472 return NumRequired;
473 }
474
475 unsigned getOpaqueData() const { return NumRequired; }
476 static RequiredArgs getFromOpaqueData(unsigned value) {
477 if (value == ~0U) return All;
478 return RequiredArgs(value);
479 }
480};
481
482// Implementation detail of CGFunctionInfo, factored out so it can be named
483// in the TrailingObjects base class of CGFunctionInfo.
484struct CGFunctionInfoArgInfo {
485 CanQualType type;
486 ABIArgInfo info;
487};
488
489/// CGFunctionInfo - Class to encapsulate the information about a
490/// function definition.
491class CGFunctionInfo final
492 : public llvm::FoldingSetNode,
493 private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo,
494 FunctionProtoType::ExtParameterInfo> {
495 typedef CGFunctionInfoArgInfo ArgInfo;
496 typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo;
497
498 /// The LLVM::CallingConv to use for this function (as specified by the
499 /// user).
500 unsigned CallingConvention : 8;
501
502 /// The LLVM::CallingConv to actually use for this function, which may
503 /// depend on the ABI.
504 unsigned EffectiveCallingConvention : 8;
505
506 /// The clang::CallingConv that this was originally created with.
507 unsigned ASTCallingConvention : 6;
508
509 /// Whether this is an instance method.
510 unsigned InstanceMethod : 1;
511
512 /// Whether this is a chain call.
513 unsigned ChainCall : 1;
514
515 /// Whether this function is noreturn.
516 unsigned NoReturn : 1;
517
518 /// Whether this function is returns-retained.
519 unsigned ReturnsRetained : 1;
520
521 /// Whether this function saved caller registers.
522 unsigned NoCallerSavedRegs : 1;
523
524 /// How many arguments to pass inreg.
525 unsigned HasRegParm : 1;
526 unsigned RegParm : 3;
527
528 /// Whether this function has nocf_check attribute.
529 unsigned NoCfCheck : 1;
530
531 RequiredArgs Required;
532
533 /// The struct representing all arguments passed in memory. Only used when
534 /// passing non-trivial types with inalloca. Not part of the profile.
535 llvm::StructType *ArgStruct;
536 unsigned ArgStructAlign : 31;
537 unsigned HasExtParameterInfos : 1;
538
539 unsigned NumArgs;
540
541 ArgInfo *getArgsBuffer() {
542 return getTrailingObjects<ArgInfo>();
543 }
544 const ArgInfo *getArgsBuffer() const {
545 return getTrailingObjects<ArgInfo>();
546 }
547
548 ExtParameterInfo *getExtParameterInfosBuffer() {
549 return getTrailingObjects<ExtParameterInfo>();
550 }
551 const ExtParameterInfo *getExtParameterInfosBuffer() const{
552 return getTrailingObjects<ExtParameterInfo>();
553 }
554
555 CGFunctionInfo() : Required(RequiredArgs::All) {}
556
557public:
558 static CGFunctionInfo *create(unsigned llvmCC,
559 bool instanceMethod,
560 bool chainCall,
561 const FunctionType::ExtInfo &extInfo,
562 ArrayRef<ExtParameterInfo> paramInfos,
563 CanQualType resultType,
564 ArrayRef<CanQualType> argTypes,
565 RequiredArgs required);
566 void operator delete(void *p) { ::operator delete(p); }
567
568 // Friending class TrailingObjects is apparently not good enough for MSVC,
569 // so these have to be public.
570 friend class TrailingObjects;
571 size_t numTrailingObjects(OverloadToken<ArgInfo>) const {
572 return NumArgs + 1;
573 }
574 size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
575 return (HasExtParameterInfos ? NumArgs : 0);
576 }
577
578 typedef const ArgInfo *const_arg_iterator;
579 typedef ArgInfo *arg_iterator;
580
581 typedef llvm::iterator_range<arg_iterator> arg_range;
582 typedef llvm::iterator_range<const_arg_iterator> const_arg_range;
583
584 arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
585 const_arg_range arguments() const {
586 return const_arg_range(arg_begin(), arg_end());
587 }
588
589 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
590 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
591 arg_iterator arg_begin() { return getArgsBuffer() + 1; }
592 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
593
594 unsigned arg_size() const { return NumArgs; }
595
596 bool isVariadic() const { return Required.allowsOptionalArgs(); }
597 RequiredArgs getRequiredArgs() const { return Required; }
598 unsigned getNumRequiredArgs() const {
599 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
600 }
601
602 bool isInstanceMethod() const { return InstanceMethod; }
603
604 bool isChainCall() const { return ChainCall; }
605
606 bool isNoReturn() const { return NoReturn; }
607
608 /// In ARC, whether this function retains its return value. This
609 /// is not always reliable for call sites.
610 bool isReturnsRetained() const { return ReturnsRetained; }
611
612 /// Whether this function no longer saves caller registers.
613 bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }
614
615 /// Whether this function has nocf_check attribute.
616 bool isNoCfCheck() const { return NoCfCheck; }
617
618 /// getASTCallingConvention() - Return the AST-specified calling
619 /// convention.
620 CallingConv getASTCallingConvention() const {
621 return CallingConv(ASTCallingConvention);
622 }
623
624 /// getCallingConvention - Return the user specified calling
625 /// convention, which has been translated into an LLVM CC.
626 unsigned getCallingConvention() const { return CallingConvention; }
627
628 /// getEffectiveCallingConvention - Return the actual calling convention to
629 /// use, which may depend on the ABI.
630 unsigned getEffectiveCallingConvention() const {
631 return EffectiveCallingConvention;
632 }
633 void setEffectiveCallingConvention(unsigned Value) {
634 EffectiveCallingConvention = Value;
635 }
636
637 bool getHasRegParm() const { return HasRegParm; }
638 unsigned getRegParm() const { return RegParm; }
639
640 FunctionType::ExtInfo getExtInfo() const {
641 return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
642 getASTCallingConvention(), isReturnsRetained(),
643 isNoCallerSavedRegs(), isNoCfCheck());
644 }
645
646 CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
647
648 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
649 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
650
651 ArrayRef<ExtParameterInfo> getExtParameterInfos() const {
652 if (!HasExtParameterInfos) return {};
653 return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs);
654 }
655 ExtParameterInfo getExtParameterInfo(unsigned argIndex) const {
656 assert(argIndex <= NumArgs);
657 if (!HasExtParameterInfos) return ExtParameterInfo();
658 return getExtParameterInfos()[argIndex];
659 }
660
661 /// Return true if this function uses inalloca arguments.
662 bool usesInAlloca() const { return ArgStruct; }
663
664 /// Get the struct type used to represent all the arguments in memory.
665 llvm::StructType *getArgStruct() const { return ArgStruct; }
666 CharUnits getArgStructAlignment() const {
667 return CharUnits::fromQuantity(ArgStructAlign);
668 }
669 void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
670 ArgStruct = Ty;
671 ArgStructAlign = Align.getQuantity();
672 }
673
674 void Profile(llvm::FoldingSetNodeID &ID) {
675 ID.AddInteger(getASTCallingConvention());
676 ID.AddBoolean(InstanceMethod);
677 ID.AddBoolean(ChainCall);
678 ID.AddBoolean(NoReturn);
679 ID.AddBoolean(ReturnsRetained);
680 ID.AddBoolean(NoCallerSavedRegs);
681 ID.AddBoolean(HasRegParm);
682 ID.AddInteger(RegParm);
683 ID.AddBoolean(NoCfCheck);
684 ID.AddInteger(Required.getOpaqueData());
685 ID.AddBoolean(HasExtParameterInfos);
686 if (HasExtParameterInfos) {
687 for (auto paramInfo : getExtParameterInfos())
688 ID.AddInteger(paramInfo.getOpaqueValue());
689 }
690 getReturnType().Profile(ID);
691 for (const auto &I : arguments())
692 I.type.Profile(ID);
693 }
694 static void Profile(llvm::FoldingSetNodeID &ID,
695 bool InstanceMethod,
696 bool ChainCall,
697 const FunctionType::ExtInfo &info,
698 ArrayRef<ExtParameterInfo> paramInfos,
699 RequiredArgs required,
700 CanQualType resultType,
701 ArrayRef<CanQualType> argTypes) {
702 ID.AddInteger(info.getCC());
703 ID.AddBoolean(InstanceMethod);
704 ID.AddBoolean(ChainCall);
705 ID.AddBoolean(info.getNoReturn());
706 ID.AddBoolean(info.getProducesResult());
707 ID.AddBoolean(info.getNoCallerSavedRegs());
708 ID.AddBoolean(info.getHasRegParm());
709 ID.AddInteger(info.getRegParm());
710 ID.AddBoolean(info.getNoCfCheck());
711 ID.AddInteger(required.getOpaqueData());
712 ID.AddBoolean(!paramInfos.empty());
713 if (!paramInfos.empty()) {
714 for (auto paramInfo : paramInfos)
715 ID.AddInteger(paramInfo.getOpaqueValue());
716 }
717 resultType.Profile(ID);
718 for (ArrayRef<CanQualType>::iterator
719 i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
720 i->Profile(ID);
721 }
722 }
723};
724
725} // end namespace CodeGen
726} // end namespace clang
727
728#endif
729