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 HeaderDescHeaderDesc58 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.inc" 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". getName(unsigned ID)103 llvm::StringRef getName(unsigned ID) const { return getRecord(ID).Name; } 104 105 /// Get the type descriptor string for the specified builtin. getTypeString(unsigned ID)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. isTSBuiltin(unsigned ID)111 bool isTSBuiltin(unsigned ID) const { 112 return ID >= Builtin::FirstTSBuiltin; 113 } 114 115 /// Return true if this function has no side effects. isPure(unsigned ID)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. isConst(unsigned ID)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. isNoThrow(unsigned ID)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. isNoReturn(unsigned ID)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. isReturnsTwice(unsigned ID)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. isUnevaluated(unsigned ID)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). isLibFunction(unsigned ID)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. isPredefinedLibFunction(unsigned ID)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. isHeaderDependentFunction(unsigned ID)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. isPredefinedRuntimeFunction(unsigned ID)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. isInStdNamespace(unsigned ID)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. isDirectlyAddressable(unsigned ID)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. hasCustomTypechecking(unsigned ID)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. allowTypeMismatch(unsigned ID)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. hasPtrArgsOrResult(unsigned ID)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. hasReferenceArgsOrResult(unsigned ID)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. getHeaderName(unsigned ID)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. isConstWithoutErrnoAndExceptions(unsigned ID)247 bool isConstWithoutErrnoAndExceptions(unsigned ID) const { 248 return strchr(getRecord(ID).Attributes, 'e') != nullptr; 249 } 250 isConstWithoutExceptions(unsigned ID)251 bool isConstWithoutExceptions(unsigned ID) const { 252 return strchr(getRecord(ID).Attributes, 'g') != nullptr; 253 } 254 getRequiredFeatures(unsigned ID)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. isAuxBuiltinID(unsigned ID)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). getAuxBuiltinID(unsigned ID)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. isConstantEvaluated(unsigned ID)279 bool isConstantEvaluated(unsigned ID) const { 280 return strchr(getRecord(ID).Attributes, 'E') != nullptr; 281 } 282 283 /// Returns true if this is an immediate (consteval) function isImmediate(unsigned ID)284 bool isImmediate(unsigned ID) const { 285 return strchr(getRecord(ID).Attributes, 'G') != nullptr; 286 } 287 288 private: 289 const Info &getRecord(unsigned ID) const; 290 291 /// Helper function for isPrintfLike and isScanfLike. 292 bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg, 293 const char *Fmt) const; 294 }; 295 296 /// Returns true if the required target features of a builtin function are 297 /// enabled. 298 /// \p TargetFeatureMap maps a target feature to true if it is enabled and 299 /// false if it is disabled. 300 bool evaluateRequiredTargetFeatures( 301 llvm::StringRef RequiredFatures, 302 const llvm::StringMap<bool> &TargetFetureMap); 303 304 } // namespace Builtin 305 306 /// Kinds of BuiltinTemplateDecl. 307 enum BuiltinTemplateKind : int { 308 /// This names the __make_integer_seq BuiltinTemplateDecl. 309 BTK__make_integer_seq, 310 311 /// This names the __type_pack_element BuiltinTemplateDecl. 312 BTK__type_pack_element 313 }; 314 315 } // end namespace clang 316 #endif 317