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

source code of clang/include/clang/CodeGen/CGFunctionInfo.h