1//==-- CIRGenFunctionInfo.h - Representation of fn 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 CIRGenFunctionInfo and associated types used in representing the
10// CIR source types and ABI-coerced types for function arguments and
11// return values.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
16#define LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
17
18#include "clang/AST/CanonicalType.h"
19#include "clang/CIR/MissingFeatures.h"
20#include "llvm/ADT/FoldingSet.h"
21#include "llvm/Support/TrailingObjects.h"
22
23namespace clang::CIRGen {
24
25/// A class for recording the number of arguments that a function signature
26/// requires.
27class RequiredArgs {
28 /// The number of required arguments, or ~0 if the signature does not permit
29 /// optional arguments.
30 unsigned numRequired;
31
32public:
33 enum All_t { All };
34
35 RequiredArgs(All_t _) : numRequired(~0U) {}
36 explicit RequiredArgs(unsigned n) : numRequired(n) { assert(n != ~0U); }
37
38 unsigned getOpaqueData() const { return numRequired; }
39
40 bool allowsOptionalArgs() const { return numRequired != ~0U; }
41
42 /// Compute the arguments required by the given formal prototype, given that
43 /// there may be some additional, non-formal arguments in play.
44 ///
45 /// If FD is not null, this will consider pass_object_size params in FD.
46 static RequiredArgs
47 getFromProtoWithExtraSlots(const clang::FunctionProtoType *prototype,
48 unsigned additional) {
49 if (!prototype->isVariadic())
50 return All;
51
52 if (prototype->hasExtParameterInfos())
53 llvm_unreachable("NYI");
54
55 return RequiredArgs(prototype->getNumParams() + additional);
56 }
57
58 static RequiredArgs
59 getFromProtoWithExtraSlots(clang::CanQual<clang::FunctionProtoType> prototype,
60 unsigned additional) {
61 return getFromProtoWithExtraSlots(prototype: prototype.getTypePtr(), additional);
62 }
63
64 unsigned getNumRequiredArgs() const {
65 assert(allowsOptionalArgs());
66 return numRequired;
67 }
68};
69
70// The TrailingObjects for this class contain the function return type in the
71// first CanQualType slot, followed by the argument types.
72class CIRGenFunctionInfo final
73 : public llvm::FoldingSetNode,
74 private llvm::TrailingObjects<CIRGenFunctionInfo, CanQualType> {
75 RequiredArgs required;
76
77 unsigned numArgs;
78
79 CanQualType *getArgTypes() { return getTrailingObjects(); }
80 const CanQualType *getArgTypes() const { return getTrailingObjects(); }
81
82 CIRGenFunctionInfo() : required(RequiredArgs::All) {}
83
84public:
85 static CIRGenFunctionInfo *create(CanQualType resultType,
86 llvm::ArrayRef<CanQualType> argTypes,
87 RequiredArgs required);
88
89 void operator delete(void *p) { ::operator delete(p); }
90
91 // Friending class TrailingObjects is apparantly not good enough for MSVC, so
92 // these have to be public.
93 friend class TrailingObjects;
94
95 using const_arg_iterator = const CanQualType *;
96 using arg_iterator = CanQualType *;
97
98 // This function has to be CamelCase because llvm::FoldingSet requires so.
99 // NOLINTNEXTLINE(readability-identifier-naming)
100 static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required,
101 CanQualType resultType,
102 llvm::ArrayRef<CanQualType> argTypes) {
103 id.AddBoolean(B: required.getOpaqueData());
104 resultType.Profile(ID&: id);
105 for (const CanQualType &arg : argTypes)
106 arg.Profile(ID&: id);
107 }
108
109 // NOLINTNEXTLINE(readability-identifier-naming)
110 void Profile(llvm::FoldingSetNodeID &id) {
111 // If the Profile functions get out of sync, we can end up with incorrect
112 // function signatures, so we call the static Profile function here rather
113 // than duplicating the logic.
114 Profile(id, required, resultType: getReturnType(), argTypes: arguments());
115 }
116
117 llvm::ArrayRef<CanQualType> arguments() const {
118 return llvm::ArrayRef<CanQualType>(argTypesBegin(), numArgs);
119 }
120
121 llvm::ArrayRef<CanQualType> requiredArguments() const {
122 return llvm::ArrayRef<CanQualType>(argTypesBegin(), getNumRequiredArgs());
123 }
124
125 CanQualType getReturnType() const { return getArgTypes()[0]; }
126
127 const_arg_iterator argTypesBegin() const { return getArgTypes() + 1; }
128 const_arg_iterator argTypesEnd() const { return getArgTypes() + 1 + numArgs; }
129 arg_iterator argTypesBegin() { return getArgTypes() + 1; }
130 arg_iterator argTypesEnd() { return getArgTypes() + 1 + numArgs; }
131
132 unsigned argTypeSize() const { return numArgs; }
133
134 llvm::MutableArrayRef<CanQualType> argTypes() {
135 return llvm::MutableArrayRef<CanQualType>(argTypesBegin(), numArgs);
136 }
137 llvm::ArrayRef<CanQualType> argTypes() const {
138 return llvm::ArrayRef<CanQualType>(argTypesBegin(), numArgs);
139 }
140
141 bool isVariadic() const { return required.allowsOptionalArgs(); }
142 RequiredArgs getRequiredArgs() const { return required; }
143 unsigned getNumRequiredArgs() const {
144 return isVariadic() ? getRequiredArgs().getNumRequiredArgs()
145 : argTypeSize();
146 }
147};
148
149} // namespace clang::CIRGen
150
151#endif
152

source code of clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h