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 {
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 namespace Builtin {
52 enum ID {
53   NotBuiltin  = 0,      // This is not a builtin function.
54 #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
55 #include "clang/Basic/Builtins.def"
56   FirstTSBuiltin
57 };
58 
59 struct Info {
60   const char *Name, *Type, *Attributes, *HeaderName;
61   LanguageID Langs;
62   const char *Features;
63 };
64 
65 /// Holds information about both target-independent and
66 /// target-specific builtins, allowing easy queries by clients.
67 ///
68 /// Builtins from an optional auxiliary target are stored in
69 /// AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to
70 /// be translated back with getAuxBuiltinID() before use.
71 class Context {
72   llvm::ArrayRef<Info> TSRecords;
73   llvm::ArrayRef<Info> AuxTSRecords;
74 
75 public:
76   Context() = default;
77 
78   /// Perform target-specific initialization
79   /// \param AuxTarget Target info to incorporate builtins from. May be nullptr.
80   void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget);
81 
82   /// Mark the identifiers for all the builtins with their
83   /// appropriate builtin ID # and mark any non-portable builtin identifiers as
84   /// such.
85   void initializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
86 
87   /// Return the identifier name for the specified builtin,
88   /// e.g. "__builtin_abs".
89   const char *getName(unsigned ID) const {
90     return getRecord(ID).Name;
91   }
92 
93   /// Get the type descriptor string for the specified builtin.
94   const char *getTypeString(unsigned ID) const {
95     return getRecord(ID).Type;
96   }
97 
98   /// Return true if this function is a target-specific builtin.
99   bool isTSBuiltin(unsigned ID) const {
100     return ID >= Builtin::FirstTSBuiltin;
101   }
102 
103   /// Return true if this function has no side effects.
104   bool isPure(unsigned ID) const {
105     return strchr(getRecord(ID).Attributes, 'U') != nullptr;
106   }
107 
108   /// Return true if this function has no side effects and doesn't
109   /// read memory.
110   bool isConst(unsigned ID) const {
111     return strchr(getRecord(ID).Attributes, 'c') != nullptr;
112   }
113 
114   /// Return true if we know this builtin never throws an exception.
115   bool isNoThrow(unsigned ID) const {
116     return strchr(getRecord(ID).Attributes, 'n') != nullptr;
117   }
118 
119   /// Return true if we know this builtin never returns.
120   bool isNoReturn(unsigned ID) const {
121     return strchr(getRecord(ID).Attributes, 'r') != nullptr;
122   }
123 
124   /// Return true if we know this builtin can return twice.
125   bool isReturnsTwice(unsigned ID) const {
126     return strchr(getRecord(ID).Attributes, 'j') != nullptr;
127   }
128 
129   /// Returns true if this builtin does not perform the side-effects
130   /// of its arguments.
131   bool isUnevaluated(unsigned ID) const {
132     return strchr(getRecord(ID).Attributes, 'u') != nullptr;
133   }
134 
135   /// Return true if this is a builtin for a libc/libm function,
136   /// with a "__builtin_" prefix (e.g. __builtin_abs).
137   bool isLibFunction(unsigned ID) const {
138     return strchr(getRecord(ID).Attributes, 'F') != nullptr;
139   }
140 
141   /// Determines whether this builtin is a predefined libc/libm
142   /// function, such as "malloc", where we know the signature a
143   /// priori.
144   /// In C, such functions behave as if they are predeclared,
145   /// possibly with a warning on first use. In Objective-C and C++,
146   /// they do not, but they are recognized as builtins once we see
147   /// a declaration.
148   bool isPredefinedLibFunction(unsigned ID) const {
149     return strchr(getRecord(ID).Attributes, 'f') != nullptr;
150   }
151 
152   /// Returns true if this builtin requires appropriate header in other
153   /// compilers. In Clang it will work even without including it, but we can emit
154   /// a warning about missing header.
155   bool isHeaderDependentFunction(unsigned ID) const {
156     return strchr(getRecord(ID).Attributes, 'h') != nullptr;
157   }
158 
159   /// Determines whether this builtin is a predefined compiler-rt/libgcc
160   /// function, such as "__clear_cache", where we know the signature a
161   /// priori.
162   bool isPredefinedRuntimeFunction(unsigned ID) const {
163     return strchr(getRecord(ID).Attributes, 'i') != nullptr;
164   }
165 
166   /// Determines whether this builtin is a C++ standard library function
167   /// that lives in (possibly-versioned) namespace std, possibly a template
168   /// specialization, where the signature is determined by the standard library
169   /// declaration.
170   bool isInStdNamespace(unsigned ID) const {
171     return strchr(getRecord(ID).Attributes, 'z') != nullptr;
172   }
173 
174   /// Determines whether this builtin can have its address taken with no
175   /// special action required.
176   bool isDirectlyAddressable(unsigned ID) const {
177     // Most standard library functions can have their addresses taken. C++
178     // standard library functions formally cannot in C++20 onwards, and when
179     // we allow it, we need to ensure we instantiate a definition.
180     return isPredefinedLibFunction(ID) && !isInStdNamespace(ID);
181   }
182 
183   /// Determines whether this builtin has custom typechecking.
184   bool hasCustomTypechecking(unsigned ID) const {
185     return strchr(getRecord(ID).Attributes, 't') != nullptr;
186   }
187 
188   /// Determines whether a declaration of this builtin should be recognized
189   /// even if the type doesn't match the specified signature.
190   bool allowTypeMismatch(unsigned ID) const {
191     return strchr(getRecord(ID).Attributes, 'T') != nullptr ||
192            hasCustomTypechecking(ID);
193   }
194 
195   /// Determines whether this builtin has a result or any arguments which
196   /// are pointer types.
197   bool hasPtrArgsOrResult(unsigned ID) const {
198     return strchr(getRecord(ID).Type, '*') != nullptr;
199   }
200 
201   /// Return true if this builtin has a result or any arguments which are
202   /// reference types.
203   bool hasReferenceArgsOrResult(unsigned ID) const {
204     return strchr(getRecord(ID).Type, '&') != nullptr ||
205            strchr(getRecord(ID).Type, 'A') != nullptr;
206   }
207 
208   /// If this is a library function that comes from a specific
209   /// header, retrieve that header name.
210   const char *getHeaderName(unsigned ID) const {
211     return getRecord(ID).HeaderName;
212   }
213 
214   /// Determine whether this builtin is like printf in its
215   /// formatting rules and, if so, set the index to the format string
216   /// argument and whether this function as a va_list argument.
217   bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
218 
219   /// Determine whether this builtin is like scanf in its
220   /// formatting rules and, if so, set the index to the format string
221   /// argument and whether this function as a va_list argument.
222   bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
223 
224   /// Determine whether this builtin has callback behavior (see
225   /// llvm::AbstractCallSites for details). If so, add the index to the
226   /// callback callee argument and the callback payload arguments.
227   bool performsCallback(unsigned ID,
228                         llvm::SmallVectorImpl<int> &Encoding) const;
229 
230   /// Return true if this function has no side effects and doesn't
231   /// read memory, except for possibly errno.
232   ///
233   /// Such functions can be const when the MathErrno lang option is disabled.
234   bool isConstWithoutErrno(unsigned ID) const {
235     return strchr(getRecord(ID).Attributes, 'e') != nullptr;
236   }
237 
238   const char *getRequiredFeatures(unsigned ID) const {
239     return getRecord(ID).Features;
240   }
241 
242   unsigned getRequiredVectorWidth(unsigned ID) const;
243 
244   /// Return true if builtin ID belongs to AuxTarget.
245   bool isAuxBuiltinID(unsigned ID) const {
246     return ID >= (Builtin::FirstTSBuiltin + TSRecords.size());
247   }
248 
249   /// Return real builtin ID (i.e. ID it would have during compilation
250   /// for AuxTarget).
251   unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); }
252 
253   /// Returns true if this is a libc/libm function without the '__builtin_'
254   /// prefix.
255   static bool isBuiltinFunc(llvm::StringRef Name);
256 
257   /// Returns true if this is a builtin that can be redeclared.  Returns true
258   /// for non-builtins.
259   bool canBeRedeclared(unsigned ID) const;
260 
261 private:
262   const Info &getRecord(unsigned ID) const;
263 
264   /// Helper function for isPrintfLike and isScanfLike.
265   bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg,
266               const char *Fmt) const;
267 };
268 
269 /// Returns true if the required target features of a builtin function are
270 /// enabled.
271 /// \p TargetFeatureMap maps a target feature to true if it is enabled and
272 ///    false if it is disabled.
273 bool evaluateRequiredTargetFeatures(
274     llvm::StringRef RequiredFatures,
275     const llvm::StringMap<bool> &TargetFetureMap);
276 
277 } // namespace Builtin
278 
279 /// Kinds of BuiltinTemplateDecl.
280 enum BuiltinTemplateKind : int {
281   /// This names the __make_integer_seq BuiltinTemplateDecl.
282   BTK__make_integer_seq,
283 
284   /// This names the __type_pack_element BuiltinTemplateDecl.
285   BTK__type_pack_element
286 };
287 
288 } // end namespace clang
289 #endif
290