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 <cstring>
20 
21 // VC++ defines 'alloca' as an object-like macro, which interferes with our
22 // builtins.
23 #undef alloca
24 
25 namespace clang {
26 class TargetInfo;
27 class IdentifierTable;
28 class LangOptions;
29 
30 enum LanguageID {
31   GNU_LANG = 0x1,     // builtin requires GNU mode.
32   C_LANG = 0x2,       // builtin for c only.
33   CXX_LANG = 0x4,     // builtin for cplusplus only.
34   OBJC_LANG = 0x8,    // builtin for objective-c and objective-c++
35   MS_LANG = 0x10,     // builtin requires MS mode.
36   OCLC20_LANG = 0x20, // builtin for OpenCL C 2.0 only.
37   OCLC1X_LANG = 0x40, // builtin for OpenCL C 1.x only.
38   OMP_LANG = 0x80,    // builtin requires OpenMP.
39   CUDA_LANG = 0x100,  // builtin requires CUDA.
40   COR_LANG = 0x200,   // builtin requires use of 'fcoroutine-ts' option.
41   ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
42   ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG,  // builtin requires GNU mode.
43   ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG,    // builtin requires MS mode.
44   ALL_OCLC_LANGUAGES = OCLC1X_LANG | OCLC20_LANG // builtin for OCLC languages.
45 };
46 
47 namespace Builtin {
48 enum ID {
49   NotBuiltin  = 0,      // This is not a builtin function.
50 #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
51 #include "clang/Basic/Builtins.def"
52   FirstTSBuiltin
53 };
54 
55 struct Info {
56   const char *Name, *Type, *Attributes, *HeaderName;
57   LanguageID Langs;
58   const char *Features;
59 };
60 
61 /// Holds information about both target-independent and
62 /// target-specific builtins, allowing easy queries by clients.
63 ///
64 /// Builtins from an optional auxiliary target are stored in
65 /// AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to
66 /// be translated back with getAuxBuiltinID() before use.
67 class Context {
68   llvm::ArrayRef<Info> TSRecords;
69   llvm::ArrayRef<Info> AuxTSRecords;
70 
71 public:
Context()72   Context() {}
73 
74   /// Perform target-specific initialization
75   /// \param AuxTarget Target info to incorporate builtins from. May be nullptr.
76   void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget);
77 
78   /// Mark the identifiers for all the builtins with their
79   /// appropriate builtin ID # and mark any non-portable builtin identifiers as
80   /// such.
81   void initializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
82 
83   /// Return the identifier name for the specified builtin,
84   /// e.g. "__builtin_abs".
getName(unsigned ID)85   const char *getName(unsigned ID) const {
86     return getRecord(ID).Name;
87   }
88 
89   /// Get the type descriptor string for the specified builtin.
getTypeString(unsigned ID)90   const char *getTypeString(unsigned ID) const {
91     return getRecord(ID).Type;
92   }
93 
94   /// Return true if this function is a target-specific builtin.
isTSBuiltin(unsigned ID)95   bool isTSBuiltin(unsigned ID) const {
96     return ID >= Builtin::FirstTSBuiltin;
97   }
98 
99   /// Return true if this function has no side effects.
isPure(unsigned ID)100   bool isPure(unsigned ID) const {
101     return strchr(getRecord(ID).Attributes, 'U') != nullptr;
102   }
103 
104   /// Return true if this function has no side effects and doesn't
105   /// read memory.
isConst(unsigned ID)106   bool isConst(unsigned ID) const {
107     return strchr(getRecord(ID).Attributes, 'c') != nullptr;
108   }
109 
110   /// Return true if we know this builtin never throws an exception.
isNoThrow(unsigned ID)111   bool isNoThrow(unsigned ID) const {
112     return strchr(getRecord(ID).Attributes, 'n') != nullptr;
113   }
114 
115   /// Return true if we know this builtin never returns.
isNoReturn(unsigned ID)116   bool isNoReturn(unsigned ID) const {
117     return strchr(getRecord(ID).Attributes, 'r') != nullptr;
118   }
119 
120   /// Return true if we know this builtin can return twice.
isReturnsTwice(unsigned ID)121   bool isReturnsTwice(unsigned ID) const {
122     return strchr(getRecord(ID).Attributes, 'j') != nullptr;
123   }
124 
125   /// Returns true if this builtin does not perform the side-effects
126   /// of its arguments.
isUnevaluated(unsigned ID)127   bool isUnevaluated(unsigned ID) const {
128     return strchr(getRecord(ID).Attributes, 'u') != nullptr;
129   }
130 
131   /// Return true if this is a builtin for a libc/libm function,
132   /// with a "__builtin_" prefix (e.g. __builtin_abs).
isLibFunction(unsigned ID)133   bool isLibFunction(unsigned ID) const {
134     return strchr(getRecord(ID).Attributes, 'F') != nullptr;
135   }
136 
137   /// Determines whether this builtin is a predefined libc/libm
138   /// function, such as "malloc", where we know the signature a
139   /// priori.
isPredefinedLibFunction(unsigned ID)140   bool isPredefinedLibFunction(unsigned ID) const {
141     return strchr(getRecord(ID).Attributes, 'f') != nullptr;
142   }
143 
144   /// Returns true if this builtin requires appropriate header in other
145   /// compilers. In Clang it will work even without including it, but we can emit
146   /// a warning about missing header.
isHeaderDependentFunction(unsigned ID)147   bool isHeaderDependentFunction(unsigned ID) const {
148     return strchr(getRecord(ID).Attributes, 'h') != nullptr;
149   }
150 
151   /// Determines whether this builtin is a predefined compiler-rt/libgcc
152   /// function, such as "__clear_cache", where we know the signature a
153   /// priori.
isPredefinedRuntimeFunction(unsigned ID)154   bool isPredefinedRuntimeFunction(unsigned ID) const {
155     return strchr(getRecord(ID).Attributes, 'i') != nullptr;
156   }
157 
158   /// Determines whether this builtin has custom typechecking.
hasCustomTypechecking(unsigned ID)159   bool hasCustomTypechecking(unsigned ID) const {
160     return strchr(getRecord(ID).Attributes, 't') != nullptr;
161   }
162 
163   /// Determines whether a declaration of this builtin should be recognized
164   /// even if the type doesn't match the specified signature.
allowTypeMismatch(unsigned ID)165   bool allowTypeMismatch(unsigned ID) const {
166     return strchr(getRecord(ID).Attributes, 'T') != nullptr ||
167            hasCustomTypechecking(ID);
168   }
169 
170   /// Determines whether this builtin has a result or any arguments which
171   /// are pointer types.
hasPtrArgsOrResult(unsigned ID)172   bool hasPtrArgsOrResult(unsigned ID) const {
173     return strchr(getRecord(ID).Type, '*') != nullptr;
174   }
175 
176   /// Return true if this builtin has a result or any arguments which are
177   /// reference types.
hasReferenceArgsOrResult(unsigned ID)178   bool hasReferenceArgsOrResult(unsigned ID) const {
179     return strchr(getRecord(ID).Type, '&') != nullptr ||
180            strchr(getRecord(ID).Type, 'A') != nullptr;
181   }
182 
183   /// If this is a library function that comes from a specific
184   /// header, retrieve that header name.
getHeaderName(unsigned ID)185   const char *getHeaderName(unsigned ID) const {
186     return getRecord(ID).HeaderName;
187   }
188 
189   /// Determine whether this builtin is like printf in its
190   /// formatting rules and, if so, set the index to the format string
191   /// argument and whether this function as a va_list argument.
192   bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
193 
194   /// Determine whether this builtin is like scanf in its
195   /// formatting rules and, if so, set the index to the format string
196   /// argument and whether this function as a va_list argument.
197   bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
198 
199   /// Determine whether this builtin has callback behavior (see
200   /// llvm::AbstractCallSites for details). If so, add the index to the
201   /// callback callee argument and the callback payload arguments.
202   bool performsCallback(unsigned ID,
203                         llvm::SmallVectorImpl<int> &Encoding) const;
204 
205   /// Return true if this function has no side effects and doesn't
206   /// read memory, except for possibly errno.
207   ///
208   /// Such functions can be const when the MathErrno lang option is disabled.
isConstWithoutErrno(unsigned ID)209   bool isConstWithoutErrno(unsigned ID) const {
210     return strchr(getRecord(ID).Attributes, 'e') != nullptr;
211   }
212 
getRequiredFeatures(unsigned ID)213   const char *getRequiredFeatures(unsigned ID) const {
214     return getRecord(ID).Features;
215   }
216 
217   unsigned getRequiredVectorWidth(unsigned ID) const;
218 
219   /// Return true if builtin ID belongs to AuxTarget.
isAuxBuiltinID(unsigned ID)220   bool isAuxBuiltinID(unsigned ID) const {
221     return ID >= (Builtin::FirstTSBuiltin + TSRecords.size());
222   }
223 
224   /// Return real builtin ID (i.e. ID it would have during compilation
225   /// for AuxTarget).
getAuxBuiltinID(unsigned ID)226   unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); }
227 
228   /// Returns true if this is a libc/libm function without the '__builtin_'
229   /// prefix.
230   static bool isBuiltinFunc(llvm::StringRef Name);
231 
232   /// Returns true if this is a builtin that can be redeclared.  Returns true
233   /// for non-builtins.
234   bool canBeRedeclared(unsigned ID) const;
235 
236 private:
237   const Info &getRecord(unsigned ID) const;
238 
239   /// Is this builtin supported according to the given language options?
240   bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
241                           const LangOptions &LangOpts);
242 
243   /// Helper function for isPrintfLike and isScanfLike.
244   bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg,
245               const char *Fmt) const;
246 };
247 
248 }
249 
250 /// Kinds of BuiltinTemplateDecl.
251 enum BuiltinTemplateKind : int {
252   /// This names the __make_integer_seq BuiltinTemplateDecl.
253   BTK__make_integer_seq,
254 
255   /// This names the __type_pack_element BuiltinTemplateDecl.
256   BTK__type_pack_element
257 };
258 
259 } // end namespace clang
260 #endif
261