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