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.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". 103 llvm::StringRef getName(unsigned ID) const { return getRecord(ID).Name; } 104 105 /// Return a quoted name for the specified builtin for use in diagnostics. 106 std::string getQuotedName(unsigned ID) const; 107 108 /// Get the type descriptor string for the specified builtin. 109 const char *getTypeString(unsigned ID) const { return getRecord(ID).Type; } 110 111 /// Return true if this function is a target-specific builtin. 112 bool isTSBuiltin(unsigned ID) const { 113 return ID >= Builtin::FirstTSBuiltin; 114 } 115 116 /// Return true if this function has no side effects. 117 bool isPure(unsigned ID) const { 118 return strchr(getRecord(ID).Attributes, 'U') != nullptr; 119 } 120 121 /// Return true if this function has no side effects and doesn't 122 /// read memory. 123 bool isConst(unsigned ID) const { 124 return strchr(getRecord(ID).Attributes, 'c') != nullptr; 125 } 126 127 /// Return true if we know this builtin never throws an exception. 128 bool isNoThrow(unsigned ID) const { 129 return strchr(getRecord(ID).Attributes, 'n') != nullptr; 130 } 131 132 /// Return true if we know this builtin never returns. 133 bool isNoReturn(unsigned ID) const { 134 return strchr(getRecord(ID).Attributes, 'r') != nullptr; 135 } 136 137 /// Return true if we know this builtin can return twice. 138 bool isReturnsTwice(unsigned ID) const { 139 return strchr(getRecord(ID).Attributes, 'j') != nullptr; 140 } 141 142 /// Returns true if this builtin does not perform the side-effects 143 /// of its arguments. 144 bool isUnevaluated(unsigned ID) const { 145 return strchr(getRecord(ID).Attributes, 'u') != nullptr; 146 } 147 148 /// Return true if this is a builtin for a libc/libm function, 149 /// with a "__builtin_" prefix (e.g. __builtin_abs). 150 bool isLibFunction(unsigned ID) const { 151 return strchr(getRecord(ID).Attributes, 'F') != nullptr; 152 } 153 154 /// Determines whether this builtin is a predefined libc/libm 155 /// function, such as "malloc", where we know the signature a 156 /// priori. 157 /// In C, such functions behave as if they are predeclared, 158 /// possibly with a warning on first use. In Objective-C and C++, 159 /// they do not, but they are recognized as builtins once we see 160 /// a declaration. 161 bool isPredefinedLibFunction(unsigned ID) const { 162 return strchr(getRecord(ID).Attributes, 'f') != nullptr; 163 } 164 165 /// Returns true if this builtin requires appropriate header in other 166 /// compilers. In Clang it will work even without including it, but we can emit 167 /// a warning about missing header. 168 bool isHeaderDependentFunction(unsigned ID) const { 169 return strchr(getRecord(ID).Attributes, 'h') != nullptr; 170 } 171 172 /// Determines whether this builtin is a predefined compiler-rt/libgcc 173 /// function, such as "__clear_cache", where we know the signature a 174 /// priori. 175 bool isPredefinedRuntimeFunction(unsigned ID) const { 176 return strchr(getRecord(ID).Attributes, 'i') != nullptr; 177 } 178 179 /// Determines whether this builtin is a C++ standard library function 180 /// that lives in (possibly-versioned) namespace std, possibly a template 181 /// specialization, where the signature is determined by the standard library 182 /// declaration. 183 bool isInStdNamespace(unsigned ID) const { 184 return strchr(getRecord(ID).Attributes, 'z') != nullptr; 185 } 186 187 /// Determines whether this builtin can have its address taken with no 188 /// special action required. 189 bool isDirectlyAddressable(unsigned ID) const { 190 // Most standard library functions can have their addresses taken. C++ 191 // standard library functions formally cannot in C++20 onwards, and when 192 // we allow it, we need to ensure we instantiate a definition. 193 return isPredefinedLibFunction(ID) && !isInStdNamespace(ID); 194 } 195 196 /// Determines whether this builtin has custom typechecking. 197 bool hasCustomTypechecking(unsigned ID) const { 198 return strchr(getRecord(ID).Attributes, 't') != nullptr; 199 } 200 201 /// Determines whether a declaration of this builtin should be recognized 202 /// even if the type doesn't match the specified signature. 203 bool allowTypeMismatch(unsigned ID) const { 204 return strchr(getRecord(ID).Attributes, 'T') != nullptr || 205 hasCustomTypechecking(ID); 206 } 207 208 /// Determines whether this builtin has a result or any arguments which 209 /// are pointer types. 210 bool hasPtrArgsOrResult(unsigned ID) const { 211 return strchr(getRecord(ID).Type, '*') != nullptr; 212 } 213 214 /// Return true if this builtin has a result or any arguments which are 215 /// reference types. 216 bool hasReferenceArgsOrResult(unsigned ID) const { 217 return strchr(getRecord(ID).Type, '&') != nullptr || 218 strchr(getRecord(ID).Type, 'A') != nullptr; 219 } 220 221 /// If this is a library function that comes from a specific 222 /// header, retrieve that header name. 223 const char *getHeaderName(unsigned ID) const { 224 return getRecord(ID).Header.getName(); 225 } 226 227 /// Determine whether this builtin is like printf in its 228 /// formatting rules and, if so, set the index to the format string 229 /// argument and whether this function as a va_list argument. 230 bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); 231 232 /// Determine whether this builtin is like scanf in its 233 /// formatting rules and, if so, set the index to the format string 234 /// argument and whether this function as a va_list argument. 235 bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); 236 237 /// Determine whether this builtin has callback behavior (see 238 /// llvm::AbstractCallSites for details). If so, add the index to the 239 /// callback callee argument and the callback payload arguments. 240 bool performsCallback(unsigned ID, 241 llvm::SmallVectorImpl<int> &Encoding) const; 242 243 /// Return true if this function has no side effects and doesn't 244 /// read memory, except for possibly errno or raising FP exceptions. 245 /// 246 /// Such functions can be const when the MathErrno lang option and FP 247 /// exceptions are disabled. 248 bool isConstWithoutErrnoAndExceptions(unsigned ID) const { 249 return strchr(getRecord(ID).Attributes, 'e') != nullptr; 250 } 251 252 bool isConstWithoutExceptions(unsigned ID) const { 253 return strchr(getRecord(ID).Attributes, 'g') != nullptr; 254 } 255 256 const char *getRequiredFeatures(unsigned ID) const { 257 return getRecord(ID).Features; 258 } 259 260 unsigned getRequiredVectorWidth(unsigned ID) const; 261 262 /// Return true if builtin ID belongs to AuxTarget. 263 bool isAuxBuiltinID(unsigned ID) const { 264 return ID >= (Builtin::FirstTSBuiltin + TSRecords.size()); 265 } 266 267 /// Return real builtin ID (i.e. ID it would have during compilation 268 /// for AuxTarget). 269 unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); } 270 271 /// Returns true if this is a libc/libm function without the '__builtin_' 272 /// prefix. 273 static bool isBuiltinFunc(llvm::StringRef Name); 274 275 /// Returns true if this is a builtin that can be redeclared. Returns true 276 /// for non-builtins. 277 bool canBeRedeclared(unsigned ID) const; 278 279 /// Return true if this function can be constant evaluated by Clang frontend. 280 bool isConstantEvaluated(unsigned ID) const { 281 return strchr(getRecord(ID).Attributes, 'E') != nullptr; 282 } 283 284 /// Returns true if this is an immediate (consteval) function 285 bool isImmediate(unsigned ID) const { 286 return strchr(getRecord(ID).Attributes, 'G') != nullptr; 287 } 288 289 private: 290 const Info &getRecord(unsigned ID) const; 291 292 /// Helper function for isPrintfLike and isScanfLike. 293 bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg, 294 const char *Fmt) const; 295 }; 296 297 /// Returns true if the required target features of a builtin function are 298 /// enabled. 299 /// \p TargetFeatureMap maps a target feature to true if it is enabled and 300 /// false if it is disabled. 301 bool evaluateRequiredTargetFeatures( 302 llvm::StringRef RequiredFatures, 303 const llvm::StringMap<bool> &TargetFetureMap); 304 305 } // namespace Builtin 306 307 /// Kinds of BuiltinTemplateDecl. 308 enum BuiltinTemplateKind : int { 309 /// This names the __make_integer_seq BuiltinTemplateDecl. 310 BTK__make_integer_seq, 311 312 /// This names the __type_pack_element BuiltinTemplateDecl. 313 BTK__type_pack_element, 314 315 /// This names the __builtin_common_type BuiltinTemplateDecl. 316 BTK__builtin_common_type, 317 }; 318 319 } // end namespace clang 320 #endif 321