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 |