1 | //===--- Builtins.h - Builtin function header -------------------*- C++ -*-===// |
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 | /// \file |
10 | /// Defines enum values for all the target-independent builtin |
11 | /// functions. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_CLANG_BASIC_BUILTINS_H |
16 | #define LLVM_CLANG_BASIC_BUILTINS_H |
17 | |
18 | #include "llvm/ADT/ArrayRef.h" |
19 | #include "llvm/ADT/StringMap.h" |
20 | #include "llvm/ADT/StringRef.h" |
21 | #include <cstring> |
22 | |
23 | // VC++ defines 'alloca' as an object-like macro, which interferes with our |
24 | // builtins. |
25 | #undef alloca |
26 | |
27 | namespace clang { |
28 | class TargetInfo; |
29 | class IdentifierTable; |
30 | class LangOptions; |
31 | |
32 | enum LanguageID : uint16_t { |
33 | GNU_LANG = 0x1, // builtin requires GNU mode. |
34 | C_LANG = 0x2, // builtin for c only. |
35 | CXX_LANG = 0x4, // builtin for cplusplus only. |
36 | OBJC_LANG = 0x8, // builtin for objective-c and objective-c++ |
37 | MS_LANG = 0x10, // builtin requires MS mode. |
38 | OMP_LANG = 0x20, // builtin requires OpenMP. |
39 | CUDA_LANG = 0x40, // builtin requires CUDA. |
40 | COR_LANG = 0x80, // builtin requires use of 'fcoroutine-ts' option. |
41 | OCL_GAS = 0x100, // builtin requires OpenCL generic address space. |
42 | OCL_PIPE = 0x200, // builtin requires OpenCL pipe. |
43 | OCL_DSE = 0x400, // builtin requires OpenCL device side enqueue. |
44 | ALL_OCL_LANGUAGES = 0x800, // builtin for OCL languages. |
45 | HLSL_LANG = 0x1000, // builtin requires HLSL. |
46 | ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages. |
47 | ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode. |
48 | ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode. |
49 | }; |
50 | |
51 | struct { |
52 | enum : uint16_t { |
53 | #define (ID, NAME) ID, |
54 | #include "clang/Basic/BuiltinHeaders.def" |
55 | #undef HEADER |
56 | } ; |
57 | |
58 | constexpr (HeaderID ID) : ID(ID) {} |
59 | |
60 | const char *() const; |
61 | }; |
62 | |
63 | namespace Builtin { |
64 | enum ID { |
65 | NotBuiltin = 0, // This is not a builtin function. |
66 | #define BUILTIN(ID, TYPE, ATTRS) BI##ID, |
67 | #include "clang/Basic/Builtins.inc" |
68 | FirstTSBuiltin |
69 | }; |
70 | |
71 | struct Info { |
72 | llvm::StringLiteral Name; |
73 | const char *Type, *Attributes; |
74 | const char *Features; |
75 | HeaderDesc ; |
76 | LanguageID Langs; |
77 | }; |
78 | |
79 | /// Holds information about both target-independent and |
80 | /// target-specific builtins, allowing easy queries by clients. |
81 | /// |
82 | /// Builtins from an optional auxiliary target are stored in |
83 | /// AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to |
84 | /// be translated back with getAuxBuiltinID() before use. |
85 | class Context { |
86 | llvm::ArrayRef<Info> TSRecords; |
87 | llvm::ArrayRef<Info> AuxTSRecords; |
88 | |
89 | public: |
90 | Context() = default; |
91 | |
92 | /// Perform target-specific initialization |
93 | /// \param AuxTarget Target info to incorporate builtins from. May be nullptr. |
94 | void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget); |
95 | |
96 | /// Mark the identifiers for all the builtins with their |
97 | /// appropriate builtin ID # and mark any non-portable builtin identifiers as |
98 | /// such. |
99 | void initializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts); |
100 | |
101 | /// Return the identifier name for the specified builtin, |
102 | /// e.g. "__builtin_abs". |
103 | llvm::StringRef getName(unsigned ID) const { return getRecord(ID).Name; } |
104 | |
105 | /// Get the type descriptor string for the specified builtin. |
106 | const char *getTypeString(unsigned ID) const { |
107 | return getRecord(ID).Type; |
108 | } |
109 | |
110 | /// Return true if this function is a target-specific builtin. |
111 | bool isTSBuiltin(unsigned ID) const { |
112 | return ID >= Builtin::FirstTSBuiltin; |
113 | } |
114 | |
115 | /// Return true if this function has no side effects. |
116 | bool isPure(unsigned ID) const { |
117 | return strchr(s: getRecord(ID).Attributes, c: 'U') != nullptr; |
118 | } |
119 | |
120 | /// Return true if this function has no side effects and doesn't |
121 | /// read memory. |
122 | bool isConst(unsigned ID) const { |
123 | return strchr(s: getRecord(ID).Attributes, c: 'c') != nullptr; |
124 | } |
125 | |
126 | /// Return true if we know this builtin never throws an exception. |
127 | bool isNoThrow(unsigned ID) const { |
128 | return strchr(s: getRecord(ID).Attributes, c: 'n') != nullptr; |
129 | } |
130 | |
131 | /// Return true if we know this builtin never returns. |
132 | bool isNoReturn(unsigned ID) const { |
133 | return strchr(s: getRecord(ID).Attributes, c: 'r') != nullptr; |
134 | } |
135 | |
136 | /// Return true if we know this builtin can return twice. |
137 | bool isReturnsTwice(unsigned ID) const { |
138 | return strchr(s: getRecord(ID).Attributes, c: 'j') != nullptr; |
139 | } |
140 | |
141 | /// Returns true if this builtin does not perform the side-effects |
142 | /// of its arguments. |
143 | bool isUnevaluated(unsigned ID) const { |
144 | return strchr(s: getRecord(ID).Attributes, c: 'u') != nullptr; |
145 | } |
146 | |
147 | /// Return true if this is a builtin for a libc/libm function, |
148 | /// with a "__builtin_" prefix (e.g. __builtin_abs). |
149 | bool isLibFunction(unsigned ID) const { |
150 | return strchr(s: getRecord(ID).Attributes, c: 'F') != nullptr; |
151 | } |
152 | |
153 | /// Determines whether this builtin is a predefined libc/libm |
154 | /// function, such as "malloc", where we know the signature a |
155 | /// priori. |
156 | /// In C, such functions behave as if they are predeclared, |
157 | /// possibly with a warning on first use. In Objective-C and C++, |
158 | /// they do not, but they are recognized as builtins once we see |
159 | /// a declaration. |
160 | bool isPredefinedLibFunction(unsigned ID) const { |
161 | return strchr(s: getRecord(ID).Attributes, c: 'f') != nullptr; |
162 | } |
163 | |
164 | /// Returns true if this builtin requires appropriate header in other |
165 | /// compilers. In Clang it will work even without including it, but we can emit |
166 | /// a warning about missing header. |
167 | bool (unsigned ID) const { |
168 | return strchr(s: getRecord(ID).Attributes, c: 'h') != nullptr; |
169 | } |
170 | |
171 | /// Determines whether this builtin is a predefined compiler-rt/libgcc |
172 | /// function, such as "__clear_cache", where we know the signature a |
173 | /// priori. |
174 | bool isPredefinedRuntimeFunction(unsigned ID) const { |
175 | return strchr(s: getRecord(ID).Attributes, c: 'i') != nullptr; |
176 | } |
177 | |
178 | /// Determines whether this builtin is a C++ standard library function |
179 | /// that lives in (possibly-versioned) namespace std, possibly a template |
180 | /// specialization, where the signature is determined by the standard library |
181 | /// declaration. |
182 | bool isInStdNamespace(unsigned ID) const { |
183 | return strchr(s: getRecord(ID).Attributes, c: 'z') != nullptr; |
184 | } |
185 | |
186 | /// Determines whether this builtin can have its address taken with no |
187 | /// special action required. |
188 | bool isDirectlyAddressable(unsigned ID) const { |
189 | // Most standard library functions can have their addresses taken. C++ |
190 | // standard library functions formally cannot in C++20 onwards, and when |
191 | // we allow it, we need to ensure we instantiate a definition. |
192 | return isPredefinedLibFunction(ID) && !isInStdNamespace(ID); |
193 | } |
194 | |
195 | /// Determines whether this builtin has custom typechecking. |
196 | bool hasCustomTypechecking(unsigned ID) const { |
197 | return strchr(s: getRecord(ID).Attributes, c: 't') != nullptr; |
198 | } |
199 | |
200 | /// Determines whether a declaration of this builtin should be recognized |
201 | /// even if the type doesn't match the specified signature. |
202 | bool allowTypeMismatch(unsigned ID) const { |
203 | return strchr(s: getRecord(ID).Attributes, c: 'T') != nullptr || |
204 | hasCustomTypechecking(ID); |
205 | } |
206 | |
207 | /// Determines whether this builtin has a result or any arguments which |
208 | /// are pointer types. |
209 | bool hasPtrArgsOrResult(unsigned ID) const { |
210 | return strchr(s: getRecord(ID).Type, c: '*') != nullptr; |
211 | } |
212 | |
213 | /// Return true if this builtin has a result or any arguments which are |
214 | /// reference types. |
215 | bool hasReferenceArgsOrResult(unsigned ID) const { |
216 | return strchr(s: getRecord(ID).Type, c: '&') != nullptr || |
217 | strchr(s: getRecord(ID).Type, c: 'A') != nullptr; |
218 | } |
219 | |
220 | /// If this is a library function that comes from a specific |
221 | /// header, retrieve that header name. |
222 | const char *(unsigned ID) const { |
223 | return getRecord(ID).Header.getName(); |
224 | } |
225 | |
226 | /// Determine whether this builtin is like printf in its |
227 | /// formatting rules and, if so, set the index to the format string |
228 | /// argument and whether this function as a va_list argument. |
229 | bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); |
230 | |
231 | /// Determine whether this builtin is like scanf in its |
232 | /// formatting rules and, if so, set the index to the format string |
233 | /// argument and whether this function as a va_list argument. |
234 | bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); |
235 | |
236 | /// Determine whether this builtin has callback behavior (see |
237 | /// llvm::AbstractCallSites for details). If so, add the index to the |
238 | /// callback callee argument and the callback payload arguments. |
239 | bool performsCallback(unsigned ID, |
240 | llvm::SmallVectorImpl<int> &Encoding) const; |
241 | |
242 | /// Return true if this function has no side effects and doesn't |
243 | /// read memory, except for possibly errno or raising FP exceptions. |
244 | /// |
245 | /// Such functions can be const when the MathErrno lang option and FP |
246 | /// exceptions are disabled. |
247 | bool isConstWithoutErrnoAndExceptions(unsigned ID) const { |
248 | return strchr(s: getRecord(ID).Attributes, c: 'e') != nullptr; |
249 | } |
250 | |
251 | bool isConstWithoutExceptions(unsigned ID) const { |
252 | return strchr(s: getRecord(ID).Attributes, c: 'g') != nullptr; |
253 | } |
254 | |
255 | const char *getRequiredFeatures(unsigned ID) const { |
256 | return getRecord(ID).Features; |
257 | } |
258 | |
259 | unsigned getRequiredVectorWidth(unsigned ID) const; |
260 | |
261 | /// Return true if builtin ID belongs to AuxTarget. |
262 | bool isAuxBuiltinID(unsigned ID) const { |
263 | return ID >= (Builtin::FirstTSBuiltin + TSRecords.size()); |
264 | } |
265 | |
266 | /// Return real builtin ID (i.e. ID it would have during compilation |
267 | /// for AuxTarget). |
268 | unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); } |
269 | |
270 | /// Returns true if this is a libc/libm function without the '__builtin_' |
271 | /// prefix. |
272 | static bool isBuiltinFunc(llvm::StringRef Name); |
273 | |
274 | /// Returns true if this is a builtin that can be redeclared. Returns true |
275 | /// for non-builtins. |
276 | bool canBeRedeclared(unsigned ID) const; |
277 | |
278 | /// Return true if this function can be constant evaluated by Clang frontend. |
279 | bool isConstantEvaluated(unsigned ID) const { |
280 | return strchr(s: getRecord(ID).Attributes, c: 'E') != nullptr; |
281 | } |
282 | |
283 | private: |
284 | const Info &getRecord(unsigned ID) const; |
285 | |
286 | /// Helper function for isPrintfLike and isScanfLike. |
287 | bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg, |
288 | const char *Fmt) const; |
289 | }; |
290 | |
291 | /// Returns true if the required target features of a builtin function are |
292 | /// enabled. |
293 | /// \p TargetFeatureMap maps a target feature to true if it is enabled and |
294 | /// false if it is disabled. |
295 | bool evaluateRequiredTargetFeatures( |
296 | llvm::StringRef RequiredFatures, |
297 | const llvm::StringMap<bool> &TargetFetureMap); |
298 | |
299 | } // namespace Builtin |
300 | |
301 | /// Kinds of BuiltinTemplateDecl. |
302 | enum BuiltinTemplateKind : int { |
303 | /// This names the __make_integer_seq BuiltinTemplateDecl. |
304 | BTK__make_integer_seq, |
305 | |
306 | /// This names the __type_pack_element BuiltinTemplateDecl. |
307 | BTK__type_pack_element |
308 | }; |
309 | |
310 | } // end namespace clang |
311 | #endif |
312 | |