Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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 HeaderDesc { |
||
52 | enum HeaderID : uint16_t { |
||
53 | #define HEADER(ID, NAME) ID, |
||
54 | #include "clang/Basic/BuiltinHeaders.def" |
||
55 | #undef HEADER |
||
56 | } ID; |
||
57 | |||
58 | constexpr HeaderDesc(HeaderID ID) : ID(ID) {} |
||
59 | |||
60 | const char *getName() 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.def" |
||
68 | FirstTSBuiltin |
||
69 | }; |
||
70 | |||
71 | struct Info { |
||
72 | llvm::StringLiteral Name; |
||
73 | const char *Type, *Attributes; |
||
74 | const char *Features; |
||
75 | HeaderDesc Header; |
||
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(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, 'n') != nullptr; |
||
129 | } |
||
130 | |||
131 | /// Return true if we know this builtin never returns. |
||
132 | bool isNoReturn(unsigned ID) const { |
||
133 | return strchr(getRecord(ID).Attributes, 'r') != nullptr; |
||
134 | } |
||
135 | |||
136 | /// Return true if we know this builtin can return twice. |
||
137 | bool isReturnsTwice(unsigned ID) const { |
||
138 | return strchr(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, '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 isHeaderDependentFunction(unsigned ID) const { |
||
168 | return strchr(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, '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(getRecord(ID).Type, '*') != 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(getRecord(ID).Type, '&') != nullptr || |
||
217 | strchr(getRecord(ID).Type, '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 *getHeaderName(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(getRecord(ID).Attributes, 'e') != nullptr; |
||
249 | } |
||
250 | |||
251 | bool isConstWithoutExceptions(unsigned ID) const { |
||
252 | return strchr(getRecord(ID).Attributes, '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(getRecord(ID).Attributes, '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 |