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