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