clang 22.0.0git
CGFunctionInfo.h
Go to the documentation of this file.
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
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.
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.
42
43 /// Extend - Valid only for integer argument types. Same as 'direct'
44 /// but also emit a zero/sign extension attribute.
46
47 /// Indirect - Pass the argument indirectly via a hidden pointer with the
48 /// specified alignment (0 indicates default alignment) and address space.
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.
63
64 /// Ignore - Ignore the argument (treat as void). Useful for void and
65 /// empty structs.
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.
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.
79
80 /// TargetSpecific - Some argument types are passed as target specific types
81 /// such as RISC-V's tuple type, these need to be handled in the target
82 /// hook.
84
85 /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
86 /// This is similar to indirect with byval, except it only applies to
87 /// arguments stored in memory and forbids any implicit copies. When
88 /// applied to a return type, it means the value is returned indirectly via
89 /// an implicit sret parameter stored in the argument struct.
93 };
94
95private:
96 llvm::Type *TypeData; // canHaveCoerceToType()
97 union {
98 llvm::Type *PaddingType; // canHavePaddingType()
99 llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand()
100 };
101 struct DirectAttrInfo {
102 unsigned Offset;
103 unsigned Align;
104 };
105 struct IndirectAttrInfo {
106 unsigned Align;
107 unsigned AddrSpace;
108 };
109 union {
110 DirectAttrInfo DirectAttr; // isDirect() || isExtend()
111 IndirectAttrInfo IndirectAttr; // isIndirect()
112 unsigned AllocaFieldIndex; // isInAlloca()
113 };
114 Kind TheKind;
115 bool PaddingInReg : 1;
116 bool InAllocaSRet : 1; // isInAlloca()
117 bool InAllocaIndirect : 1;// isInAlloca()
118 bool IndirectByVal : 1; // isIndirect()
119 bool IndirectRealign : 1; // isIndirect()
120 bool SRetAfterThis : 1; // isIndirect()
121 bool InReg : 1; // isDirect() || isExtend() || isIndirect()
122 bool CanBeFlattened: 1; // isDirect()
123 bool SignExt : 1; // isExtend()
124 bool ZeroExt : 1; // isExtend()
125
126 bool canHavePaddingType() const {
127 return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
129 }
130 void setPaddingType(llvm::Type *T) {
131 assert(canHavePaddingType());
132 PaddingType = T;
133 }
134
135 void setUnpaddedCoerceToType(llvm::Type *T) {
136 assert(isCoerceAndExpand());
138 }
139
140public:
142 : TypeData(nullptr), PaddingType(nullptr), DirectAttr{0, 0}, TheKind(K),
143 PaddingInReg(false), InAllocaSRet(false),
144 InAllocaIndirect(false), IndirectByVal(false), IndirectRealign(false),
145 SRetAfterThis(false), InReg(false), CanBeFlattened(false),
146 SignExt(false), ZeroExt(false) {}
147
148 static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
149 llvm::Type *Padding = nullptr,
150 bool CanBeFlattened = true, unsigned Align = 0) {
151 auto AI = ABIArgInfo(Direct);
152 AI.setCoerceToType(T);
153 AI.setPaddingType(Padding);
154 AI.setDirectOffset(Offset);
155 AI.setDirectAlign(Align);
156 AI.setCanBeFlattened(CanBeFlattened);
157 return AI;
158 }
159 static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
160 auto AI = getDirect(T);
161 AI.setInReg(true);
162 return AI;
163 }
164
165 static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) {
166 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
167 auto AI = ABIArgInfo(Extend);
168 AI.setCoerceToType(T);
169 AI.setPaddingType(nullptr);
170 AI.setDirectOffset(0);
171 AI.setDirectAlign(0);
172 AI.setSignExt(true);
173 return AI;
174 }
175
176 static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) {
177 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
178 auto AI = ABIArgInfo(Extend);
179 AI.setCoerceToType(T);
180 AI.setPaddingType(nullptr);
181 AI.setDirectOffset(0);
182 AI.setDirectAlign(0);
183 AI.setZeroExt(true);
184 return AI;
185 }
186
187 // ABIArgInfo will record the argument as being extended based on the sign
188 // of its type. Produces a sign or zero extension.
189 static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
190 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
192 return getSignExtend(Ty, T);
193 return getZeroExtend(Ty, T);
194 }
195
196 // Struct in register marked explicitly as not needing extension.
197 static ABIArgInfo getNoExtend(llvm::IntegerType *T) {
198 auto AI = ABIArgInfo(Extend);
199 AI.setCoerceToType(T);
200 AI.setPaddingType(nullptr);
201 AI.setDirectOffset(0);
202 AI.setDirectAlign(0);
203 return AI;
204 }
205
206 static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
207 auto AI = getExtend(Ty, T);
208 AI.setInReg(true);
209 return AI;
210 }
212 return ABIArgInfo(Ignore);
213 }
214 static ABIArgInfo getIndirect(CharUnits Alignment, unsigned AddrSpace,
215 bool ByVal = true, bool Realign = false,
216 llvm::Type *Padding = nullptr) {
217 auto AI = ABIArgInfo(Indirect);
218 AI.setIndirectAlign(Alignment);
219 AI.setIndirectByVal(ByVal);
220 AI.setIndirectRealign(Realign);
221 AI.setSRetAfterThis(false);
222 AI.setPaddingType(Padding);
223 AI.setIndirectAddrSpace(AddrSpace);
224 return AI;
225 }
226
227 /// Pass this in memory using the IR byref attribute.
228 static ABIArgInfo getIndirectAliased(CharUnits Alignment, unsigned AddrSpace,
229 bool Realign = false,
230 llvm::Type *Padding = nullptr) {
231 auto AI = ABIArgInfo(IndirectAliased);
232 AI.setIndirectAlign(Alignment);
233 AI.setIndirectRealign(Realign);
234 AI.setPaddingType(Padding);
235 AI.setIndirectAddrSpace(AddrSpace);
236 return AI;
237 }
238
239 static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
240 bool Realign = false) {
241 auto AI = getIndirect(Alignment, 0, ByVal, Realign);
242 AI.setInReg(true);
243 return AI;
244 }
245 static ABIArgInfo getInAlloca(unsigned FieldIndex, bool Indirect = false) {
246 auto AI = ABIArgInfo(InAlloca);
247 AI.setInAllocaFieldIndex(FieldIndex);
248 AI.setInAllocaIndirect(Indirect);
249 return AI;
250 }
252 auto AI = ABIArgInfo(Expand);
253 AI.setPaddingType(nullptr);
254 return AI;
255 }
256 static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
257 llvm::Type *Padding) {
258 auto AI = getExpand();
259 AI.setPaddingInReg(PaddingInReg);
260 AI.setPaddingType(Padding);
261 return AI;
262 }
263
264 /// \param unpaddedCoerceToType The coerce-to type with padding elements
265 /// removed, canonicalized to a single element if it would otherwise
266 /// have exactly one element.
267 static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
268 llvm::Type *unpaddedCoerceToType) {
269#ifndef NDEBUG
270 // Check that unpaddedCoerceToType has roughly the right shape.
271
272 // Assert that we only have a struct type if there are multiple elements.
273 auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType);
274 assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1);
275
276 // Assert that all the non-padding elements have a corresponding element
277 // in the unpadded type.
278 unsigned unpaddedIndex = 0;
279 for (auto eltType : coerceToType->elements()) {
280 if (isPaddingForCoerceAndExpand(eltType))
281 continue;
282 unpaddedIndex++;
283 }
284
285 // Assert that there aren't extra elements in the unpadded type.
286 if (unpaddedStruct) {
287 assert(unpaddedStruct->getNumElements() == unpaddedIndex);
288 } else {
289 assert(unpaddedIndex == 1);
290 }
291#endif
292
293 auto AI = ABIArgInfo(CoerceAndExpand);
294 AI.setCoerceToType(coerceToType);
295 AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
296 return AI;
297 }
298
299 static ABIArgInfo getTargetSpecific(llvm::Type *T = nullptr,
300 unsigned Offset = 0,
301 llvm::Type *Padding = nullptr,
302 bool CanBeFlattened = true,
303 unsigned Align = 0) {
304 auto AI = ABIArgInfo(TargetSpecific);
305 AI.setCoerceToType(T);
306 AI.setPaddingType(Padding);
307 AI.setDirectOffset(Offset);
308 AI.setDirectAlign(Align);
309 AI.setCanBeFlattened(CanBeFlattened);
310 return AI;
311 }
312
313 static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
314 return eltType->isArrayTy() &&
315 eltType->getArrayElementType()->isIntegerTy(8);
316 }
317
318 Kind getKind() const { return TheKind; }
319 bool isDirect() const { return TheKind == Direct; }
320 bool isInAlloca() const { return TheKind == InAlloca; }
321 bool isExtend() const { return TheKind == Extend; }
322 bool isIgnore() const { return TheKind == Ignore; }
323 bool isIndirect() const { return TheKind == Indirect; }
324 bool isIndirectAliased() const { return TheKind == IndirectAliased; }
325 bool isExpand() const { return TheKind == Expand; }
326 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
327 bool isTargetSpecific() const { return TheKind == TargetSpecific; }
328
329 bool canHaveCoerceToType() const {
330 return isDirect() || isExtend() || isCoerceAndExpand() ||
332 }
333
334 // Direct/Extend accessors
335 unsigned getDirectOffset() const {
336 assert((isDirect() || isExtend() || isTargetSpecific()) &&
337 "Not a direct or extend or target specific kind");
338 return DirectAttr.Offset;
339 }
340 void setDirectOffset(unsigned Offset) {
341 assert((isDirect() || isExtend() || isTargetSpecific()) &&
342 "Not a direct or extend or target specific kind");
343 DirectAttr.Offset = Offset;
344 }
345
346 unsigned getDirectAlign() const {
347 assert((isDirect() || isExtend() || isTargetSpecific()) &&
348 "Not a direct or extend or target specific kind");
349 return DirectAttr.Align;
350 }
351 void setDirectAlign(unsigned Align) {
352 assert((isDirect() || isExtend() || isTargetSpecific()) &&
353 "Not a direct or extend or target specific kind");
354 DirectAttr.Align = Align;
355 }
356
357 bool isSignExt() const {
358 assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
359 return SignExt;
360 }
361 void setSignExt(bool SExt) {
362 assert(isExtend() && "Invalid kind!");
363 SignExt = SExt;
364 }
365
366 bool isZeroExt() const {
367 assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
368 return ZeroExt;
369 }
370 void setZeroExt(bool ZExt) {
371 assert(isExtend() && "Invalid kind!");
372 ZeroExt = ZExt;
373 }
374
375 bool isNoExt() const {
376 assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
377 return !SignExt && !ZeroExt;
378 }
379
380 llvm::Type *getPaddingType() const {
381 return (canHavePaddingType() ? PaddingType : nullptr);
382 }
383
384 bool getPaddingInReg() const {
385 return PaddingInReg;
386 }
387 void setPaddingInReg(bool PIR) {
388 PaddingInReg = PIR;
389 }
390
391 llvm::Type *getCoerceToType() const {
392 assert(canHaveCoerceToType() && "Invalid kind!");
393 return TypeData;
394 }
395
396 void setCoerceToType(llvm::Type *T) {
397 assert(canHaveCoerceToType() && "Invalid kind!");
398 TypeData = T;
399 }
400
401 llvm::StructType *getCoerceAndExpandType() const {
402 assert(isCoerceAndExpand());
403 return cast<llvm::StructType>(TypeData);
404 }
405
406 llvm::Type *getUnpaddedCoerceAndExpandType() const {
407 assert(isCoerceAndExpand());
409 }
410
412 assert(isCoerceAndExpand());
413 if (auto structTy =
414 dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) {
415 return structTy->elements();
416 } else {
418 }
419 }
420
421 bool getInReg() const {
422 assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
423 "Invalid kind!");
424 return InReg;
425 }
426
427 void setInReg(bool IR) {
428 assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
429 "Invalid kind!");
430 InReg = IR;
431 }
432
433 // Indirect accessors
435 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
437 }
439 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
440 IndirectAttr.Align = IA.getQuantity();
441 }
442
443 bool getIndirectByVal() const {
444 assert(isIndirect() && "Invalid kind!");
445 return IndirectByVal;
446 }
447 void setIndirectByVal(bool IBV) {
448 assert(isIndirect() && "Invalid kind!");
449 IndirectByVal = IBV;
450 }
451
452 unsigned getIndirectAddrSpace() const {
453 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
454 return IndirectAttr.AddrSpace;
455 }
456
457 void setIndirectAddrSpace(unsigned AddrSpace) {
458 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
459 IndirectAttr.AddrSpace = AddrSpace;
460 }
461
462 bool getIndirectRealign() const {
463 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
464 return IndirectRealign;
465 }
466 void setIndirectRealign(bool IR) {
467 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
468 IndirectRealign = IR;
469 }
470
471 bool isSRetAfterThis() const {
472 assert(isIndirect() && "Invalid kind!");
473 return SRetAfterThis;
474 }
475 void setSRetAfterThis(bool AfterThis) {
476 assert(isIndirect() && "Invalid kind!");
477 SRetAfterThis = AfterThis;
478 }
479
480 unsigned getInAllocaFieldIndex() const {
481 assert(isInAlloca() && "Invalid kind!");
482 return AllocaFieldIndex;
483 }
484 void setInAllocaFieldIndex(unsigned FieldIndex) {
485 assert(isInAlloca() && "Invalid kind!");
486 AllocaFieldIndex = FieldIndex;
487 }
488
489 unsigned getInAllocaIndirect() const {
490 assert(isInAlloca() && "Invalid kind!");
491 return InAllocaIndirect;
492 }
494 assert(isInAlloca() && "Invalid kind!");
495 InAllocaIndirect = Indirect;
496 }
497
498 /// Return true if this field of an inalloca struct should be returned
499 /// to implement a struct return calling convention.
500 bool getInAllocaSRet() const {
501 assert(isInAlloca() && "Invalid kind!");
502 return InAllocaSRet;
503 }
504
505 void setInAllocaSRet(bool SRet) {
506 assert(isInAlloca() && "Invalid kind!");
507 InAllocaSRet = SRet;
508 }
509
510 bool getCanBeFlattened() const {
511 assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
512 return CanBeFlattened;
513 }
514
515 void setCanBeFlattened(bool Flatten) {
516 assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
517 CanBeFlattened = Flatten;
518 }
519
520 void dump() const;
521};
522
523/// A class for recording the number of arguments that a function
524/// signature requires.
526 /// The number of required arguments, or ~0 if the signature does
527 /// not permit optional arguments.
528 unsigned NumRequired;
529public:
530 enum All_t { All };
531
532 RequiredArgs(All_t _) : NumRequired(~0U) {}
533 explicit RequiredArgs(unsigned n) : NumRequired(n) {
534 assert(n != ~0U);
535 }
536
537 /// Compute the arguments required by the given formal prototype,
538 /// given that there may be some additional, non-formal arguments
539 /// in play.
540 ///
541 /// If FD is not null, this will consider pass_object_size params in FD.
543 unsigned additional) {
544 if (!prototype->isVariadic()) return All;
545
546 if (prototype->hasExtParameterInfos())
547 additional += llvm::count_if(
548 prototype->getExtParameterInfos(),
549 [](const FunctionProtoType::ExtParameterInfo &ExtInfo) {
550 return ExtInfo.hasPassObjectSize();
551 });
552
553 return RequiredArgs(prototype->getNumParams() + additional);
554 }
555
557 unsigned additional) {
558 return forPrototypePlus(prototype.getTypePtr(), additional);
559 }
560
561 static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
562 return forPrototypePlus(prototype, 0);
563 }
564
566 return forPrototypePlus(prototype.getTypePtr(), 0);
567 }
568
569 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
570 unsigned getNumRequiredArgs() const {
571 assert(allowsOptionalArgs());
572 return NumRequired;
573 }
574
575 /// Return true if the argument at a given index is required.
576 bool isRequiredArg(unsigned argIdx) const {
577 return argIdx == ~0U || argIdx < NumRequired;
578 }
579
580 unsigned getOpaqueData() const { return NumRequired; }
581 static RequiredArgs getFromOpaqueData(unsigned value) {
582 if (value == ~0U) return All;
583 return RequiredArgs(value);
584 }
585};
586
587// Implementation detail of CGFunctionInfo, factored out so it can be named
588// in the TrailingObjects base class of CGFunctionInfo.
592};
593
594/// CGFunctionInfo - Class to encapsulate the information about a
595/// function definition.
596class CGFunctionInfo final
597 : public llvm::FoldingSetNode,
598 private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo,
599 FunctionProtoType::ExtParameterInfo> {
602
603 /// The LLVM::CallingConv to use for this function (as specified by the
604 /// user).
605 unsigned CallingConvention : 8;
606
607 /// The LLVM::CallingConv to actually use for this function, which may
608 /// depend on the ABI.
609 unsigned EffectiveCallingConvention : 8;
610
611 /// The clang::CallingConv that this was originally created with.
612 LLVM_PREFERRED_TYPE(CallingConv)
613 unsigned ASTCallingConvention : 6;
614
615 /// Whether this is an instance method.
616 LLVM_PREFERRED_TYPE(bool)
617 unsigned InstanceMethod : 1;
618
619 /// Whether this is a chain call.
620 LLVM_PREFERRED_TYPE(bool)
621 unsigned ChainCall : 1;
622
623 /// Whether this function is called by forwarding arguments.
624 /// This doesn't support inalloca or varargs.
625 LLVM_PREFERRED_TYPE(bool)
626 unsigned DelegateCall : 1;
627
628 /// Whether this function is a CMSE nonsecure call
629 LLVM_PREFERRED_TYPE(bool)
630 unsigned CmseNSCall : 1;
631
632 /// Whether this function is noreturn.
633 LLVM_PREFERRED_TYPE(bool)
634 unsigned NoReturn : 1;
635
636 /// Whether this function is returns-retained.
637 LLVM_PREFERRED_TYPE(bool)
638 unsigned ReturnsRetained : 1;
639
640 /// Whether this function saved caller registers.
641 LLVM_PREFERRED_TYPE(bool)
642 unsigned NoCallerSavedRegs : 1;
643
644 /// How many arguments to pass inreg.
645 LLVM_PREFERRED_TYPE(bool)
646 unsigned HasRegParm : 1;
647 unsigned RegParm : 3;
648
649 /// Whether this function has nocf_check attribute.
650 LLVM_PREFERRED_TYPE(bool)
651 unsigned NoCfCheck : 1;
652
653 /// Log 2 of the maximum vector width.
654 unsigned MaxVectorWidth : 4;
655
656 RequiredArgs Required;
657
658 /// The struct representing all arguments passed in memory. Only used when
659 /// passing non-trivial types with inalloca. Not part of the profile.
660 llvm::StructType *ArgStruct;
661 unsigned ArgStructAlign : 31;
662 LLVM_PREFERRED_TYPE(bool)
663 unsigned HasExtParameterInfos : 1;
664
665 unsigned NumArgs;
666
667 ArgInfo *getArgsBuffer() {
668 return getTrailingObjects<ArgInfo>();
669 }
670 const ArgInfo *getArgsBuffer() const {
671 return getTrailingObjects<ArgInfo>();
672 }
673
674 ExtParameterInfo *getExtParameterInfosBuffer() {
675 return getTrailingObjects<ExtParameterInfo>();
676 }
677 const ExtParameterInfo *getExtParameterInfosBuffer() const{
678 return getTrailingObjects<ExtParameterInfo>();
679 }
680
682
683public:
684 static CGFunctionInfo *
685 create(unsigned llvmCC, bool instanceMethod, bool chainCall,
686 bool delegateCall, const FunctionType::ExtInfo &extInfo,
687 ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
688 ArrayRef<CanQualType> argTypes, RequiredArgs required);
689 void operator delete(void *p) { ::operator delete(p); }
690
691 // Friending class TrailingObjects is apparently not good enough for MSVC,
692 // so these have to be public.
693 friend class TrailingObjects;
694 size_t numTrailingObjects(OverloadToken<ArgInfo>) const {
695 return NumArgs + 1;
696 }
697 size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
698 return (HasExtParameterInfos ? NumArgs : 0);
699 }
700
703
705 return MutableArrayRef<ArgInfo>(arg_begin(), NumArgs);
706 }
708 return ArrayRef<ArgInfo>(arg_begin(), NumArgs);
709 }
710
711 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
712 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
713 arg_iterator arg_begin() { return getArgsBuffer() + 1; }
714 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
715
716 unsigned arg_size() const { return NumArgs; }
717
718 bool isVariadic() const { return Required.allowsOptionalArgs(); }
720 unsigned getNumRequiredArgs() const {
722 }
723
724 bool isInstanceMethod() const { return InstanceMethod; }
725
726 bool isChainCall() const { return ChainCall; }
727
728 bool isDelegateCall() const { return DelegateCall; }
729
730 bool isCmseNSCall() const { return CmseNSCall; }
731
732 bool isNoReturn() const { return NoReturn; }
733
734 /// In ARC, whether this function retains its return value. This
735 /// is not always reliable for call sites.
736 bool isReturnsRetained() const { return ReturnsRetained; }
737
738 /// Whether this function no longer saves caller registers.
739 bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }
740
741 /// Whether this function has nocf_check attribute.
742 bool isNoCfCheck() const { return NoCfCheck; }
743
744 /// getASTCallingConvention() - Return the AST-specified calling
745 /// convention.
747 return CallingConv(ASTCallingConvention);
748 }
749
750 /// getCallingConvention - Return the user specified calling
751 /// convention, which has been translated into an LLVM CC.
752 unsigned getCallingConvention() const { return CallingConvention; }
753
754 /// getEffectiveCallingConvention - Return the actual calling convention to
755 /// use, which may depend on the ABI.
757 return EffectiveCallingConvention;
758 }
760 EffectiveCallingConvention = Value;
761 }
762
763 bool getHasRegParm() const { return HasRegParm; }
764 unsigned getRegParm() const { return RegParm; }
765
770 isCmseNSCall());
771 }
772
773 CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
774
775 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
776 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
777
779 if (!HasExtParameterInfos) return {};
780 return llvm::ArrayRef(getExtParameterInfosBuffer(), NumArgs);
781 }
782 ExtParameterInfo getExtParameterInfo(unsigned argIndex) const {
783 assert(argIndex <= NumArgs);
784 if (!HasExtParameterInfos) return ExtParameterInfo();
785 return getExtParameterInfos()[argIndex];
786 }
787
788 /// Return true if this function uses inalloca arguments.
789 bool usesInAlloca() const { return ArgStruct; }
790
791 /// Get the struct type used to represent all the arguments in memory.
792 llvm::StructType *getArgStruct() const { return ArgStruct; }
794 return CharUnits::fromQuantity(ArgStructAlign);
795 }
796 void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
797 ArgStruct = Ty;
798 ArgStructAlign = Align.getQuantity();
799 }
800
801 /// Return the maximum vector width in the arguments.
802 unsigned getMaxVectorWidth() const {
803 return MaxVectorWidth ? 1U << (MaxVectorWidth - 1) : 0;
804 }
805
806 /// Set the maximum vector width in the arguments.
807 void setMaxVectorWidth(unsigned Width) {
808 assert(llvm::isPowerOf2_32(Width) && "Expected power of 2 vector");
809 MaxVectorWidth = llvm::countr_zero(Width) + 1;
810 }
811
812 void Profile(llvm::FoldingSetNodeID &ID) {
813 ID.AddInteger(getASTCallingConvention());
814 ID.AddBoolean(InstanceMethod);
815 ID.AddBoolean(ChainCall);
816 ID.AddBoolean(DelegateCall);
817 ID.AddBoolean(NoReturn);
818 ID.AddBoolean(ReturnsRetained);
819 ID.AddBoolean(NoCallerSavedRegs);
820 ID.AddBoolean(HasRegParm);
821 ID.AddInteger(RegParm);
822 ID.AddBoolean(NoCfCheck);
823 ID.AddBoolean(CmseNSCall);
824 ID.AddInteger(Required.getOpaqueData());
825 ID.AddBoolean(HasExtParameterInfos);
826 if (HasExtParameterInfos) {
827 for (auto paramInfo : getExtParameterInfos())
828 ID.AddInteger(paramInfo.getOpaqueValue());
829 }
831 for (const auto &I : arguments())
832 I.type.Profile(ID);
833 }
834 static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod,
835 bool ChainCall, bool IsDelegateCall,
836 const FunctionType::ExtInfo &info,
838 RequiredArgs required, CanQualType resultType,
839 ArrayRef<CanQualType> argTypes) {
840 ID.AddInteger(info.getCC());
841 ID.AddBoolean(InstanceMethod);
842 ID.AddBoolean(ChainCall);
843 ID.AddBoolean(IsDelegateCall);
844 ID.AddBoolean(info.getNoReturn());
845 ID.AddBoolean(info.getProducesResult());
846 ID.AddBoolean(info.getNoCallerSavedRegs());
847 ID.AddBoolean(info.getHasRegParm());
848 ID.AddInteger(info.getRegParm());
849 ID.AddBoolean(info.getNoCfCheck());
850 ID.AddBoolean(info.getCmseNSCall());
851 ID.AddInteger(required.getOpaqueData());
852 ID.AddBoolean(!paramInfos.empty());
853 if (!paramInfos.empty()) {
854 for (auto paramInfo : paramInfos)
855 ID.AddInteger(paramInfo.getOpaqueValue());
856 }
857 resultType.Profile(ID);
858 for (const CanQualType &argType : argTypes)
859 argType.Profile(ID);
860 }
861};
862
863} // end namespace CodeGen
864} // end namespace clang
865
866#endif
static char ID
Definition: Arena.cpp:183
C Language Family Type Representation.
Represents a canonical, potentially-qualified type.
Definition: CanonicalType.h:66
void Profile(llvm::FoldingSetNodeID &ID) const
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
Definition: CanonicalType.h:84
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition: CharUnits.h:185
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
unsigned getInAllocaFieldIndex() const
void setIndirectAddrSpace(unsigned AddrSpace)
static ABIArgInfo getNoExtend(llvm::IntegerType *T)
llvm::StructType * getCoerceAndExpandType() const
static ABIArgInfo getInAlloca(unsigned FieldIndex, bool Indirect=false)
static ABIArgInfo getIgnore()
static ABIArgInfo getExpand()
void setCoerceToType(llvm::Type *T)
llvm::Type * getUnpaddedCoerceAndExpandType() const
unsigned getDirectOffset() const
static bool isPaddingForCoerceAndExpand(llvm::Type *eltType)
void setDirectOffset(unsigned Offset)
static ABIArgInfo getTargetSpecific(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
void setPaddingInReg(bool PIR)
bool getInAllocaSRet() const
Return true if this field of an inalloca struct should be returned to implement a struct return calli...
void setIndirectAlign(CharUnits IA)
llvm::Type * getPaddingType() const
void setIndirectByVal(bool IBV)
static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T=nullptr)
static ABIArgInfo getExpandWithPadding(bool PaddingInReg, llvm::Type *Padding)
unsigned getDirectAlign() const
unsigned getIndirectAddrSpace() const
static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal=true, bool Realign=false)
void setIndirectRealign(bool IR)
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
@ Extend
Extend - Valid only for integer argument types.
@ Ignore
Ignore - Ignore the argument (treat as void).
@ IndirectAliased
IndirectAliased - Similar to Indirect, but the pointer may be to an object that is otherwise referenc...
@ Expand
Expand - Only valid for aggregate argument types.
@ TargetSpecific
TargetSpecific - Some argument types are passed as target specific types such as RISC-V's tuple type,...
@ InAlloca
InAlloca - Pass the argument directly using the LLVM inalloca attribute.
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
@ CoerceAndExpand
CoerceAndExpand - Only valid for aggregate argument types.
@ Direct
Direct - Pass the argument directly using the normal converted LLVM type, or by coercing to another s...
static ABIArgInfo getIndirect(CharUnits Alignment, unsigned AddrSpace, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
ArrayRef< llvm::Type * > getCoerceAndExpandTypeSequence() const
static ABIArgInfo getIndirectAliased(CharUnits Alignment, unsigned AddrSpace, bool Realign=false, llvm::Type *Padding=nullptr)
Pass this in memory using the IR byref attribute.
void setSRetAfterThis(bool AfterThis)
void setInAllocaIndirect(bool Indirect)
void setInAllocaSRet(bool SRet)
static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T=nullptr)
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr)
static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, llvm::Type *unpaddedCoerceToType)
unsigned getInAllocaIndirect() const
llvm::Type * getCoerceToType() const
void setInAllocaFieldIndex(unsigned FieldIndex)
IndirectAttrInfo IndirectAttr
llvm::Type * UnpaddedCoerceAndExpandType
void setCanBeFlattened(bool Flatten)
void setDirectAlign(unsigned Align)
static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T=nullptr)
CharUnits getIndirectAlign() const
static ABIArgInfo getDirectInReg(llvm::Type *T=nullptr)
CGFunctionInfo - Class to encapsulate the information about a function definition.
bool usesInAlloca() const
Return true if this function uses inalloca arguments.
FunctionType::ExtInfo getExtInfo() const
bool isReturnsRetained() const
In ARC, whether this function retains its return value.
unsigned getCallingConvention() const
getCallingConvention - Return the user specified calling convention, which has been translated into a...
void Profile(llvm::FoldingSetNodeID &ID)
const_arg_iterator arg_begin() const
bool isNoCallerSavedRegs() const
Whether this function no longer saves caller registers.
ArrayRef< ExtParameterInfo > getExtParameterInfos() const
CanQualType getReturnType() const
bool isNoCfCheck() const
Whether this function has nocf_check attribute.
CallingConv getASTCallingConvention() const
getASTCallingConvention() - Return the AST-specified calling convention.
const ABIArgInfo & getReturnInfo() const
ArrayRef< ArgInfo > arguments() const
static CGFunctionInfo * create(unsigned llvmCC, bool instanceMethod, bool chainCall, bool delegateCall, const FunctionType::ExtInfo &extInfo, ArrayRef< ExtParameterInfo > paramInfos, CanQualType resultType, ArrayRef< CanQualType > argTypes, RequiredArgs required)
Definition: CGCall.cpp:895
static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod, bool ChainCall, bool IsDelegateCall, const FunctionType::ExtInfo &info, ArrayRef< ExtParameterInfo > paramInfos, RequiredArgs required, CanQualType resultType, ArrayRef< CanQualType > argTypes)
MutableArrayRef< ArgInfo > arguments()
const_arg_iterator arg_end() const
unsigned getEffectiveCallingConvention() const
getEffectiveCallingConvention - Return the actual calling convention to use, which may depend on the ...
void setArgStruct(llvm::StructType *Ty, CharUnits Align)
size_t numTrailingObjects(OverloadToken< ArgInfo >) const
ExtParameterInfo getExtParameterInfo(unsigned argIndex) const
unsigned getMaxVectorWidth() const
Return the maximum vector width in the arguments.
CharUnits getArgStructAlignment() const
size_t numTrailingObjects(OverloadToken< ExtParameterInfo >) const
RequiredArgs getRequiredArgs() const
void setEffectiveCallingConvention(unsigned Value)
unsigned getNumRequiredArgs() const
llvm::StructType * getArgStruct() const
Get the struct type used to represent all the arguments in memory.
void setMaxVectorWidth(unsigned Width)
Set the maximum vector width in the arguments.
A class for recording the number of arguments that a function signature requires.
static RequiredArgs forPrototypePlus(CanQual< FunctionProtoType > prototype, unsigned additional)
unsigned getNumRequiredArgs() const
static RequiredArgs forPrototype(CanQual< FunctionProtoType > prototype)
static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
static RequiredArgs getFromOpaqueData(unsigned value)
bool isRequiredArg(unsigned argIdx) const
Return true if the argument at a given index is required.
static RequiredArgs forPrototype(const FunctionProtoType *prototype)
unsigned getOpaqueData() const
Represents a prototype with parameter type info, e.g.
Definition: TypeBase.h:5282
unsigned getNumParams() const
Definition: TypeBase.h:5560
bool isVariadic() const
Whether this function prototype is variadic.
Definition: TypeBase.h:5686
ArrayRef< ExtParameterInfo > getExtParameterInfos() const
Definition: TypeBase.h:5755
bool hasExtParameterInfos() const
Is there any interesting extra information for any of the parameters of this function type?
Definition: TypeBase.h:5751
A class which abstracts out some details necessary for making a call.
Definition: TypeBase.h:4589
CallingConv getCC() const
Definition: TypeBase.h:4648
unsigned getRegParm() const
Definition: TypeBase.h:4641
bool getNoCallerSavedRegs() const
Definition: TypeBase.h:4637
bool getProducesResult() const
Definition: TypeBase.h:4635
Interesting information about a specific parameter that can't simply be reflected in parameter's type...
Definition: TypeBase.h:4504
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: TypeBase.h:9054
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2247
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
CallingConv
CallingConv - Specifies the calling convention that a function uses.
Definition: Specifiers.h:278
#define false
Definition: stdbool.h:26