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 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
166 auto AI = ABIArgInfo(Extend);
167 AI.setCoerceToType(T);
168 AI.setPaddingType(nullptr);
169 AI.setDirectOffset(0);
170 AI.setDirectAlign(0);
171 AI.setSignExt(true);
172 return AI;
173 }
174
175 static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) {
176 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
177 auto AI = ABIArgInfo(Extend);
178 AI.setCoerceToType(T);
179 AI.setPaddingType(nullptr);
180 AI.setDirectOffset(0);
181 AI.setDirectAlign(0);
182 AI.setZeroExt(true);
183 return AI;
184 }
185
186 // ABIArgInfo will record the argument as being extended based on the sign
187 // of its type. Produces a sign or zero extension.
188 static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
189 assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
191 return getSignExtend(Ty, T);
192 return getZeroExtend(Ty, T);
193 }
194
195 // Struct in register marked explicitly as not needing extension.
196 static ABIArgInfo getNoExtend(llvm::IntegerType *T) {
197 auto AI = ABIArgInfo(Extend);
198 AI.setCoerceToType(T);
199 AI.setPaddingType(nullptr);
200 AI.setDirectOffset(0);
201 AI.setDirectAlign(0);
202 return AI;
203 }
204
205 static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
206 auto AI = getExtend(Ty, T);
207 AI.setInReg(true);
208 return AI;
209 }
211 return ABIArgInfo(Ignore);
212 }
213 static ABIArgInfo getIndirect(CharUnits Alignment, unsigned AddrSpace,
214 bool ByVal = true, bool Realign = false,
215 llvm::Type *Padding = nullptr) {
216 auto AI = ABIArgInfo(Indirect);
217 AI.setIndirectAlign(Alignment);
218 AI.setIndirectByVal(ByVal);
219 AI.setIndirectRealign(Realign);
220 AI.setSRetAfterThis(false);
221 AI.setPaddingType(Padding);
222 AI.setIndirectAddrSpace(AddrSpace);
223 return AI;
224 }
225
226 /// Pass this in memory using the IR byref attribute.
227 static ABIArgInfo getIndirectAliased(CharUnits Alignment, unsigned AddrSpace,
228 bool Realign = false,
229 llvm::Type *Padding = nullptr) {
230 auto AI = ABIArgInfo(IndirectAliased);
231 AI.setIndirectAlign(Alignment);
232 AI.setIndirectRealign(Realign);
233 AI.setPaddingType(Padding);
234 AI.setIndirectAddrSpace(AddrSpace);
235 return AI;
236 }
237
238 static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
239 bool Realign = false) {
240 auto AI = getIndirect(Alignment, 0, ByVal, Realign);
241 AI.setInReg(true);
242 return AI;
243 }
244 static ABIArgInfo getInAlloca(unsigned FieldIndex, bool Indirect = false) {
245 auto AI = ABIArgInfo(InAlloca);
246 AI.setInAllocaFieldIndex(FieldIndex);
247 AI.setInAllocaIndirect(Indirect);
248 return AI;
249 }
251 auto AI = ABIArgInfo(Expand);
252 AI.setPaddingType(nullptr);
253 return AI;
254 }
255 static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
256 llvm::Type *Padding) {
257 auto AI = getExpand();
258 AI.setPaddingInReg(PaddingInReg);
259 AI.setPaddingType(Padding);
260 return AI;
261 }
262
263 /// \param unpaddedCoerceToType The coerce-to type with padding elements
264 /// removed, canonicalized to a single element if it would otherwise
265 /// have exactly one element.
266 static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
267 llvm::Type *unpaddedCoerceToType) {
268#ifndef NDEBUG
269 // Check that unpaddedCoerceToType has roughly the right shape.
270
271 // Assert that we only have a struct type if there are multiple elements.
272 auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType);
273 assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1);
274
275 // Assert that all the non-padding elements have a corresponding element
276 // in the unpadded type.
277 unsigned unpaddedIndex = 0;
278 for (auto eltType : coerceToType->elements()) {
279 if (isPaddingForCoerceAndExpand(eltType))
280 continue;
281 unpaddedIndex++;
282 }
283
284 // Assert that there aren't extra elements in the unpadded type.
285 if (unpaddedStruct) {
286 assert(unpaddedStruct->getNumElements() == unpaddedIndex);
287 } else {
288 assert(unpaddedIndex == 1);
289 }
290#endif
291
292 auto AI = ABIArgInfo(CoerceAndExpand);
293 AI.setCoerceToType(coerceToType);
294 AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
295 return AI;
296 }
297
298 static ABIArgInfo getTargetSpecific(llvm::Type *T = nullptr,
299 unsigned Offset = 0,
300 llvm::Type *Padding = nullptr,
301 bool CanBeFlattened = true,
302 unsigned Align = 0) {
303 auto AI = ABIArgInfo(TargetSpecific);
304 AI.setCoerceToType(T);
305 AI.setPaddingType(Padding);
306 AI.setDirectOffset(Offset);
307 AI.setDirectAlign(Align);
308 AI.setCanBeFlattened(CanBeFlattened);
309 return AI;
310 }
311
312 static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) {
313 return eltType->isArrayTy() &&
314 eltType->getArrayElementType()->isIntegerTy(8);
315 }
316
317 Kind getKind() const { return TheKind; }
318 bool isDirect() const { return TheKind == Direct; }
319 bool isInAlloca() const { return TheKind == InAlloca; }
320 bool isExtend() const { return TheKind == Extend; }
321 bool isIgnore() const { return TheKind == Ignore; }
322 bool isIndirect() const { return TheKind == Indirect; }
323 bool isIndirectAliased() const { return TheKind == IndirectAliased; }
324 bool isExpand() const { return TheKind == Expand; }
325 bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
326 bool isTargetSpecific() const { return TheKind == TargetSpecific; }
327
328 bool canHaveCoerceToType() const {
329 return isDirect() || isExtend() || isCoerceAndExpand() ||
331 }
332
333 // Direct/Extend accessors
334 unsigned getDirectOffset() const {
335 assert((isDirect() || isExtend() || isTargetSpecific()) &&
336 "Not a direct or extend or target specific kind");
337 return DirectAttr.Offset;
338 }
339 void setDirectOffset(unsigned Offset) {
340 assert((isDirect() || isExtend() || isTargetSpecific()) &&
341 "Not a direct or extend or target specific kind");
342 DirectAttr.Offset = Offset;
343 }
344
345 unsigned getDirectAlign() const {
346 assert((isDirect() || isExtend() || isTargetSpecific()) &&
347 "Not a direct or extend or target specific kind");
348 return DirectAttr.Align;
349 }
350 void setDirectAlign(unsigned Align) {
351 assert((isDirect() || isExtend() || isTargetSpecific()) &&
352 "Not a direct or extend or target specific kind");
353 DirectAttr.Align = Align;
354 }
355
356 bool isSignExt() const {
357 assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
358 return SignExt;
359 }
360 void setSignExt(bool SExt) {
361 assert(isExtend() && "Invalid kind!");
362 SignExt = SExt;
363 }
364
365 bool isZeroExt() const {
366 assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
367 return ZeroExt;
368 }
369 void setZeroExt(bool ZExt) {
370 assert(isExtend() && "Invalid kind!");
371 ZeroExt = ZExt;
372 }
373
374 bool isNoExt() const {
375 assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
376 return !SignExt && !ZeroExt;
377 }
378
379 llvm::Type *getPaddingType() const {
380 return (canHavePaddingType() ? PaddingType : nullptr);
381 }
382
383 bool getPaddingInReg() const {
384 return PaddingInReg;
385 }
386 void setPaddingInReg(bool PIR) {
387 PaddingInReg = PIR;
388 }
389
390 llvm::Type *getCoerceToType() const {
391 assert(canHaveCoerceToType() && "Invalid kind!");
392 return TypeData;
393 }
394
395 void setCoerceToType(llvm::Type *T) {
396 assert(canHaveCoerceToType() && "Invalid kind!");
397 TypeData = T;
398 }
399
400 llvm::StructType *getCoerceAndExpandType() const {
401 assert(isCoerceAndExpand());
402 return cast<llvm::StructType>(TypeData);
403 }
404
405 llvm::Type *getUnpaddedCoerceAndExpandType() const {
406 assert(isCoerceAndExpand());
408 }
409
411 assert(isCoerceAndExpand());
412 if (auto structTy =
413 dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) {
414 return structTy->elements();
415 } else {
417 }
418 }
419
420 bool getInReg() const {
421 assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
422 "Invalid kind!");
423 return InReg;
424 }
425
426 void setInReg(bool IR) {
427 assert((isDirect() || isExtend() || isIndirect() || isTargetSpecific()) &&
428 "Invalid kind!");
429 InReg = IR;
430 }
431
432 // Indirect accessors
434 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
436 }
438 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
439 IndirectAttr.Align = IA.getQuantity();
440 }
441
442 bool getIndirectByVal() const {
443 assert(isIndirect() && "Invalid kind!");
444 return IndirectByVal;
445 }
446 void setIndirectByVal(bool IBV) {
447 assert(isIndirect() && "Invalid kind!");
448 IndirectByVal = IBV;
449 }
450
451 unsigned getIndirectAddrSpace() const {
452 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
453 return IndirectAttr.AddrSpace;
454 }
455
456 void setIndirectAddrSpace(unsigned AddrSpace) {
457 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
458 IndirectAttr.AddrSpace = AddrSpace;
459 }
460
461 bool getIndirectRealign() const {
462 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
463 return IndirectRealign;
464 }
465 void setIndirectRealign(bool IR) {
466 assert((isIndirect() || isIndirectAliased()) && "Invalid kind!");
467 IndirectRealign = IR;
468 }
469
470 bool isSRetAfterThis() const {
471 assert(isIndirect() && "Invalid kind!");
472 return SRetAfterThis;
473 }
474 void setSRetAfterThis(bool AfterThis) {
475 assert(isIndirect() && "Invalid kind!");
476 SRetAfterThis = AfterThis;
477 }
478
479 unsigned getInAllocaFieldIndex() const {
480 assert(isInAlloca() && "Invalid kind!");
481 return AllocaFieldIndex;
482 }
483 void setInAllocaFieldIndex(unsigned FieldIndex) {
484 assert(isInAlloca() && "Invalid kind!");
485 AllocaFieldIndex = FieldIndex;
486 }
487
488 unsigned getInAllocaIndirect() const {
489 assert(isInAlloca() && "Invalid kind!");
490 return InAllocaIndirect;
491 }
493 assert(isInAlloca() && "Invalid kind!");
494 InAllocaIndirect = Indirect;
495 }
496
497 /// Return true if this field of an inalloca struct should be returned
498 /// to implement a struct return calling convention.
499 bool getInAllocaSRet() const {
500 assert(isInAlloca() && "Invalid kind!");
501 return InAllocaSRet;
502 }
503
504 void setInAllocaSRet(bool SRet) {
505 assert(isInAlloca() && "Invalid kind!");
506 InAllocaSRet = SRet;
507 }
508
509 bool getCanBeFlattened() const {
510 assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
511 return CanBeFlattened;
512 }
513
514 void setCanBeFlattened(bool Flatten) {
515 assert((isDirect() || isTargetSpecific()) && "Invalid kind!");
516 CanBeFlattened = Flatten;
517 }
518
519 void dump() const;
520};
521
522/// A class for recording the number of arguments that a function
523/// signature requires.
525 /// The number of required arguments, or ~0 if the signature does
526 /// not permit optional arguments.
527 unsigned NumRequired;
528public:
529 enum All_t { All };
530
531 RequiredArgs(All_t _) : NumRequired(~0U) {}
532 explicit RequiredArgs(unsigned n) : NumRequired(n) {
533 assert(n != ~0U);
534 }
535
536 /// Compute the arguments required by the given formal prototype,
537 /// given that there may be some additional, non-formal arguments
538 /// in play.
539 ///
540 /// If FD is not null, this will consider pass_object_size params in FD.
542 unsigned additional) {
543 if (!prototype->isVariadic()) return All;
544
545 if (prototype->hasExtParameterInfos())
546 additional += llvm::count_if(
547 prototype->getExtParameterInfos(),
548 [](const FunctionProtoType::ExtParameterInfo &ExtInfo) {
549 return ExtInfo.hasPassObjectSize();
550 });
551
552 return RequiredArgs(prototype->getNumParams() + additional);
553 }
554
556 unsigned additional) {
557 return forPrototypePlus(prototype.getTypePtr(), additional);
558 }
559
560 static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
561 return forPrototypePlus(prototype, 0);
562 }
563
565 return forPrototypePlus(prototype.getTypePtr(), 0);
566 }
567
568 bool allowsOptionalArgs() const { return NumRequired != ~0U; }
569 unsigned getNumRequiredArgs() const {
570 assert(allowsOptionalArgs());
571 return NumRequired;
572 }
573
574 /// Return true if the argument at a given index is required.
575 bool isRequiredArg(unsigned argIdx) const {
576 return argIdx == ~0U || argIdx < NumRequired;
577 }
578
579 unsigned getOpaqueData() const { return NumRequired; }
580 static RequiredArgs getFromOpaqueData(unsigned value) {
581 if (value == ~0U) return All;
582 return RequiredArgs(value);
583 }
584};
585
586// Implementation detail of CGFunctionInfo, factored out so it can be named
587// in the TrailingObjects base class of CGFunctionInfo.
592
593/// CGFunctionInfo - Class to encapsulate the information about a
594/// function definition.
595class CGFunctionInfo final
596 : public llvm::FoldingSetNode,
597 private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo,
598 FunctionProtoType::ExtParameterInfo> {
599 typedef CGFunctionInfoArgInfo ArgInfo;
600 typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo;
601
602 /// The LLVM::CallingConv to use for this function (as specified by the
603 /// user).
604 unsigned CallingConvention : 8;
605
606 /// The LLVM::CallingConv to actually use for this function, which may
607 /// depend on the ABI.
608 unsigned EffectiveCallingConvention : 8;
609
610 /// The clang::CallingConv that this was originally created with.
611 LLVM_PREFERRED_TYPE(CallingConv)
612 unsigned ASTCallingConvention : 6;
613
614 /// Whether this is an instance method.
615 LLVM_PREFERRED_TYPE(bool)
616 unsigned InstanceMethod : 1;
617
618 /// Whether this is a chain call.
619 LLVM_PREFERRED_TYPE(bool)
620 unsigned ChainCall : 1;
621
622 /// Whether this function is called by forwarding arguments.
623 /// This doesn't support inalloca or varargs.
624 LLVM_PREFERRED_TYPE(bool)
625 unsigned DelegateCall : 1;
626
627 /// Whether this function is a CMSE nonsecure call
628 LLVM_PREFERRED_TYPE(bool)
629 unsigned CmseNSCall : 1;
630
631 /// Whether this function is noreturn.
632 LLVM_PREFERRED_TYPE(bool)
633 unsigned NoReturn : 1;
634
635 /// Whether this function is returns-retained.
636 LLVM_PREFERRED_TYPE(bool)
637 unsigned ReturnsRetained : 1;
638
639 /// Whether this function saved caller registers.
640 LLVM_PREFERRED_TYPE(bool)
641 unsigned NoCallerSavedRegs : 1;
642
643 /// How many arguments to pass inreg.
644 LLVM_PREFERRED_TYPE(bool)
645 unsigned HasRegParm : 1;
646 unsigned RegParm : 3;
647
648 /// Whether this function has nocf_check attribute.
649 LLVM_PREFERRED_TYPE(bool)
650 unsigned NoCfCheck : 1;
651
652 /// Log 2 of the maximum vector width.
653 unsigned MaxVectorWidth : 4;
654
655 /// X86 AVX Level, can be different from global / module level AVX level
656 /// because of target attributes.
657 unsigned X86ABIAVXLevel = 0;
658
659 RequiredArgs Required;
660
661 /// The struct representing all arguments passed in memory. Only used when
662 /// passing non-trivial types with inalloca. Not part of the profile.
663 llvm::StructType *ArgStruct;
664 unsigned ArgStructAlign : 31;
665 LLVM_PREFERRED_TYPE(bool)
666 unsigned HasExtParameterInfos : 1;
667
668 unsigned NumArgs;
669
670 ArgInfo *getArgsBuffer() {
671 return getTrailingObjects<ArgInfo>();
672 }
673 const ArgInfo *getArgsBuffer() const {
674 return getTrailingObjects<ArgInfo>();
675 }
676
677 ExtParameterInfo *getExtParameterInfosBuffer() {
678 return getTrailingObjects<ExtParameterInfo>();
679 }
680 const ExtParameterInfo *getExtParameterInfosBuffer() const{
681 return getTrailingObjects<ExtParameterInfo>();
682 }
683
684 CGFunctionInfo() : Required(RequiredArgs::All) {}
685
686public:
687 static CGFunctionInfo *
688 create(unsigned llvmCC, bool instanceMethod, bool chainCall,
689 bool delegateCall, unsigned X86ABIAVXLevel,
690 const FunctionType::ExtInfo &extInfo,
691 ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
692 ArrayRef<CanQualType> argTypes, RequiredArgs required);
693 void operator delete(void *p) { ::operator delete(p); }
694
695 // Friending class TrailingObjects is apparently not good enough for MSVC,
696 // so these have to be public.
697 friend class TrailingObjects;
698 size_t numTrailingObjects(OverloadToken<ArgInfo>) const {
699 return NumArgs + 1;
700 }
701 size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const {
702 return (HasExtParameterInfos ? NumArgs : 0);
703 }
704
705 typedef const ArgInfo *const_arg_iterator;
706 typedef ArgInfo *arg_iterator;
707
712 return ArrayRef<ArgInfo>(arg_begin(), NumArgs);
713 }
714
715 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
716 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
717 arg_iterator arg_begin() { return getArgsBuffer() + 1; }
718 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
719
720 unsigned arg_size() const { return NumArgs; }
721
722 bool isVariadic() const { return Required.allowsOptionalArgs(); }
723 RequiredArgs getRequiredArgs() const { return Required; }
724 unsigned getNumRequiredArgs() const {
726 }
727
728 bool isInstanceMethod() const { return InstanceMethod; }
729
730 bool isChainCall() const { return ChainCall; }
731
732 bool isDelegateCall() const { return DelegateCall; }
733
734 bool isCmseNSCall() const { return CmseNSCall; }
735
736 bool isNoReturn() const { return NoReturn; }
737
738 /// In ARC, whether this function retains its return value. This
739 /// is not always reliable for call sites.
740 bool isReturnsRetained() const { return ReturnsRetained; }
741
742 /// Whether this function no longer saves caller registers.
743 bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; }
744
745 /// Whether this function has nocf_check attribute.
746 bool isNoCfCheck() const { return NoCfCheck; }
747
748 /// getASTCallingConvention() - Return the AST-specified calling
749 /// convention.
751 return CallingConv(ASTCallingConvention);
752 }
753
754 /// getCallingConvention - Return the user specified calling
755 /// convention, which has been translated into an LLVM CC.
756 unsigned getCallingConvention() const { return CallingConvention; }
757
758 /// getEffectiveCallingConvention - Return the actual calling convention to
759 /// use, which may depend on the ABI.
761 return EffectiveCallingConvention;
762 }
764 EffectiveCallingConvention = Value;
765 }
766
767 bool getHasRegParm() const { return HasRegParm; }
768 unsigned getRegParm() const { return RegParm; }
769
776
777 CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
778
779 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
780 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
781
783 if (!HasExtParameterInfos) return {};
784 return llvm::ArrayRef(getExtParameterInfosBuffer(), NumArgs);
785 }
786 ExtParameterInfo getExtParameterInfo(unsigned argIndex) const {
787 assert(argIndex <= NumArgs);
788 if (!HasExtParameterInfos) return ExtParameterInfo();
789 return getExtParameterInfos()[argIndex];
790 }
791
792 /// Return true if this function uses inalloca arguments.
793 bool usesInAlloca() const { return ArgStruct; }
794
795 /// Get the struct type used to represent all the arguments in memory.
796 llvm::StructType *getArgStruct() const { return ArgStruct; }
798 return CharUnits::fromQuantity(ArgStructAlign);
799 }
800 void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
801 ArgStruct = Ty;
802 ArgStructAlign = Align.getQuantity();
803 }
804
805 /// Return the maximum vector width in the arguments.
806 unsigned getMaxVectorWidth() const {
807 return MaxVectorWidth ? 1U << (MaxVectorWidth - 1) : 0;
808 }
809
810 /// Set the maximum vector width in the arguments.
811 void setMaxVectorWidth(unsigned Width) {
812 assert(llvm::isPowerOf2_32(Width) && "Expected power of 2 vector");
813 MaxVectorWidth = llvm::countr_zero(Width) + 1;
814 }
815
816 unsigned getX86ABIAVXLevel() const { return X86ABIAVXLevel; }
817
818 void Profile(llvm::FoldingSetNodeID &ID) {
819 ID.AddInteger(getASTCallingConvention());
820 ID.AddBoolean(InstanceMethod);
821 ID.AddBoolean(ChainCall);
822 ID.AddBoolean(DelegateCall);
823 ID.AddBoolean(NoReturn);
824 ID.AddBoolean(ReturnsRetained);
825 ID.AddBoolean(NoCallerSavedRegs);
826 ID.AddBoolean(HasRegParm);
827 ID.AddInteger(RegParm);
828 ID.AddBoolean(NoCfCheck);
829 ID.AddBoolean(CmseNSCall);
830 ID.AddInteger(X86ABIAVXLevel);
831 ID.AddInteger(Required.getOpaqueData());
832 ID.AddBoolean(HasExtParameterInfos);
833 if (HasExtParameterInfos) {
834 for (auto paramInfo : getExtParameterInfos())
835 ID.AddInteger(paramInfo.getOpaqueValue());
836 }
838 for (const auto &I : arguments())
839 I.type.Profile(ID);
840 }
841 static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod,
842 bool ChainCall, bool IsDelegateCall,
843 unsigned X86ABIAVXLevel,
844 const FunctionType::ExtInfo &info,
846 RequiredArgs required, CanQualType resultType,
847 ArrayRef<CanQualType> argTypes) {
848 ID.AddInteger(info.getCC());
849 ID.AddBoolean(InstanceMethod);
850 ID.AddBoolean(ChainCall);
851 ID.AddBoolean(IsDelegateCall);
852 ID.AddBoolean(info.getNoReturn());
853 ID.AddBoolean(info.getProducesResult());
854 ID.AddBoolean(info.getNoCallerSavedRegs());
855 ID.AddBoolean(info.getHasRegParm());
856 ID.AddInteger(info.getRegParm());
857 ID.AddBoolean(info.getNoCfCheck());
858 ID.AddBoolean(info.getCmseNSCall());
859 ID.AddInteger(X86ABIAVXLevel);
860 ID.AddInteger(required.getOpaqueData());
861 ID.AddBoolean(!paramInfos.empty());
862 if (!paramInfos.empty()) {
863 for (auto paramInfo : paramInfos)
864 ID.AddInteger(paramInfo.getOpaqueValue());
865 }
866 resultType.Profile(ID);
867 for (const CanQualType &argType : argTypes)
868 argType.Profile(ID);
869 }
870};
871
872} // end namespace CodeGen
873} // end namespace clang
874
875#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 ...
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)
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 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)
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:1143
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:5406
unsigned getNumParams() const
Definition TypeBase.h:5684
bool isVariadic() const
Whether this function prototype is variadic.
Definition TypeBase.h:5810
ArrayRef< ExtParameterInfo > getExtParameterInfos() const
Definition TypeBase.h:5879
bool hasExtParameterInfos() const
Is there any interesting extra information for any of the parameters of this function type?
Definition TypeBase.h:5875
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4713
CallingConv getCC() const
Definition TypeBase.h:4772
unsigned getRegParm() const
Definition TypeBase.h:4765
bool getNoCallerSavedRegs() const
Definition TypeBase.h:4761
Interesting information about a specific parameter that can't simply be reflected in parameter's type...
Definition TypeBase.h:4628
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9214
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2314
The JSON file list parser is used to communicate input to InstallAPI.
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